Compare commits

...

234 次程式碼提交

作者 SHA1 備註 提交日期
  Jason Chuang 62c3a6bbfd FPS enable web-to-app 1 周之前
  Alex Cheung 32c3b256da update check page 3 週之前
  Alex Cheung fbd0a00b8b update db check page /databaseHealthCheck 4 週之前
  Alex Cheung 520de2f87c update recon download file btn 1 月之前
  Alex Cheung 8a873414c6 update download btn disable 1 月之前
  Alex Cheung 0347064423 add get jvm info 2 月之前
  Alex Cheung 3fdf6311bb update jvm page 2 月之前
  Alex Cheung 7777e520c4 FIx FPS cancel 2 月之前
  Alex Cheung f5e671ca7f fix public notes save search criteria 2 月之前
  Jason Chuang 985118ae10 fix audit log export 2 月之前
  Alex Cheung ad333c8621 update SearchCriteria save 2 月之前
  Alex Cheung ab6377db8c update save page number for data gird 2 月之前
  Alex Cheung afd6fe0242 update massage 2 月之前
  Alex Cheung 3cf55a0191 update message 2 月之前
  Alex Cheung 673229bbe5 update org register remove '()' checking 2 月之前
  Alex Cheung 3cc816b55c update org user faxNo and org faxNo and dashboard clear search 3 月之前
  Alex Cheung f85eb71007 fix clear combo 3 月之前
  Alex Cheung 923c8577f3 update gld view searching and gld user search page bug fix 3 月之前
  Alex Cheung c2fe95a1a6 update application and bug fix 3 月之前
  Alex Cheung 70e6943b4a update public search criteria save 3 月之前
  Alex Cheung 868e84838d update proof searchCriteria save 3 月之前
  Alex Cheung ef23ec8af9 layout fix 7 月之前
  Alex Cheung 75f4c51fff update home page message and about us 7 月之前
  Alex Cheung d849afb6fc update about us 7 月之前
  Alex Cheung b436ffa1d0 update application reset btn 7 月之前
  Alex Cheung fe84a6f046 add back FPS auto cancel 8 月之前
  Alex Cheung 6a07b6cc71 add careOf and org combo 9 月之前
  Jason Chuang 257526d37c emport phone no 9 月之前
  Alex Cheung 18a990b716 Merge branch 'New_Enhancement' into CR003 9 月之前
  Alex Cheung ebcccfc705 update proof combo 9 月之前
  Alex Cheung d66410f7ac fix table field for dummy user 9 月之前
  Alex Cheung d748c23f51 update fps web to app for testing 9 月之前
  Alex Cheung 68914b6406 updated contactPerson with empty string when user is dummy user 9 月之前
  Alex Cheung 71541441a5 update fps expired 9 月之前
  Alex Cheung a591027d29 update fps 9 月之前
  Alex Cheung 324548afbf update gen gdn 9 月之前
  Alex Cheung 50a22d0d69 handle dummy user client display 9 月之前
  Alex Cheung 48a88815c1 add search combo for gld views 9 月之前
  Alex Cheung ded2428881 combo update 10 月之前
  Alex Cheung 6015900f57 update audit log auth 10 月之前
  Alex Cheung 77efaee1da add application remark auth 10 月之前
  Alex Cheung c16e0af999 update group 10 月之前
  Alex Cheung 35daecbf33 add auth 10 月之前
  Alex Cheung 874aeeb2cc fix grid loading 11 月之前
  Alex Cheung 9d537b917c remove build 11 月之前
  Alex Cheung 4952fcab16 search button update 11 月之前
  Alex Cheung efa7c3933b fix datagrid error 11 月之前
  Alex Cheung 9d4ecf4390 fix datagird without search button 11 月之前
  Alex Cheung 20902d5305 fix disable button with error 11 月之前
  Alex Cheung 5b5589566a update search button 11 月之前
  Alex Cheung 9c5bd9ac95 fix double search api for data table 11 月之前
  Alex Cheung 50ddd841b4 add loading to datagird 11 月之前
  Alex Cheung 63738d8b6a add loading for iAmsmart loading data 11 月之前
  Anna Ho 44325ecc10 CriOS as iOS_Chrome 11 月之前
  Alex Cheung 3ef7e45af1 update FPS test 11 月之前
  Jason Chuang 46aa7177fe Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 11 月之前
  Jason Chuang 6b9998fccc FPS 11 月之前
  Alex Cheung 3b0753f753 update user guide 11 月之前
  Jason Chuang 505554a408 update user guide label 1 年之前
  Jason Chuang 0e92a27d81 update label 1 年之前
  Jason Chuang 70b87c12db update user guide pub link 1 年之前
  Anna Ho 3adb028a51 add 1 年之前
  Jason Chuang 8b0caa2231 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang f971b01920 update about us 1 年之前
  Anna Ho ddad685252 cn use zh user guide file 1 年之前
  Anna Ho e91b67420c change path 1 年之前
  Anna Ho 6d4e1cd767 add header 1 年之前
  Jason Chuang 5548862d84 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang c98e2c0a83 fps and about us 1 年之前
  Anna Ho f9e43b23e7 user-guide-pub 1 年之前
  Alex Cheung 4d74c29810 date change 1 年之前
  Alex Cheung 53ac90879b fix pending payment deadline 1 年之前
  Alex Cheung c1c38cdb53 update wordings 1 年之前
  Alex Cheung dd3c15fe40 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung c74c956d76 disable console.log 1 年之前
  Anna Ho 561610a51d change folder name 1 年之前
  Alex Cheung b6d805afa5 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung 78e85c246f update uat title color change 1 年之前
  Anna Ho 47da9555d4 AboutUs, ImportantNotice, PrivacyPolicy 1 年之前
  Jason Chuang 6b81ba3544 enable FPS web to app 1 年之前
  Alex Cheung 33f312ce75 update fps disable check mobile 1 年之前
  Alex Cheung 40ef9d6fe3 update district 1 年之前
  Anna Ho 0460eae108 about us color 1 年之前
  Anna Ho cddce62251 About Us UI fix 1 年之前
  Anna Ho 1f07220334 about us 1 年之前
  Alex Cheung bd313899b5 update wordings and userprofile 1 年之前
  Alex Cheung 8091aaeb27 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung 1bdbd45897 update idNo check 1 年之前
  Jason Chuang 3dfc109d63 iam smart label update 1 年之前
  Alex Cheung b1e5a946c4 fix display detail 1 年之前
  Alex Cheung b284fd5ba2 wording update 1 年之前
  Anna Ho 524272274d update 1 年之前
  Alex Cheung c0b27730d8 fix date bug 1 年之前
  Alex Cheung 0b46126b8c add admin header display 1 年之前
  Alex Cheung 1ceebfdb87 update wordings 1 年之前
  Anna Ho 3761c1184e iamsmart and fix dn sendDate bug 1 年之前
  Anna Ho ceed5c5cec change header to "Deadline for online manuscript revision (Pay online via PNSPS)" 1 年之前
  Anna Ho bd9655c4d2 fix bug 1 年之前
  Anna Ho 6880ed72ba iAM Smart set brokerPage=true 1 年之前
  Alex Cheung 0ee39a7fde update ui layout 1 年之前
  Alex Cheung 96b7bc6ef5 update i18n 1 年之前
  Alex Cheung 4afb60358b update i18n 1 年之前
  Alex Cheung e8a24e7403 update comment from Matt 1 年之前
  Alex Cheung ed089e64d1 fix i18n bug 1 年之前
  Alex Cheung 724e79b2fe Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung 505af12820 update i18n 1 年之前
  Anna Ho 783bf7ccc8 update UI 1 年之前
  Anna Ho 602c4b420b fix bug 1 年之前
  Anna Ho c0811a72df fix i18n 1 年之前
  Anna Ho b04f433b4d update i18n 1 年之前
  Anna Ho 0cee61df7d remove "pnspsdev.gld.gov.hk" 1 年之前
  Anna Ho 875458a76f update UI 1 年之前
  Anna Ho a322555297 update UI 1 年之前
  Anna Ho ffd3f166fa update i18n 1 年之前
  Anna Ho 26b3f9597b update string 1 年之前
  Jason Chuang f378e4f16d Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang 858d9d727e update message 1 年之前
  Alex Cheung f02a69cb4d Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung 6e97e779d8 update payment status 1 年之前
  Anna Ho 428abdc670 on iamsmart fail page 1 年之前
  Alex Cheung 0cb399846f update payment status display 1 年之前
  Alex Cheung 5219813c26 fix gns routes 1 年之前
  Jason Chuang 2de38844d0 update access right for GDN 1 年之前
  Anna Ho f952d2a7fc fix url 1 年之前
  Anna Ho c2dabf0d9f update i18n 1 年之前
  Anna Ho cd93eccdc8 update user guide ui 1 年之前
  Anna Ho 09eb8afdd3 add userGuide 1 年之前
  Anna Ho aa370d75ed add Important Notice 1 年之前
  Anna Ho 6c3aca90bf update check ID 1 年之前
  Alex Cheung 07a6f593b6 fix user profile 1 年之前
  Anna Ho c91f032a2d Login Routes re 1 年之前
  Alex Cheung ab3adaad33 Merge branch 'test_HKID' into New_Enhancement 1 年之前
  Alex Cheung f1af83023b fix cnid cannot save 1 年之前
  Anna Ho 1a632f2cad add SYS.ui.manage.allowRegistration 1 年之前
  Alex Cheung a640af8c79 update change password page add text 1 年之前
  Alex Cheung f8d82db96d update user HKid and checkdigi 1 年之前
  Alex Cheung 51e3209acc Merge branch 'New_Enhancement' into test_HKID 1 年之前
  Anna Ho dedcbf29bd move iAM Smart api path to properties 1 年之前
  Alex Cheung dda5735faf fix login with wrong username 1 年之前
  Alex Cheung cdbf342265 update index icon 1 年之前
  Jason Chuang a683d36674 update about us 1 年之前
  Anna Ho ef73acfeb3 fix create proof bug 1 年之前
  Anna Ho a3217e28c3 update forgot username 1 年之前
  Anna Ho 89dcb5cad8 update reply proof UI 1 年之前
  Jason Chuang 524be841e9 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang bfe26b8160 update label 1 年之前
  Alex Cheung 4506564ee0 update fps prod url 1 年之前
  Anna Ho 6d3f5550a4 add about us 1 年之前
  Alex Cheung fd8b5427bc update gdn 1 年之前
  Anna Ho 7a5d5e6ede address5 change update phone 1 年之前
  Anna Ho ea4d92337c check proof column should > 0 1 年之前
  Anna Ho ca0dca8c10 update words 1 年之前
  Alex Cheung 09bd2f5098 Merge branch 'New_Enhancement' into SRAA_Test 1 年之前
  Alex Cheung 8ec89dec0f sraa update 1 年之前
  Jason Chuang fe5d91e148 update locale 1 年之前
  Anna Ho 4f95510418 word 1 年之前
  Anna Ho 3c4e51ca35 update word 1 年之前
  Alex Cheung a5d16b54a6 update Axios version for Vulnerable JS Library 1 年之前
  Anna Ho 415c86d1b9 update word 1 年之前
  Jason Chuang e70b0cbf05 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang 5982711ad6 update label 1 年之前
  Anna Ho b727c5cb8f privacyPolicy 1 年之前
  Jason Chuang 1fcfcbe8ec update label 1 年之前
  Anna Ho 1db138f63e user group fix bug 1 年之前
  Anna Ho f43c78838d fix i am smart bug 1 年之前
  Alex Cheung 36ebdfce6f update fps mobile btn 1 年之前
  Jason Chuang bcf88deadd Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang fa974d4856 update label 1 年之前
  Terence 51dce719c3 update route case sensitive 1 年之前
  Anna Ho 4dd1b26a02 update iAM Smart button 1 年之前
  Alex Cheung bf113662ee Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung 414e5da675 update check pasword special character and update org btn auth and application Id i18n 1 年之前
  Anna Ho 6bfed621e7 update iAM Smart button text 1 年之前
  Alex Cheung cd687d6cb9 update hidle payment table for credit user 1 年之前
  Anna Ho 63400671a7 GLD proof search statue 1 年之前
  Jason Chuang cb28ce731c Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang b4eb579409 update label 1 年之前
  Anna Ho b700fff6e2 iAM Smart & status i18n 1 年之前
  Anna Ho bdf58c0b2d "iAM Smart" update Login Success UI 1 年之前
  Anna Ho f6fbec0c45 "iAM Smart" from update 1 年之前
  Anna Ho 13bf252cdb "iAM Smart" update 1 年之前
  Alex Cheung a88c79deb8 update emailConfirm handle 1 年之前
  Alex Cheung 066ba60193 update Amendment zip 1 年之前
  Anna Ho 53e51f84c3 update gen O/S dn List 1 年之前
  Anna Ho 7b8b15398d status 1 年之前
  Anna Ho 6d76833cd4 iAm Smart fix typo 1 年之前
  Jason Chuang d36afa6ee9 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang 2999987498 update i18n 1 年之前
  Alex Cheung a91c53694e update check not accept btn checking and ui update 1 年之前
  Anna Ho 3aa8d99095 Proof Records Starus 1 年之前
  Anna Ho af54518f20 update status i18n 1 年之前
  Alex Cheung f120ab9edb update dummy user edit apply public notice fax and phone number 1 年之前
  Anna Ho 8fdc98276d fix bug 1 年之前
  Anna Ho 0c0b97456f GET_SEND_OVERDUE_CREDITOR_LIST 1 年之前
  Alex Cheung 99a229cf0c update setting 1 年之前
  Jason Chuang 646421d897 update label 1 年之前
  Jason Chuang a7b5878ecf update label 1 年之前
  Alex Cheung ad18ada2dc Merge branch 'master' into New_Enhancement 1 年之前
  Jason Chuang 1eed4d7f3d Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang 55f53d384c update label 1 年之前
  Alex Cheung b8b843aae2 fix preferLocale and add orgPaymentRecord for org check online payment record 1 年之前
  Jason Chuang 922abf73ac Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Jason Chuang 9234d74a74 label and layout update 1 年之前
  Alex Cheung 95e1b8c921 update 1 年之前
  Alex Cheung 13ec88f514 update fps second 1 年之前
  Alex Cheung e5614037b8 fix autoFocus 1 年之前
  Alex Cheung 51462e8283 fix eng name and cht name 1 年之前
  Alex Cheung 6ae8ba07a6 hidle error message without edit mode 1 年之前
  Alex Cheung 9e55135d38 update check captcha 1 年之前
  Alex Cheung 016ea6235d update check captcha 1 年之前
  Alex Cheung 39b150a58c update layout 1 年之前
  Alex Cheung e3cdffa2f5 update proof and payment page text 1 年之前
  Alex Cheung d7ae3c0ee1 update check name 1 年之前
  Anna Ho 4dca798a3a disable 15:00 Scheduled, add send mail Button 1 年之前
  Anna Ho 81639691e5 fix bug - reload after mark "published" 1 年之前
  Anna Ho ff0cbe1c05 Merge branch 'master' into New_Enhancement 1 年之前
  Anna Ho f13b166d63 Merge branch 'master' into New_Enhancement 1 年之前
  Alex Cheung cbc8eb2c90 update dashboard loading 1 年之前
  Alex Cheung 37a6b1f9e9 update 1 年之前
  Alex Cheung e9f2fdb852 update 1 年之前
  Alex Cheung b2a727ca61 add change password page 1 年之前
  Alex Cheung 55f9a1d78f Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung bd40598a1d update password log 1 年之前
  Anna Ho da6bcd39fb fix bug 1 年之前
  Anna Ho 7af45e4e8d Merge branch 'master' into New_Enhancement 1 年之前
  Anna Ho c2e1d3a305 dn revoke paid 1 年之前
  Alex Cheung 630344cfc4 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung a78cdad254 add password remark 1 年之前
  Anna Ho 131b31f850 email and paid button at application 1 年之前
  Alex Cheung cb04b13088 Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung b61dc7d04a update captcha 1 年之前
  Anna Ho a0d8c5f0db Merge branch 'master' into New_Enhancement 1 年之前
  Alex Cheung b7a919f44e Merge branch 'New_Enhancement' of https://git.2fi-solutions.com/alex/PNSPS-frontend-MaterialUI into New_Enhancement 1 年之前
  Alex Cheung ec5aa563e4 update gldRemarks for gld user 1 年之前
共有 100 個檔案被更改,包括 4015 行新增2815 行删除
統一視圖
  1. +15
    -0
      .vscode/launch.json
  2. +1371
    -1569
      package-lock.json
  3. +1
    -1
      package.json
  4. 二進制
      public/apple-touch-icon.png
  5. 二進制
      public/favicon-16x16.png
  6. 二進制
      public/favicon-32x32.png
  7. +9
    -38
      public/index.html
  8. +54
    -0
      public/safari-pinned-tab.svg
  9. 二進制
      src/assets/images/icons/expiredQrcodeCN.png
  10. 二進制
      src/assets/images/icons/expiredQrcodeEN.png
  11. 二進制
      src/assets/images/icons/expiredQrcodeZH.png
  12. +2
    -0
      src/auth/index.js
  13. +33
    -20
      src/auth/utils.js
  14. +4
    -1
      src/components/AdminLogo/index.js
  15. +5
    -1
      src/components/AutoLogoutProvider.js
  16. +85
    -22
      src/components/FiDataGrid.js
  17. +10
    -0
      src/components/FileList.js
  18. +35
    -0
      src/components/SysSettingProvider.js
  19. +2
    -3
      src/components/cards/AuthFooter.js
  20. +8
    -4
      src/index.js
  21. +419
    -293
      src/layout/MainLayout/Header/index.js
  22. +23
    -13
      src/layout/MainLayout/index.js
  23. +9
    -3
      src/pages/Announcement/Search/DataGrid.js
  24. +5
    -2
      src/pages/Announcement/Search/SearchForm.js
  25. +26
    -5
      src/pages/Announcement/Search/index.js
  26. +10
    -4
      src/pages/Announcement/Search_Public/DataGrid.js
  27. +22
    -3
      src/pages/Announcement/Search_Public/SearchForm.js
  28. +26
    -5
      src/pages/Announcement/Search_Public/index.js
  29. +12
    -9
      src/pages/AuditLog/AuditLogSearchForm.js
  30. +10
    -4
      src/pages/AuditLog/AuditLogTable.js
  31. +10
    -1
      src/pages/AuditLog/index.js
  32. +1
    -1
      src/pages/DemandNote/Details/ApplicationDetailCard.js
  33. +15
    -9
      src/pages/DemandNote/Export/DataGrid.js
  34. +86
    -15
      src/pages/DemandNote/Search/DataGrid.js
  35. +48
    -6
      src/pages/DemandNote/Search/SearchForm.js
  36. +21
    -4
      src/pages/DemandNote/Search/index.js
  37. +14
    -6
      src/pages/DemandNote/Search_Public/DataGrid.js
  38. +23
    -3
      src/pages/DemandNote/Search_Public/SearchForm.js
  39. +22
    -5
      src/pages/DemandNote/Search_Public/index.js
  40. +3
    -3
      src/pages/EmailTemplate/Detail_GLD/index.js
  41. +8
    -4
      src/pages/EmailTemplate/Search_GLD/DataGrid.js
  42. +2
    -1
      src/pages/GFMIS/DataGrid.js
  43. +2
    -1
      src/pages/GFMIS/SearchForm.js
  44. +14
    -5
      src/pages/GFMIS/index.js
  45. +8
    -3
      src/pages/GazetteIssue/DataGrid.js
  46. +2
    -2
      src/pages/GazetteIssue/ExportForm.js
  47. +2
    -1
      src/pages/GazetteIssue/SearchForm.js
  48. +41
    -29
      src/pages/GazetteIssue/index.js
  49. +7
    -2
      src/pages/Holiday/DataGrid.js
  50. +2
    -1
      src/pages/Holiday/SearchForm.js
  51. +35
    -24
      src/pages/Holiday/index.js
  52. +121
    -0
      src/pages/JVM/index.js
  53. +38
    -22
      src/pages/Message/Search/DataGrid.js
  54. +5
    -2
      src/pages/Message/Search/SearchForm.js
  55. +46
    -24
      src/pages/Message/Search/index.js
  56. +113
    -62
      src/pages/Organization/DetailPage/OrganizationCard.js
  57. +51
    -55
      src/pages/Organization/DetailPage/OrganizationPubCard.js
  58. +14
    -12
      src/pages/Organization/DetailPage_FromUser/OrganizationCard_loadFromUser.js
  59. +30
    -4
      src/pages/Organization/SearchPage/OrganizationSearchForm.js
  60. +10
    -4
      src/pages/Organization/SearchPage/OrganizationTable.js
  61. +24
    -2
      src/pages/Organization/SearchPage/index.js
  62. +1
    -1
      src/pages/Payment/Details_GLD/DataGrid.js
  63. +10
    -10
      src/pages/Payment/Details_GLD/PaymentDetails.js
  64. +1
    -1
      src/pages/Payment/Details_GLD/index.js
  65. +1
    -1
      src/pages/Payment/Details_Public/DataGrid.js
  66. +43
    -20
      src/pages/Payment/Details_Public/PaymentDetails.js
  67. +6
    -6
      src/pages/Payment/Details_Public/index.js
  68. +38
    -26
      src/pages/Payment/FPS/AckPage.js
  69. +129
    -68
      src/pages/Payment/FPS/FPS.js
  70. +1
    -1
      src/pages/Payment/FPS/FPSTest.js
  71. +50
    -40
      src/pages/Payment/FPS/fpscallback.js
  72. +7
    -7
      src/pages/Payment/MultiPaymentWindow.js
  73. +24
    -14
      src/pages/Payment/PaymentCallback.js
  74. +11
    -5
      src/pages/Payment/Search_GLD/DataGrid.js
  75. +18
    -2
      src/pages/Payment/Search_GLD/SearchForm.js
  76. +26
    -6
      src/pages/Payment/Search_GLD/index.js
  77. +10
    -4
      src/pages/Payment/Search_Public/DataGrid.js
  78. +9
    -3
      src/pages/Payment/Search_Public/SearchForm.js
  79. +28
    -3
      src/pages/Payment/Search_Public/index.js
  80. +3
    -1
      src/pages/Payment/index.js
  81. +53
    -22
      src/pages/Proof/Create_FromApp/ApplicationDetails.js
  82. +16
    -1
      src/pages/Proof/Create_FromApp/ProofForm.js
  83. +4
    -4
      src/pages/Proof/Create_FromApp/UploadFileTable.js
  84. +1
    -1
      src/pages/Proof/Payment/Pay.js
  85. +1
    -0
      src/pages/Proof/Payment/Pay_Creditor.js
  86. +5
    -4
      src/pages/Proof/Payment/Pay_DN.js
  87. +4
    -3
      src/pages/Proof/Payment/Pay_Office.js
  88. +9
    -6
      src/pages/Proof/Payment/Pay_Online.js
  89. +60
    -25
      src/pages/Proof/Reply_GLD/ApplicationDetails.js
  90. +1
    -1
      src/pages/Proof/Reply_GLD/ProofForm.js
  91. +4
    -4
      src/pages/Proof/Reply_GLD/UploadFileTable.js
  92. +57
    -12
      src/pages/Proof/Reply_Public/ApplicationDetails.js
  93. +175
    -141
      src/pages/Proof/Reply_Public/ProofForm.js
  94. +4
    -4
      src/pages/Proof/Reply_Public/UploadFileTable.js
  95. +14
    -5
      src/pages/Proof/Search_GLD/DataGrid.js
  96. +71
    -12
      src/pages/Proof/Search_GLD/SearchForm.js
  97. +22
    -5
      src/pages/Proof/Search_GLD/index.js
  98. +32
    -21
      src/pages/Proof/Search_Public/DataGrid.js
  99. +32
    -8
      src/pages/Proof/Search_Public/SearchForm.js
  100. +20
    -4
      src/pages/Proof/Search_Public/index.js

+ 15
- 0
.vscode/launch.json 查看文件

@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}/src"
}
]
}

+ 1371
- 1569
package-lock.json
文件差異過大導致無法顯示
查看文件


+ 1
- 1
package.json 查看文件

@@ -22,7 +22,7 @@
"@testing-library/user-event": "^14.4.3", "@testing-library/user-event": "^14.4.3",
"@types/react-input-mask": "^3.0.2", "@types/react-input-mask": "^3.0.2",
"apexcharts": "^3.35.5", "apexcharts": "^3.35.5",
"axios": "^1.4.0",
"axios": "^1.7.1",
"date-fns": "^3.0.6", "date-fns": "^3.0.6",
"dayjs": "^1.11.9", "dayjs": "^1.11.9",
"formik": "^2.2.9", "formik": "^2.2.9",


二進制
public/apple-touch-icon.png 查看文件

Before After
Width: 180  |  Height: 180  |  Size: 6.4 KiB

二進制
public/favicon-16x16.png 查看文件

Before After
Width: 16  |  Height: 16  |  Size: 1.1 KiB

二進制
public/favicon-32x32.png 查看文件

Before After
Width: 32  |  Height: 32  |  Size: 1.7 KiB

+ 9
- 38
public/index.html 查看文件

@@ -2,52 +2,23 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.svg" />
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/favicon-16x16.png">
<link rel="mask-icon" href="%PUBLIC_URL%/safari-pinned-tab.svg" color="#5bbad5">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#1f1f1f" />
<meta name="theme-color" content="#ffffff" />
<meta name="msapplication-TileColor" content="#da532c">
<meta name="title" content="PNSPS" /> <meta name="title" content="PNSPS" />
<meta <meta
name="description" name="description"
content="Mantis is a free, super flexible and customizable react redux dashboard template built using MUI React components with open source MIT license."
content="The Government of the Hong Kong Special Administrative Region Gazette Public Notice Submission and Payment System."
/> />
<meta <meta
name="keywords" name="keywords"
content="react dashboard, react admin, react redux dashboard, ant design template, saas admin, free react dashboard"
content="PNSPS, GLD, react redux dashboard, Gazette, Public Notice"
/> />
<meta name="author" content="CodedThemes" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!-- Open Graph / Facebook -->
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://mantisdashboard.io/" />
<meta property="og:site_name" content="mantisdashboard.io" />
<meta property="article:publisher" content="https://www.facebook.com/codedthemes" />
<meta property="og:title" content="PNSPS" />
<meta
property="og:description"
content="Mantis is a free, super flexible and customizable react redux dashboard template built using MUI React components with open source MIT license."
/>
<meta property="og:image" content="https://mantisdashboard.io/adv-banner-images/og-social.png" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://mantisdashboard.io" />
<meta property="twitter:title" content="PNSPS" />
<meta
property="twitter:description"
content="Mantis is a free, super flexible and customizable react redux dashboard template built using MUI React components with open source MIT license."
/>
<meta property="twitter:image" content="https://mantisdashboard.io/adv-banner-images/og-social.png" />
<meta name="twitter:creator" content="@codedthemes" />

<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.

Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<meta name="author" content="Government Logistics Department" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png" />
<title>PNSPS</title> <title>PNSPS</title>
<link rel="preconnect" href="https://fonts.gstatic.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" />
<link <link


+ 54
- 0
public/safari-pinned-tab.svg 查看文件

@@ -0,0 +1,54 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="680.000000pt" height="680.000000pt" viewBox="0 0 680.000000 680.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,680.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M2270 4555 l0 -1345 912 2 913 3 0 340 0 340 -195 2 c-107 1 -322 2
-476 3 l-282 0 -1 928 c0 510 -1 960 -1 1000 l0 72 -435 0 -435 0 0 -1345z"/>
<path d="M4627 5044 c-1 -1 -45 -5 -97 -8 -85 -5 -126 -9 -210 -20 -56 -8
-159 -28 -215 -43 -33 -8 -68 -17 -78 -19 -47 -9 -204 -72 -307 -124 -170 -85
-180 -91 -181 -120 0 -14 -1 -151 -2 -306 l-2 -280 280 0 280 1 0 112 0 112
49 22 c86 37 195 69 286 84 19 3 46 7 60 10 21 4 175 17 205 17 24 1 212 -13
235 -16 14 -2 43 -7 65 -10 48 -7 203 -48 264 -71 76 -28 203 -95 291 -153 99
-66 288 -250 345 -337 22 -33 43 -62 46 -65 9 -7 98 -173 100 -185 0 -5 9 -26
19 -45 44 -86 102 -303 117 -435 13 -114 5 -428 -12 -454 -2 -4 -6 -26 -9 -49
-9 -79 -78 -288 -132 -401 -113 -237 -256 -417 -449 -561 -64 -47 -103 -70
-255 -144 -14 -7 -45 -18 -70 -25 -25 -8 -52 -15 -60 -18 -8 -2 -16 -4 -17 -4
-2 0 -16 -4 -33 -9 -87 -25 -340 -34 -472 -17 -32 4 -84 10 -115 13 -63 6
-116 13 -148 19 -11 2 -41 6 -67 10 l-47 8 -1 -260 c0 -200 2 -262 12 -270 7
-6 36 -16 63 -22 28 -7 57 -14 65 -17 186 -45 213 -49 420 -48 221 0 307 11
517 64 100 25 340 113 353 129 3 3 31 19 63 35 32 16 97 55 145 87 300 198
551 508 697 859 35 86 102 291 110 336 3 20 7 39 9 43 2 3 7 22 10 41 10 60
16 94 20 115 28 130 28 570 1 700 -3 11 -7 36 -10 55 -19 133 -79 336 -137
470 -79 181 -210 395 -312 508 -185 207 -395 366 -631 478 -103 49 -316 126
-381 138 -16 2 -40 7 -54 11 -24 5 -89 18 -155 30 -46 8 -155 19 -197 19 -21
1 -38 3 -38 6 0 4 -229 8 -233 4z"/>
<path d="M1958 5035 c-2 -1 -30 -5 -63 -8 -114 -11 -231 -31 -320 -54 -33 -8
-67 -17 -75 -18 -8 -2 -15 -4 -15 -5 0 -2 -14 -5 -53 -14 -12 -3 -27 -8 -32
-11 -5 -3 -18 -8 -27 -10 -122 -25 -529 -238 -603 -315 -3 -3 -30 -25 -60 -50
-184 -148 -367 -375 -487 -605 -77 -148 -171 -436 -188 -575 -4 -30 -9 -58
-11 -61 -17 -29 -26 -431 -11 -564 9 -86 20 -157 31 -205 3 -14 8 -36 11 -50
8 -44 42 -167 49 -179 4 -6 9 -21 11 -33 15 -78 144 -348 212 -445 13 -17 23
-36 23 -41 0 -5 9 -17 20 -27 11 -10 20 -22 20 -26 0 -10 0 -10 96 -124 178
-213 410 -391 664 -512 181 -86 425 -159 595 -179 22 -2 54 -7 70 -10 17 -3
109 -7 205 -9 200 -5 254 3 420 56 3 1 19 6 35 12 17 6 30 10 30 8 0 -1 45 21
100 49 185 96 342 213 510 384 104 105 185 194 185 202 0 3 9 15 21 27 31 33
126 159 179 237 8 12 20 29 27 38 8 13 11 -62 10 -317 -1 -210 2 -339 8 -347
8 -10 285 -111 355 -129 17 -5 97 -33 120 -42 23 -9 33 -12 55 -15 20 -3 20 5
20 947 l0 950 -910 0 -910 -1 -3 -277 -2 -277 287 -1 c159 0 372 -1 475 -2
204 -1 198 1 146 -58 -13 -15 -36 -44 -53 -65 -133 -169 -383 -441 -491 -534
-282 -242 -401 -288 -684 -266 -78 6 -97 8 -167 20 -24 4 -44 7 -45 6 -2 -1
-16 3 -31 9 -15 6 -42 13 -60 16 -76 13 -364 140 -397 175 -3 3 -30 23 -60 45
-30 22 -60 44 -66 50 -82 75 -126 120 -159 161 -21 27 -42 51 -45 54 -3 3 -27
38 -53 78 -79 118 -176 337 -201 452 -8 35 -25 120 -31 150 -26 135 -26 428 0
550 3 14 8 36 10 50 24 152 133 412 226 544 16 22 37 52 47 65 45 65 157 182
237 250 167 141 481 282 685 307 19 2 46 7 59 10 14 3 57 7 95 10 39 3 76 6
81 8 6 2 10 102 10 272 l-1 269 -62 1 c-34 1 -63 0 -64 -1z"/>
</g>
</svg>

二進制
src/assets/images/icons/expiredQrcodeCN.png 查看文件

Before After
Width: 300  |  Height: 300  |  Size: 6.8 KiB

二進制
src/assets/images/icons/expiredQrcodeEN.png 查看文件

Before After
Width: 300  |  Height: 300  |  Size: 8.8 KiB

二進制
src/assets/images/icons/expiredQrcodeZH.png 查看文件

Before After
Width: 300  |  Height: 300  |  Size: 6.9 KiB

+ 2
- 0
src/auth/index.js 查看文件

@@ -32,6 +32,7 @@ export const handleLogin = data => {
localStorage.setItem('accessToken', data.accessToken) localStorage.setItem('accessToken', data.accessToken)
localStorage.setItem('refreshToken', data.refreshToken) localStorage.setItem('refreshToken', data.refreshToken)
localStorage.setItem('axiosToken', "Bearer " + data.accessToken) localStorage.setItem('axiosToken', "Bearer " + data.accessToken)
localStorage.setItem('searchCriteria',"")
//localStorage.setItem(config.storageUserRoleKeyName, JSON.stringify(data.role).slice(1).slice(0, -1)) //localStorage.setItem(config.storageUserRoleKeyName, JSON.stringify(data.role).slice(1).slice(0, -1))
localStorage.setItem(refreshIntervalName, "60") localStorage.setItem(refreshIntervalName, "60")
// for demo only // for demo only
@@ -91,6 +92,7 @@ export const handleLogoutFunction = () => {
localStorage.removeItem('refreshToken') localStorage.removeItem('refreshToken')
localStorage.removeItem('webtoken') localStorage.removeItem('webtoken')
localStorage.removeItem('transactionid') localStorage.removeItem('transactionid')
localStorage.removeItem('searchCriteria')
//localStorage.removeItem(config.storageUserRoleKeyName) //localStorage.removeItem(config.storageUserRoleKeyName)
localStorage.removeItem('expiredAlertShown') localStorage.removeItem('expiredAlertShown')
localStorage.removeItem(refreshIntervalName) localStorage.removeItem(refreshIntervalName)


+ 33
- 20
src/auth/utils.js 查看文件

@@ -14,25 +14,10 @@ export const paymentPath = window.location.href.match("localhost:3000") ? `${hos


export const delBugMode = true; export const delBugMode = true;


/**
* Testing:
* Domain: apigw-isit.staging-eid.gov.hk
* URL: hk.gov.iamsmart.testapp://
*
* Production
* Domain: apigw.iamsmart.gov.hk
* URL: hk.gov.iamsmart://
*/
export const iAmSmartPath = `https://apigw-isit.staging-eid.gov.hk`;
export const iAmSmartAppPath = `hk.gov.iamsmart.testapp://`;
export const clientId = "cf61fa7c121e4869966f69c8694b1cd2";

export const iAmSmartCallbackPath = () => { export const iAmSmartCallbackPath = () => {
let hostname = window.location.hostname; let hostname = window.location.hostname;
if (hostname.match("pnspsuat")) { if (hostname.match("pnspsuat")) {
hostname = "pnspsuat.gld.gov.hk"; hostname = "pnspsuat.gld.gov.hk";
} else {
hostname = "pnspsdev.gld.gov.hk";
} }
return hostname; return hostname;
}; };
@@ -57,7 +42,10 @@ export const getBowserType = () => {
if (navigator.userAgent.match(/Android/i)) return "Android_Chrome" if (navigator.userAgent.match(/Android/i)) return "Android_Chrome"
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Chrome" if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Chrome"
return "PC_Browser" return "PC_Browser"
} else if (navigator.userAgent.indexOf("Safari") != -1) {
} else if (navigator.userAgent.indexOf('CriOS') != -1) {
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Chrome"
return "PC_Browser"
} else if (navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1) {
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Safari" if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Safari"
return "PC_Browser" return "PC_Browser"
} else if (navigator.userAgent.indexOf("Firefox") != -1) { } else if (navigator.userAgent.indexOf("Firefox") != -1) {
@@ -89,7 +77,7 @@ export const isGranted = (auth) => {
const abilities = getUserData() ? getUserData()["abilities"] : null; const abilities = getUserData() ? getUserData()["abilities"] : null;
if (abilities == null || abilities.length == 0) return false; if (abilities == null || abilities.length == 0) return false;
if (!Array.isArray(auth)) return _checkAuth(abilities, auth); if (!Array.isArray(auth)) return _checkAuth(abilities, auth);
if (auth.length > abilities.length) return false; if (auth.length > abilities.length) return false;
let haveAuth = true; let haveAuth = true;
for (let i = 0; i < auth.length; i++) { for (let i = 0; i < auth.length; i++) {
@@ -138,8 +126,33 @@ export const local = { en: "en-us", zh: "zh-hk", cn: "zh-cn" };
export const preferpaymentmethods = ['visa', 'mastercard', 'pps', 'creditcard', 'fps']; export const preferpaymentmethods = ['visa', 'mastercard', 'pps', 'creditcard', 'fps'];


export const getPaymentMethod = (paymentMethod) => { export const getPaymentMethod = (paymentMethod) => {
if(paymentMethod == "online") return 'payOnlineMethod';
if(paymentMethod == "demandNote") return 'payDnMethod';
if(paymentMethod == "office") return 'payNPGOMethod';
if (paymentMethod == "online") return 'payOnlineMethod';
if (paymentMethod == "demandNote") return 'payDnMethod';
if (paymentMethod == "office") return 'payNPGOMethod';
return "other"; return "other";
}

export const getSearchCriteria = (path) =>{
let searchCriteria = ""
if (localStorage.getItem('searchCriteria')==""){
return searchCriteria
} else if (Object.keys(localStorage.getItem('searchCriteria')).length>0){
searchCriteria = JSON.parse(localStorage.getItem("searchCriteria"))
if (searchCriteria.path === path){
return searchCriteria.data
} else {
return ""
}
}
}

export const checkSearchCriteriaPath = (path) =>{
if(!path.startsWith("/application")
|| path === "/application/search"){
if(!path.startsWith("/user/")){
if(!path.startsWith("/publicNotice/")|| path === "/publicNotice"){
return true
}
}
}
} }

+ 4
- 1
src/components/AdminLogo/index.js 查看文件

@@ -11,6 +11,9 @@ import Logo from './AdminLogo';
import config from 'config'; import config from 'config';
import { activeItem } from 'store/reducers/menu'; import { activeItem } from 'store/reducers/menu';
import { Stack } from '@mui/material'; import { Stack } from '@mui/material';
import {
checkSysEnv
} from "utils/Utils";


// ==============================|| MAIN LOGO ||============================== // // ==============================|| MAIN LOGO ||============================== //


@@ -28,7 +31,7 @@ const LogoSection = ({ sx, to }) => {
> >
<Logo /> <Logo />
</ButtonBase> </ButtonBase>
<span id="systemTitle" >PNSPS</span>
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="systemTitle">PNSPS</span>
</Stack> </Stack>


); );


+ 5
- 1
src/components/AutoLogoutProvider.js 查看文件

@@ -5,7 +5,8 @@ import { handleLogoutFunction } from 'auth/index';
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { import {
isUserLoggedIn, isUserLoggedIn,
isGLDLoggedIn,
isGLDLoggedIn,
isPasswordExpiry
} from "utils/Utils"; } from "utils/Utils";


const TimerContext = createContext(); const TimerContext = createContext();
@@ -81,6 +82,9 @@ const AutoLogoutProvider = ({ children }) => {
// console.log(logoutInterval) // console.log(logoutInterval)
const interval = setInterval(async () => { const interval = setInterval(async () => {
const currentTime = Date.now(); const currentTime = Date.now();
if (isPasswordExpiry()){
navigate('/user/changePassword');
}
// getRemainingTime(); // getRemainingTime();
if(state !== "Active" && lastActiveTab){ if(state !== "Active" && lastActiveTab){
const timeElapsed = currentTime - lastRequestTime; const timeElapsed = currentTime - lastRequestTime;


+ 85
- 22
src/components/FiDataGrid.js 查看文件

@@ -1,17 +1,18 @@
// material-ui // material-ui
import {useState, useEffect} from 'react';
import { useState, useEffect } from 'react';
import { import {
DataGrid, GridOverlay, DataGrid, GridOverlay,
} from "@mui/x-data-grid"; } from "@mui/x-data-grid";
import * as HttpUtils from "utils/HttpUtils"; import * as HttpUtils from "utils/HttpUtils";
import {FormattedMessage, useIntl} from "react-intl";
import {TablePagination, Typography} from '@mui/material';
import { FormattedMessage, useIntl } from "react-intl";
import { TablePagination, Typography } from '@mui/material';
import { getSearchCriteria, checkSearchCriteriaPath } from "auth/utils";


// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export function FiDataGrid({ rows, columns, sx, autoHeight, export function FiDataGrid({ rows, columns, sx, autoHeight,
hideFooterSelectedRowCount, rowModesModel, editMode,
pageSizeOptions, filterItems, customPageSize, doLoad, ...props }) {
hideFooterSelectedRowCount, rowModesModel, editMode,
pageSizeOptions, filterItems, customPageSize, doLoad, applyGridOnReady, applySearch, tab, ...props }) {
const intl = useIntl(); const intl = useIntl();
const [_rows, set_rows] = useState([]); const [_rows, set_rows] = useState([]);
const [_doLoad, set_doLoad] = useState({}); const [_doLoad, set_doLoad] = useState({});
@@ -20,6 +21,7 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
const [_editMode, set_editMode] = useState("row"); const [_editMode, set_editMode] = useState("row");
const [_pageSizeOptions, set_pageSizeOptions] = useState([10]); const [_pageSizeOptions, set_pageSizeOptions] = useState([10]);
const [_filterItems, set_filterItems] = useState([]); const [_filterItems, set_filterItems] = useState([]);
const [loading, setLoading] = useState(false);


const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(10); const [pageSize, setPageSize] = useState(10);
@@ -27,6 +29,7 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
const [myHideFooterSelectedRowCount, setMyHideFooterSelectedRowCount] = useState(true); const [myHideFooterSelectedRowCount, setMyHideFooterSelectedRowCount] = useState(true);
const [_sx, set_sx] = useState({ const [_sx, set_sx] = useState({
padding: "4 2 4 2", padding: "4 2 4 2",
lineHeight: "normal",
'& .MuiDataGrid-cell': { '& .MuiDataGrid-cell': {
borderTop: 1, borderTop: 1,
borderBottom: 1, borderBottom: 1,
@@ -36,18 +39,38 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
border: 1, border: 1,
borderColor: "#EEE" borderColor: "#EEE"
}, },
"& .MuiDataGrid-columnHeaderTitle": {
whiteSpace: "normal",
lineHeight: "normal"
},
"& .MuiDataGrid-columnHeader": {
// Forced to use important since overriding inline styles
height: "unset !important"
},
}); });


const [rowCount, setRowCount] = useState(0); const [rowCount, setRowCount] = useState(0);
useEffect(() => {
setPage(0);
set_doLoad(doLoad);

useEffect(() => {
if (doLoad !== undefined && Object.keys(doLoad).length>0 ){
if(applySearch!=undefined){
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
const localStorageSearchCriteria = getSearchCriteria(window.location.pathname)
if(localStorageSearchCriteria.start!=undefined){
setPage(localStorageSearchCriteria.start/pageSize);
}
}
}else{
setPage(0);
}
set_doLoad(doLoad);
setLoading(true)
}
}, [doLoad]); }, [doLoad]);


useEffect(()=>{
useEffect(() => {
getDataList(); getDataList();
},[_doLoad, page]);
}, [_doLoad, page]);




useEffect(() => { useEffect(() => {
@@ -70,18 +93,25 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
if (pageSizeOptions) { if (pageSizeOptions) {
set_pageSizeOptions(pageSizeOptions) set_pageSizeOptions(pageSizeOptions)
} }
if(autoHeight !== undefined){
if (autoHeight !== undefined) {
set_autoHeight(autoHeight) set_autoHeight(autoHeight)
} }
if(editMode){
if (editMode) {
set_editMode(editMode); set_editMode(editMode);
} }
if(filterItems){
if (filterItems) {
set_filterItems(filterItems); set_filterItems(filterItems);
} }
if(customPageSize){
if (customPageSize) {
setPageSize(customPageSize); setPageSize(customPageSize);
} }
// console.log(_doLoad)
if (_doLoad !== undefined && Object.keys(_doLoad).length==0 ){
setLoading(false)
if (applyGridOnReady !== undefined){
applyGridOnReady(false)
}
}
}, [sx, hideFooterSelectedRowCount, rowModesModel, rows, columns, pageSizeOptions, autoHeight, editMode, filterItems, customPageSize]); }, [sx, hideFooterSelectedRowCount, rowModesModel, rows, columns, pageSizeOptions, autoHeight, editMode, filterItems, customPageSize]);


const handleChangePage = (event, newPage) => { const handleChangePage = (event, newPage) => {
@@ -103,21 +133,51 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
); );
} }


function getDataList() { function getDataList() {
if(_doLoad?.url == null) return;
if(_doLoad.params == null) _doLoad.params = {};
_doLoad.params.start = page*pageSize;
// console.log(Object.keys(_doLoad.params).length > 0)
// console.log(Object.keys(_doLoad.params).length > 0)

if (_doLoad?.url == null){
setLoading(false)
return;
}
if (_doLoad.params == undefined) return;
if (_doLoad.params.searchCriteria !== undefined) return;
if (_doLoad.params == null) _doLoad.params = {};
_doLoad.params.start = page * pageSize;
_doLoad.params.limit = pageSize; _doLoad.params.limit = pageSize;
if(checkSearchCriteriaPath(window.location.pathname)){
if(window.location.pathname === "/publicNotice"){
if (tab != undefined && tab ==="application"){
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:_doLoad.params}))
}
}else if (window.location.pathname != "/publicNotice"){
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:_doLoad.params}))
}
}
HttpUtils.get({ HttpUtils.get({
url: _doLoad.url, url: _doLoad.url,
params: _doLoad.params, params: _doLoad.params,
onSuccess: function (responseData) { onSuccess: function (responseData) {
set_rows(responseData?.records); set_rows(responseData?.records);
setRowCount(responseData?.count); setRowCount(responseData?.count);
if(_doLoad.callback != null){
if (_doLoad.callback != null) {
_doLoad.callback(responseData); _doLoad.callback(responseData);
} }
setLoading(false)
// console.log(applyGridOnReady)
if (applyGridOnReady !== undefined){
applyGridOnReady(false)
}
},
onError: function (error){
console.log(error)
setLoading(false)
if (applyGridOnReady !== undefined){
applyGridOnReady(false)
}
} }
}); });
} }
@@ -127,9 +187,11 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
<DataGrid <DataGrid
{...props} {...props}
rows={_rows} rows={_rows}
rowCount={rowCount ? rowCount : 0}
columns={_columns} columns={_columns}
paginationMode="server" paginationMode="server"
disableColumnMenu disableColumnMenu
shrinkWrap={true}
rowModesModel={_rowModesModel} rowModesModel={_rowModesModel}
pageSizeOptions={_pageSizeOptions} pageSizeOptions={_pageSizeOptions}
editMode={_editMode} editMode={_editMode}
@@ -137,16 +199,17 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
hideFooterSelectedRowCount={myHideFooterSelectedRowCount} hideFooterSelectedRowCount={myHideFooterSelectedRowCount}
filterModel={{ items: _filterItems }} filterModel={{ items: _filterItems }}
sx={_sx} sx={_sx}
loading={loading}
components={{ components={{
noRowsOverlay: CustomNoRowsOverlay, noRowsOverlay: CustomNoRowsOverlay,
Pagination: () => ( Pagination: () => (
<TablePagination <TablePagination
count={rowCount?rowCount:0}
count={rowCount ? rowCount : 0}
page={page} page={page}
rowsPerPage={pageSize} rowsPerPage={pageSize}
rowsPerPageOptions={_pageSizeOptions} rowsPerPageOptions={_pageSizeOptions}
labelDisplayedRows={() => labelDisplayedRows={() =>
`${(_rows?.length?page*pageSize+1:0)}-${page*pageSize+(_rows?.length??0)} ${intl.formatMessage({ id: "of" })} ${rowCount}`
`${(_rows?.length ? page * pageSize + 1 : 0)}-${page * pageSize + (_rows?.length ?? 0)} ${intl.formatMessage({ id: "of" })} ${rowCount}`
} }
labelRowsPerPage={intl.formatMessage({ id: "rowsPerPage" }) + ":"} labelRowsPerPage={intl.formatMessage({ id: "rowsPerPage" }) + ":"}
onPageChange={handleChangePage} onPageChange={handleChangePage}


+ 10
- 0
src/components/FileList.js 查看文件

@@ -19,6 +19,7 @@ export default function FileList({ refType, refId, allowDelete, sx, dateHideable
const theme = useTheme(); const theme = useTheme();
const isMdOrLg = useMediaQuery(theme.breakpoints.up('md')); const isMdOrLg = useMediaQuery(theme.breakpoints.up('md'));
const intl = useIntl(); const intl = useIntl();
const [onDownload, setOnDownload] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
loadData(); loadData();
@@ -41,10 +42,17 @@ export default function FileList({ refType, refId, allowDelete, sx, dateHideable
}; };


const onDownloadClick = (fileId, skey, filename) => () => { const onDownloadClick = (fileId, skey, filename) => () => {
setOnDownload(true)
HttpUtils.fileDownload({ HttpUtils.fileDownload({
fileId: fileId, fileId: fileId,
skey: skey, skey: skey,
filename: filename, filename: filename,
onResponse:()=>{
setOnDownload(false)
},
onError:()=>{
setOnDownload(false)
}
}); });
}; };


@@ -91,6 +99,7 @@ export default function FileList({ refType, refId, allowDelete, sx, dateHideable
className="textPrimary" className="textPrimary"
onClick={onDownloadClick(params.id, params.row.skey, params.row.filename)} onClick={onDownloadClick(params.id, params.row.skey, params.row.filename)}
color="primary" color="primary"
disabled={onDownload}
/>] />]
}, },
}, },
@@ -139,6 +148,7 @@ export default function FileList({ refType, refId, allowDelete, sx, dateHideable
className="textPrimary" className="textPrimary"
onClick={onDownloadClick(params.id, params.row.skey, params.row.filename)} onClick={onDownloadClick(params.id, params.row.skey, params.row.filename)}
color="primary" color="primary"
disabled={onDownload}
/>] />]
}, },
}, },


+ 35
- 0
src/components/SysSettingProvider.js 查看文件

@@ -0,0 +1,35 @@
import { useState, useEffect, createContext } from 'react';
import { get } from "utils/HttpUtils"
import {GET_SYS_SETTING} from "utils/ApiPathConst"


const SysContext = createContext();

const SysSettingProvider = ({ children }) => {

const [sysSetting, setSysSetting] = useState({});

useEffect(() => {
loadSysSetting();
}, []);


const loadSysSetting = () => {
get({
url: GET_SYS_SETTING,
onSuccess: (responseData) => {
// console.log(responseData)
setSysSetting(responseData);
localStorage.setItem('sysEnv', responseData.sysEnv)
}
});
}

return (
<SysContext.Provider value={{ sysSetting, setSysSetting }} >
{children}
</SysContext.Provider>
);
}

export {SysContext, SysSettingProvider};

+ 2
- 3
src/components/cards/AuthFooter.js 查看文件

@@ -26,7 +26,7 @@ const AuthFooter = () => {
variant="subtitle2" variant="subtitle2"
color="secondary" color="secondary"
component={Link} component={Link}
// href="https://material-ui.com/store/contributors/codedthemes/"
href="/importantNotice"
target="_blank" target="_blank"
underline="hover" underline="hover"
> >
@@ -36,8 +36,7 @@ const AuthFooter = () => {
variant="subtitle2" variant="subtitle2"
color="secondary" color="secondary"
component={Link} component={Link}
href="https://www.gld.gov.hk/zh-hk/privacy-policy/"
//href="/testMailPage"
href="/privacyPolicy"
target="_blank" target="_blank"
underline="hover" underline="hover"
> >


+ 8
- 4
src/index.js 查看文件

@@ -16,9 +16,10 @@ import 'assets/third-party/apex-chart.css';
import App from './App'; import App from './App';
import { store } from 'store'; import { store } from 'store';
import reportWebVitals from './reportWebVitals'; import reportWebVitals from './reportWebVitals';
import {I18nProvider} from "components/I18nProvider";
import {AutoLogoutProvider} from "components/AutoLogoutProvider";
import {RefreshTokenProvider} from "components/RefreshTokenProvider";
import { I18nProvider } from "components/I18nProvider";
import { AutoLogoutProvider } from "components/AutoLogoutProvider";
import { RefreshTokenProvider } from "components/RefreshTokenProvider";
import { SysSettingProvider } from "components/SysSettingProvider";


// ==============================|| MAIN - REACT DOM RENDER ||============================== // // ==============================|| MAIN - REACT DOM RENDER ||============================== //


@@ -26,18 +27,21 @@ const container = document.getElementById('root');
const root = createRoot(container); // createRoot(container!) if you use TypeScript const root = createRoot(container); // createRoot(container!) if you use TypeScript
//const NotAuthorized = lazy(() => import('../views/NotAuthorized')) //const NotAuthorized = lazy(() => import('../views/NotAuthorized'))
//const Error = lazy(() => import('../views/Error')) //const Error = lazy(() => import('../views/Error'))

root.render( root.render(
<StrictMode> <StrictMode>
<ReduxProvider store={store}> <ReduxProvider store={store}>
<SysSettingProvider>
<I18nProvider> <I18nProvider>
<BrowserRouter basename="/"> <BrowserRouter basename="/">
<RefreshTokenProvider> <RefreshTokenProvider>
<AutoLogoutProvider> <AutoLogoutProvider>
<App />
<App />
</AutoLogoutProvider> </AutoLogoutProvider>
</RefreshTokenProvider> </RefreshTokenProvider>
</BrowserRouter> </BrowserRouter>
</I18nProvider> </I18nProvider>
</SysSettingProvider>
</ReduxProvider> </ReduxProvider>
</StrictMode> </StrictMode>
); );


+ 419
- 293
src/layout/MainLayout/Header/index.js 查看文件

@@ -1,9 +1,10 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React import React
, { useState }
, { useState, useContext }
from 'react'; from 'react';
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { SysContext } from "components/SysSettingProvider"


// material-ui // material-ui
// import { useTheme } from '@mui/material/styles'; // import { useTheme } from '@mui/material/styles';
@@ -47,7 +48,10 @@ import {
isPrimaryLoggedIn, isPrimaryLoggedIn,
isCreditorLoggedIn, isCreditorLoggedIn,
isINDLoggedIn, isINDLoggedIn,
// isORGLoggedIn,
isPasswordExpiry,
haveOrgPaymentRecord,
isORGLoggedIn,
checkSysEnv
// getUserId // getUserId
} from "utils/Utils"; } from "utils/Utils";
import { handleLogoutFunction } from 'auth/index'; import { handleLogoutFunction } from 'auth/index';
@@ -66,6 +70,7 @@ const drawerWidth = 300;
// ==============================|| MAIN LAYOUT - HEADER ||============================== // // ==============================|| MAIN LAYOUT - HEADER ||============================== //


function Header(props) { function Header(props) {
const { sysSetting } = useContext(SysContext);
const { window } = props; const { window } = props;
const [mobileOpen, setMobileOpen] = useState(false); const [mobileOpen, setMobileOpen] = useState(false);
const dispatch = useDispatch() const dispatch = useDispatch()
@@ -76,346 +81,438 @@ function Header(props) {
}; };


const handleLogout = async () => { const handleLogout = async () => {
dispatch(handleLogoutFunction());
await dispatch(handleLogoutFunction());
//await handleLogoutFunction(); //await handleLogoutFunction();
navigate('/login');

await navigate('/login');
}; };


const loginContent = ( const loginContent = (
isGLDLoggedIn() ? isGLDLoggedIn() ?
<div id="adminContent"> <div id="adminContent">
<li>
<Link className="dashboard" to='/dashboard'>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} >
Dashboard
</Typography>
</Link>
</li>
<li>
<Link className="application" to='/application/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Application</Typography></Link>
</li>
{
isGrantedAny(["VIEW_PROOF", "MAINTAIN_PROOF"]) ?
{isPasswordExpiry() ?
<div id="passwordExpiryedContent">
<li> <li>
<Link className="proof" to='/proof/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Proof</Typography></Link>
<Link className="manageUser" to={'/user/changePassword'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userChangePassword" />
</Typography>
</Link>
</li> </li>
: <></>
}

{
isGrantedAny(["MAINTAIN_PAYMENT", "MAINTAIN_RECON", "VIEW_DEMANDNOTE", "MAINTAIN_DEMANDNOTE"]) ?
</div>
:
<div id="adminContentList">
<li> <li>
<Link className="paymentTop" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Payment</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1vw' }} /></Link>
<ul className='dropdown'>
{
isGranted("MAINTAIN_DEMANDNOTE") ?
<li>
<Link className="exportDemandNote" to='/paymentPage/exportGDN' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Export for GDN</Typography></Link>
</li>
:
<></>
}
<Link className="dashboard" to='/dashboard'>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} >
Dashboard
</Typography>
</Link>
</li>
{
isGrantedAny(["VIEW_APPLICATION", "MAINTAIN_APPLICATION"]) ?
<li>
<Link className="application" to='/application/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Application</Typography></Link>
</li>
: <></>
}
{
isGrantedAny(["VIEW_PROOF", "MAINTAIN_PROOF"]) ?
<li>
<Link className="proof" to='/proof/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Proof</Typography></Link>
</li>
: <></>
}


{
isGranted("MAINTAIN_PAYMENT") ?
<li>
<Link className="application" to='/application/markAsPaid/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Mark Payment</Typography></Link>
</li>
:
<></>
}
{
isGrantedAny(["MAINTAIN_PROOF", "MAINTAIN_PAYMENT", "MAINTAIN_RECON", "VIEW_DEMANDNOTE", "MAINTAIN_DEMANDNOTE"]) ?
<li>
<Link className="paymentTop" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Payment</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1vw' }} /></Link>
<ul className='dropdown'>
{
isGranted("MAINTAIN_PROOF") ?
<li>
<Link className="exportDemandNote" to='/paymentPage/exportGDN' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Export for GDN</Typography></Link>
</li>
:
<></>
}


{
isGranted("MAINTAIN_PAYMENT") ?
<li>
<Link className="application" to='/application/markAsPaid/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Mark Payment</Typography></Link>
</li>
:
<></>
}

{
isGranted("MAINTAIN_PAYMENT") ?
<li>
<Link className="payment" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Online Payment Record</Typography></Link>
</li>
:
<></>
}

{
isGranted("MAINTAIN_RECON") ?
<>
<li>
<Link className="downloadXML" to='/gfmis/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>GFMIS Generate XML</Typography></Link>
</li>
</>

:
<></>
}

{
isGranted("MAINTAIN_DEMANDNOTE") ?
<li>
<Link className="createDemandNote" to='/paymentPage/createDemandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Create Demand Note</Typography></Link>
</li>
:
<></>
}
{
isGrantedAny(["VIEW_DEMANDNOTE", "MAINTAIN_DEMANDNOTE"]) ?
<li>
<Link className="demandNote" to='/paymentPage/demandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Demand Note</Typography></Link>
</li>
:
<></>
}
{
isGranted("MAINTAIN_RECON") ?
<>
<li>
<Link className="reconReport" to='/paymentPage/reconReport'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Recon Report</Typography></Link>
</li>
</>

:
<></>
}
</ul>
</li>
:
<></>
}

{
isGrantedAny(["VIEW_USER", "MAINTAIN_USER", "VIEW_ORG", "MAINTAIN_ORG", "VIEW_GROUP", "MAINTAIN_GROUP", "VIEW_GLD_USER", "VIEW_IND_USER", "VIEW_ORG_USER", "MAINTAIN_GLD_USER", "MAINTAIN_IND_USER", "MAINTAIN_ORG_USER"]) ?
<li>
<Link className="client" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Client</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1vw' }} /></Link>
<ul className='dropdown'>
{
isGrantedAny(["VIEW_USER","MAINTAIN_USER"]) ?
<>
<li>
<Link className="userSearchview" to='/userSearchview'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (GLD)</Typography></Link>
</li>
<li>
<Link className="indUser" to='/indUser'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (Individual)</Typography></Link>
</li>
<li>
<Link className="orgUser" to='/orgUser'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (Organisation)</Typography></Link>
</li>
</>
:
<>
{
isGrantedAny(["VIEW_GLD_USER" ,"MAINTAIN_GLD_USER"]) ?
<li>
<Link className="userSearchview" to='/userSearchview'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (GLD)</Typography></Link>
</li> : <></>
}
{
isGrantedAny(["VIEW_IND_USER", "MAINTAIN_IND_USER"]) ?
<li>
<Link className="indUser" to='/indUser'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (Individual)</Typography></Link>
</li> : <></>
}
{
isGrantedAny(["VIEW_ORG_USER", "MAINTAIN_ORG_USER"]) ?
<li>
<Link className="orgUser" to='/orgUser'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (Organisation)</Typography></Link>
</li> : <></>
}
</>
}
{
isGrantedAny(["VIEW_ORG", "MAINTAIN_ORG"]) ?
<li>
<Link className="org" to='/org'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Organisation</Typography></Link>
</li>
:
<></>
}
{
isGrantedAny(["VIEW_GROUP", "MAINTAIN_GROUP"]) ?
<li>
<Link className="usergroupSearchview" to='/usergroupSearchview'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>User Group</Typography></Link>
</li>
:
<></>
}

</ul>
</li>
:
<></>
}
<li>
<Link className="setting" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Settings</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1vw' }} /></Link>
<ul className='dropdown'>
<li>
<Link className="userProfileGld" to='/user/profile'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>My Profile</Typography></Link>
</li>
<li>
<Link className="manageUser" to={'/user/changePassword'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userChangePassword" />
</Typography>
</Link>
</li>
{ {
isGranted("MAINTAIN_PAYMENT") ?
<li>
<Link className="payment" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Online Payment Record</Typography></Link>
</li>
:
<></>
}
{
isGranted("MAINTAIN_RECON") ?
isGranted("VIEW_GAZETTE_ISSUE", "MAINTAIN_GAZETTE_ISSUE") ?
<> <>
<li> <li>
<Link className="downloadXML" to='/gfmis/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>GFMIS Generate XML</Typography></Link>
<Link className="holidaySetting" to='/setting/holiday'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Holiday Settings</Typography></Link>
</li>
<li>
<Link className="gazetteissueSetting" to='/setting/gazetteissuepage'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Gazette Issues</Typography></Link>
</li> </li>
</> </>

:
<></>
}

{
isGranted("MAINTAIN_DEMANDNOTE") ?
<li>
<Link className="createDemandNote" to='/paymentPage/createDemandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Create Demand Note</Typography></Link>
</li>
: :
<></> <></>
} }


{ {
isGrantedAny(["VIEW_DEMANDNOTE", "MAINTAIN_DEMANDNOTE"]) ?
isGranted("MAINTAIN_ANNOUNCEMENT") ?
<li> <li>
<Link className="demandNote" to='/paymentPage/demandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Demand Note</Typography></Link>
<Link className="announcement" to='/setting/announcement'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Announcement</Typography></Link>
</li> </li>
: :
<></> <></>
} }
{
isGranted("MAINTAIN_RECON") ?
<>
<li>
<Link className="reconReport" to='/paymentPage/reconReport'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Recon Report</Typography></Link>
</li>
</>


:
<></>
{isGranted("MAINTAIN_EMAIL") ?
<li>
<Link className="emailTemplate" to='/setting/emailTemplate'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Email Template</Typography></Link>
</li>
:
<></>
} }


</ul>
</li>
:
<></>
}

{
isGrantedAny(["VIEW_USER", "MAINTAIN_USER", "VIEW_ORG", "MAINTAIN_ORG", "VIEW_GROUP", "MAINTAIN_GROUP"]) ?
<li>
<Link className="client" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Client</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1vw' }} /></Link>
<ul className='dropdown'>
{ {
isGrantedAny(["VIEW_USER", "MAINTAIN_USER"]) ?
<>
<li>
<Link className="userSearchview" to='/userSearchview'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (GLD)</Typography></Link>
</li>
<li>
<Link className="indUser" to='/indUser'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (Individual)</Typography></Link>
</li>
<li>
<Link className="orgUser" to='/orgUser'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (Organisation)</Typography></Link>
</li>
</>
isGranted("MAINTAIN_DR") ?
<li>
<Link className="drImport" to='/setting/drImport'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>DR Import</Typography></Link>
</li>
: :
<></> <></>
} }


{ {
isGrantedAny(["VIEW_ORG", "MAINTAIN_ORG"]) ?
isGranted("MAINTAIN_SETTING") ?
<li> <li>
<Link className="org" to='/org'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Organisation</Typography></Link>
<Link className="systemSetting" to='/setting/sys'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>System Settings</Typography></Link>
</li> </li>
: :
<></> <></>
} }

{ {
isGrantedAny(["VIEW_GROUP", "MAINTAIN_GROUP"]) ?
isGranted("MAINTAIN_SETTING") ?
<li> <li>
<Link className="usergroupSearchview" to='/usergroupSearchview'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>User Group</Typography></Link>
<Link className="auditLogSetting" to='/setting/auditLog'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Audit Log</Typography></Link>
</li> </li>
: :
<></> <></>
} }

</ul> </ul>
</li> </li>
:
<></>
}


<li>
<Link className="setting" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Settings</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1vw' }} /></Link>
<ul className='dropdown'>
<li>
<Link className="userProfileGld" to='/user/profile'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>My Profile</Typography></Link>
</li>
{
isGranted("MAINTAIN_GAZETTE_ISSUE") ?
<>
<li>
<Link className="holidaySetting" to='/setting/holiday'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Holiday Settings</Typography></Link>
</li>
<li>
<Link className="gazetteissueSetting" to='/setting/gazetteissuepage'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Gazette Issues</Typography></Link>
</li>
</>
:
<></>
}

{
isGranted("MAINTAIN_ANNOUNCEMENT") ?
<li>
<Link className="announcement" to='/setting/announcement'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Announcement</Typography></Link>
</li>
:
<></>
}

{isGranted("MAINTAIN_EMAIL") ?
<Box sx={{ display: { xs: 'none', sm: 'none', md: 'block' } }}>
<li> <li>
<Link className="emailTemplate" to='/setting/emailTemplate'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Email Template</Typography></Link>
<Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Logout</Typography></Link>
</li> </li>
:
<></>
}

{
isGranted("MAINTAIN_DR") ?
<li>
<Link className="drImport" to='/setting/drImport'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>DR Import</Typography></Link>
</li>
:
<></>
}

{
isGranted("MAINTAIN_SETTING") ?
<li>
<Link className="systemSetting" to='/setting/sys'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>System Settings</Typography></Link>
</li>
:
<></>
}

<li>
<Link className="auditLogSetting" to='/setting/auditLog'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Audit Log</Typography></Link>
</li>
</ul>
</li>
<Box sx={{ display: { xs: 'none', sm: 'none', md: 'block' } }}>
<li>
<Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Logout</Typography></Link>
</li>
</Box>
</Box>
</div>
}
</div> </div>
: :
<div id="individualUserContent"> <div id="individualUserContent">
<li>
<Link className="dashboard" to='/dashboard'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="mainPage" />
</Typography></Link>
</li>
<li>
<Link className="myDocumet" to='/publicNotice'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="myPublicNotice" />
</Typography></Link>
</li>
<li>
<Link className="documentRecord" to='/proof/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="proofRecord" />
</Typography></Link>
</li>
<li>
{isCreditorLoggedIn() ?
<>
<Link className="paymentRecord">
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="paymentHistory" />
{isPasswordExpiry() ?
<div id="passwordExpiryedContent">
<li>
<Link className="manageUser" to={'/user/changePassword'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userChangePassword" />
</Typography> </Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link> </Link>
<ul className='dropdown'>
<li>
<Link className="manageOrgUser" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="onlinePaymentHistory" />
</Typography></Link>
</li>
<li>
</li>
</div>
:
<div id="individualUserContentList">
<li>
<Link className="dashboard" to='/dashboard'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="mainPage" />
</Typography></Link>
</li>
<li>
<Link className="myDocumet" to='/publicNotice'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="myPublicNotice" />
</Typography></Link>
</li>
<li>
<Link className="documentRecord" to='/proof/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="proofRecord" />
</Typography></Link>
</li>
<li>
{isCreditorLoggedIn() ?
haveOrgPaymentRecord() ?
<>
<Link className="paymentRecord">
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="paymentHistory" />
</Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link>
<ul className='dropdown'>
<li>
<Link className="manageOrgUser" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="onlinePaymentHistory" />
</Typography></Link>
</li>
<li>
<Link className="manageOrgUser" to='/paymentPage/demandNote'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="paymentInfoRecord" />
</Typography></Link>
</li>
</ul>
</>
:
<Link className="manageOrgUser" to='/paymentPage/demandNote'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}> <Link className="manageOrgUser" to='/paymentPage/demandNote'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="paymentInfoRecord" /> <FormattedMessage id="paymentInfoRecord" />
</Typography></Link> </Typography></Link>
</li>
</ul>
</>
:
<Link className="manageOrgUser" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="onlinePaymentHistory" />
</Typography></Link>
}
</li>
<li>

{isPrimaryLoggedIn() ?
<>
<Link className="userSetting" >
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} onClick={(event) => console.log(event)}>
<FormattedMessage id="setting" />
</Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link>
<ul className='dropdown' style={{ width: "max-content" }}>
<li>
<Link className="manageOrgUser" to='setting/manageUser'>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="companyOrUserRecord" />
</Typography>
</Link>
</li>
<li>
<Link className="manageUser" to={'/orgUser'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
{/* <FormattedMessage id="companyOrUserRecord" /> */}
<FormattedMessage id="userProfile" />
</Typography>
</Link>
</li>
<li>
<Link className="manageUser" to={'/org'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
{/* <FormattedMessage id="companyOrUserRecord" /> */}
<FormattedMessage id="organizationProfile" />
:
isORGLoggedIn() ?
haveOrgPaymentRecord() ?
<Link className="manageOrgUser" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="onlinePaymentHistory" />
</Typography></Link>
:
<Link className="manageOrgUser" to='/paymentPage/demandNote'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="paymentInfoRecord" />
</Typography></Link>
:
<Link className="manageOrgUser" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>
<FormattedMessage id="onlinePaymentHistory" />
</Typography></Link>
}
</li>
<li>

{isPrimaryLoggedIn() ?
<>
<Link className="userSetting" >
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} onClick={(event) => console.log(event)}>
<FormattedMessage id="setting" />
</Typography> </Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link> </Link>
</li>
</ul>
</>
:
isINDLoggedIn() ?
<>
<Link className="userSetting" >
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} onClick={(event) => console.log(event)}>
<FormattedMessage id="setting" />
</Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link>
<ul className='dropdown' style={{ width: "max-content" }}>
<li>
<Link className="manageUser" to={'/indUser'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
{/* <FormattedMessage id="companyOrUserRecord" /> */}
<FormattedMessage id="userProfile" />
<ul className='dropdown' style={{ width: "max-content" }}>
<li>
<Link className="manageOrgUser" to='setting/manageUser'>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="companyOrUserRecord" />
</Typography>
</Link>
</li>
<li>
<Link className="manageUser" to={'/org'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
{/* <FormattedMessage id="companyOrUserRecord" /> */}
<FormattedMessage id="organizationProfile" />
</Typography>
</Link>
</li>
<li>
<Link className="manageUser" to={'/orgUser'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
{/* <FormattedMessage id="companyOrUserRecord" /> */}
<FormattedMessage id="userProfile" />
</Typography>
</Link>
</li>
<li>
<Link className="manageUser" to={'/user/changePassword'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userChangePassword" />
</Typography>
</Link>
</li>
</ul>
</>
:
isINDLoggedIn() ?
<>
<Link className="userSetting" >
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} onClick={(event) => console.log(event)}>
<FormattedMessage id="setting" />
</Typography> </Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link> </Link>
</li>
</ul>
</>
:
<>
<Link className="userSetting" >
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} onClick={(event) => console.log(event)}>
<FormattedMessage id="setting" />
</Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link>
<ul className='dropdown' style={{ width: "max-content" }}>
<li>
<Link className="manageUser" to={'/orgUser'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userProfile" />
<ul className='dropdown' style={{ width: "max-content" }}>
<li>
<Link className="manageUser" to={'/indUser'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
{/* <FormattedMessage id="companyOrUserRecord" /> */}
<FormattedMessage id="userProfile" />
</Typography>
</Link>
</li>
<li>
<Link className="manageUser" to={'/user/changePassword'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userChangePassword" />
</Typography>
</Link>
</li>
</ul>
</>
:
<>
<Link className="userSetting" >
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }} onClick={(event) => console.log(event)}>
<FormattedMessage id="setting" />
</Typography> </Typography>
<KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} />
</Link> </Link>
</li>
</ul>
</>
}
</li>
<ul className='dropdown' style={{ width: "max-content" }}>
<li>
<Link className="manageUser" to={'/orgUser'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userProfile" />
</Typography>
</Link>
</li>
<li>
<Link className="manageUser" to={'/user/changePassword'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userChangePassword" />
</Typography>
</Link>
</li>
</ul>
</>
}
</li>
</div>
}
<Box sx={{ display: { xs: 'none', sm: 'none', md: 'block' } }}> <Box sx={{ display: { xs: 'none', sm: 'none', md: 'block' } }}>
<li> <li>
<Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}> <Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
@@ -429,19 +526,38 @@ function Header(props) {
const logoutContent = ( const logoutContent = (
<div> <div>
<li> <li>
<Link className="login" to='/login'>
<Link className="login" to={'/aboutUs'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}> <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="login" />
<FormattedMessage id="aboutUs" />
</Typography>
</Link>
</li>
<li>
<Link className="login" to={'/userGuidePub'}>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="userGuide" />
</Typography> </Typography>
</Link> </Link>
</li> </li>
<li> <li>
<Link className="register" to='/register'>
<Link className="login" to='/login'>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}> <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="register" />
<FormattedMessage id="login" />
</Typography> </Typography>
</Link> </Link>
</li> </li>
{
sysSetting?.allowRegistration ?
<li>
<Link className="register" to='/register'>
<Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="register" />
</Typography>
</Link>
</li>
:
<></>
}
</div> </div>
); );


@@ -453,7 +569,7 @@ function Header(props) {
</Typography> */} </Typography> */}
<Box sx={{ mr: 2, mt: 1, display: { md: 'none' } }}> <Box sx={{ mr: 2, mt: 1, display: { md: 'none' } }}>
<MobileLogo /> <MobileLogo />
<span id="mobileTitle" >PNSPS</span>
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="mobileTitle" >PNSPS</span>
</Box> </Box>
<Divider /> <Divider />
<ul id="sidebartop"> <ul id="sidebartop">
@@ -472,7 +588,7 @@ function Header(props) {
<Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}> <Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
<Box sx={{ mr: 2, mt: 1, display: { md: 'none' } }}> <Box sx={{ mr: 2, mt: 1, display: { md: 'none' } }}>
<MobileLogo /> <MobileLogo />
<span id="mobileTitle" >PNSPS</span>
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="mobileTitle" >PNSPS</span>
</Box> </Box>
<Divider /> <Divider />
<ul id="logoutContent"> <ul id="logoutContent">
@@ -495,8 +611,9 @@ function Header(props) {
justifyContent="flex-start" justifyContent="flex-start"
alignItems="center" alignItems="center"
spacing={0} spacing={0}
sx={{ width: { xs: '100%', md: '5%' } }}
> >
<Box mt={0.5} sx={{ display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Box mt={0.5} sx={{ flexGrow: 1, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<AdminLogo /> <AdminLogo />
</Box> </Box>
<IconButton <IconButton
@@ -508,9 +625,16 @@ function Header(props) {
> >
<MenuIcon style={{ color: '#0C489E' }} /> <MenuIcon style={{ color: '#0C489E' }} />
</IconButton> </IconButton>
<Box sx={{ mr: 2, display: { md: 'none' } }}>
<MobileLogo />
<span id="mobileTitle" >PNSPS</span>
<Box sx={{ flexGrow: 1, mr: 2, display: { sm: 'block', md: 'none' } }}>
<Stack direction="row" justifyContent="space-between" alignItems="center" width="100%">
<MobileLogo />
<Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}>
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="mobileTitle">PNSPS</span>
</Stack>
<Stack justifyContent="flex-end" alignItems="center">
<span style={{color:"#B11B1B",fontWeight:'bold',fontSize:'15px'}}>RESTRICTED</span>
</Stack>
</Stack>
</Box> </Box>
</Stack> : </Stack> :
<Stack <Stack
@@ -520,13 +644,13 @@ function Header(props) {
spacing={0} spacing={0}
sx={{ width: { xs: '100%', md: '25%' } }} sx={{ width: { xs: '100%', md: '25%' } }}
> >
<Box sx={{ width: '260px', flexGrow: 1, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Box sx={{ width: '450px', flexGrow: 1, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Stack direction="row" justifyContent="flex-start" alignItems="center"> <Stack direction="row" justifyContent="flex-start" alignItems="center">
<Logo /> <Logo />
<Stack justifyContent="flex-start" alignItems="center"> <Stack justifyContent="flex-start" alignItems="center">
{/*<span id="systemTitle">公共啟事提交</span>*/} {/*<span id="systemTitle">公共啟事提交</span>*/}
{/*<span id="systemTitle">及繳費系統</span>*/} {/*<span id="systemTitle">及繳費系統</span>*/}
<span id="systemTitle">
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="systemTitle">
<FormattedMessage id="PNSPS" /> <FormattedMessage id="PNSPS" />
</span> </span>
</Stack> </Stack>
@@ -545,7 +669,7 @@ function Header(props) {
<Stack direction="row" justifyContent="space-between" alignItems="center" width="100%"> <Stack direction="row" justifyContent="space-between" alignItems="center" width="100%">
<MobileLogo /> <MobileLogo />
<Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}> <Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}>
<span id="mobileTitle">
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="mobileTitle">
<FormattedMessage id="PNSPS" /> <FormattedMessage id="PNSPS" />
</span> </span>
</Stack> </Stack>
@@ -576,7 +700,9 @@ function Header(props) {
> >
{ {
isGLDLoggedIn() ? isGLDLoggedIn() ?
<Grid item />
<Grid item >
<span style={{color:"#B11B1B",fontWeight:'bold',fontSize:'15px'}}>RESTRICTED</span>
</Grid>
: :
<Grid item> <Grid item>
<LocaleSelector /> <LocaleSelector />
@@ -642,7 +768,7 @@ function Header(props) {
<Stack direction="row" justifyContent="space-between" alignItems="center" width="100%"> <Stack direction="row" justifyContent="space-between" alignItems="center" width="100%">
<MobileLogo /> <MobileLogo />
<Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}> <Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}>
<span id="mobileTitle">
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="mobileTitle">
<FormattedMessage id="PNSPS" /> <FormattedMessage id="PNSPS" />
</span> </span>
</Stack> </Stack>


+ 23
- 13
src/layout/MainLayout/index.js 查看文件

@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Outlet } from 'react-router-dom'; import { Outlet } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';


// material-ui // material-ui
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
@@ -31,7 +32,8 @@ const MainLayout = () => {
const theme = useTheme(); const theme = useTheme();
const matchDownLG = useMediaQuery(theme.breakpoints.down('lg')); const matchDownLG = useMediaQuery(theme.breakpoints.down('lg'));
const dispatch = useDispatch(); const dispatch = useDispatch();

const location = useLocation();
const hideNavbarRoutes = ['/databaseHealthCheck']
const { drawerOpen } = useSelector((state) => state.menu); const { drawerOpen } = useSelector((state) => state.menu);


// drawer toggler // drawer toggler
@@ -55,18 +57,26 @@ const MainLayout = () => {
}, [drawerOpen]); }, [drawerOpen]);


return ( return (
<Box sx={{backgroundColor:'#ffffff', display: 'flex', width: '100%', flexDirection: "column", paddingTop: { xs: "5px", sm: "25px", md: "43px" }}}>
<Header/>
{/* <Drawer open={open} handleDrawerToggle={handleDrawerToggle} /> */}
<Box style={{ width: '100%', flexGrow: 1 } } sx={{ paddingTop: "38px" }}>
{/* <Toolbar /> */}
{/* <Breadcrumbs navigation={navigation} title /> */}
<Outlet />
</Box>
<Box sx={{borderTop: "3px solid #0C489E"}}>
<Footer/>
</Box>
</Box>
<>
{!hideNavbarRoutes.includes(location.pathname) && (
<Box sx={{backgroundColor:'#ffffff', display: 'flex', width: '100%', flexDirection: "column", paddingTop: { xs: "5px", sm: "25px", md: "43px" }}}>
<Header/>
{/* <Drawer open={open} handleDrawerToggle={handleDrawerToggle} /> */}
<Box style={{ width: '100%', flexGrow: 1 } } sx={{ paddingTop: "38px" }}>
{/* <Toolbar /> */}
{/* <Breadcrumbs navigation={navigation} title /> */}
<Outlet />
</Box>
<Box sx={{borderTop: "3px solid #0C489E"}}>
<Footer/>
</Box>
</Box>
)}
{hideNavbarRoutes.includes(location.pathname) && (
<Outlet />
)}
</>
); );
}; };




+ 9
- 3
src/pages/Announcement/Search/DataGrid.js 查看文件

@@ -10,7 +10,7 @@ import { clickableLink } from 'utils/CommonFunction';
import {GET_ANNOUNCE_LIST} from "utils/ApiPathConst"; import {GET_ANNOUNCE_LIST} from "utils/ApiPathConst";
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchPublicNoticeTable({ searchCriteria }) {
export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnReady, applySearch}) {


const navigate = useNavigate() const navigate = useNavigate()


@@ -73,10 +73,16 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
customPageSize={10} customPageSize={10}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
onRowDoubleClick={handleRowDoubleClick} onRowDoubleClick={handleRowDoubleClick}
doLoad={{
applyGridOnReady={applyGridOnReady}
applySearch = {applySearch}
// doLoad={{
// url: GET_ANNOUNCE_LIST,
// params: _searchCriteria,
// }}
doLoad={React.useMemo(() => ({
url: GET_ANNOUNCE_LIST, url: GET_ANNOUNCE_LIST,
params: _searchCriteria, params: _searchCriteria,
}}
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 5
- 2
src/pages/Announcement/Search/SearchForm.js 查看文件

@@ -17,8 +17,9 @@ import dayjs from "dayjs";
import {DemoItem} from "@mui/x-date-pickers/internals/demo"; import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";

// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchPublicNoticeForm = ({ applySearch, searchCriteria}) => {
const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady}) => {
const navigate = useNavigate() const navigate = useNavigate()


const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
@@ -58,7 +59,8 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria}) => {
function resetForm() { function resetForm() {
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
reset();
reset({key:""});
localStorage.setItem('searchCriteria',"")
} }




@@ -180,6 +182,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria}) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Submit Submit
</Button> </Button>


+ 26
- 5
src/pages/Announcement/Search/index.js 查看文件

@@ -7,6 +7,7 @@ import {
import MainCard from "components/MainCard"; import MainCard from "components/MainCard";
import * as React from "react"; import * as React from "react";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import { getSearchCriteria } from "auth/utils";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
@@ -28,20 +29,37 @@ const BackgroundHead = {


const UserSearchPage_Individual = () => { const UserSearchPage_Individual = () => {


const [searchCriteria, setSearchCriteria] = React.useState({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 90)),
});
const [searchCriteria, setSearchCriteria] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);

React.useEffect(() => {
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []);


React.useEffect(() => { React.useEffect(() => {
setOnReady(true); setOnReady(true);
}, [searchCriteria]); }, [searchCriteria]);


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }



return ( return (
!onReady ? !onReady ?
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center"> <Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
@@ -63,6 +81,7 @@ const UserSearchPage_Individual = () => {
<SearchForm <SearchForm
applySearch={applySearch} applySearch={applySearch}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -73,7 +92,9 @@ const UserSearchPage_Individual = () => {
sx={{ backgroundColor: '#fff' }} sx={{ backgroundColor: '#fff' }}
> >
<EventTable <EventTable
searchCriteria={searchCriteria}
searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 10
- 4
src/pages/Announcement/Search_Public/DataGrid.js 查看文件

@@ -6,7 +6,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import {GET_ANNOUNCE_LIST} from "utils/ApiPathConst"; import {GET_ANNOUNCE_LIST} from "utils/ApiPathConst";
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchPublicNoticeTable({ searchCriteria }) {
export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnReady,applySearch }) {


const intl = useIntl(); const intl = useIntl();
const { locale } = intl; const { locale } = intl;
@@ -57,10 +57,16 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
columns={columns} columns={columns}
customPageSize={10} customPageSize={10}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
doLoad={{
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
// doLoad={{
// url: GET_ANNOUNCE_LIST,
// params: _searchCriteria
// }}
doLoad={React.useMemo(() => ({
url: GET_ANNOUNCE_LIST, url: GET_ANNOUNCE_LIST,
params: _searchCriteria
}}
params: _searchCriteria,
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 22
- 3
src/pages/Announcement/Search_Public/SearchForm.js 查看文件

@@ -19,7 +19,7 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => {
// const navigate = useNavigate() // const navigate = useNavigate()


const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
@@ -39,6 +39,22 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
setToDateValue(maxDate); setToDateValue(maxDate);
}, [maxDate]); }, [maxDate]);


const _sx = {
padding: "4 2 4 2",
boxShadow: 1,
border: 1,
borderColor: '#DDD',
'& .MuiDataGrid-cell': {
borderTop: 1,
borderBottom: 1,
borderColor: "#EEE"
},
'& .MuiDataGrid-footerContainer': {
border: 1,
borderColor: "#EEE"
}
}

const marginBottom = 2.5; const marginBottom = 2.5;
const { reset, register, handleSubmit } = useForm() const { reset, register, handleSubmit } = useForm()
const onSubmit = (data) => { const onSubmit = (data) => {
@@ -60,7 +76,8 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
function resetForm() { function resetForm() {
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
reset();
reset({key:""});
localStorage.setItem('searchCriteria',"")
} }




@@ -68,7 +85,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
<MainCard xs={12} md={12} lg={12} <MainCard xs={12} md={12} lg={12}
border={false} border={false}
content={false} content={false}
sx={{ backgroundColor: '#fff' }}
sx={_sx}
> >


<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
@@ -186,6 +203,8 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
aria-label={intl.formatMessage({id: 'submit'})}
> >
<FormattedMessage id="submit"></FormattedMessage> <FormattedMessage id="submit"></FormattedMessage>
</Button> </Button>


+ 26
- 5
src/pages/Announcement/Search_Public/index.js 查看文件

@@ -14,6 +14,7 @@ const SearchForm = Loadable(React.lazy(() => import('./SearchForm')));
const EventTable = Loadable(React.lazy(() => import('./DataGrid'))); const EventTable = Loadable(React.lazy(() => import('./DataGrid')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
import { getSearchCriteria } from "auth/utils";


const BackgroundHead = { const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`, backgroundImage: `url(${titleBackgroundImg})`,
@@ -29,19 +30,36 @@ const BackgroundHead = {


const UserSearchPage_Individual = () => { const UserSearchPage_Individual = () => {


const [searchCriteria, setSearchCriteria] = React.useState({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 90)),
});
const [searchCriteria, setSearchCriteria] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
setOnReady(true);
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []);

React.useEffect(() => {
if(Object.keys(searchCriteria).length>0){
setOnReady(true);
}
}, [searchCriteria]); }, [searchCriteria]);




function applySearch(input) { function applySearch(input) {
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -65,6 +83,7 @@ const UserSearchPage_Individual = () => {
<SearchForm <SearchForm
applySearch={applySearch} applySearch={applySearch}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -76,6 +95,8 @@ const UserSearchPage_Individual = () => {
> >
<EventTable <EventTable
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 12
- 9
src/pages/AuditLog/AuditLogSearchForm.js 查看文件

@@ -21,16 +21,18 @@ import {ThemeProvider} from "@emotion/react";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import * as UrlUtils from "utils/ApiPathConst"; import * as UrlUtils from "utils/ApiPathConst";
import * as HttpUtils from "utils/HttpUtils"; import * as HttpUtils from "utils/HttpUtils";
import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
// import Loadable from 'components/Loadable';
// const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));


import {DatePicker} from "@mui/x-date-pickers/DatePicker"; import {DatePicker} from "@mui/x-date-pickers/DatePicker";
import dayjs from "dayjs"; import dayjs from "dayjs";
import {DemoItem} from "@mui/x-date-pickers/internals/demo"; import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
import { isGranted } from "auth/utils";

// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const AuditLogSearchForm = ({ applySearch, searchCriteria}) => {
const AuditLogSearchForm = ({ applySearch, searchCriteria, onGridReady}) => {
// const navigate = useNavigate(); // const navigate = useNavigate();


const [minDate, setMinDate] = React.useState(searchCriteria.modifiedFrom); const [minDate, setMinDate] = React.useState(searchCriteria.modifiedFrom);
@@ -77,6 +79,7 @@ const AuditLogSearchForm = ({ applySearch, searchCriteria}) => {
setOnDownload(true) setOnDownload(true)
HttpUtils.fileDownload({ HttpUtils.fileDownload({
url: UrlUtils.AUDIT_LOG_EXPORT, url: UrlUtils.AUDIT_LOG_EXPORT,
params: searchCriteria,
onResponse:()=>{ onResponse:()=>{
setOnDownload(false) setOnDownload(false)
}, },
@@ -185,18 +188,17 @@ const AuditLogSearchForm = ({ applySearch, searchCriteria}) => {
<ThemeProvider theme={PNSPS_BUTTON_THEME}> <ThemeProvider theme={PNSPS_BUTTON_THEME}>
<Grid item xs={12} md={12}> <Grid item xs={12} md={12}>
<Grid container maxWidth justifyContent="flex-end"> <Grid container maxWidth justifyContent="flex-end">
<Grid item sx={{ ml: 3, mr: 3, mb: 3,}}>
{onDownload?
<LoadingComponent disableText={true} alignItems="flex-start"/>
:
{isGranted("MAINTAIN_SETTING") ?
<Grid item sx={{ ml: 3, mr: 3, mb: 3,}}>
<Button <Button
variant="contained" variant="contained"
onClick={exportExcel} onClick={exportExcel}
disabled={onDownload}
> >
Export Export
</Button> </Button>
}
</Grid>
</Grid> : null
}
<Grid item sx={{ ml: 3, mr: 3, mb: 3,}}> <Grid item sx={{ ml: 3, mr: 3, mb: 3,}}>
<Button <Button
variant="contained" variant="contained"
@@ -210,6 +212,7 @@ const AuditLogSearchForm = ({ applySearch, searchCriteria}) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Search Search
</Button> </Button>


+ 10
- 4
src/pages/AuditLog/AuditLogTable.js 查看文件

@@ -12,7 +12,7 @@ import {
} from '@mui/material'; } from '@mui/material';
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function AuditLogTable({searchCriteria}) {
export default function AuditLogTable({searchCriteria, applyGridOnReady,applySearch}) {
const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria);


useEffect(() => { useEffect(() => {
@@ -87,10 +87,16 @@ export default function AuditLogTable({searchCriteria}) {
columns={columns} columns={columns}
customPageSize={10} customPageSize={10}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
doLoad={{
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
// doLoad={{
// url: GET_AUDIT_LOG_LIST,
// params: _searchCriteria
// }}
doLoad={React.useMemo(() => ({
url: GET_AUDIT_LOG_LIST, url: GET_AUDIT_LOG_LIST,
params: _searchCriteria
}}
params: _searchCriteria,
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 10
- 1
src/pages/AuditLog/index.js 查看文件

@@ -8,6 +8,7 @@ import {
import MainCard from "components/MainCard"; import MainCard from "components/MainCard";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import * as React from "react";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
import { lazy } from 'react'; import { lazy } from 'react';
@@ -33,15 +34,21 @@ const AuditLogPage = () => {
modifiedFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)), modifiedFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
}); });
const [onReady, setOnReady] = useState(false); const [onReady, setOnReady] = useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


useEffect(() => { useEffect(() => {
setOnReady(true); setOnReady(true);
}, [searchCriteria]); }, [searchCriteria]);


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
} }


function applyGridOnReady(input) {
setGridOnReady(input);
}
return ( return (
!onReady ? !onReady ?
<Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center"> <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
@@ -64,7 +71,7 @@ const AuditLogPage = () => {
<SearchForm <SearchForm
applySearch={applySearch} applySearch={applySearch}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -75,6 +82,8 @@ const AuditLogPage = () => {
> >
<EventTable <EventTable
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 1
- 1
src/pages/DemandNote/Details/ApplicationDetailCard.js 查看文件

@@ -143,7 +143,7 @@ const ApplicationDetailCard = ({ data }) => {
</Grid> </Grid>
<Grid container direction="row" justifyContent="space-between" <Grid container direction="row" justifyContent="space-between"
alignItems="center"> alignItems="center">
<Grid item xs={12} md={6} lg={6} mt={1}>
<Grid item xs={12} md={6} lg={6} mt={1} mb={2}>
<Grid container alignItems={"center"}> <Grid container alignItems={"center"}>
<Grid item xs={12} md={12} lg={12}> <Grid item xs={12} md={12} lg={12}>
<Grid container direction="row"> <Grid container direction="row">


+ 15
- 9
src/pages/DemandNote/Export/DataGrid.js 查看文件

@@ -77,9 +77,9 @@ export default function SearchPublicNoticeTable({ searchCriteria,}) {
// let user = params.row.enCompanyName != null ? params.row.enCompanyName : params.row.chCompanyName; // let user = params.row.enCompanyName != null ? params.row.enCompanyName : params.row.chCompanyName;
let user = params.row.contactPerson; let user = params.row.contactPerson;
// user = user != null ? user : ""; // user = user != null ? user : "";
if (params.row.sysType != null && params.row.sysType == "dummy"){
user = "Dummy - PD"
}
// if (params.row.sysType != null && params.row.sysType == "dummy"){
// user = "Dummy - PD"
// }
return <div> return <div>
{user} {user}
</div>; </div>;
@@ -95,7 +95,7 @@ export default function SearchPublicNoticeTable({ searchCriteria,}) {
let company = params.row.enCompanyName != null ? params.row.enCompanyName : params.row.chCompanyName; let company = params.row.enCompanyName != null ? params.row.enCompanyName : params.row.chCompanyName;
company = company != null ? company : ""; company = company != null ? company : "";
if (params.row.sysType != null && params.row.sysType == "dummy"){ if (params.row.sysType != null && params.row.sysType == "dummy"){
company = params.row.contactPerson
company = params.row.custName
} }
return <div> return <div>
{company} {company}
@@ -109,7 +109,13 @@ export default function SearchPublicNoticeTable({ searchCriteria,}) {
flex: 2, flex: 2,
minWidth: 200, minWidth: 200,
renderCell: (params) => { renderCell: (params) => {
return <>{(params?.value)}</>;
let careOf = params.row.careOf
// if (params.row.sysType != null && params.row.sysType == "dummy"){
// careOf = ''
// }
return <div>
{careOf}
</div>;
} }
}, },
{ {
@@ -120,13 +126,13 @@ export default function SearchPublicNoticeTable({ searchCriteria,}) {
minWidth: 100, minWidth: 100,
valueGetter: (params) => { valueGetter: (params) => {
let length = params.row.length let length = params.row.length
let colCount = params.row.colCount
// let colCount = params.row.colCount
let noOfPages = params.row.noOfPages let noOfPages = params.row.noOfPages
let dimension = 0 let dimension = 0
if (noOfPages != null){ if (noOfPages != null){
dimension = length*colCount*noOfPages
dimension = length*noOfPages
}else{ }else{
dimension = length*colCount
dimension = length
} }
return dimension; return dimension;
} }
@@ -134,7 +140,7 @@ export default function SearchPublicNoticeTable({ searchCriteria,}) {
{ {
id: 'fee', id: 'fee',
field: 'fee', field: 'fee',
headerName: 'Amount(HK$)',
headerName: 'Amount($)',
flex: 1, flex: 1,
minWidth: 100, minWidth: 100,
valueGetter: (params) => { valueGetter: (params) => {


+ 86
- 15
src/pages/DemandNote/Search/DataGrid.js 查看文件

@@ -19,7 +19,8 @@ import {
DEMAND_NOTE_SEND, DEMAND_NOTE_SEND,
DEMAND_NOTE_ATTACH, DEMAND_NOTE_ATTACH,
DEMAND_NOTE_MARK_PAID, DEMAND_NOTE_MARK_PAID,
DEMAND_NOTE_LIST_ALL
DEMAND_NOTE_LIST_ALL,
DEMAND_NOTE_REVOKE_PAID
} from "utils/ApiPathConst"; } from "utils/ApiPathConst";
import * as HttpUtils from "utils/HttpUtils"; import * as HttpUtils from "utils/HttpUtils";
import { PNSPS_BUTTON_THEME } from "themes/buttonConst"; import { PNSPS_BUTTON_THEME } from "themes/buttonConst";
@@ -27,23 +28,26 @@ import { ThemeProvider } from "@emotion/react";
import { isGrantedAny } from "auth/utils"; import { isGrantedAny } from "auth/utils";
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchDemandNote({ searchCriteria, applySearch }) {
export default function SearchDemandNote({ applySearch, searchCriteria, applyGridOnReady }) {


const [isConfirmPopUp, setConfirmPopUp] = useState(false); const [isConfirmPopUp, setConfirmPopUp] = useState(false);
const [isRevokePopUp, setRevokePopUp] = useState(false);
const [isSendPopUp, setSendPopUp] = useState(false); const [isSendPopUp, setSendPopUp] = useState(false);
const [isErrorPopUp, setIsErrorPopUp] = useState(false); const [isErrorPopUp, setIsErrorPopUp] = useState(false);
const [selectonWarning, setSelectonWarning] = useState(false); const [selectonWarning, setSelectonWarning] = useState(false);
const [wait, setWait] = useState(false); const [wait, setWait] = useState(false);
const [reload, setReload] = useState(new Date());
const [rows, setRows] = useState([]); const [rows, setRows] = useState([]);
const [_searchCriteria, set_searchCriteria] = useState(searchCriteria);
const [_searchCriteria, set_searchCriteria] = useState({});
const [selectedRowItems, setSelectedRowItems] = useState([]); const [selectedRowItems, setSelectedRowItems] = useState([]);
const navigate = useNavigate() const navigate = useNavigate()
const [onDownload, setOnDownload] = useState(false);


useEffect(() => { useEffect(() => {
set_searchCriteria(searchCriteria); set_searchCriteria(searchCriteria);
}, [searchCriteria]); }, [searchCriteria]);



const handleDnClick = (params) => () => { const handleDnClick = (params) => () => {
navigate('/paymentPage/demandNote/details/' + params.id); navigate('/paymentPage/demandNote/details/' + params.id);
}; };
@@ -83,10 +87,17 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
} }


const onDownloadClick = (params) => () => { const onDownloadClick = (params) => () => {
setOnDownload(true)
HttpUtils.fileDownload({ HttpUtils.fileDownload({
fileId: params.row.fileId, fileId: params.row.fileId,
skey: params.row.skey, skey: params.row.skey,
filename: params.row.filename, filename: params.row.filename,
onResponse:()=>{
setOnDownload(false)
},
onError:()=>{
setOnDownload(false)
}
}); });
}; };


@@ -109,7 +120,7 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
dnIdList: idList dnIdList: idList
}, },
onSuccess: () => { onSuccess: () => {
if (reloadFun) reloadFun();
setReload(new Date());
} }
}); });


@@ -133,13 +144,36 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
}, },
files: [file], files: [file],
onSuccess() { onSuccess() {
setWait(false);
if (reloadFun) reloadFun();
setReload(new Date());
}, },
}); });
document.getElementById("uploadFileBtn").value = ""; document.getElementById("uploadFileBtn").value = "";
} }


const revokePaid = () => {
setRevokePopUp(false);
let idList = [];
const datas = rows?.filter((row) =>
selectedRowItems.includes(row.id)
);
if (datas?.length < 1) {
setSelectonWarning(true);
return;
}
for (var i = 0; i < datas?.length; i++) {
idList.push(datas[i].id);
}
HttpUtils.post({
url: DEMAND_NOTE_REVOKE_PAID,
params: {
dnIdList: idList
},
onSuccess: () => {
setReload(new Date());
}
});
}

const markPaid = () => { const markPaid = () => {
setConfirmPopUp(false); setConfirmPopUp(false);
let idList = []; let idList = [];
@@ -159,7 +193,7 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
dnIdList: idList dnIdList: idList
}, },
onSuccess: () => { onSuccess: () => {
if (reloadFun) reloadFun();
setReload(new Date());
} }
}); });
} }
@@ -240,9 +274,11 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
width: 300, width: 300,
renderCell: (params) => { renderCell: (params) => {
return (<table> return (<table>
<tr><td>Issue:</td><td>{DateUtils.dateStr(params?.row.issueDate)}</td></tr>
<tr><td>Due:</td><td>{params?.value ? DateUtils.dateStr(params?.value) : "--"}</td></tr>
<tr><td>Sent:</td><td>{params.row.sentDate ? <> {DateUtils.datetimeStr(params.row.sentDate)} - {params.row.sentBy} </> : <> To be sent</>}</td></tr>
<tbody>
<tr><td>Issue:</td><td>{DateUtils.dateStr(params?.row.issueDate)}</td></tr>
<tr><td>Due:</td><td>{params?.value ? DateUtils.dateStr(params?.value) : "--"}</td></tr>
<tr><td>Sent:</td><td>{params.row.sentDate ? DateUtils.datetimeStr(params.row.sentDate) +" - "+ params.row.sentBy : "To be sent"}</td></tr>
</tbody>
</table>); </table>);
} }
}, },
@@ -254,7 +290,7 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
), ),
width: 280, width: 280,
renderCell: (params) => { renderCell: (params) => {
return <Button onClick={onDownloadClick(params)}><u>{params.row.filename}</u></Button>;
return <Button disabled={onDownload} onClick={onDownloadClick(params)}><u>{params.row.filename}</u></Button>;
}, },
}, },
{ {
@@ -262,7 +298,7 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
headerName: 'Status', headerName: 'Status',
width: 175, width: 175,
renderCell: (params) => { renderCell: (params) => {
return [StatusUtils.getStatus_Eng(params)]
return StatusUtils.getStatus_Eng(params)
}, },
}, },
]; ];
@@ -300,6 +336,7 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
</Button> </Button>
</label> </label>
</Grid> </Grid>

<Grid item sx={{ ml: 3, mr: 3, mb: 3, mt: 3 }}> <Grid item sx={{ ml: 3, mr: 3, mb: 3, mt: 3 }}>
<Button <Button
variant="contained" variant="contained"
@@ -334,13 +371,23 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
Mark as Paid Mark as Paid
</Button> </Button>
</Grid> </Grid>

<Grid item sx={{ ml: 3, mr: 3, mb: 3, mt: 3 }}>
<Button
variant="contained"
onClick={() => setRevokePopUp(true)}
>
Revoke payment
</Button>
</Grid>

</ThemeProvider> </ThemeProvider>
</Grid> </Grid>
: <></> : <></>
} }
<Box sx={{ backgroundColor: "#fff", ml: 2 }} width="98%"> <Box sx={{ backgroundColor: "#fff", ml: 2 }} width="98%">
<FiDataGrid <FiDataGrid
checkboxSelection = {isGrantedAny(["MAINTAIN_DEMANDNOTE"])}
checkboxSelection={isGrantedAny(["MAINTAIN_DEMANDNOTE"])}
disableRowSelectionOnClick disableRowSelectionOnClick
onRowSelectionModelChange={(newSelection) => { onRowSelectionModelChange={(newSelection) => {
setSelectedRowItems(newSelection); setSelectedRowItems(newSelection);
@@ -349,13 +396,15 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
customPageSize={100} customPageSize={100}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
onRowDoubleClick={handleRowDoubleClick} onRowDoubleClick={handleRowDoubleClick}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
doLoad={useMemo(() => ({ doLoad={useMemo(() => ({
url: DEMAND_NOTE_LIST_ALL, url: DEMAND_NOTE_LIST_ALL,
params: _searchCriteria, params: _searchCriteria,
callback: function (responseData) { callback: function (responseData) {
setRows(responseData?.records); setRows(responseData?.records);
} }
}), [_searchCriteria])}
}), [_searchCriteria, reload])}
/> />
</Box> </Box>
<div> <div>
@@ -422,6 +471,28 @@ export default function SearchDemandNote({ searchCriteria, applySearch }) {
</DialogActions> </DialogActions>
</Dialog> </Dialog>
</div> </div>
<div>
<Dialog
open={isRevokePopUp}
onClose={() => setRevokePopUp(false)}
PaperProps={{
sx: {
minWidth: '40vw',
maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
}
}}
>
<DialogTitle><Typography variant="h3">Confirm</Typography></DialogTitle>
<DialogContent style={{ display: 'flex', }}>
<Typography variant="h4" style={{ padding: '16px' }}>Are you sure to revoke DN as To Be Paid?</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setRevokePopUp(false)}><Typography variant="h5">Cancel</Typography></Button>
<Button onClick={() => revokePaid()}><Typography variant="h5">Confirm</Typography></Button>
</DialogActions>
</Dialog>
</div>
<div> <div>
<Dialog <Dialog
open={isSendPopUp} open={isSendPopUp}


+ 48
- 6
src/pages/DemandNote/Search/SearchForm.js 查看文件

@@ -21,7 +21,7 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issueComboData
const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issueComboData, onGridReady
}) => { }) => {


const [type, setType] = React.useState([]); const [type, setType] = React.useState([]);
@@ -44,6 +44,28 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue
const intl = useIntl(); const intl = useIntl();
const { locale } = intl; const { locale } = intl;
React.useEffect(() => {
if(searchCriteria.status!=undefined){
if(searchCriteria.status === ""){
ComboData.denmandNoteStatus[0]
}else{
setSelectedStatus(ComboData.denmandNoteStatus.find(item => item.type === searchCriteria.status))
}
if(searchCriteria.dueDateFrom != ""){
setMinDueDate(DateUtils.dateValue(searchCriteria.dueDateFrom))
}else{
setMinDueDate(null)
}
if(searchCriteria.dueDateTo != ""){
setMaxDueDate(DateUtils.dateValue(searchCriteria.dueDateTo))
}else{
setMaxDueDate(null);
}
}else{
setSelectedStatus(ComboData.denmandNoteStatus[0])
}
}, [searchCriteria]);
React.useEffect(() => { React.useEffect(() => {
setFromDateValue(minDate); setFromDateValue(minDate);
}, [minDate]); }, [minDate]);
@@ -101,12 +123,18 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue
React.useEffect(() => { React.useEffect(() => {
if (orgComboData && orgComboData.length > 0) { if (orgComboData && orgComboData.length > 0) {
setOrgCombo(orgComboData); setOrgCombo(orgComboData);
if(searchCriteria.orgId!=undefined){
setOrgSelected(orgComboData.find(item => item.key === searchCriteria.orgId))
}
} }
}, [orgComboData]); }, [orgComboData]);


React.useEffect(() => { React.useEffect(() => {
if (issueComboData && issueComboData.length > 0) { if (issueComboData && issueComboData.length > 0) {
setIssueCombo(issueComboData); setIssueCombo(issueComboData);
if(searchCriteria.issueId!=undefined){
setIssueSelected(issueComboData.find(item => item.id === searchCriteria.issueId))
}
} }
}, [issueComboData]); }, [issueComboData]);


@@ -117,9 +145,13 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue
setSelectedStatus(ComboData.denmandNoteStatus[0]); setSelectedStatus(ComboData.denmandNoteStatus[0]);
setMinDueDate(null); setMinDueDate(null);
setMaxDueDate(null); setMaxDueDate(null);
setMinDate(searchCriteria.dateFrom);
setMaxDate(searchCriteria.dateTo);
reset();
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date()))
reset({
appNo:"",
dnNo:"",
});
localStorage.setItem('searchCriteria',"")
} }


function getIssueLabel(data) { function getIssueLabel(data) {
@@ -209,10 +241,12 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue
disablePortal disablePortal
id="orgId" id="orgId"
options={orgCombo} options={orgCombo}
groupBy={(option) => option.groupType}
size="small" size="small"
value={orgSelected} value={orgSelected}
getOptionLabel={(option) => option.name? option.name : ""} getOptionLabel={(option) => option.name? option.name : ""}
inputValue={orgSelected ? orgSelected.name : ""}
inputValue={orgSelected ? orgSelected.name!=undefined?orgSelected.name:"" : ""}

onChange={(event, newValue) => { onChange={(event, newValue) => {
if (newValue !== null) { if (newValue !== null) {
setOrgSelected(newValue); setOrgSelected(newValue);
@@ -228,12 +262,19 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue
}} }}
/> />
)} )}
renderGroup={(params) => (
<Grid item key={params.key}>
<Typography fontSize={20} fontStyle="italic" p={1}>
{params.group}
</Typography>
{params.children}
</Grid>
)}
/> />
</Grid> </Grid>
: <></> : <></>
} }



<Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
<TextField <TextField
fullWidth fullWidth
@@ -411,6 +452,7 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Submit Submit
</Button> </Button>


+ 21
- 4
src/pages/DemandNote/Search/index.js 查看文件

@@ -10,6 +10,7 @@ import * as React from "react";
import * as UrlUtils from "utils/ApiPathConst"; import * as UrlUtils from "utils/ApiPathConst";
import * as HttpUtils from "utils/HttpUtils"; import * as HttpUtils from "utils/HttpUtils";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import { getSearchCriteria } from "auth/utils";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
@@ -35,16 +36,26 @@ const UserSearchPage_Individual = () => {
const [orgCombo, setOrgCombo] = React.useState([]); const [orgCombo, setOrgCombo] = React.useState([]);
const [issueCombo, setIssueCombo] = React.useState([]); const [issueCombo, setIssueCombo] = React.useState([]);
const [searchCriteria, setSearchCriteria] = React.useState({ const [searchCriteria, setSearchCriteria] = React.useState({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14)),
// dateTo: DateUtils.dateValue(new Date()),
// dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14)),
// dueDateTo: DateUtils.dateValue(new Date()), // dueDateTo: DateUtils.dateValue(new Date()),
// dueDateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14)), // dueDateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14)),
}); });
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
getOrgCombo(); getOrgCombo();
getIssueCombo(); getIssueCombo();
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []); }, []);


React.useEffect(() => { React.useEffect(() => {
@@ -72,9 +83,14 @@ const UserSearchPage_Individual = () => {
}); });
} }



function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -102,7 +118,7 @@ const UserSearchPage_Individual = () => {
orgComboData={orgCombo} orgComboData={orgCombo}
issueComboData={issueCombo} issueComboData={issueCombo}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -115,6 +131,7 @@ const UserSearchPage_Individual = () => {
<EventTable <EventTable
applySearch={applySearch} applySearch={applySearch}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 14
- 6
src/pages/DemandNote/Search_Public/DataGrid.js 查看文件

@@ -15,11 +15,12 @@ import {useIntl} from "react-intl";
import {DEMAND_NOTE_LIST} from "utils/ApiPathConst"; import {DEMAND_NOTE_LIST} from "utils/ApiPathConst";
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchDemandNote({ searchCriteria }) {
export default function SearchDemandNote({ searchCriteria, applyGridOnReady,applySearch }) {
const intl = useIntl(); const intl = useIntl();
const theme = useTheme(); const theme = useTheme();
const isMdOrLg = useMediaQuery(theme.breakpoints.up('md')); const isMdOrLg = useMediaQuery(theme.breakpoints.up('md'));
const { locale } = intl;




const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria);
@@ -52,7 +53,7 @@ export default function SearchDemandNote({ searchCriteria }) {
{ {
id: 'issueDate', id: 'issueDate',
field: 'issueDate', field: 'issueDate',
headerName: intl.formatMessage({id: 'receiptDate'}),
headerName: intl.formatMessage({id: 'sendDate'}),
width: isMdOrLg ? 'auto' : 175, width: isMdOrLg ? 'auto' : 175,
flex: isMdOrLg ? 1 : undefined, flex: isMdOrLg ? 1 : undefined,
valueGetter: (params) => { valueGetter: (params) => {
@@ -65,12 +66,13 @@ export default function SearchDemandNote({ searchCriteria }) {
width: isMdOrLg ? 'auto' : 175, width: isMdOrLg ? 'auto' : 175,
flex: isMdOrLg ? 1 : undefined, flex: isMdOrLg ? 1 : undefined,
renderCell: (params) => { renderCell: (params) => {
return [StatusUtils.getStatus_Cht(params)]

return [StatusUtils.getStatus_i18n(params, locale) ]
}, },
}, },
{ {
field: 'sentDate', field: 'sentDate',
headerName: intl.formatMessage({id: 'sendDate'}),
headerName: intl.formatMessage({id: 'sendDateTime'}),
width: isMdOrLg ? 'auto' : 200, width: isMdOrLg ? 'auto' : 200,
flex: isMdOrLg ? 1 : undefined, flex: isMdOrLg ? 1 : undefined,
valueGetter: (params) => { valueGetter: (params) => {
@@ -95,10 +97,16 @@ export default function SearchDemandNote({ searchCriteria }) {
columns={columns} columns={columns}
customPageSize={10} customPageSize={10}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
doLoad={{
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
// doLoad={{
// url: DEMAND_NOTE_LIST,
// params: _searchCriteria,
// }}
doLoad={React.useMemo(() => ({
url: DEMAND_NOTE_LIST, url: DEMAND_NOTE_LIST,
params: _searchCriteria, params: _searchCriteria,
}}
}), [_searchCriteria])}
/> />
</Box> </Box>
</div> </div>


+ 23
- 3
src/pages/DemandNote/Search_Public/SearchForm.js 查看文件

@@ -22,7 +22,7 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData
const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData, onGridReady
}) => { }) => {


const intl = useIntl(); const intl = useIntl();
@@ -38,6 +38,18 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData
const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy");
const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy");


React.useEffect(() => {
if(searchCriteria.status!=undefined){
if(searchCriteria.status === ""){
ComboData.denmandNoteStatus_Public[0]
}else{
setSelectedStatus(ComboData.denmandNoteStatus_Public.find(item => item.type === searchCriteria.status))
}
}else{
setSelectedStatus(ComboData.denmandNoteStatus_Public[0])
}
}, [searchCriteria]);

React.useEffect(() => { React.useEffect(() => {
setFromDateValue(minDate); setFromDateValue(minDate);
}, [minDate]); }, [minDate]);
@@ -76,17 +88,23 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData
React.useEffect(() => { React.useEffect(() => {
if (issueComboData && issueComboData.length > 0) { if (issueComboData && issueComboData.length > 0) {
setIssueCombo(issueComboData); setIssueCombo(issueComboData);
if(searchCriteria.issueId!=undefined){
setIssueSelected(issueComboData.find(item => item.id === searchCriteria.issueId))
}
} }
}, [issueComboData]); }, [issueComboData]);


function resetForm() { function resetForm() {
setType([]); setType([]);
// setStatus({ key: 0, label: 'All', type: 'all' });
setSelectedStatus(ComboData.denmandNoteStatus_Public[0]);
// setOrgSelected({}); // setOrgSelected({});
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
setIssueSelected({}); setIssueSelected({});
reset();
reset({
appNo:"",
dnNo:"",
});
} }


function getIssueLabel(data) { function getIssueLabel(data) {
@@ -246,6 +264,7 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData
{...register("status")} {...register("status")}
id="status" id="status"
size="small" size="small"
disableClearable
options={ComboData.denmandNoteStatus_Public} options={ComboData.denmandNoteStatus_Public}
getOptionLabel={(option) => option?.i18nLabel ? intl.formatMessage({ id: option.i18nLabel }) : ""} getOptionLabel={(option) => option?.i18nLabel ? intl.formatMessage({ id: option.i18nLabel }) : ""}
inputValue={selectedStatus?.i18nLabel ? intl.formatMessage({ id: selectedStatus.i18nLabel }) : ""} inputValue={selectedStatus?.i18nLabel ? intl.formatMessage({ id: selectedStatus.i18nLabel }) : ""}
@@ -288,6 +307,7 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
<FormattedMessage id="submit" /> <FormattedMessage id="submit" />
</Button> </Button>


+ 22
- 5
src/pages/DemandNote/Search_Public/index.js 查看文件

@@ -10,6 +10,7 @@ import * as React from "react";
import {GET_ORG_COMBO, GET_ISSUE_COMBO} from "utils/ApiPathConst"; import {GET_ORG_COMBO, GET_ISSUE_COMBO} from "utils/ApiPathConst";
import * as HttpUtils from "utils/HttpUtils"; import * as HttpUtils from "utils/HttpUtils";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import { getSearchCriteria } from "auth/utils";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
@@ -34,15 +35,22 @@ const SearchPage_DemandNote_Pub = () => {


const [orgCombo, setOrgCombo] = React.useState([]); const [orgCombo, setOrgCombo] = React.useState([]);
const [issueCombo, setIssueCombo] = React.useState([]); const [issueCombo, setIssueCombo] = React.useState([]);
const [searchCriteria, setSearchCriteria] = React.useState({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14)),
});
const [searchCriteria, setSearchCriteria] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
getOrgCombo(); getOrgCombo();
getIssueCombo(); getIssueCombo();
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []); }, []);


React.useEffect(() => { React.useEffect(() => {
@@ -72,7 +80,13 @@ const SearchPage_DemandNote_Pub = () => {




function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -100,6 +114,7 @@ const SearchPage_DemandNote_Pub = () => {
orgComboData={orgCombo} orgComboData={orgCombo}
issueComboData={issueCombo} issueComboData={issueCombo}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -110,7 +125,9 @@ const SearchPage_DemandNote_Pub = () => {
sx={{ backgroundColor: '#fff' }} sx={{ backgroundColor: '#fff' }}
> >
<EventTable <EventTable
searchCriteria={searchCriteria}
searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 3
- 3
src/pages/EmailTemplate/Detail_GLD/index.js 查看文件

@@ -50,7 +50,7 @@ const Index = () => {
axios.get(`${UrlUtils.GET_EMAIL}/${params.id}`) axios.get(`${UrlUtils.GET_EMAIL}/${params.id}`)
.then((response) => { .then((response) => {
if (response.status === 200) { if (response.status === 200) {
console.log(response)
// console.log(response)
setRecord(response.data.data) setRecord(response.data.data)
} }
}) })
@@ -95,14 +95,14 @@ const Index = () => {
console.log(error); console.log(error);
return false; return false;
}); });
console.log(data)
// console.log(data)
} }


const handleDelete = () => { const handleDelete = () => {
axios.delete(`${UrlUtils.DELETE_EMAIL}/${params.id}`, axios.delete(`${UrlUtils.DELETE_EMAIL}/${params.id}`,
) )
.then((response) => { .then((response) => {
console.log(response)
// console.log(response)
if (response.status === 204) { if (response.status === 204) {
// location.reload(); // location.reload();
navigate('/setting/emailTemplate'); navigate('/setting/emailTemplate');


+ 8
- 4
src/pages/EmailTemplate/Search_GLD/DataGrid.js 查看文件

@@ -97,10 +97,14 @@ export default function EmailTemplateTable({ responseData }) {
customPageSize={10} customPageSize={10}
onRowDoubleClick={handleRowDoubleClick} onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
doLoad={{
url:GET_EMAIL_LIST,
params: _responseData
}}
// doLoad={{
// url:GET_EMAIL_LIST,
// params: _responseData
// }}
doLoad={React.useMemo(() => ({
url: GET_EMAIL_LIST,
params: _responseData,
}), [_responseData])}
/> />
</div> </div>
); );

+ 2
- 1
src/pages/GFMIS/DataGrid.js 查看文件

@@ -6,7 +6,7 @@ import { useNavigate } from "react-router-dom";
import { FiDataGrid } from "components/FiDataGrid"; import { FiDataGrid } from "components/FiDataGrid";
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchTable({ searchCriteria }) {
export default function SearchTable({ searchCriteria, applyGridOnReady }) {
const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria);
const navigate = useNavigate() const navigate = useNavigate()
// const [rows, setRows] = React.useState([]); // const [rows, setRows] = React.useState([]);
@@ -67,6 +67,7 @@ export default function SearchTable({ searchCriteria }) {
columns={columns} columns={columns}
customPageSize={10} customPageSize={10}
onRowDoubleClick={handleEditClick} onRowDoubleClick={handleEditClick}
applyGridOnReady={applyGridOnReady}
doLoad={React.useMemo(() => ({ doLoad={React.useMemo(() => ({
url: GFIMIS_LIST, url: GFIMIS_LIST,
params: _searchCriteria, params: _searchCriteria,


+ 2
- 1
src/pages/GFMIS/SearchForm.js 查看文件

@@ -21,7 +21,7 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria }) => {
const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGridReady }) => {


// const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); // const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
@@ -146,6 +146,7 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria }) =>
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Preview Preview
</Button> </Button>


+ 14
- 5
src/pages/GFMIS/index.js 查看文件

@@ -35,6 +35,7 @@ const Index = () => {
// dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)), // dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
}); });
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
setOnReady(true); setOnReady(true);
@@ -50,7 +51,7 @@ const Index = () => {
dateFrom: input.dateFrom, dateFrom: input.dateFrom,
}, },
onSuccess: (responseData) => { onSuccess: (responseData) => {
console.log(responseData)
// console.log(responseData)
const parser = new DOMParser(); const parser = new DOMParser();
const xmlDoc = parser.parseFromString(responseData, 'application/xml'); const xmlDoc = parser.parseFromString(responseData, 'application/xml');
// Get the DCBHeader element // Get the DCBHeader element
@@ -75,7 +76,7 @@ const Index = () => {
const updatedXmlString = new XMLSerializer().serializeToString(xmlDoc); const updatedXmlString = new XMLSerializer().serializeToString(xmlDoc);
const filename = xmlDoc.querySelector('FileHeader').getAttribute('H_Filename'); const filename = xmlDoc.querySelector('FileHeader').getAttribute('H_Filename');
console.log(updatedXmlString)
// console.log(updatedXmlString)
const blob = new Blob([updatedXmlString], { type: 'application/xml' }); const blob = new Blob([updatedXmlString], { type: 'application/xml' });
// Create a download link // Create a download link
const link = document.createElement('a'); const link = document.createElement('a');
@@ -97,9 +98,14 @@ const Index = () => {




function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
} }


function applyGridOnReady(input) {
setGridOnReady(input);
}

function generateXML(input) { function generateXML(input) {
downloadXML(input); downloadXML(input);
} }
@@ -121,9 +127,10 @@ const Index = () => {
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} lg={12} sx={{mb:-1}}> <Grid item xs={12} md={12} lg={12} sx={{mb:-1}}>
<SearchForm <SearchForm
applySearch={applySearch}
generateXML={generateXML}
searchCriteria={searchCriteria}
applySearch={applySearch}
generateXML={generateXML}
searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -135,6 +142,8 @@ const Index = () => {
> >
<EventTable <EventTable
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 8
- 3
src/pages/GazetteIssue/DataGrid.js 查看文件

@@ -7,7 +7,7 @@ import {GET_ISSUE} from "utils/ApiPathConst";


// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function GazetteIssueTable({ searchCriteria }) {
export default function GazetteIssueTable({ searchCriteria, applyGridOnReady }) {
const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria);


React.useEffect(() => { React.useEffect(() => {
@@ -100,10 +100,15 @@ export default function GazetteIssueTable({ searchCriteria }) {
customPageSize={10} customPageSize={10}
// onRowDoubleClick={handleRowDoubleClick} // onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
doLoad={{
applyGridOnReady={applyGridOnReady}
// doLoad={{
// url: GET_ISSUE,
// params: _searchCriteria,
// }}
doLoad={React.useMemo(() => ({
url: GET_ISSUE, url: GET_ISSUE,
params: _searchCriteria, params: _searchCriteria,
}}
}), [_searchCriteria])}
/> />
</div> </div>
); );

+ 2
- 2
src/pages/GazetteIssue/ExportForm.js 查看文件

@@ -27,9 +27,9 @@ const SearchGazetteIssueForm = ({ applyExport, comboData, waitDownload}) => {
handleSubmit } = useForm() handleSubmit } = useForm()


const onSubmit = () => { const onSubmit = () => {
console.log(selectedYear)
// console.log(selectedYear)
if (selectedYear !=null && Object.keys(selectedYear).length>0){ if (selectedYear !=null && Object.keys(selectedYear).length>0){
console.log("okkkkkkkkkkkkkkkk")
// console.log("okkkkkkkkkkkkkkkk")
const temp = { const temp = {
year: selectedYear.label, year: selectedYear.label,
}; };


+ 2
- 1
src/pages/GazetteIssue/SearchForm.js 查看文件

@@ -16,7 +16,7 @@ import {ThemeProvider} from "@emotion/react";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //




const SearchGazetteIssueForm = ({ applySearch, comboData}) => {
const SearchGazetteIssueForm = ({ applySearch, comboData, onGridReady}) => {
const [selectedYear, setSelectedYear] = React.useState([]); const [selectedYear, setSelectedYear] = React.useState([]);
// const [defaultYear, setDefaultYear] = React.useState(searchCriteria.year); // const [defaultYear, setDefaultYear] = React.useState(searchCriteria.year);
const [comboList, setComboList] = React.useState([]); const [comboList, setComboList] = React.useState([]);
@@ -114,6 +114,7 @@ const SearchGazetteIssueForm = ({ applySearch, comboData}) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Search Search
</Button> </Button>


+ 41
- 29
src/pages/GazetteIssue/index.js 查看文件

@@ -31,6 +31,7 @@ import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react"; import {ThemeProvider} from "@emotion/react";
import { dateStr_Year } from "utils/DateUtils"; import { dateStr_Year } from "utils/DateUtils";
import { notifySaveSuccess } from 'utils/CommonFunction'; import { notifySaveSuccess } from 'utils/CommonFunction';
import { isGrantedAny } from "auth/utils";


// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //


@@ -38,6 +39,8 @@ const Index = () => {
const [comboData, setComboData] = React.useState([]); const [comboData, setComboData] = React.useState([]);
const [holidayComboData, setHolidayComboData] = React.useState([]); const [holidayComboData, setHolidayComboData] = React.useState([]);
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);

const [onSearchReady, setOnSearchReady] = React.useState(false); const [onSearchReady, setOnSearchReady] = React.useState(false);
const [onExportReady, setOnExportReady] = React.useState(false); const [onExportReady, setOnExportReady] = React.useState(false);
const [searchCriteria, setSearchCriteria] = React.useState({ const [searchCriteria, setSearchCriteria] = React.useState({
@@ -89,6 +92,7 @@ const Index = () => {
} }


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
} }
@@ -96,6 +100,10 @@ const Index = () => {
setExportCriteria(input); setExportCriteria(input);
} }


function applyGridOnReady(input) {
setGridOnReady(input);
}

React.useEffect(() => { React.useEffect(() => {
if (Object.keys(exportCriteria).length > 0) { if (Object.keys(exportCriteria).length > 0) {
// console.log(exportCriteria) // console.log(exportCriteria)
@@ -185,40 +193,43 @@ const Index = () => {
/> />
</Grid> </Grid>
} }
<Grid item xs={12} md={12} lg={6} width="100%">
<Stack direction="row" justifyContent="flex-start" alignItems="center" spacing={2} sx={{ml:2,mt:1}} >
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<input
id="uploadFileBtn"
name="file"
type="file"
accept=".xlsx"
style={{ display: 'none' }}
disabled={waitImport}
onChange={(event) => {
readFile(event)
}}
/>
<label htmlFor="uploadFileBtn">
<Button
component="span"
variant="contained"
size="large"
{isGrantedAny(["MAINTAIN_GAZETTE_ISSUE"]) ?
<Grid item xs={12} md={12} lg={6} width="100%">
<Stack direction="row" justifyContent="flex-start" alignItems="center" spacing={2} sx={{ml:2,mt:1}} >
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<input
id="uploadFileBtn"
name="file"
type="file"
accept=".xlsx"
style={{ display: 'none' }}
disabled={waitImport} disabled={waitImport}
>
<Typography variant="h5">Upload Files</Typography>
</Button>
</label>
</ThemeProvider>
</Stack>
</Grid>
onChange={(event) => {
readFile(event)
}}
/>
<label htmlFor="uploadFileBtn">
<Button
component="span"
variant="contained"
size="large"
disabled={waitImport}
>
<Typography variant="h5">Upload Files</Typography>
</Button>
</label>
</ThemeProvider>
</Stack>
</Grid>
:null
}
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} lg={12} width="100%"> <Grid item xs={12} md={12} lg={12} width="100%">
<SearchForm <SearchForm
applySearch={applySearch} applySearch={applySearch}
comboData={comboData} comboData={comboData}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -230,7 +241,8 @@ const Index = () => {
content={false} content={false}
> >
<GazetteIssueTable <GazetteIssueTable
searchCriteria={searchCriteria}
searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 7
- 2
src/pages/Holiday/DataGrid.js 查看文件

@@ -9,13 +9,13 @@ import { dateStr } from "utils/DateUtils";


// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function HolidayTable({ recordList }) {
export default function HolidayTable({ recordList, applyGridOnReady }) {
const [rows, setRows] = React.useState(recordList); const [rows, setRows] = React.useState(recordList);


// const navigate = useNavigate() // const navigate = useNavigate()


useEffect(() => { useEffect(() => {
console.log(recordList)
// console.log(recordList)
setRows(recordList.records); setRows(recordList.records);
}, [recordList]); }, [recordList]);


@@ -48,8 +48,13 @@ export default function HolidayTable({ recordList }) {
rows={rows} rows={rows}
columns={columns} columns={columns}
customPageSize={20} customPageSize={20}
applyGridOnReady={applyGridOnReady}
// onRowDoubleClick={handleRowDoubleClick} // onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
// doLoad={React.useMemo(() => ({
// url: LIST_PROOF,
// params: _searchCriteria,
// }), [_searchCriteria])}
/> />
</div> </div>
); );

+ 2
- 1
src/pages/Holiday/SearchForm.js 查看文件

@@ -16,7 +16,7 @@ import {ThemeProvider} from "@emotion/react";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //




const SearchHolidayForm = ({ applySearch, comboData}) => {
const SearchHolidayForm = ({ applySearch, comboData, onGridReady}) => {
const [selectedYear, setSelectedYear] = React.useState([]); const [selectedYear, setSelectedYear] = React.useState([]);
// const [defaultYear, setDefaultYear] = React.useState(searchCriteria.year); // const [defaultYear, setDefaultYear] = React.useState(searchCriteria.year);
const [comboList, setComboList] = React.useState([]); const [comboList, setComboList] = React.useState([]);
@@ -114,6 +114,7 @@ const SearchHolidayForm = ({ applySearch, comboData}) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Search Search
</Button> </Button>


+ 35
- 24
src/pages/Holiday/index.js 查看文件

@@ -32,6 +32,7 @@ import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react"; import {ThemeProvider} from "@emotion/react";
import { dateStr_Year } from "utils/DateUtils"; import { dateStr_Year } from "utils/DateUtils";
import { notifySaveSuccess } from 'utils/CommonFunction'; import { notifySaveSuccess } from 'utils/CommonFunction';
import { isGrantedAny } from "auth/utils";


// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //


@@ -41,6 +42,8 @@ const Index = () => {
const [comboData, setComboData] = React.useState([]); const [comboData, setComboData] = React.useState([]);
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onSearchReady, setOnSearchReady] = React.useState(false); const [onSearchReady, setOnSearchReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);

// const navigate = useNavigate() // const navigate = useNavigate()
const [searchCriteria, setSearchCriteria] = React.useState({ const [searchCriteria, setSearchCriteria] = React.useState({
year: dateStr_Year(new Date()), year: dateStr_Year(new Date()),
@@ -97,9 +100,14 @@ const Index = () => {
} }


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
} }


function applyGridOnReady(input) {
setGridOnReady(input);
}

React.useEffect(() => { React.useEffect(() => {
if (attachments.length > 0) { if (attachments.length > 0) {
importHoliday(); importHoliday();
@@ -187,31 +195,32 @@ const Index = () => {
</Button> </Button>
</label> </label>
</ThemeProvider> </ThemeProvider>
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<input
id="uploadFileBtn"
name="file"
type="file"
accept=".xlsx"
style={{ display: 'none' }}
disabled={waitImport}
onChange={(event) => {
readFile(event)
}}
/>
<label htmlFor="uploadFileBtn">
<Button
component="span"
variant="contained"
size="large"
{isGrantedAny(["MAINTAIN_GAZETTE_ISSUE"]) ?
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<input
id="uploadFileBtn"
name="file"
type="file"
accept=".xlsx"
style={{ display: 'none' }}
disabled={waitImport} disabled={waitImport}
>
<Typography variant="h5">Upload Files</Typography>
</Button>
</label>
</ThemeProvider>
onChange={(event) => {
readFile(event)
}}
/>
<label htmlFor="uploadFileBtn">
<Button
component="span"
variant="contained"
size="large"
disabled={waitImport}
>
<Typography variant="h5">Upload Files</Typography>
</Button>
</label>
</ThemeProvider>
:null
}
</Stack> </Stack>
</Grid> </Grid>


@@ -222,6 +231,7 @@ const Index = () => {
// generateXML={generateXML} // generateXML={generateXML}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
comboData={comboData} comboData={comboData}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -234,6 +244,7 @@ const Index = () => {
> >
<HolidayTable <HolidayTable
recordList={record} recordList={record}
applyGridOnReady={applyGridOnReady}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 121
- 0
src/pages/JVM/index.js 查看文件

@@ -0,0 +1,121 @@
// import { useState } from 'react';

// material-ui
import {
Grid,
Typography,
Stack,
Paper,
Box,
CircularProgress,
Button
} from '@mui/material';
import * as React from "react";
import { GET_JVM_INFO } from "utils/ApiPathConst";
import axios from "axios";

import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'

const JVMDefault = () => {
const [jvmInfo, setJvmInfo] = React.useState(null);
const [loading, setLoading] = React.useState(true);
const [error, setError] = React.useState(null);
const fetchJvmInfo = () => {
setLoading(true);
setError(null);
axios.get(`${GET_JVM_INFO}`)
.then((response) => {
if (response.status === 200) {
console.log(response)
setJvmInfo(response.data);
}
})
.catch(error => {
setError(error);
setLoading(false);
});
};

React.useEffect(() => {
localStorage.setItem('searchCriteria', "");
setLoading(false);
}, []);

React.useEffect(() => {
if(jvmInfo != null) {
if (Object.keys(jvmInfo).length > 0 && jvmInfo !== undefined) {
setLoading(false);
}
}
}, [jvmInfo]);
const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: '100%',
height: '100%',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
};

return (
<Grid container sx={{ minHeight: '87vh', backgroundColor: "backgroundColor.default" }} direction="column">
<Grid item xs={12}>
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="space-between" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>
JVM Information
</Typography>
</Stack>
</div>
</Grid>
<Grid item xs={12} ml={15} mb={2} mt={2}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}
onClick={fetchJvmInfo}
disabled={loading}
>
<Typography variant="h5">JVM Info</Typography>
</Button>
</Grid>
<Grid item xs={12} ml={15} mb={2} mt={2}>
<Paper elevation={3} sx={{ p: 2, bgcolor: 'background.paper' }}>
{loading ? (
<Box display="flex" justifyContent="center" alignItems="center" minHeight={200}>
<CircularProgress />
</Box>
) : error ? (
<Typography color="error">Error: {error.message}</Typography>
) : jvmInfo ? (
<Box
component="pre"
sx={{
p: 2,
borderRadius: 1,
bgcolor: 'grey.100',
overflow: 'auto',
maxHeight: 400,
fontSize: '0.875rem',
lineHeight: 1.6
}}
>
{JSON.stringify(jvmInfo, null, 2)}
</Box>
) : (
<Typography>No data available</Typography>
)}
</Paper>
</Grid>
</Grid>
);
};

export default JVMDefault;

+ 38
- 22
src/pages/Message/Search/DataGrid.js 查看文件

@@ -5,13 +5,21 @@ import { useNavigate } from "react-router-dom";
import { FiDataGrid } from "components/FiDataGrid"; import { FiDataGrid } from "components/FiDataGrid";
import {useIntl} from "react-intl"; import {useIntl} from "react-intl";
import { clickableLink } from 'utils/CommonFunction'; import { clickableLink } from 'utils/CommonFunction';
import {GET_MSG_LIST} from "utils/ApiPathConst";

// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function MsgTable({ recordList }) {
const [rows, setRows] = React.useState(recordList);
export default function MsgTable({ searchCriteria, applyGridOnReady, applySearch}) {
const navigate = useNavigate() const navigate = useNavigate()
const intl = useIntl(); const intl = useIntl();


const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria);
React.useEffect(() => {
set_searchCriteria(searchCriteria);
}, [searchCriteria]);

const _sx = { const _sx = {
padding: "4 2 4 2", padding: "4 2 4 2",
boxShadow: 1, boxShadow: 1,
@@ -25,48 +33,56 @@ export default function MsgTable({ recordList }) {
'& .MuiDataGrid-footerContainer': { '& .MuiDataGrid-footerContainer': {
border: 1, border: 1,
borderColor: "#EEE" borderColor: "#EEE"
}
},
"& .MuiDataGrid-columnHeaderTitle": {
whiteSpace: "normal",
lineHeight: "normal"
},
"& .MuiDataGrid-columnHeader": {
// Forced to use important since overriding inline styles
height: "unset !important"
},
} }

React.useEffect(() => {
setRows(recordList);
}, [recordList]);

const handleEditClick = (params) => () => {
navigate('/msg/details/' + params.row.id);
};

const columns = [ const columns = [
{ {
id: 'sentDate', id: 'sentDate',
field: 'sentDate', field: 'sentDate',
headerName: intl.formatMessage({id: 'date'}), headerName: intl.formatMessage({id: 'date'}),
width: 160,
renderCell: (params) => {
return DateUtils.datetimeStr(params.row.sentDate);
width: 170,
valueGetter: (params) => {
return DateUtils.datetimeStr(params?.value);
}, },
}, },
{ {
field: 'actions',
headerName: intl.formatMessage({id: 'payId'}),
field: 'subject',
headerName: intl.formatMessage({id: 'subject'}),
flex: 1 , flex: 1 ,
cellClassName: 'actions',
cellClassName: 'subject',
renderCell: (params) => { renderCell: (params) => {
return clickableLink('/msg/details/' + params.row.id, params.row.subject); return clickableLink('/msg/details/' + params.row.id, params.row.subject);
}, },
}, },
]; ];


function handleEditClick(params) {
navigate('/msg/details/' + params.row.id);
}

return ( return (
<div style={{ minHeight: 400, width: '100%' }}>
<div style={{ width: '100%', overflowX: 'auto'}}>


<FiDataGrid <FiDataGrid
sx={_sx} sx={_sx}
rowHeight={80}
rows={rows}
columns={columns} columns={columns}
customPageSize={20}
customPageSize={10}
getRowHeight={() => 'auto'}
onRowDoubleClick={handleEditClick} onRowDoubleClick={handleEditClick}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
doLoad={React.useMemo(() => ({
url: GET_MSG_LIST,
params: _searchCriteria,
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 5
- 2
src/pages/Message/Search/SearchForm.js 查看文件

@@ -21,7 +21,7 @@ import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //




const SearchForm = ({ applySearch, searchCriteria }) => {
const SearchForm = ({ applySearch, searchCriteria, onGridReady }) => {
const intl = useIntl(); const intl = useIntl();
const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
@@ -64,7 +64,7 @@ const SearchForm = ({ applySearch, searchCriteria }) => {
sentDateTo = DateUtils.dateValue(toDateValue) sentDateTo = DateUtils.dateValue(toDateValue)
} }
const temp = { const temp = {
keywork: data.keywork,
keyword: data.keyword,
dateFrom: sentDateFrom, dateFrom: sentDateFrom,
dateTo: sentDateTo, dateTo: sentDateTo,
}; };
@@ -75,6 +75,8 @@ const SearchForm = ({ applySearch, searchCriteria }) => {
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
reset(); reset();
localStorage.setItem('searchCriteria',"")

} }




@@ -196,6 +198,7 @@ const SearchForm = ({ applySearch, searchCriteria }) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
aria-label={intl.formatMessage({id: 'submit'})} aria-label={intl.formatMessage({id: 'submit'})}
> >
<FormattedMessage id="submit"/> <FormattedMessage id="submit"/>


+ 46
- 24
src/pages/Message/Search/index.js 查看文件

@@ -5,9 +5,9 @@ import {
Stack Stack
} from '@mui/material'; } from '@mui/material';
import MainCard from "components/MainCard"; import MainCard from "components/MainCard";
import * as UrlUtils from "utils/ApiPathConst";
// import * as UrlUtils from "utils/ApiPathConst";
import * as React from "react"; import * as React from "react";
import * as HttpUtils from "utils/HttpUtils";
// import * as HttpUtils from "utils/HttpUtils";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
@@ -16,6 +16,7 @@ const SearchForm = Loadable(React.lazy(() => import('./SearchForm')));
const EventTable = Loadable(React.lazy(() => import('./DataGrid'))); const EventTable = Loadable(React.lazy(() => import('./DataGrid')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import {FormattedMessage} from "react-intl"; import {FormattedMessage} from "react-intl";
import { getSearchCriteria } from "auth/utils";


const BackgroundHead = { const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`, backgroundImage: `url(${titleBackgroundImg})`,
@@ -31,41 +32,58 @@ const BackgroundHead = {


const Index = () => { const Index = () => {


const [record,setRecord] = React.useState([]);
const [searchCriteria, setSearchCriteria] = React.useState({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
});
const [searchCriteria, setSearchCriteria] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
setOnReady(true);
}, [record]);
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []);


React.useEffect(() => { React.useEffect(() => {
loadGrid();
if(Object.keys(searchCriteria).length>0){
setOnReady(true);
}
}, [searchCriteria]); }, [searchCriteria]);


function loadGrid(){
HttpUtils.get({
url: UrlUtils.GET_MSG_LIST,
params: searchCriteria,
onSuccess: function(responseData){
setRecord(responseData);
}
});
}
// function loadGrid(){
// HttpUtils.get({
// url: UrlUtils.GET_MSG_LIST,
// params: searchCriteria,
// onSuccess: function(responseData){
// setRecord(responseData);
// }
// });
// }




function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
!onReady ? !onReady ?
<LoadingComponent/>
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
<Grid item>
<LoadingComponent />
</Grid>
</Grid>
: :
<Grid container sx={{minHeight: '85vh',backgroundColor:'#ffffff'}} direction="column">
<Grid container sx={{ minHeight: '95vh',backgroundColor: 'backgroundColor.default' }} direction="column">
<Grid item xs={12}> <Grid item xs={12}>
<div style={BackgroundHead}> <div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
@@ -78,8 +96,9 @@ const Index = () => {
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} lg={12}> <Grid item xs={12} md={12} lg={12}>
<SearchForm <SearchForm
applySearch={applySearch}
searchCriteria={searchCriteria}
applySearch={applySearch}
searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -90,7 +109,10 @@ const Index = () => {
sx={{width: "-webkit-fill-available"}} sx={{width: "-webkit-fill-available"}}
> >
<EventTable <EventTable
recordList={record}
// recordList={record}
searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 113
- 62
src/pages/Organization/DetailPage/OrganizationCard.js 查看文件

@@ -24,18 +24,20 @@ import { PNSPS_BUTTON_THEME } from "themes/buttonConst";
import { ThemeProvider } from "@emotion/react"; import { ThemeProvider } from "@emotion/react";
import { isGrantedAny } from "auth/utils"; import { isGrantedAny } from "auth/utils";


import {DatePicker} from "@mui/x-date-pickers/DatePicker";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import dayjs from "dayjs"; import dayjs from "dayjs";
import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
import { DemoItem } from "@mui/x-date-pickers/internals/demo";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => { const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
const intl = useIntl(); const intl = useIntl();
const [creditorConfirmPopUp, setCreditorConfirmPopUp] = React.useState(false); const [creditorConfirmPopUp, setCreditorConfirmPopUp] = React.useState(false);
const [nonCreditorConfirmPopUp, setNonCreditorConfirmPopUp] = React.useState(false); const [nonCreditorConfirmPopUp, setNonCreditorConfirmPopUp] = React.useState(false);
const [afterSendPopUp, setAfterSendPopUp] = React.useState(false);


const [currentUserData, setCurrentUserData] = useState({}); const [currentUserData, setCurrentUserData] = useState({});
const [overduePublicNotice, setOverduePublicNotice] = useState(0);
const [editMode, setEditMode] = useState(false); const [editMode, setEditMode] = useState(false);
const [createMode, setCreateMode] = useState(false); const [createMode, setCreateMode] = useState(false);
const [onReady, setOnReady] = useState(false); const [onReady, setOnReady] = useState(false);
@@ -44,7 +46,7 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
const [fromDate, setFromDate] = React.useState(null); const [fromDate, setFromDate] = React.useState(null);
const [currentFromDate, setCurrentFromDate] = React.useState(null); const [currentFromDate, setCurrentFromDate] = React.useState(null);
const [fromDateValue, setFromDateValue] = React.useState(null); const [fromDateValue, setFromDateValue] = React.useState(null);
const {register, handleSubmit, reset} = useForm()
const { register, handleSubmit, reset } = useForm()


React.useEffect(() => { React.useEffect(() => {
setFromDateValue(fromDate); setFromDateValue(fromDate);
@@ -54,14 +56,14 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
//if state data are ready and assign to different field //if state data are ready and assign to different field
// console.log(currentApplicationDetailData) // console.log(currentApplicationDetailData)
if (Object.keys(currentUserData).length > 0) { if (Object.keys(currentUserData).length > 0) {
console.log(currentUserData)
if(DateUtils.dateValue(currentUserData.brExpiryDate)>DateUtils.dateValue(minDate)){
// console.log(currentUserData)
if (DateUtils.dateValue(currentUserData.brExpiryDate) > DateUtils.dateValue(minDate)) {
setFromDate(currentUserData.brExpiryDate); setFromDate(currentUserData.brExpiryDate);
}else{
} else {
setCurrentFromDate(currentUserData.brExpiryDate); setCurrentFromDate(currentUserData.brExpiryDate);
// setErrorMsg("Please select a date after today.") // setErrorMsg("Please select a date after today.")
} }
setOnReady(true); setOnReady(true);
} }
}, [currentUserData]); }, [currentUserData]);
@@ -115,7 +117,7 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
let sentDateFrom = ""; let sentDateFrom = "";
if (fromDateValue == null) { if (fromDateValue == null) {
setErrorMsg(intl.formatMessage({ id: 'pleaseFillInBusinessRegCertValidityDate' })) setErrorMsg(intl.formatMessage({ id: 'pleaseFillInBusinessRegCertValidityDate' }))
}else{
} else {
sentDateFrom = DateUtils.dateValue(fromDateValue) sentDateFrom = DateUtils.dateValue(fromDateValue)
HttpUtils.post({ HttpUtils.post({
url: UrlUtils.POST_ORG_SAVE_PATH, url: UrlUtils.POST_ORG_SAVE_PATH,
@@ -123,7 +125,7 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
id: id > 0 ? id : null, id: id > 0 ? id : null,
enCompanyName: values.enCompanyName, enCompanyName: values.enCompanyName,
chCompanyName: values.chCompanyName, chCompanyName: values.chCompanyName,
orgShortName: values.orgShortName==="N/A"?"":values.orgShortName,
orgShortName: values.orgShortName === "N/A" ? "" : values.orgShortName,
brNo: values.brNo, brNo: values.brNo,
// brExpiryDate: values.brExpiryDate, // brExpiryDate: values.brExpiryDate,
brExpiryDate: sentDateFrom, brExpiryDate: sentDateFrom,
@@ -188,9 +190,9 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {


const onSubmit = (data) => { const onSubmit = (data) => {
let sentOrgShortName = ""; let sentOrgShortName = "";
if(data.orgShortName!=null && data.orgShortName!="" && data.orgShortName!="N/A"){
sentOrgShortName = data.orgShortName
if (sentOrgShortName.length <=24){
if (data.orgShortName != null && data.orgShortName != "" && data.orgShortName != "N/A") {
sentOrgShortName = data.orgShortName
if (sentOrgShortName.length <= 24) {
const temp = { const temp = {
orgShortName: sentOrgShortName, orgShortName: sentOrgShortName,
}; };
@@ -230,6 +232,17 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
}); });
} }


const sendDn_Overdue = () => {
setNonCreditorConfirmPopUp(false);
HttpUtils.get({
url: UrlUtils.GET_SEND_OVERDUE_CREDITOR_LIST + "/" + id,
onSuccess: (responseData) => {
setOverduePublicNotice(responseData.overduePublicNotice);
setAfterSendPopUp(true);
}
});
}

return ( return (
<MainCard elevation={0} <MainCard elevation={0}
border={false} border={false}
@@ -311,17 +324,32 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
</ThemeProvider> </ThemeProvider>
</Grid> </Grid>
: :
<Grid item sx={{ ml: 3, mr: 3 }}>
<ThemeProvider theme={PNSPS_BUTTON_THEME}>
<Button
variant="contained"
color="orange"
onClick={() => setCreditorConfirmPopUp(true)}
>
Mark as Credit Client
</Button>
</ThemeProvider>
</Grid>
<>
<Grid item sx={{ ml: 3, mr: 3 }}>
<ThemeProvider theme={PNSPS_BUTTON_THEME}>
<Button
variant="contained"
color="orange"
onClick={() => setCreditorConfirmPopUp(true)}
>
Mark as Credit Client
</Button>
</ThemeProvider>
</Grid>
{ isGrantedAny("MAINTAIN_DEMANDNOTE")?
<Grid item sx={{ ml: 3, mr: 3 }}>
<ThemeProvider theme={PNSPS_BUTTON_THEME}>
<Button
variant="contained"
color="primary"
onClick={() => sendDn_Overdue(true)}
>
Generate O&#47;S DN List
</Button>
</ThemeProvider>
</Grid> : null
}
</>
} }
</> </>
} }
@@ -396,18 +424,18 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
<Typography variant="pnspsFormParagraphBold">{FieldUtils.notNullFieldLabel("Expiry Date:")}</Typography> <Typography variant="pnspsFormParagraphBold">{FieldUtils.notNullFieldLabel("Expiry Date:")}</Typography>
</Grid> </Grid>
<Grid item xs={12} md={6} lg={6}> <Grid item xs={12} md={6} lg={6}>
{(!editMode && !createMode)?
{(!editMode && !createMode) ?
<TextField <TextField
fullWidth fullWidth
id="currentExDate" id="currentExDate"
// error={(fromDate===null)} // error={(fromDate===null)}
// type="date" // type="date"
name="currentExDate" name="currentExDate"
value={fromDate!=null?DateUtils.dateStr(fromDate):DateUtils.dateStr(currentFromDate)}
value={fromDate != null ? DateUtils.dateStr(fromDate) : DateUtils.dateStr(currentFromDate)}
disabled={true} disabled={true}
/>:
/> :
<LocalizationProvider dateAdapter={AdapterDayjs}> <LocalizationProvider dateAdapter={AdapterDayjs}>
<DemoItem components={['DatePicker']}>
<DemoItem components={['DatePicker']}>
<DatePicker <DatePicker
id="brExpiryDate" id="brExpiryDate"
name="brExpiryDate" name="brExpiryDate"
@@ -426,9 +454,9 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
onChange={(newValue) => { onChange={(newValue) => {
// console.log(newValue) // console.log(newValue)
// setErrorMsg("") // setErrorMsg("")
if(DateUtils.dateValue(newValue)>DateUtils.dateValue(new Date())){
if (DateUtils.dateValue(newValue) > DateUtils.dateValue(new Date())) {
setFromDate(newValue); setFromDate(newValue);
}else{
} else {
// setErrorMsg("Please select a date after today.") // setErrorMsg("Please select a date after today.")
} }
}} }}
@@ -438,19 +466,20 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
} }
</Grid> </Grid>
{ {
fromDate==null?
(!editMode && !createMode)?
<FormHelperText error id="helper-text-date">
Please select a date after today.
</FormHelperText>
:
fromDate == null ?
(!editMode && !createMode) ?
// <FormHelperText error id="helper-text-date">
// Please select a date after today.
// </FormHelperText>
null
:
<FormHelperText error id="helper-text-date"> <FormHelperText error id="helper-text-date">
{intl.formatMessage({ id: 'pleaseFillInBusinessRegCertValidityDate' })} {intl.formatMessage({ id: 'pleaseFillInBusinessRegCertValidityDate' })}
</FormHelperText> </FormHelperText>
:
:
null null
}
}
</Grid> </Grid>


</Grid> </Grid>
@@ -488,27 +517,6 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
})} })}
</Grid> </Grid>


<Grid item xs={12} lg={4} >
{FieldUtils.getComboField({
label: FieldUtils.notNullFieldLabel("Country:"),
valueName: "country",
disabled: (!editMode && !createMode),
dataList: ComboData.country,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
form: formik
})}
</Grid>

<Grid item xs={12} lg={4} >
{FieldUtils.getComboField({
label: FieldUtils.notNullFieldLabel("District:"),
valueName: "district",
disabled: (!editMode && !createMode),
dataList: ComboData.district,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
form: formik
})}
</Grid>
{ {
currentUserData.creditor ? currentUserData.creditor ?
<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
@@ -533,6 +541,28 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
})} })}
</Grid> </Grid>


<Grid item xs={12} lg={12} >
{FieldUtils.getProfileComboField({
label: "",
valueName: "district",
disabled: (!editMode && !createMode),
dataList: ComboData.district,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
form: formik
})}
</Grid>

<Grid item xs={12} lg={12} >
{FieldUtils.getProfileComboField({
label: "",
valueName: "country",
disabled: true,
dataList: ComboData.country,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
form: formik
})}
</Grid>

<Grid item lg={12} ></Grid> <Grid item lg={12} ></Grid>


</Grid> </Grid>
@@ -566,7 +596,7 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
{...register("orgShortName")} {...register("orgShortName")}
id='orgShortName' id='orgShortName'
label="Organisation Short Name" label="Organisation Short Name"
defaultValue={currentUserData.orgShortName!="N/A"?currentUserData.orgShortName:""}
defaultValue={currentUserData.orgShortName != "N/A" ? currentUserData.orgShortName : ""}
InputLabelProps={{ InputLabelProps={{
shrink: true shrink: true
}} }}
@@ -605,6 +635,27 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
</DialogActions> </DialogActions>
</Dialog> </Dialog>
</div> </div>
<div>
<Dialog
open={afterSendPopUp}
onClose={() => setAfterSendPopUp(false)}
PaperProps={{
sx: {
minWidth: '40vw',
maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
}
}}
>
<DialogTitle><Typography variant="h3">Info</Typography></DialogTitle>
<DialogContent style={{ display: 'flex', }}>
<Typography variant="h4" style={{ padding: '16px' }}>Overdue Public Notice count: {overduePublicNotice}</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setAfterSendPopUp(false)}><Typography variant="h5">OK</Typography></Button>
</DialogActions>
</Dialog>
</div>
</MainCard> </MainCard>
); );
}; };


+ 51
- 55
src/pages/Organization/DetailPage/OrganizationPubCard.js 查看文件

@@ -1,6 +1,6 @@
// material-ui // material-ui
import { import {
Grid, Button,
Grid, Button,
// Checkbox, FormControlLabel, // Checkbox, FormControlLabel,
Typography, Typography,
Dialog, DialogTitle, DialogContent, DialogActions, Dialog, DialogTitle, DialogContent, DialogActions,
@@ -20,9 +20,9 @@ const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingCo
import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
import { lazy } from 'react'; import { lazy } from 'react';
import { notifySaveSuccess } from 'utils/CommonFunction'; import { notifySaveSuccess } from 'utils/CommonFunction';
import {FormattedMessage, useIntl} from "react-intl";
import {PNSPS_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react";
import { FormattedMessage, useIntl } from "react-intl";
import { PNSPS_BUTTON_THEME } from "themes/buttonConst";
import { ThemeProvider } from "@emotion/react";


// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //


@@ -54,19 +54,19 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
enableReinitialize: true, enableReinitialize: true,
initialValues: currentUserData, initialValues: currentUserData,
validationSchema: yup.object().shape({ validationSchema: yup.object().shape({
addressLine1: yup.string().max(40).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine1'}))),
addressLine2: yup.string().max(40, displayErrorMsg(intl.formatMessage({id: 'noMoreThen40Words'}))),
addressLine3: yup.string().max(40, displayErrorMsg(intl.formatMessage({id: 'noMoreThen40Words'}))),
tel_countryCode: yup.string().min(3, displayErrorMsg(intl.formatMessage({id: 'requireDialingCode'}))),
phoneNumber: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'requiredValidNumber'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireContactNumber'}))),
addressLine1: yup.string().max(40).required(displayErrorMsg(intl.formatMessage({ id: 'validateAddressLine1' }))),
addressLine2: yup.string().max(40, displayErrorMsg(intl.formatMessage({ id: 'noMoreThen40Words' }))),
addressLine3: yup.string().max(40, displayErrorMsg(intl.formatMessage({ id: 'noMoreThen40Words' }))),
tel_countryCode: yup.string().min(3, displayErrorMsg(intl.formatMessage({ id: 'requireDialingCode' }))),
phoneNumber: yup.string().min(8, displayErrorMsg(intl.formatMessage({ id: 'requiredValidNumber' }))).required(displayErrorMsg(intl.formatMessage({ id: 'requireContactNumber' }))),
faxNumber: yup.string().min(8, displayErrorMsg(intl.formatMessage({ id: 'require8Number' }))).nullable(), faxNumber: yup.string().min(8, displayErrorMsg(intl.formatMessage({ id: 'require8Number' }))).nullable(),
}), }),
onSubmit: values => { onSubmit: values => {
if (values.country==null){
setErrorMsg(intl.formatMessage({id: 'pleaseFillInCountry'}))
if (values.country == null) {
setErrorMsg(intl.formatMessage({ id: 'pleaseFillInCountry' }))
} else { } else {
if (values.country.type =="hongKong" && values.district == null){
setErrorMsg(intl.formatMessage({id: 'pleaseFillInDistrict'}))
if (values.country.type == "hongKong" && values.district == null) {
setErrorMsg(intl.formatMessage({ id: 'pleaseFillInDistrict' }))
} else { } else {
HttpUtils.post({ HttpUtils.post({
url: UrlUtils.POST_PUB_ORG_SAVE_PATH, url: UrlUtils.POST_PUB_ORG_SAVE_PATH,
@@ -100,9 +100,9 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
} }
}); });


useEffect(()=>{
useEffect(() => {
setEditModeFun(editMode); setEditModeFun(editMode);
},[editMode]);
}, [editMode]);


useEffect(() => { useEffect(() => {
if (Object.keys(userData).length > 0) { if (Object.keys(userData).length > 0) {
@@ -188,7 +188,7 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
onClick={onEditClick} onClick={onEditClick}
color="success" color="success"
> >
< FormattedMessage id="edit" />
< FormattedMessage id="edit" />
</Button> </Button>
</ThemeProvider> </ThemeProvider>
</Grid> </Grid>
@@ -202,11 +202,11 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
<LoadingComponent /> <LoadingComponent />
: :
<Grid container spacing={1}> <Grid container spacing={1}>
<Grid item xs={12}>
{/* <Grid item xs={12}>
<Typography variant="h4" sx={{ mb: 2, mr: 3, borderBottom: "1px solid black" }}> <Typography variant="h4" sx={{ mb: 2, mr: 3, borderBottom: "1px solid black" }}>
<FormattedMessage id="organizationDetails" /> <FormattedMessage id="organizationDetails" />
</Typography> </Typography>
</Grid>
</Grid> */}
<Grid item xs={12}> <Grid item xs={12}>
<FormHelperText error id="helper-text-address1-signup"> <FormHelperText error id="helper-text-address1-signup">
<Typography variant="errorMessage1"> <Typography variant="errorMessage1">
@@ -216,27 +216,27 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
</Grid> </Grid>
<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{FieldUtils.getTextField({ {FieldUtils.getTextField({
label: intl.formatMessage({id: 'brNo'}) + ":",
label: intl.formatMessage({ id: 'brNo' }) + ":",
valueName: "brNo", valueName: "brNo",
disabled: true, disabled: true,
form: formik form: formik
})} })}
</Grid> </Grid>
<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{/* {FieldUtils.getTextField({
label: intl.formatMessage({id: 'creditorAccount'}) + ":",
valueName: "creditor",
disabled: true,
form: formik
})} */}
{FieldUtils.getTextField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({ id: 'expiryDate' }) + ":"),
valueName: "brExpiryDate",
disabled: true,
form: formik
})}
</Grid> </Grid>


<Grid item xs={12} lg={4} ></Grid> <Grid item xs={12} lg={4} ></Grid>


<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{FieldUtils.getTextField({ {FieldUtils.getTextField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({id: 'nameEng'}) + ":"),
label: FieldUtils.notNullFieldLabel(intl.formatMessage({ id: 'nameEng' }) + ":"),
valueName: "enCompanyName", valueName: "enCompanyName",
disabled: true, disabled: true,
form: formik form: formik
@@ -245,7 +245,7 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {


<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{FieldUtils.getTextField({ {FieldUtils.getTextField({
label: intl.formatMessage({id: 'nameChi'}) + ":",
label: intl.formatMessage({ id: 'nameChi' }) + ":",
valueName: "chCompanyName", valueName: "chCompanyName",
disabled: true, disabled: true,
form: formik form: formik
@@ -253,17 +253,12 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
</Grid> </Grid>


<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{FieldUtils.getTextField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({id: 'expiryDate'}) + ":"),
valueName: "brExpiryDate",
disabled: true,
form: formik
})}

</Grid> </Grid>


<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{FieldUtils.getTextField({ {FieldUtils.getTextField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({id: 'contactPerson'}) + ":"),
label: FieldUtils.notNullFieldLabel(intl.formatMessage({ id: 'contactPerson' }) + ":"),
valueName: "contactPerson", valueName: "contactPerson",
disabled: (!editMode && !createMode), disabled: (!editMode && !createMode),
form: formik form: formik
@@ -272,7 +267,7 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {


<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{FieldUtils.getPhoneField({ {FieldUtils.getPhoneField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({id: 'userContactNumber'}) + ":"),
label: FieldUtils.notNullFieldLabel(intl.formatMessage({ id: 'userContactNumber' }) + ":"),
valueName: { valueName: {
code: "tel_countryCode", code: "tel_countryCode",
num: "phoneNumber" num: "phoneNumber"
@@ -284,7 +279,7 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {


<Grid item xs={12} lg={4} > <Grid item xs={12} lg={4} >
{FieldUtils.getPhoneField({ {FieldUtils.getPhoneField({
label: intl.formatMessage({id: 'contactFaxNumber'}) + ":",
label: intl.formatMessage({ id: 'contactFaxNumber' }) + ":",
valueName: { valueName: {
code: "fax_countryCode", code: "fax_countryCode",
num: "faxNumber" num: "faxNumber"
@@ -294,34 +289,35 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
})} })}
</Grid> </Grid>


<Grid item xs={12} lg={4} >
{FieldUtils.getComboField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({id: 'country'}) + ":"),
valueName: "country",
<Grid item xs={12} lg={12} >
{FieldUtils.getAddressField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({ id: 'formAddress' }) + ":"),
valueName: ["addressLine1", "addressLine2", "addressLine3"],
disabled: (!editMode && !createMode), disabled: (!editMode && !createMode),
dataList: ComboData.country,
getOptionLabel: (option) => option.type? intl.formatMessage({ id: option.type }) : "",
form: formik form: formik
})} })}
</Grid> </Grid>


<Grid item xs={12} lg={4} >
{FieldUtils.getComboField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({id: 'district'}) + ":"),
<Grid item xs={12} lg={12} >
{FieldUtils.getProfileComboField({
// label: FieldUtils.notNullFieldLabel(""),
label: "",
valueName: "district", valueName: "district",
disabled: (!editMode && !createMode), disabled: (!editMode && !createMode),
dataList: ComboData.district, dataList: ComboData.district,
getOptionLabel: (option) => option.type? intl.formatMessage({ id: option.type }) : "",
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
form: formik form: formik
})} })}
</Grid> </Grid>


<Grid item xs={12} lg={12} > <Grid item xs={12} lg={12} >
{FieldUtils.getAddressField({
label: FieldUtils.notNullFieldLabel(intl.formatMessage({id: 'formAddress'}) + ":"),
valueName: ["addressLine1", "addressLine2", "addressLine3"],
disabled: (!editMode && !createMode),
{FieldUtils.getProfileComboField({
// label: FieldUtils.notNullFieldLabel(""),
label: "",
valueName: "country",
disabled: true,
dataList: ComboData.country,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
form: formik form: formik
})} })}
</Grid> </Grid>
@@ -348,7 +344,7 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
<Typography variant="h4" style={{ padding: '16px' }}>Are you sure mark as Credit Client?</Typography> <Typography variant="h4" style={{ padding: '16px' }}>Are you sure mark as Credit Client?</Typography>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setCreditorConfirmPopUp(false)}><Typography variant="h5">Cancel</Typography></Button>
<Button onClick={() => setCreditorConfirmPopUp(false)}><Typography variant="h5">Cancel</Typography></Button>
<Button onClick={() => markAsCreditor()}><Typography variant="h5">Confirm</Typography></Button> <Button onClick={() => markAsCreditor()}><Typography variant="h5">Confirm</Typography></Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
@@ -370,7 +366,7 @@ const OrganizationPubCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
<Typography variant="h4" style={{ padding: '16px' }}>Are you sure mark as Non-Credit Client?</Typography> <Typography variant="h4" style={{ padding: '16px' }}>Are you sure mark as Non-Credit Client?</Typography>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setNonCreditorConfirmPopUp(false)}><Typography variant="h5">Cancel</Typography></Button>
<Button onClick={() => setNonCreditorConfirmPopUp(false)}><Typography variant="h5">Cancel</Typography></Button>
<Button onClick={() => markAsNonCreditor()}><Typography variant="h5">Confirm</Typography></Button> <Button onClick={() => markAsNonCreditor()}><Typography variant="h5">Confirm</Typography></Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>


+ 14
- 12
src/pages/Organization/DetailPage_FromUser/OrganizationCard_loadFromUser.js 查看文件

@@ -310,19 +310,17 @@ const OrganizationCard_loadFromUser = ({ userData, userId }) => {
})} })}
</Grid> </Grid>


<Grid item xs={12} lg={4}>
{FieldUtils.getComboField({
label: FieldUtils.notNullFieldLabel("Country:"),
valueName: "country",
dataList: ComboData.country,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
<Grid item xs={12}>
{FieldUtils.getAddressField({
label: FieldUtils.notNullFieldLabel("Address:"),
valueName: ["addressLine1", "addressLine2", "addressLine3"],
form: formik form: formik
})} })}
</Grid> </Grid>


<Grid item xs={12} lg={4}>
<Grid item xs={12} lg={12}>
{FieldUtils.getComboField({ {FieldUtils.getComboField({
label: FieldUtils.notNullFieldLabel("District:"),
label: "",
valueName: "district", valueName: "district",
dataList: ComboData.district, dataList: ComboData.district,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "", getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
@@ -330,13 +328,17 @@ const OrganizationCard_loadFromUser = ({ userData, userId }) => {
})} })}
</Grid> </Grid>


<Grid item xs={12}>
{FieldUtils.getAddressField({
label: FieldUtils.notNullFieldLabel("Address:"),
valueName: ["addressLine1", "addressLine2", "addressLine3"],
<Grid item xs={12} lg={12}>
{FieldUtils.getComboField({
label: "",
valueName: "country",
disabled: true,
dataList: ComboData.country,
getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
form: formik form: formik
})} })}
</Grid> </Grid>

</Grid> </Grid>
} }
</form> </form>


+ 30
- 4
src/pages/Organization/SearchPage/OrganizationSearchForm.js 查看文件

@@ -8,7 +8,7 @@ import {
import MainCard from "components/MainCard"; import MainCard from "components/MainCard";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";


import { useState } from "react";
import { useState,useEffect } from "react";
import * as React from "react"; import * as React from "react";


import * as UrlUtils from "utils/ApiPathConst"; import * as UrlUtils from "utils/ApiPathConst";
@@ -19,11 +19,21 @@ import {ThemeProvider} from "@emotion/react";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //




const OrganizationSearchForm = ({ applySearch }) => {
const OrganizationSearchForm = ({ applySearch, onGridReady, searchCriteria }) => {


const [type, setType] = useState([]); const [type, setType] = useState([]);
const [creditorSelected, setCreditorSelected] = React.useState(ComboData.CreditorStatus[0]); const [creditorSelected, setCreditorSelected] = React.useState(ComboData.CreditorStatus[0]);
const { reset, register, handleSubmit } = useForm() const { reset, register, handleSubmit } = useForm()
const [onDownload, setOnDownload] = React.useState(false);
useEffect(() => {
if(searchCriteria.creditor!=undefined){
setCreditorSelected(ComboData.CreditorStatus.find(item => item.type === searchCriteria.creditor.toString()))
}else{
setCreditorSelected(ComboData.CreditorStatus[0]);
}
}, [searchCriteria]);

const onSubmit = (data) => { const onSubmit = (data) => {


let typeArray = []; let typeArray = [];
@@ -48,12 +58,23 @@ const OrganizationSearchForm = ({ applySearch }) => {
function resetForm() { function resetForm() {
setType([]); setType([]);
setCreditorSelected(ComboData.CreditorStatus[0]); setCreditorSelected(ComboData.CreditorStatus[0]);
reset();
reset({
brNo: "",
enCompanyName: "",
chCompanyName: "",
});
} }


const doExport=()=>{ const doExport=()=>{
setOnDownload(true)
HttpUtils.fileDownload({ HttpUtils.fileDownload({
url: UrlUtils.GET_ORG_EXPORT
url: UrlUtils.GET_ORG_EXPORT,
onResponse:()=>{
setOnDownload(false)
},
onError:()=>{
setOnDownload(false)
}
}); });
} }


@@ -80,6 +101,7 @@ const OrganizationSearchForm = ({ applySearch }) => {
{...register("brNo")} {...register("brNo")}
id='brNo' id='brNo'
label="BR No." label="BR No."
defaultValue={searchCriteria.brNo}
InputLabelProps={{ InputLabelProps={{
shrink: true shrink: true
}} }}
@@ -92,6 +114,7 @@ const OrganizationSearchForm = ({ applySearch }) => {
{...register("enCompanyName")} {...register("enCompanyName")}
id="enCompanyName" id="enCompanyName"
label="Name (English)" label="Name (English)"
defaultValue={searchCriteria.enCompanyName}
InputLabelProps={{ InputLabelProps={{
shrink: true shrink: true
}} }}
@@ -104,6 +127,7 @@ const OrganizationSearchForm = ({ applySearch }) => {
{...register("chCompanyName")} {...register("chCompanyName")}
id="chCompanyName" id="chCompanyName"
label="Name (Chinese)" label="Name (Chinese)"
defaultValue={searchCriteria.chCompanyName}
InputLabelProps={{ InputLabelProps={{
shrink: true shrink: true
}} }}
@@ -148,6 +172,7 @@ const OrganizationSearchForm = ({ applySearch }) => {
<Button <Button
variant="contained" variant="contained"
onClick={doExport} onClick={doExport}
disabled={onDownload}
> >
Export Export
</Button> </Button>
@@ -167,6 +192,7 @@ const OrganizationSearchForm = ({ applySearch }) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Submit Submit
</Button> </Button>


+ 10
- 4
src/pages/Organization/SearchPage/OrganizationTable.js 查看文件

@@ -11,7 +11,7 @@ import { clickableLink} from 'utils/CommonFunction';
import {GET_ORG_PATH} from "utils/ApiPathConst"; import {GET_ORG_PATH} from "utils/ApiPathConst";
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function OrganizationTable({ searchCriteria }) {
export default function OrganizationTable({ searchCriteria, applyGridOnReady, applySearch}) {
const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria);
const navigate = useNavigate() const navigate = useNavigate()


@@ -111,12 +111,18 @@ export default function OrganizationTable({ searchCriteria }) {
<div style={{ height: "fit-content", width: '100%' }}> <div style={{ height: "fit-content", width: '100%' }}>
<FiDataGrid <FiDataGrid
columns={columns} columns={columns}
customPageSize={5}
customPageSize={10}
onRowDoubleClick={handleRowDoubleClick} onRowDoubleClick={handleRowDoubleClick}
doLoad={{
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
// doLoad={{
// url: GET_ORG_PATH,
// params: _searchCriteria,
// }}
doLoad={React.useMemo(() => ({
url: GET_ORG_PATH, url: GET_ORG_PATH,
params: _searchCriteria, params: _searchCriteria,
}}
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 24
- 2
src/pages/Organization/SearchPage/index.js 查看文件

@@ -5,7 +5,7 @@ import {
import MainCard from "components/MainCard"; import MainCard from "components/MainCard";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import * as React from "react"; import * as React from "react";
import { getSearchCriteria } from "auth/utils";


// import LoadingComponent from "../extra-pages/LoadingComponent"; // import LoadingComponent from "../extra-pages/LoadingComponent";
// import SearchForm from "./OrganizationSearchForm"; // import SearchForm from "./OrganizationSearchForm";
@@ -32,13 +32,29 @@ const OrganizationSearchPage = () => {


const [searchCriteria, setSearchCriteria] = useState({}); const [searchCriteria, setSearchCriteria] = useState({});
const [onReady, setOnReady] = useState(false); const [onReady, setOnReady] = useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);

useEffect(() => {
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({})
}
}, []);


useEffect(() => { useEffect(() => {
setOnReady(true); setOnReady(true);
}, [searchCriteria]); }, [searchCriteria]);


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -59,7 +75,11 @@ const OrganizationSearchPage = () => {
</Grid> </Grid>
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} lg={12} sx={{ mb: -1 }}> <Grid item xs={12} md={12} lg={12} sx={{ mb: -1 }}>
<SearchForm applySearch={applySearch} />
<SearchForm
applySearch={applySearch}
onGridReady={onGridReady}
searchCriteria={searchCriteria}
/>
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
<Grid item xs={12} md={12} lg={12}> <Grid item xs={12} md={12} lg={12}>
@@ -69,6 +89,8 @@ const OrganizationSearchPage = () => {
> >
<EventTable <EventTable
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 1
- 1
src/pages/Payment/Details_GLD/DataGrid.js 查看文件

@@ -43,7 +43,7 @@ export default function SearchPublicNoticeTable({ recordList }) {
flex: 1, flex: 1,
renderCell: (params) => { renderCell: (params) => {
let appNo = params.row.appNo; let appNo = params.row.appNo;
console.log(params.row)
// console.log(params.row)
return <div style={{ margin: 4, textAlign:"left"}}>Gazette Supplement No. 6 <br/> return <div style={{ margin: 4, textAlign:"left"}}>Gazette Supplement No. 6 <br/>
{isORGLoggedIn()&&params.row.careOf!=null&&params.row.careOf!=""?<>{params.row.careOf}<br /></>:null} {isORGLoggedIn()&&params.row.careOf!=null&&params.row.careOf!=""?<>{params.row.careOf}<br /></>:null}
App No: {appNo}<br/> App No: {appNo}<br/>


+ 10
- 10
src/pages/Payment/Details_GLD/PaymentDetails.js 查看文件

@@ -9,15 +9,19 @@ import {
import * as React from "react"; import * as React from "react";
import * as FormatUtils from "utils/FormatUtils"; import * as FormatUtils from "utils/FormatUtils";
import * as PaymentStatus from "utils/statusUtils/PaymentStatus"; import * as PaymentStatus from "utils/statusUtils/PaymentStatus";
import * as DateUtils from "utils/DateUtils";
import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const MainCard = Loadable(React.lazy(() => import('components/MainCard'))); const MainCard = Loadable(React.lazy(() => import('components/MainCard')));
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
import DownloadIcon from '@mui/icons-material/Download'; import DownloadIcon from '@mui/icons-material/Download';
import {useIntl} from "react-intl";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const PaymentDetails = ({ formData,doPrint,onDownload }) => { const PaymentDetails = ({ formData,doPrint,onDownload }) => {


const intl = useIntl();
const [data, setData] = React.useState({}); const [data, setData] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
// const { locale } = intl;


React.useEffect(() => { React.useEffect(() => {
if (formData != null && formData != undefined && Object.keys(formData).length > 0) { if (formData != null && formData != undefined && Object.keys(formData).length > 0) {
@@ -89,7 +93,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => {
</Grid> </Grid>
<Grid item xs={6} md={5} sx={{ml:5, textAlign: "left" }}> <Grid item xs={6} md={5} sx={{ml:5, textAlign: "left" }}>
<FormLabel sx={{ color: "#000000" }}> <FormLabel sx={{ color: "#000000" }}>
{data.transDateStr + " (DD/MM/YYYY)"}
{DateUtils.dateFormat(data.transDateStr, intl.formatMessage({id: "dateStrFormat"})) +" ("+intl.formatMessage({id: "dateStrFormat"})+")"}
</FormLabel> </FormLabel>
</Grid> </Grid>
</Grid> </Grid>
@@ -131,7 +135,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => {
</Grid> </Grid>
<Grid item xs={6} md={5} sx={{ml:5, textAlign: "left" }}> <Grid item xs={6} md={5} sx={{ml:5, textAlign: "left" }}>
<FormLabel sx={{ color: "#000000" }}> <FormLabel sx={{ color: "#000000" }}>
{"HK$ " + FormatUtils.currencyFormat(data.payload?.amount)}
{"$ " + FormatUtils.currencyFormat(data.payload?.amount)}
</FormLabel> </FormLabel>
</Grid> </Grid>
</Grid> </Grid>
@@ -161,14 +165,10 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => {
</FormLabel> </FormLabel>
</Grid> </Grid>
<Grid xs={6} md={5} sx={{ml:5,textAlign: "left" }}> <Grid xs={6} md={5} sx={{ml:5,textAlign: "left" }}>
{onDownload?
<LoadingComponent disableText={true} alignItems="flex-start"/>
:
<Button className="printHidden" variant="contained" sx={{ mt:2 }} onClick={doPrint}>
<DownloadIcon/>
<Typography sx={{fontSize: "16px"}}>Download</Typography>
</Button>
}
<Button className="printHidden" variant="contained" disabled={onDownload} sx={{ mt:2 }} onClick={doPrint}>
<DownloadIcon/>
<Typography sx={{fontSize: "16px"}}>Download</Typography>
</Button>
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>


+ 1
- 1
src/pages/Payment/Details_GLD/index.js 查看文件

@@ -77,7 +77,7 @@ const Index = () => {
if (!responseData.data?.id) { if (!responseData.data?.id) {
navigate("/paymentPage/search"); navigate("/paymentPage/search");
} }
responseData.data["transDateStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "DD/MM/YYYY");
responseData.data["transDateStr"] = responseData.data.transDateTime;
responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss");
setItemList(responseData.paymentItemList) setItemList(responseData.paymentItemList)
setRecord(responseData.data); setRecord(responseData.data);


+ 1
- 1
src/pages/Payment/Details_Public/DataGrid.js 查看文件

@@ -81,7 +81,7 @@ export default function SearchPublicNoticeTable({ recordList }) {
{ {
id: 'fee', id: 'fee',
field: 'fee', field: 'fee',
headerName: intl.formatMessage({id: 'currencyAmount'}) + ' ($)',
headerName: intl.formatMessage({id: 'currencyAmount'}),
width: 200, width: 200,
valueGetter: (params) => { valueGetter: (params) => {
return (params?.value) ? "$ " + FormatUtils.currencyFormat(params?.value) : ""; return (params?.value) ? "$ " + FormatUtils.currencyFormat(params?.value) : "";


+ 43
- 20
src/pages/Payment/Details_Public/PaymentDetails.js 查看文件

@@ -9,6 +9,7 @@ import {
import * as React from "react"; import * as React from "react";
import * as FormatUtils from "utils/FormatUtils"; import * as FormatUtils from "utils/FormatUtils";
import * as PaymentStatus from "utils/statusUtils/PaymentStatus"; import * as PaymentStatus from "utils/statusUtils/PaymentStatus";
import * as DateUtils from "utils/DateUtils";
import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const MainCard = Loadable(React.lazy(() => import('components/MainCard'))); const MainCard = Loadable(React.lazy(() => import('components/MainCard')));
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
@@ -24,30 +25,56 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => {


React.useEffect(() => { React.useEffect(() => {
if (formData != null && formData != undefined && Object.keys(formData).length > 0) { if (formData != null && formData != undefined && Object.keys(formData).length > 0) {
console.log(formData)
// console.log(formData)
setData(formData); setData(formData);
} }
}, [formData]); }, [formData]);
React.useEffect(() => { React.useEffect(() => {
if (data != null && data != undefined && Object.keys(data).length > 0) { if (data != null && data != undefined && Object.keys(data).length > 0) {
console.log(data)
// console.log(data)
setOnReady(data != {}); setOnReady(data != {});
} }
}, [data]); }, [data]);


const getPaymentMethod=()=>{ const getPaymentMethod=()=>{
let paymentmethod = "" let paymentmethod = ""
// console.log(locale)
if (data?.payload!=null) { if (data?.payload!=null) {
paymentmethod = data.payload?.paymentdetail.paymentmethod; paymentmethod = data.payload?.paymentdetail.paymentmethod;
if("01" == paymentmethod) return "PPS";
if("02" == paymentmethod || "03" == paymentmethod) return "Credit Card";
if("04" == paymentmethod) return "FPS";
if (locale == "zh-HK"){
if("01" == paymentmethod) return "繳費靈";
if("02" == paymentmethod || "03" == paymentmethod) return "信用卡";
if("04" == paymentmethod) return "轉數快";
}
else if (locale == "zh-CN"){
if("01" == paymentmethod) return "缴费灵";
if("02" == paymentmethod || "03" == paymentmethod) return "信用卡";
if("04" == paymentmethod) return "转数快";
}
else {
if("01" == paymentmethod) return "PPS";
if("02" == paymentmethod || "03" == paymentmethod) return "Credit Card";
if("04" == paymentmethod) return "FPS";
}
} else { } else {
paymentmethod = data.payMethod; paymentmethod = data.payMethod;
if("01,PPSB,PPS" == paymentmethod) return "PPS";
if("02,BCMP,CreditCard" == paymentmethod || "03,BCMP,CreditCard" == paymentmethod) return "Credit Card";
if("04,BCFP,FPS" == paymentmethod) return "FPS";
if (locale == "zh-HK"){
if("01,PPSB,PPS" == paymentmethod) return "繳費靈";
if("02,BCMP,CreditCard" == paymentmethod || "03,BCMP,CreditCard" == paymentmethod) return "信用卡";
if("04,BCFP,FPS" == paymentmethod) return "轉數快";
}
else if (locale == "zh-CN"){
if("01,PPSB,PPS" == paymentmethod) return "缴费灵";
if("02,BCMP,CreditCard" == paymentmethod || "03,BCMP,CreditCard" == paymentmethod) return "信用卡";
if("04,BCFP,FPS" == paymentmethod) return "转数快";
}
else {
if("01,PPSB,PPS" == paymentmethod) return "PPS";
if("02,BCMP,CreditCard" == paymentmethod || "03,BCMP,CreditCard" == paymentmethod) return "Credit Card";
if("04,BCFP,FPS" == paymentmethod) return "FPS";
}
} }
return paymentmethod; return paymentmethod;
} }
@@ -109,7 +136,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => {
</Grid> </Grid>
<Grid item xs={6} md={6} sx={{textAlign: "left" }}> <Grid item xs={6} md={6} sx={{textAlign: "left" }}>
<FormLabel sx={{ fontSize: "16px", color: "#000000" }}> <FormLabel sx={{ fontSize: "16px", color: "#000000" }}>
{data.transDateStr + " (DD/MM/YYYY)"}
{DateUtils.dateFormat(data.transDateStr, intl.formatMessage({id: "dateStrFormat"})) +" ("+intl.formatMessage({id: "dateStrFormat"})+")"}
</FormLabel> </FormLabel>
</Grid> </Grid>
</Grid> </Grid>
@@ -151,7 +178,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => {
</Grid> </Grid>
<Grid item xs={6} md={6} sx={{textAlign: "left" }}> <Grid item xs={6} md={6} sx={{textAlign: "left" }}>
<FormLabel sx={{ fontSize: "16px", color: "#000000" }}> <FormLabel sx={{ fontSize: "16px", color: "#000000" }}>
{"HK$ " + FormatUtils.currencyFormat(data.payload?.amount?data.payload?.amount:data.payAmount)}
{"$ " + FormatUtils.currencyFormat(data.payload?.amount?data.payload?.amount:data.payAmount)}
</FormLabel> </FormLabel>
</Grid> </Grid>
</Grid> </Grid>
@@ -181,16 +208,12 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => {
</FormLabel> </FormLabel>
</Grid> </Grid>
<Grid item xs={6} md={5} sx={{textAlign: "left" }}> <Grid item xs={6} md={5} sx={{textAlign: "left" }}>
{onDownload?
<LoadingComponent disableText={true} alignItems="flex-start"/>
:
<Button className="printHidden" variant="contained" sx={{ mt:2 }} onClick={doPrint}>
<DownloadIcon/>
<Typography sx={{fontSize: "16px"}}>
<FormattedMessage id="download"/>
</Typography>
</Button>
}
<Button className="printHidden" variant="contained" disabled={onDownload} sx={{ mt:2 }} onClick={doPrint}>
<DownloadIcon/>
<Typography sx={{fontSize: "16px"}}>
<FormattedMessage id="download"/>
</Typography>
</Button>
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>


+ 6
- 6
src/pages/Payment/Details_Public/index.js 查看文件

@@ -59,9 +59,9 @@ const Index = () => {
React.useEffect(() => { React.useEffect(() => {
if (Object.keys(transactionData).length > 0) { if (Object.keys(transactionData).length > 0) {
console.log(transactionData)
console.log(itemList)
console.log(record)
// console.log(transactionData)
// console.log(itemList)
// console.log(record)
setOnReady(true); setOnReady(true);
} }
}, [transactionData]); }, [transactionData]);
@@ -102,21 +102,21 @@ const Index = () => {
"paymentId": params.id "paymentId": params.id
}, },
onSuccess: function(responseData2){ onSuccess: function(responseData2){
responseData2.data["transDateStr"] = DateUtils.dateFormat(responseData2.data.transDateTime, "DD/MM/YYYY");
responseData2.data["transDateStr"] = responseData2.data.transDateTime;
responseData2.data["transTimeStr"] = DateUtils.dateFormat(responseData2.data.transDateTime, "HH:mm:ss"); responseData2.data["transTimeStr"] = DateUtils.dateFormat(responseData2.data.transDateTime, "HH:mm:ss");
setResponeData(responseData2.transactionData) setResponeData(responseData2.transactionData)
setItemList(responseData2.paymentItemList) setItemList(responseData2.paymentItemList)
setRecord(responseData2.data); setRecord(responseData2.data);
}, },
onError: function(){ onError: function(){
responseData.data["transDateStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "DD/MM/YYYY");
responseData.data["transDateStr"] = responseData.data.transDateTime;
responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss");
setResponeData(responseData) setResponeData(responseData)


} }
}); });
}else{ }else{
responseData.data["transDateStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "DD/MM/YYYY");
responseData.data["transDateStr"] = responseData.data.transDateTime;
responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss");
setResponeData(responseData) setResponeData(responseData)
setItemList(responseData.paymentItemList) setItemList(responseData.paymentItemList)


+ 38
- 26
src/pages/Payment/FPS/AckPage.js 查看文件

@@ -104,7 +104,7 @@ const AckPage = () => {
onSuccess: function(responseData){ onSuccess: function(responseData){
localStorage.removeItem("webtoken"); localStorage.removeItem("webtoken");
localStorage.removeItem("transactionid"); localStorage.removeItem("transactionid");
responseData.data["transDateStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "DD/MM/YYYY");
responseData.data["transDateStr"] = DateUtils.dateFormat(responseData.data.transDateTime, intl.formatMessage({id: "dateStrFormat"}));
responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss");
setResponeDataData(responseData.transactionData) setResponeDataData(responseData.transactionData)
setItemList(responseData.paymentItemList) setItemList(responseData.paymentItemList)
@@ -202,7 +202,8 @@ const AckPage = () => {
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} spacing={2} sx={{ textAlign: "center" }}> <Grid item xs={12} md={12} spacing={2} sx={{ textAlign: "center" }}>
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
您的申請和付款已收到
{/* 您的申請和付款已收到 */}
<FormattedMessage id="MSG.paymentMsg"/>
</Typography> </Typography>
<Grid container justifyContent="center" direction="column" spacing={2} sx={{ p: 2 }} alignitems="stretch" > <Grid container justifyContent="center" direction="column" spacing={2} sx={{ p: 2 }} alignitems="stretch" >
<Grid item className="printOrder" xs={12} md={12} sx={{ pt: 2 }} style={{ height: '100%', order: 1 }}> <Grid item className="printOrder" xs={12} md={12} sx={{ pt: 2 }} style={{ height: '100%', order: 1 }}>
@@ -253,21 +254,22 @@ const AckPage = () => {
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >
<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> <Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
付款取消訊息:
{/* 付款取消訊息: */}
<FormattedMessage id="MSG.paymentCancelMsg1"/>
<br /><br /> <br /><br />
您的付款已被取消。我們收到了您的付款請求,但由於某些原因,付款無法完成。請注意以下事項:
<FormattedMessage id="MSG.paymentCancelMsg2"/>
<br /><br /> <br /><br />
如果您主動取消了支付,請確認並確保取消是您的意願。
<FormattedMessage id="MSG.paymentCancelMsg3"/>
<br /> <br />
如果付款被取消是由於系統問題或其他原因,請您嘗試以下解決方法:
<FormattedMessage id="MSG.paymentCancelMsg4"/>
<br /><br /> <br /><br />
檢查您的支付帳戶是否有任何異常或限制。
<FormattedMessage id="MSG.paymentCancelMsg5"/>
<br /> <br />
確保您的付款資訊準確無誤。
<FormattedMessage id="MSG.paymentCancelMsg6"/>
<br /> <br />
檢查您的網路連線是否正常。
<FormattedMessage id="MSG.paymentCancelMsg7"/>
<br /><br /> <br /><br />
如果您需要進一步的協助或有任何疑問,請隨時與我們聯繫,我們將盡快解決您的付款問題。謝謝!
<FormattedMessage id="MSG.paymentCancelMsg8"/>
</Typography> </Typography>
</Grid> </Grid>
</center> </center>
@@ -296,29 +298,39 @@ const AckPage = () => {
<Grid container justifyContent="flex-start" alignItems="center" > <Grid container justifyContent="flex-start" alignItems="center" >
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >

<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> <Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
付款失敗訊息:
<FormattedMessage id="MSG.paymentFailMsg1"/>
<br /><br /> <br /><br />
親愛的用戶,很遺憾地告訴您,您的付款操作未成功。我們在處理您的付款時遇到了問題。請您仔細檢查以下事項:
<FormattedMessage id="MSG.paymentFailMsg2"/>
<br /><br /> <br /><br />
您的支付帳戶餘額是否足夠。
<br />
您提供的付款資訊是否準確無誤。
<br />
請檢查您的網路連線是否正常。
<ul>
<li>
<FormattedMessage id="MSG.paymentFailMsg3"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg4"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg5"/>
</li>
</ul>
<br /><br /> <br /><br />
如果您已確認以上問題無誤,但付款失敗,請您嘗試以下解決方法:
<FormattedMessage id="MSG.paymentFailMsg6"/>
<br /><br /> <br /><br />
嘗試使用其他付款方式進行付款。
<br />
檢查您的支付帳戶是否有異常或限制。
<br />
聯絡我們的客服人員尋求協助。
<ul>
<li>
<FormattedMessage id="MSG.paymentFailMsg7"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg8"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg9"/>
</li>
</ul>
<br /><br /> <br /><br />
如果您需要進一步的協助或有任何疑問,請隨時與我們聯繫。非常抱歉給您帶來不便,我們將盡快解決您的付款問題。謝謝!
<FormattedMessage id="MSG.paymentFailMsg10"/>
</Typography> </Typography>

</Grid> </Grid>
</center> </center>
</Grid> </Grid>


+ 129
- 68
src/pages/Payment/FPS/FPS.js 查看文件

@@ -10,6 +10,9 @@ import * as HttpUtils from "utils/HttpUtils";
import * as UrlUtils from "utils/ApiPathConst"; import * as UrlUtils from "utils/ApiPathConst";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import FpsIcon from "assets/images/icons/fps.svg"; import FpsIcon from "assets/images/icons/fps.svg";
import expiredQrcodeEN from "assets/images/icons/expiredQrcodeEN.png";
import expiredQrcodeZH from "assets/images/icons/expiredQrcodeZH.png";
import expiredQrcodeCN from "assets/images/icons/expiredQrcodeCN.png";
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
// import {paymentPath} from "auth/utils"; // import {paymentPath} from "auth/utils";
import {currencyFormat} from "utils/FormatUtils"; import {currencyFormat} from "utils/FormatUtils";
@@ -19,7 +22,7 @@ import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));


import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import {FormattedMessage} from "react-intl";
import {FormattedMessage, useIntl} from "react-intl";
const BackgroundHead = { const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`, backgroundImage: `url(${titleBackgroundImg})`,
width: '100%', width: '100%',
@@ -30,15 +33,21 @@ const BackgroundHead = {
backgroundPosition: 'right' backgroundPosition: 'right'
} }



// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //


const Index = () => { const Index = () => {
const navigate = useNavigate() const navigate = useNavigate()
const location = useLocation(); const location = useLocation();
const intl = useIntl();
const { locale } = intl;


const [locationData, setLocationData] = React.useState({}); const [locationData, setLocationData] = React.useState({});
const [paymentData, setPaymentData] = React.useState({}); const [paymentData, setPaymentData] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [qrCodeTimeout, setqrCodeTimeout] = React.useState(false);
const [paymentStatusCode, setPaymentStatusCode] = React.useState("");
const [expiredQrcode, setExpiredQrcode] = React.useState(expiredQrcodeEN);
const [responeData, setResponeDataData] = React.useState({}); const [responeData, setResponeDataData] = React.useState({});
const [fpsTransctionData, setFpsTransctionData] = React.useState({}); const [fpsTransctionData, setFpsTransctionData] = React.useState({});
@@ -49,6 +58,7 @@ const Index = () => {
const [fpsqrcodeurlPrd, setFpsqrcodeurlPrd] = React.useState(""); const [fpsqrcodeurlPrd, setFpsqrcodeurlPrd] = React.useState("");
const [fpsqrcodeurlFps, setFpsqrcodeurlFps] = React.useState(""); const [fpsqrcodeurlFps, setFpsqrcodeurlFps] = React.useState("");
const [browserType, setBrowserType] = React.useState(""); const [browserType, setBrowserType] = React.useState("");
const [sysEnv, setSysEnv] = React.useState("");
const mobileBrowser = "Mobile"; const mobileBrowser = "Mobile";
const desktopBrowser = "Desktop"; const desktopBrowser = "Desktop";
@@ -69,12 +79,14 @@ const Index = () => {
if(Object.keys(location.state).length > 0){ if(Object.keys(location.state).length > 0){
// console.log (location.state) // console.log (location.state)
setLocationData(location.state) setLocationData(location.state)
setBrowserType(desktopBrowser)

if (/Android|webOS|iPhone|iPad|iPod|Opera Mini/i.test(navigator.userAgent)) { if (/Android|webOS|iPhone|iPad|iPod|Opera Mini/i.test(navigator.userAgent)) {
console.log('Mobile web browser');
// console.log('Mobile web browser');
setBrowserType(mobileBrowser) setBrowserType(mobileBrowser)
// setFpsqrcodeurl(openPASGUrl) // setFpsqrcodeurl(openPASGUrl)
} else { } else {
console.log('Desktop web browser');
// console.log('Desktop web browser');
setBrowserType(desktopBrowser) setBrowserType(desktopBrowser)
} }
} }
@@ -88,6 +100,17 @@ const Index = () => {
} }
}, [locationData]); }, [locationData]);


React.useEffect(() => {
// console.log (locationData)
if (locale === 'zh-HK'){
setExpiredQrcode(expiredQrcodeZH)
} else if (locale === 'en'){
setExpiredQrcode(expiredQrcodeEN)
} else {
setExpiredQrcode(expiredQrcodeCN)
}
}, [locale]);

React.useEffect(() => { React.useEffect(() => {
// console.log (paymentData) // console.log (paymentData)
if (Object.keys(paymentData).length > 0){ if (Object.keys(paymentData).length > 0){
@@ -159,6 +182,7 @@ const Index = () => {
*/ */
setResponeDataData(responseData) setResponeDataData(responseData)
const timeoutdatetime = responseData.fpsmerchanttimeoutdatetime const timeoutdatetime = responseData.fpsmerchanttimeoutdatetime
setSysEnv(responseData.sysEnv)
const searchString = "[UTC]"; const searchString = "[UTC]";
let convertedDateString = ""; let convertedDateString = "";
if ( timeoutdatetime.toString().includes(searchString) ){ if ( timeoutdatetime.toString().includes(searchString) ){
@@ -175,12 +199,18 @@ const Index = () => {
console.log(fpsqrcodeurl) console.log(fpsqrcodeurl)
console.log(fpsqrcodeurlwithFps) console.log(fpsqrcodeurlwithFps)
const openPASGUrl = pasgPath + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurl) + '&callback='
+ encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?TRANSACTION_ID='+transactionid+"&WEB_TOKEN="+webtoken+"&PAYMENT_ID="+localStorage.getItem("paymentId"));
const openPASGUrlPrd = pasgPathPrd + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurl) + '&callback='
+ encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?TRANSACTION_ID='+transactionid+"&WEB_TOKEN="+webtoken+"&PAYMENT_ID="+localStorage.getItem("paymentId"));
const openPASGUrl = pasgPath + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurlwithFps) + '&callback='
+ encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?&PAYMENT_ID='+localStorage.getItem("paymentId"));
const openPASGUrlPrd = pasgPathPrd + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurlwithFps) + '&callback='
+ encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?&PAYMENT_ID='+localStorage.getItem("paymentId"));
const openPASGUrlPrdFps = pasgPath + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurlwithFps) + '&callback=' const openPASGUrlPrdFps = pasgPath + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurlwithFps) + '&callback='
+ encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?TRANSACTION_ID='+transactionid+"&WEB_TOKEN="+webtoken+"&PAYMENT_ID="+localStorage.getItem("paymentId"));
+ encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?&PAYMENT_ID='+localStorage.getItem("paymentId"));
// const openPASGUrl = pasgPath + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurlwithFps) + '&callback='
// + encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?TRANSACTION_ID='+transactionid+"&WEB_TOKEN="+webtoken+"&PAYMENT_ID="+localStorage.getItem("paymentId"));
// const openPASGUrlPrd = pasgPathPrd + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurlwithFps) + '&callback='
// + encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?TRANSACTION_ID='+transactionid+"&WEB_TOKEN="+webtoken+"&PAYMENT_ID="+localStorage.getItem("paymentId"));
// const openPASGUrlPrdFps = pasgPath + '?pay_req_obj=' + encodeURIComponent(fpsqrcodeurlwithFps) + '&callback='
// + encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/fpscallback?TRANSACTION_ID='+transactionid+"&WEB_TOKEN="+webtoken+"&PAYMENT_ID="+localStorage.getItem("paymentId"));
setFpsqrcodeurl(openPASGUrl) setFpsqrcodeurl(openPASGUrl)
setFpsqrcodeurlPrd(openPASGUrlPrd) setFpsqrcodeurlPrd(openPASGUrlPrd)
setFpsqrcodeurlFps(openPASGUrlPrdFps) setFpsqrcodeurlFps(openPASGUrlPrdFps)
@@ -188,7 +218,7 @@ const Index = () => {
}); });


//testing //testing
// const timeoutdatetime = "2024-05-06T11:10:30Z[UTC]"
// const timeoutdatetime = "2024-11-18T07:04:35Z[UTC]"
// const convertedDateString = timeoutdatetime.replace("[UTC]", ""); // const convertedDateString = timeoutdatetime.replace("[UTC]", "");
// setFpsmerchanttimeoutdatetime(convertedDateString) // setFpsmerchanttimeoutdatetime(convertedDateString)
// setPaymentId("C202310268000681") // setPaymentId("C202310268000681")
@@ -196,7 +226,7 @@ const Index = () => {
// { // {
// "paymentid": "C202310268000681", // "paymentid": "C202310268000681",
// "paymentstatus": "INPR", // "paymentstatus": "INPR",
// "fpsmerchanttimeoutdatetime": "2024-05-06T11:10:30Z[UTC]",
// "fpsmerchanttimeoutdatetime": "2024-11-18T07:04:35Z[UTC]",
// "fpsqrcodeimgbase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAuyklEQVR4Xu3dfcy/d1nff2IAAAAASUVORK5CYII=", // "fpsqrcodeimgbase64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAuyklEQVR4Xu3dfcy/d1nff2IAAAAASUVORK5CYII=",
// "fpsqrcodeurl": "http://127.0.0.1:8080/api/payment/wallet/fps/enquiryfpspayload/vm.JKDDlTOavR3ASviSwUnS1Lw4-" // "fpsqrcodeurl": "http://127.0.0.1:8080/api/payment/wallet/fps/enquiryfpspayload/vm.JKDDlTOavR3ASviSwUnS1Lw4-"
// } // }
@@ -231,6 +261,7 @@ const Index = () => {
}, },
onSuccess: function(responseData){ onSuccess: function(responseData){
const paymentstatuscode = responseData.paymentdetail.result.paymentstatuscode; const paymentstatuscode = responseData.paymentdetail.result.paymentstatuscode;
setPaymentStatusCode(paymentstatuscode)
if (paymentstatuscode != "" && paymentstatuscode != "INPR" ){ if (paymentstatuscode != "" && paymentstatuscode != "INPR" ){
if (paymentstatuscode === 'APPR') { if (paymentstatuscode === 'APPR') {
// const timestamp = Date.now(); // const timestamp = Date.now();
@@ -249,7 +280,8 @@ const Index = () => {
} }
}, },
onError: function(){ onError: function(){
cancelPayment()
alert("ERROR")
// cancelPayment()
// clearInterval(currentTimer.current); // clearInterval(currentTimer.current);
} }
}); });
@@ -260,35 +292,43 @@ const Index = () => {
const timeOutDate = new Date(fpsmerchanttimeoutdatetime); const timeOutDate = new Date(fpsmerchanttimeoutdatetime);
const currentTime = new Date; const currentTime = new Date;
const timedowncount = Math.round((timeOutDate.getTime() - currentTime.getTime()) / 1000); const timedowncount = Math.round((timeOutDate.getTime() - currentTime.getTime()) / 1000);
setTimeDownCount(timedowncount);
// console.log(time) // console.log(time)
// console.log(timeOutDate) // console.log(timeOutDate)
// console.log(currentTime) // console.log(currentTime)
// console.log(timeOutDate.getTime()-currentTime.getTime()) // console.log(timeOutDate.getTime()-currentTime.getTime())
getPaymentStatus();
if (timeOutDate.getTime()<currentTime.getTime()){
// console.log("stop");
clearInterval(currentTimer.current);
cancelPayment()
if (browserType === desktopBrowser){
getPaymentStatus();
if (timeOutDate.getTime()<currentTime.getTime()){
// console.log("stop");
clearInterval(currentTimer.current);
setqrCodeTimeout(true)
setTimeDownCount(0);
cancelPayment()
}else{
setTimeDownCount(timedowncount);
}
} }
},[time]) },[time])


const cancelPayment = ()=>{ const cancelPayment = ()=>{
if (Object.keys(paymentData).length>0){ if (Object.keys(paymentData).length>0){
HttpUtils.post({
url: UrlUtils.CANCEL_PAYMENT_URL,
params:{
"transactionid": paymentData.transactionid,
"webtoken": paymentData.webtoken,
"paymentid": fpsTransctionData.paymentid
},
onSuccess: function(){
// navigate('/paymentPage/fps/ackpage');
let page = '/paymentPage/fps/ackpage';
let stateParams = { state: { transactionid: paymentData.transactionid} }
navigate(page, stateParams);
}
});
getPaymentStatus()
if (paymentStatusCode === "INPR"){
HttpUtils.post({
url: UrlUtils.CANCEL_PAYMENT_URL,
params:{
"transactionid": paymentData.transactionid,
"webtoken": paymentData.webtoken,
"paymentid": fpsTransctionData.paymentid
},
onSuccess: function(){
navigate('/paymentPage/fps/ackpage');
let page = '/paymentPage/fps/ackpage';
let stateParams = { state: { transactionid: paymentData.transactionid} }
navigate(page, stateParams);
}
});
}
} }
} }


@@ -330,6 +370,8 @@ const Index = () => {
<Grid item xs={12} md={12} > <Grid item xs={12} md={12} >


<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
<FormattedMessage id="payAlert"/>
<br /><br />
<img src={FpsIcon} width="80" height="80" alt="FPS"></img> <img src={FpsIcon} width="80" height="80" alt="FPS"></img>
<br /> <br />
<FormattedMessage id="payTotalDeatail"/> <FormattedMessage id="payTotalDeatail"/>
@@ -338,50 +380,69 @@ const Index = () => {
</Typography> </Typography>
{browserType==mobileBrowser? {browserType==mobileBrowser?
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
<Button
component="span"
variant="contained"
size="large"
color="primary"
onClick={()=>{
mobliePayment();
}}
sx={{ m: 4 }}
>請選擇支付程式付款-Testing</Button>
<Button
component="span"
variant="contained"
size="large"
color="primary"
onClick={()=>{
mobliePaymentPrd();
}}
sx={{ m: 4 }}
>請選擇支付程式付款-PRD</Button>
<Button
component="span"
variant="contained"
size="large"
color="primary"
onClick={()=>{
mobliePaymentFps();
}}
sx={{ m: 4 }}
>請選擇支付程式付款-fps prefix</Button>
{
sysEnv=="prod"?
<Button
component="span"
variant="contained"
size="large"
color="primary"
onClick={()=>{
mobliePaymentPrd();
}}
sx={{ m: 4 }}
>請選擇支付程式付款</Button>
:
<>
<Button
component="span"
variant="contained"
size="large"
color="primary"
onClick={()=>{
mobliePayment();
}}
sx={{ m: 4 }}
>請選擇支付程式付款-Testing</Button>
<Button
component="span"
variant="contained"
size="large"
color="primary"
onClick={()=>{
mobliePaymentFps();
}}
sx={{ m: 4 }}
>請選擇支付程式付款-fps prefix</Button>
</>
}
</Typography> </Typography>
: :
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
請掃描以下二維碼
<FormattedMessage id="fpsQrcodeTitle1"/>
<br /> <br />
<img src={fpsTransctionData.fpsqrcodeimgbase64} alt="QR Code"/>
{
!qrCodeTimeout?
<img src={fpsTransctionData.fpsqrcodeimgbase64} alt="QR Code"/>
:<img src={expiredQrcode} alt="Expired QR Code"/>
}
<br /> <br />
{"["+paymentId+"]"} {"["+paymentId+"]"}
<br/> <br/>
二維碼有效期限3分鐘
<br />
請在規定時間內完成付款流程
<br />
{"剩餘時間: "+timeDownCount+ "秒"}
{
timeDownCount<=0?
<FormattedMessage id="fpsQrcodeExpired"/>:
<>
<FormattedMessage id="fpsQrcodeTitle2"/>
<br />
<FormattedMessage id="fpsQrcodeTitle3"/>
<br />
<FormattedMessage id="fpsQrcodeTitle4"/>&nbsp;
{timeDownCount}&nbsp;
<FormattedMessage id="fpsQrcodeTitle5"/>
</>
}
</Typography> </Typography>
} }
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>


+ 1
- 1
src/pages/Payment/FPS/FPSTest.js 查看文件

@@ -312,7 +312,7 @@ const Index = () => {
<br/> <br/>
二維碼有效期限3分鐘 二維碼有效期限3分鐘
<br /> <br />
請在規定時間內完成付款流程
請在規定時間內完成付款流程
<br /> <br />
{"剩餘時間:"+timeDownCount} {"剩餘時間:"+timeDownCount}
</Typography> </Typography>


+ 50
- 40
src/pages/Payment/FPS/fpscallback.js 查看文件

@@ -76,22 +76,22 @@ const Fpscallback = () => {


const loadForm = () => { const loadForm = () => {
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
let transactionid = params.get("TRANSACTION_ID")
let webtoken = params.get("WEB_TOKEN")
// let transactionid = params.get("TRANSACTION_ID")
// let webtoken = params.get("WEB_TOKEN")
let paymentId = params.get("PAYMENT_ID") let paymentId = params.get("PAYMENT_ID")
paymentId = paymentId.split('?is_successful')[0]; paymentId = paymentId.split('?is_successful')[0];


console.log(transactionid)
console.log(webtoken)
// console.log(transactionid)
// console.log(webtoken)
console.log(paymentId) console.log(paymentId)


HttpUtils.post({ HttpUtils.post({
url: UrlUtils.PAYMENT_CALLBACK_STATUS_API, url: UrlUtils.PAYMENT_CALLBACK_STATUS_API,
params:{ params:{
"apprefid": transactionid,
"webtoken": webtoken,
// "apprefid": transactionid,
// "webtoken": webtoken,
"paymentId": paymentId, "paymentId": paymentId,
"transactionid":Number(transactionid)
// "transactionid":Number(transactionid)
}, },
onSuccess: function(responseData){ onSuccess: function(responseData){
setResponeDataData(responseData) setResponeDataData(responseData)
@@ -99,7 +99,7 @@ const Fpscallback = () => {
localStorage.removeItem("webtoken"); localStorage.removeItem("webtoken");
localStorage.removeItem("transactionid"); localStorage.removeItem("transactionid");
} }
responseData.data["transDateStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "DD/MM/YYYY");
responseData.data["transDateStr"] = responseData.data.transDateTime;
responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss");
setResponeDataData(responseData.transactionData) setResponeDataData(responseData.transactionData)
setItemList(responseData.paymentItemList) setItemList(responseData.paymentItemList)
@@ -191,7 +191,7 @@ const Fpscallback = () => {
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} spacing={2} sx={{ textAlign: "center" }}> <Grid item xs={12} md={12} spacing={2} sx={{ textAlign: "center" }}>
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
您的申請和付款已收到
<FormattedMessage id="MSG.paymentMsg"/>
</Typography> </Typography>
<Grid container justifyContent="center" direction="column" spacing={2} sx={{ p: 2 }} alignitems="stretch" > <Grid container justifyContent="center" direction="column" spacing={2} sx={{ p: 2 }} alignitems="stretch" >
<Grid item className="printOrder" xs={12} md={12} sx={{ pt: 2 }} style={{ height: '100%', order: 1 }}> <Grid item className="printOrder" xs={12} md={12} sx={{ pt: 2 }} style={{ height: '100%', order: 1 }}>
@@ -242,21 +242,21 @@ const Fpscallback = () => {
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >
<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> <Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
付款取消訊息:
<br /><br />
您的付款已被取消。我們收到了您的付款請求,但由於某些原因,付款無法完成。請注意以下事項:
<br /><br />
如果您主動取消了支付,請確認並確保取消是您的意願。
<br />
如果付款被取消是由於系統問題或其他原因,請您嘗試以下解決方法:
<br /><br />
檢查您的支付帳戶是否有任何異常或限制。
<br />
確保您的付款資訊準確無誤。
<br />
檢查您的網路連線是否正常。
<br /><br />
如果您需要進一步的協助或有任何疑問,請隨時與我們聯繫,我們將盡快解決您的付款問題。謝謝!
<FormattedMessage id="MSG.paymentCancelMsg1"/>
<br /><br />
<FormattedMessage id="MSG.paymentCancelMsg2"/>
<br /><br />
<FormattedMessage id="MSG.paymentCancelMsg3"/>
<br />
<FormattedMessage id="MSG.paymentCancelMsg4"/>
<br /><br />
<FormattedMessage id="MSG.paymentCancelMsg5"/>
<br />
<FormattedMessage id="MSG.paymentCancelMsg6"/>
<br />
<FormattedMessage id="MSG.paymentCancelMsg7"/>
<br /><br />
<FormattedMessage id="MSG.paymentCancelMsg8"/>
</Typography> </Typography>
</Grid> </Grid>
</center> </center>
@@ -285,29 +285,39 @@ const Fpscallback = () => {
<Grid container justifyContent="flex-start" alignItems="center" > <Grid container justifyContent="flex-start" alignItems="center" >
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >

<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> <Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
付款失敗訊息:
<FormattedMessage id="MSG.paymentFailMsg1"/>
<br /><br /> <br /><br />
親愛的用戶,很遺憾地告訴您,您的付款操作未成功。我們在處理您的付款時遇到了問題。請您仔細檢查以下事項:
<FormattedMessage id="MSG.paymentFailMsg2"/>
<br /><br /> <br /><br />
您的支付帳戶餘額是否足夠。
<br />
您提供的付款資訊是否準確無誤。
<br />
請檢查您的網路連線是否正常。
<ul>
<li>
<FormattedMessage id="MSG.paymentFailMsg3"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg4"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg5"/>
</li>
</ul>
<br /><br /> <br /><br />
如果您已確認以上問題無誤,但付款失敗,請您嘗試以下解決方法:
<FormattedMessage id="MSG.paymentFailMsg6"/>
<br /><br /> <br /><br />
嘗試使用其他付款方式進行付款。
<br />
檢查您的支付帳戶是否有異常或限制。
<br />
聯絡我們的客服人員尋求協助。
<ul>
<li>
<FormattedMessage id="MSG.paymentFailMsg7"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg8"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg9"/>
</li>
</ul>
<br /><br /> <br /><br />
如果您需要進一步的協助或有任何疑問,請隨時與我們聯繫。非常抱歉給您帶來不便,我們將盡快解決您的付款問題。謝謝!
<FormattedMessage id="MSG.paymentFailMsg10"/>
</Typography> </Typography>

</Grid> </Grid>
</center> </center>
</Grid> </Grid>


+ 7
- 7
src/pages/Payment/MultiPaymentWindow.js 查看文件

@@ -64,7 +64,7 @@ const MultiPaymentWindow = (props) => {
// console.log(props.transactionData) // console.log(props.transactionData)
if(Object.keys(props.transactionData).length > 0){ if(Object.keys(props.transactionData).length > 0){
setLoadtTransactionData(props.transactionData) setLoadtTransactionData(props.transactionData)
console.log(props.browserType)
// console.log(props.browserType)
} }
}, [props.transactionData]); }, [props.transactionData]);


@@ -292,7 +292,7 @@ const MultiPaymentWindow = (props) => {
<DialogContent> <DialogContent>
<DialogContentText> <DialogContentText>
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "left", ml:1}}> <FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "left", ml:1}}>
<FormattedMessage id="paymentProcessLimited"/>
<FormattedMessage id="paymentProcessLimited"/>
</FormLabel> </FormLabel>
<Grid item xs={12} md={12} sx={{ pt: 2 }} style={{ height: '100%' }} width="100%"> <Grid item xs={12} md={12} sx={{ pt: 2 }} style={{ height: '100%' }} width="100%">
<Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} >
@@ -304,7 +304,7 @@ const MultiPaymentWindow = (props) => {
</Typography> </Typography>


{/* <Typography variant="h5" sx={{ textAlign: "left" }}> {/* <Typography variant="h5" sx={{ textAlign: "left" }}>
付金額: HK$ {FormatUtils.currencyFormat(props.totalAmount)}
金額: HK$ {FormatUtils.currencyFormat(props.totalAmount)}
</Typography> */} </Typography> */}
{!props.onReady ? {!props.onReady ?
<LoadingComponent /> <LoadingComponent />
@@ -373,7 +373,7 @@ const MultiPaymentWindow = (props) => {
</Grid>: </Grid>:
<Grid container direction="row" justifyContent="center" alignItems="center"> <Grid container direction="row" justifyContent="center" alignItems="center">
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "center"}}> <FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "center"}}>
<FormattedMessage id="paymentMethodNotAvailable"/>
<FormattedMessage id="paymentMethodNotAvailable"/>
</FormLabel> </FormLabel>
</Grid> </Grid>
} }
@@ -381,12 +381,12 @@ const MultiPaymentWindow = (props) => {
<Grid item xs={12} md={12}> <Grid item xs={12} md={12}>
<Grid container > <Grid container >
<Grid item> <Grid item>
<Typography variant="pnspsFormParagraphBold" sx={{ color: "#000000", textAlign: "left" }}>
<FormattedMessage id="payTotal"/>(HK$):&nbsp;
<Typography variant="h5" sx={{ color: "#000000", textAlign: "left" }}>
<FormattedMessage id="payTotal"/>&nbsp;($):&nbsp;
</Typography> </Typography>
</Grid> </Grid>
<Grid item> <Grid item>
<Typography variant="pnspsFormParagraphBold" sx={{color: "#000000", textAlign: "left" }}>
<Typography variant="h5" sx={{color: "#000000", textAlign: "left" }}>
{" HK$ " + FormatUtils.currencyFormat(props.totalAmount)} {" HK$ " + FormatUtils.currencyFormat(props.totalAmount)}
</Typography> </Typography>
</Grid> </Grid>


+ 24
- 14
src/pages/Payment/PaymentCallback.js 查看文件

@@ -123,7 +123,7 @@ const Index = () => {
localStorage.removeItem("webtoken"); localStorage.removeItem("webtoken");
localStorage.removeItem("transactionid"); localStorage.removeItem("transactionid");
} }
responseData.data["transDateStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "DD/MM/YYYY");
responseData.data["transDateStr"] = responseData.data.transDateTime;
responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss");
setResponeDataData(responseData.transactionData) setResponeDataData(responseData.transactionData)
setItemList(responseData.paymentItemList) setItemList(responseData.paymentItemList)
@@ -294,29 +294,39 @@ const Index = () => {
<Grid container justifyContent="flex-start" alignItems="center" > <Grid container justifyContent="flex-start" alignItems="center" >
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >

<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> <Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
<FormattedMessage id="MSG.paymentFailMsg1"/> <FormattedMessage id="MSG.paymentFailMsg1"/>
<br /><br /> <br /><br />
<FormattedMessage id="MSG.paymentFailMsg2"/> <FormattedMessage id="MSG.paymentFailMsg2"/>
<br /><br /> <br /><br />
<FormattedMessage id="MSG.paymentFailMsg3"/>
<br />
<FormattedMessage id="MSG.paymentFailMsg4"/>
<br />
<FormattedMessage id="MSG.paymentFailMsg5"/>
<ul>
<li>
<FormattedMessage id="MSG.paymentFailMsg3"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg4"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg5"/>
</li>
</ul>
<br /><br /> <br /><br />
<FormattedMessage id="MSG.paymentFailMsg6"/> <FormattedMessage id="MSG.paymentFailMsg6"/>
<br /><br /> <br /><br />
<FormattedMessage id="MSG.paymentFailMsg7"/>
<br />
<FormattedMessage id="MSG.paymentFailMsg8"/>
<br />
<FormattedMessage id="MSG.paymentFailMsg9"/>
<ul>
<li>
<FormattedMessage id="MSG.paymentFailMsg7"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg8"/>
</li>
<li>
<FormattedMessage id="MSG.paymentFailMsg9"/>
</li>
</ul>
<br /><br /> <br /><br />
<FormattedMessage id="MSG.paymentFailMsg10"/> <FormattedMessage id="MSG.paymentFailMsg10"/>
</Typography>

</Typography>
</Grid> </Grid>
</center> </center>
</Grid> </Grid>


+ 11
- 5
src/pages/Payment/Search_GLD/DataGrid.js 查看文件

@@ -9,7 +9,7 @@ import { FiDataGrid } from "components/FiDataGrid";
import { clickableLink } from 'utils/CommonFunction'; import { clickableLink } from 'utils/CommonFunction';
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchPaymentTable({ searchCriteria }) {
export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, applySearch}) {
const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria);
const navigate = useNavigate() const navigate = useNavigate()


@@ -96,10 +96,16 @@ export default function SearchPaymentTable({ searchCriteria }) {
columns={columns} columns={columns}
customPageSize={10} customPageSize={10}
onRowDoubleClick={handleEditClick} onRowDoubleClick={handleEditClick}
doLoad={{
url:PAYMENT_LIST,
params:_searchCriteria,
}}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
// doLoad={{
// url:PAYMENT_LIST,
// params:_searchCriteria,
// }}
doLoad={React.useMemo(() => ({
url: PAYMENT_LIST,
params: _searchCriteria,
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 18
- 2
src/pages/Payment/Search_GLD/SearchForm.js 查看文件

@@ -19,7 +19,7 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => {


const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
@@ -31,6 +31,18 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy");
const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy");


React.useEffect(() => {
if(searchCriteria.status!=undefined){
if(searchCriteria.status === ""){
ComboData.paymentStatus[0]
}else{
setStatus(ComboData.paymentStatus.find(item => item.type === searchCriteria.status))
}
}else{
setStatus(ComboData.paymentStatus[0])
}
}, [searchCriteria]);

React.useEffect(() => { React.useEffect(() => {
setFromDateValue(minDate); setFromDateValue(minDate);
}, [minDate]); }, [minDate]);
@@ -62,7 +74,10 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
setStatus(ComboData.paymentStatus[0]); setStatus(ComboData.paymentStatus[0]);
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
reset();
reset({
code:"",
transNo:""
});
} }




@@ -215,6 +230,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
disabled={onGridReady}
> >
Submit Submit
</Button> </Button>


+ 26
- 6
src/pages/Payment/Search_GLD/index.js 查看文件

@@ -7,6 +7,7 @@ import {
import MainCard from "components/MainCard"; import MainCard from "components/MainCard";
import * as React from "react"; import * as React from "react";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import { getSearchCriteria } from "auth/utils";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
@@ -28,18 +29,34 @@ const BackgroundHead = {


const Index = () => { const Index = () => {


const [searchCriteria, setSearchCriteria] = React.useState({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
});
const [searchCriteria, setSearchCriteria] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);

React.useEffect(() => {
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []);


React.useEffect(() => { React.useEffect(() => {
setOnReady(true); setOnReady(true);
}, [searchCriteria]); }, [searchCriteria]);


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -63,8 +80,9 @@ const Index = () => {
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} lg={12} sx={{mb:-1}}> <Grid item xs={12} md={12} lg={12} sx={{mb:-1}}>
<SearchForm <SearchForm
applySearch={applySearch}
searchCriteria={searchCriteria}
applySearch={applySearch}
searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -76,6 +94,8 @@ const Index = () => {
> >
<EventTable <EventTable
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 10
- 4
src/pages/Payment/Search_Public/DataGrid.js 查看文件

@@ -14,7 +14,7 @@ import { clickableLink } from 'utils/CommonFunction';
import {PAYMENT_LIST} from "utils/ApiPathConst"; import {PAYMENT_LIST} from "utils/ApiPathConst";
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchPublicNoticeTable({ searchCriteria }) {
export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnReady, applySearch }) {
const navigate = useNavigate() const navigate = useNavigate()
const theme = useTheme(); const theme = useTheme();
const isMdOrLg = useMediaQuery(theme.breakpoints.up('md')); const isMdOrLg = useMediaQuery(theme.breakpoints.up('md'));
@@ -94,7 +94,7 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
{ {
id: 'payAmount', id: 'payAmount',
field: 'payAmount', field: 'payAmount',
headerName: intl.formatMessage({id: 'currencyAmount'}) + ' ($)',
headerName: intl.formatMessage({id: 'currencyAmount'}),
width: 150, width: 150,
valueGetter: (params) => { valueGetter: (params) => {
return (params?.value) ? "$ " + FormatUtils.currencyFormat(params?.value) : ""; return (params?.value) ? "$ " + FormatUtils.currencyFormat(params?.value) : "";
@@ -110,10 +110,16 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
columns={columns} columns={columns}
customPageSize={10} customPageSize={10}
onRowDoubleClick={handleEditDoubleClick} onRowDoubleClick={handleEditDoubleClick}
doLoad={{
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
// doLoad={{
// url: PAYMENT_LIST,
// params: _searchCriteria,
// }}
doLoad={React.useMemo(() => ({
url: PAYMENT_LIST, url: PAYMENT_LIST,
params: _searchCriteria, params: _searchCriteria,
}}
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 9
- 3
src/pages/Payment/Search_Public/SearchForm.js 查看文件

@@ -21,11 +21,11 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => {
const intl = useIntl(); const intl = useIntl();
const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
const [status, setStatus] = React.useState(ComboData.paymentStatus[0]);
const [status, setStatus] = React.useState(searchCriteria.status!=undefined?ComboData.paymentStatus.find(item => item.type === searchCriteria.status):ComboData.paymentStatus[0]);


const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy");
const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy");
@@ -78,7 +78,11 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
setStatus(ComboData.paymentStatus[0]); setStatus(ComboData.paymentStatus[0]);
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
reset();
reset({
code:"",
transNo:""
});
localStorage.setItem('searchCriteria',"")
} }




@@ -181,6 +185,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
disablePortal={false} disablePortal={false}
id="status" id="status"
size="small" size="small"
disableClearable
filterOptions={(options) => options} filterOptions={(options) => options}
options={ComboData.paymentStatus} options={ComboData.paymentStatus}
value={status} value={status}
@@ -239,6 +244,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {
variant="contained" variant="contained"
type="submit" type="submit"
aria-label={intl.formatMessage({id: 'submit'})} aria-label={intl.formatMessage({id: 'submit'})}
disabled={onGridReady}
> >
<FormattedMessage id="submit"/> <FormattedMessage id="submit"/>
</Button> </Button>


+ 28
- 3
src/pages/Payment/Search_Public/index.js 查看文件

@@ -14,6 +14,7 @@ const SearchForm = Loadable(React.lazy(() => import('./SearchForm')));
const EventTable = Loadable(React.lazy(() => import('./DataGrid'))); const EventTable = Loadable(React.lazy(() => import('./DataGrid')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import {FormattedMessage} from "react-intl"; import {FormattedMessage} from "react-intl";
import { getSearchCriteria } from "auth/utils";


const BackgroundHead = { const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`, backgroundImage: `url(${titleBackgroundImg})`,
@@ -33,13 +34,34 @@ const Index = () => {
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)), dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
}); });
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
setOnReady(true);
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []);
React.useEffect(() => {
if(Object.keys(searchCriteria).length>0){
setOnReady(true);
}
}, [searchCriteria]); }, [searchCriteria]);


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -63,8 +85,9 @@ const Index = () => {
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} lg={12}> <Grid item xs={12} md={12} lg={12}>
<SearchForm <SearchForm
applySearch={applySearch}
searchCriteria={searchCriteria}
applySearch={applySearch}
searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -76,6 +99,8 @@ const Index = () => {
> >
<EventTable <EventTable
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 3
- 1
src/pages/Payment/index.js 查看文件

@@ -520,7 +520,9 @@ const Index = () => {
}} }}
> >
<DialogTitle></DialogTitle> <DialogTitle></DialogTitle>
<Typography variant="h2" style={{ padding: '16px' }}>行動失敗</Typography>
<Typography variant="h2" style={{ padding: '16px' }}>
<FormattedMessage id ="MSG.actionFail"/>
</Typography>
<DialogContent style={{ display: 'flex', }}> <DialogContent style={{ display: 'flex', }}>
<Stack direction="column" justifyContent="space-between"> <Stack direction="column" justifyContent="space-between">
{ {


+ 53
- 22
src/pages/Proof/Create_FromApp/ApplicationDetails.js 查看文件

@@ -27,26 +27,50 @@ const SearchPublicNoticeForm = ({ formData }) => {
initialValues: data, initialValues: data,
}); });


const DisplayField = ({ name, width }) => {
return <TextField
fullWidth
disabled
size="small"
onChange={formik.handleChange}
id={name}
name={name}
value={formik.values[name]}
variant="outlined"
sx={
{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
background: "#f8f8f8",
},
width: width ? width : '100%'
}
const DisplayField = ({ name, width, dummyUser }) => {
return <>
{dummyUser?
<TextField
fullWidth
disabled
size="small"
onChange={formik.handleChange}
id={name}
name={name}
value={"GLD: "+formik.values[name]}
variant="outlined"
sx={
{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
background: "#f8f8f8",
},
width: width ? width : '100%'
}
}
/>
:
<TextField
fullWidth
disabled
size="small"
onChange={formik.handleChange}
id={name}
name={name}
value={formik.values[name]}
variant="outlined"
sx={
{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
background: "#f8f8f8",
},
width: width ? width : '100%'
}
}
/>
} }
/>;
</>
} }




@@ -97,9 +121,16 @@ const SearchPublicNoticeForm = ({ formData }) => {
</Grid> </Grid>


<Grid item xs={12} md={8} lg={8}> <Grid item xs={12} md={8} lg={8}>
<DisplayField
name={formik.values?.orgId ? 'enCompanyName' : 'contactPerson'}
/>
{
formik.values?.orgId?
<DisplayField
name={formik.values?.enCompanyName == "GLD" ? 'custName' : 'enCompanyName'}
dummyUser={true}
/>:
<DisplayField
name={'contactPerson'}
/>
}
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>


+ 16
- 1
src/pages/Proof/Create_FromApp/ProofForm.js 查看文件

@@ -131,6 +131,21 @@ const FormPanel = ({ formData }) => {
setSaving(false); setSaving(false);
return; return;
} }

if (!values.length|| values.length <= 0) {
setWarningText("Column should > 0");
setIsWarningPopUp(true);
setSaving(false);
return;
}
if(formik.values.groupType == "Private Bill" ){
if (!values.noOfPages || values.noOfPages <= 0) {
setWarningText("Page should > 0");
setIsWarningPopUp(true);
setSaving(false);
return;
}
}
// console.log(values); // console.log(values);
HttpUtils.postWithFiles({ HttpUtils.postWithFiles({
url: UrlUtils.CREATE_PROOF, url: UrlUtils.CREATE_PROOF,
@@ -208,7 +223,7 @@ const FormPanel = ({ formData }) => {
<Grid item xs={12} md={12}> <Grid item xs={12} md={12}>
<Stack direction="row" sx={{ display: 'flex', alignItems: 'center' }}> <Stack direction="row" sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel sx={{ paddingRight: 2, textAlign: "center" }}> <FormLabel sx={{ paddingRight: 2, textAlign: "center" }}>
<Typography variant="h5">Deadline for online proof with revision:</Typography>
<Typography variant="h5">Deadline for online manuscript revision:</Typography>
</FormLabel> </FormLabel>
<TextField <TextField
fullWidth fullWidth


+ 4
- 4
src/pages/Proof/Create_FromApp/UploadFileTable.js 查看文件

@@ -59,10 +59,10 @@ export default function UploadFileTable({ recordList, setRecordList, showPageCol
...rowModesModel, ...rowModesModel,
[id]: { mode: GridRowModes.View, ignoreModifications: true }, [id]: { mode: GridRowModes.View, ignoreModifications: true },
}); });
console.log("Starting Delete")
const editedRow = rows.find((row) => row.id === id);
console.log(editedRow)
console.log(editedRow.isNew)
// console.log("Starting Delete")
// const editedRow = rows.find((row) => row.id === id);
// console.log(editedRow)
// console.log(editedRow.isNew)
setRecordList(rows.filter((row) => row.id !== id)); setRecordList(rows.filter((row) => row.id !== id));
setRows(rows.filter((row) => row.id !== id)); setRows(rows.filter((row) => row.id !== id));
} }


+ 1
- 1
src/pages/Proof/Payment/Pay.js 查看文件

@@ -181,7 +181,7 @@ const Index = ({ record }) => {
<DialogContent style={{ display: 'flex', }}> <DialogContent style={{ display: 'flex', }}>
<Stack direction="column" justifyContent="space-between"> <Stack direction="column" justifyContent="space-between">
<Typography variant="h4"> <Typography variant="h4">
<FormattedMessage id="totalAmount" /> (HK$): {FormatUtils.currencyFormat(record.fee)}
<FormattedMessage id="totalAmount" /> ($): {FormatUtils.currencyFormat(record.fee)}
</Typography> </Typography>
</Stack> </Stack>
</DialogContent> </DialogContent>


+ 1
- 0
src/pages/Proof/Payment/Pay_Creditor.js 查看文件

@@ -70,6 +70,7 @@ const Index = ({ record }) => {
navigate("/publicNotice"); navigate("/publicNotice");
}} }}
> >
<FormattedMessage id="backToNoticePage" />
</Button> </Button>
</Typography> </Typography>
</Grid> </Grid>


+ 5
- 4
src/pages/Proof/Payment/Pay_DN.js 查看文件

@@ -44,12 +44,12 @@ const Index = ({ record }) => {
<Grid container justifyContent="flex-start" alignItems="center" > <Grid container justifyContent="flex-start" alignItems="center" >
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >
<Typography variant="h2" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
<Typography variant="h4" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
<FormattedMessage id="proofPaymentHeader_demandNote" /> <FormattedMessage id="proofPaymentHeader_demandNote" />
</Typography> </Typography>




<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
<div dangerouslySetInnerHTML={{ <div dangerouslySetInnerHTML={{
__html: intl.formatMessage( __html: intl.formatMessage(
{ {
@@ -67,7 +67,7 @@ const Index = ({ record }) => {
id: 'proofPaymentBody_demandNote2' id: 'proofPaymentBody_demandNote2'
}, },
{ {
closingDateOff: DateUtils.dateStr(record.closingDateOff),
closingDateOff: DateUtils.dateFormat(record?.closingDateOff, intl.formatMessage({id: "dateStrFormat"})),
email: record?.mail, email: record?.mail,
} }
) )
@@ -79,7 +79,7 @@ const Index = ({ record }) => {
id: 'proofPaymentBody_demandNote3' id: 'proofPaymentBody_demandNote3'
}, },
{ {
paymentDeadline: DateUtils.dateStr(record?.closingDate),
paymentDeadline: DateUtils.dateFormat(record?.closingDate, intl.formatMessage({id: "dateStrFormat"})),
} }
) )
}} /> }} />
@@ -105,6 +105,7 @@ const Index = ({ record }) => {
navigate("/publicNotice"); navigate("/publicNotice");
}} }}
> >
<FormattedMessage id="backToNoticePage" />
</Button> </Button>
</Typography> </Typography>
</Grid> </Grid>


+ 4
- 3
src/pages/Proof/Payment/Pay_Office.js 查看文件

@@ -44,12 +44,12 @@ const Index = ({ record }) => {
<Grid container justifyContent="flex-start" alignItems="center" > <Grid container justifyContent="flex-start" alignItems="center" >
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >
<Typography variant="h2" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
<Typography variant="h4" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
<FormattedMessage id="proofPaymentHeader_office" /> <FormattedMessage id="proofPaymentHeader_office" />
</Typography> </Typography>




<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
<div dangerouslySetInnerHTML={{ <div dangerouslySetInnerHTML={{
__html: intl.formatMessage( __html: intl.formatMessage(
{ {
@@ -91,7 +91,7 @@ const Index = ({ record }) => {
id: 'proofPaymentBody_office5' id: 'proofPaymentBody_office5'
}, },
{ {
paymentDeadline: DateUtils.dateStr(record?.closingDate),
paymentDeadline: DateUtils.dateFormat(record?.closingDate, intl.formatMessage({id: "dateStrFormat"})),
} }
) )
}} /> }} />
@@ -117,6 +117,7 @@ const Index = ({ record }) => {
navigate("/publicNotice"); navigate("/publicNotice");
}} }}
> >
<FormattedMessage id="backToNoticePage" />
</Button> </Button>
</Typography> </Typography>
</Grid> </Grid>


+ 9
- 6
src/pages/Proof/Payment/Pay_Online.js 查看文件

@@ -32,7 +32,9 @@ import {
// useEffect, // useEffect,
useState useState
} from "react"; } from "react";
import { PNSPS_BUTTON_THEME, PNSPS_LONG_BUTTON_THEME } from "../../../themes/buttonConst";
import { PNSPS_BUTTON_THEME,
// PNSPS_LONG_BUTTON_THEME
} from "../../../themes/buttonConst";
import { ThemeProvider } from "@emotion/react"; import { ThemeProvider } from "@emotion/react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
@@ -145,11 +147,11 @@ const Index = () => {
<Grid container justifyContent="flex-start" alignItems="center" > <Grid container justifyContent="flex-start" alignItems="center" >
<center> <center>
<Grid item xs={12} md={8} > <Grid item xs={12} md={8} >
<Typography variant="h3" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
<Typography variant="h4" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
<FormattedMessage id="proofPaymentHeader_online" /> <FormattedMessage id="proofPaymentHeader_online" />
</Typography> </Typography>


<Typography variant="h4" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
<div dangerouslySetInnerHTML={{ <div dangerouslySetInnerHTML={{
__html: intl.formatMessage( __html: intl.formatMessage(
{ {
@@ -167,7 +169,7 @@ const Index = () => {
id: 'proofPaymentBody_online2' id: 'proofPaymentBody_online2'
}, },
{ {
paymentDeadline: DateUtils.dateStr(record?.closingDate),
paymentDeadline: DateUtils.dateFormat(record?.closingDate, intl.formatMessage({id: "dateStrFormat"})),
} }
) )
}} /> }} />
@@ -175,10 +177,11 @@ const Index = () => {
</Typography> </Typography>


<Typography variant="h4" sx={{ ml: 8, textAlign: "left" }}> <Typography variant="h4" sx={{ ml: 8, textAlign: "left" }}>
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<ThemeProvider theme={PNSPS_BUTTON_THEME}>
<Button <Button
component="span" component="span"
variant="contained" variant="contained"
// sx={{ ml: { sm: 4, md: 4, lg: 4 }, mr: 4, mt: { xs: 2, sm: 2 }, mb: { xs: 2, sm: 2 } }}
sx={{mr: 4 }} sx={{mr: 4 }}
onClick={() => { setIsPopUp(true) }} onClick={() => { setIsPopUp(true) }}
> >
@@ -238,7 +241,7 @@ const Index = () => {
<DialogContent style={{ display: 'flex', }}> <DialogContent style={{ display: 'flex', }}>
<Stack direction="column" justifyContent="space-between"> <Stack direction="column" justifyContent="space-between">
<Typography variant="h4"> <Typography variant="h4">
<FormattedMessage id="totalAmount" /> (HK$): {FormatUtils.currencyFormat(fee)}
<FormattedMessage id="totalAmount" /> ($): {FormatUtils.currencyFormat(fee)}
</Typography> </Typography>
</Stack> </Stack>
</DialogContent> </DialogContent>


+ 60
- 25
src/pages/Proof/Reply_GLD/ApplicationDetails.js 查看文件

@@ -34,9 +34,11 @@ const ApplicationDetailCard = ({


const [data, setData] = useState({}); const [data, setData] = useState({});
const [cancelPopUp, setCancelPopUp] = useState(false); const [cancelPopUp, setCancelPopUp] = useState(false);
const [onDownload, setOnDownload] = useState(false);


useEffect(() => { useEffect(() => {
if (formData) { if (formData) {
console.log(formData)
setData(formData); setData(formData);
} }
}, [formData]); }, [formData]);
@@ -46,26 +48,50 @@ const ApplicationDetailCard = ({
initialValues: data, initialValues: data,
}); });


const DisplayField = ({ name, width }) => {
return <TextField
fullWidth
disabled
size="small"
onChange={formik.handleChange}
id={name}
name={name}
value={formik.values[name]}
variant="outlined"
sx={
{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
background: "#f8f8f8",
},
width: width ? width : '100%'
}
const DisplayField = ({ name, width, dummyUser }) => {
return <>
{dummyUser?
<TextField
fullWidth
disabled
size="small"
onChange={formik.handleChange}
id={name}
name={name}
value={"GLD: "+formik.values[name]}
variant="outlined"
sx={
{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
background: "#f8f8f8",
},
width: width ? width : '100%'
}
}
/>
:
<TextField
fullWidth
disabled
size="small"
onChange={formik.handleChange}
id={name}
name={name}
value={formik.values[name]}
variant="outlined"
sx={
{
"& .MuiInputBase-input.Mui-disabled": {
WebkitTextFillColor: "#000000",
background: "#f8f8f8",
},
width: width ? width : '100%'
}
}
/>
} }
/>;
</>
} }


const confirmCancel = () => { const confirmCancel = () => {
@@ -83,8 +109,15 @@ const ApplicationDetailCard = ({
} }


const genProof = () => { const genProof = () => {
setOnDownload(true)
HttpUtils.fileDownload({ HttpUtils.fileDownload({
url: UrlUtils.GEN_GAZETTE_PROOF + "/" + params.id
url: UrlUtils.GEN_GAZETTE_PROOF + "/" + params.id,
onResponse:()=>{
setOnDownload(false)
},
onError:()=>{
setOnDownload(false)
}
}); });
} }


@@ -105,7 +138,7 @@ const ApplicationDetailCard = ({
component="span" component="span"
variant="contained" variant="contained"
size="large" size="large"
disabled={!showProofBtn}
disabled={!showProofBtn||onDownload}
onClick={genProof} onClick={genProof}
> >
<Typography variant="h5">Proof Slip</Typography> <Typography variant="h5">Proof Slip</Typography>
@@ -170,10 +203,12 @@ const ApplicationDetailCard = ({


<Grid item xs={12} md={9} lg={9}> <Grid item xs={12} md={9} lg={9}>
<FormControl variant="outlined" fullWidth disabled > <FormControl variant="outlined" fullWidth disabled >
{data.orgId === null ?
<DisplayField name="contactPerson" />
{data?.orgId?
<DisplayField
name="applicant"
dummyUser={data?.enCompanyName == "GLD" ? true : false}/>
: :
<DisplayField name="applicant" />
<DisplayField name="contactPerson" />
} }
</FormControl> </FormControl>
</Grid> </Grid>
@@ -270,7 +305,7 @@ const ApplicationDetailCard = ({
</Grid> </Grid>
<Grid item xs={12} md={12} lg={12} <Grid item xs={12} md={12} lg={12}
sx={{ display: 'flex', alignItems: 'center' }}> sx={{ display: 'flex', alignItems: 'center' }}>
<Typography variant="h5">Deadline for confirm proof and payment</Typography>
<Typography variant="h5">Deadline for confirm proof and payment</Typography>
</Grid> </Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 4, display: 'flex', alignItems: 'center' }}> <Grid item xs={12} md={12} lg={12} sx={{ mb: 4, display: 'flex', alignItems: 'center' }}>
<Typography variant="h5">Before {DateUtils.datetimeStr(data.proofPaymentDeadline)}</Typography> <Typography variant="h5">Before {DateUtils.datetimeStr(data.proofPaymentDeadline)}</Typography>


+ 1
- 1
src/pages/Proof/Reply_GLD/ProofForm.js 查看文件

@@ -76,7 +76,7 @@ const FormPanel = ({ formData, isOverTime }) => {
isOverTime ? isOverTime ?
<Grid container direction="column" sx={{ paddingLeft: 4, paddingRight: 4 }} spacing={1}> <Grid container direction="column" sx={{ paddingLeft: 4, paddingRight: 4 }} spacing={1}>
<Grid item xs={12} md={12} textAlign="left"> <Grid item xs={12} md={12} textAlign="left">
<Typography variant="h5">The response timed out, please apply again.</Typography>
<Typography variant="h5">Proofing timed out. Please apply again.</Typography>
</Grid> </Grid>
</Grid> </Grid>
: :


+ 4
- 4
src/pages/Proof/Reply_GLD/UploadFileTable.js 查看文件

@@ -44,10 +44,10 @@ export default function UploadFileTable({recordList, setRecordList,}) {
...rowModesModel, ...rowModesModel,
[id]: { mode: GridRowModes.View, ignoreModifications: true }, [id]: { mode: GridRowModes.View, ignoreModifications: true },
}); });
console.log("Starting Delete")
const editedRow = rows.find((row) => row.id === id);
console.log(editedRow)
console.log(editedRow.isNew)
// console.log("Starting Delete")
// const editedRow = rows.find((row) => row.id === id);
// console.log(editedRow)
// console.log(editedRow.isNew)
setRecordList(rows.filter((row) => row.id !== id)); setRecordList(rows.filter((row) => row.id !== id));
setRows(rows.filter((row) => row.id !== id)); setRows(rows.filter((row) => row.id !== id));
} }


+ 57
- 12
src/pages/Proof/Reply_Public/ApplicationDetails.js 查看文件

@@ -18,6 +18,9 @@ const MainCard = Loadable(React.lazy(() => import('components/MainCard')));
import * as StatusUtils from "utils/statusUtils/PublicNoteStatusUtils"; import * as StatusUtils from "utils/statusUtils/PublicNoteStatusUtils";
import FileList from "components/FileList" import FileList from "components/FileList"
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import {
isORGLoggedIn,
} from "utils/Utils";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const ApplicationDetailCard = ({ formData, }) => { const ApplicationDetailCard = ({ formData, }) => {


@@ -175,6 +178,32 @@ const ApplicationDetailCard = ({ formData, }) => {
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>
{isORGLoggedIn() ?
<>
<Grid container direction="row" justifyContent="space-between"
alignItems="center">
<Grid item xs={12} md={6} lg={6} sx={{ mb: 1, }}>
<Grid container alignItems="left">
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel><Typography variant="pnspsFormParagraph">
<FormattedMessage id="careOf" />:
</Typography></FormLabel>
</Grid>

<Grid item xs={12} md={9} lg={9}>
<Stack direction="row">
<DisplayField name="careOf" />
</Stack>
</Grid>
</Grid>
</Grid>
</Grid>
</>
:
null

}
<Grid container direction="row" justifyContent="space-between" <Grid container direction="row" justifyContent="space-between"
alignItems="center"> alignItems="center">
<Grid item xs={12} md={6} lg={6} sx={{ mb: 1, }}> <Grid item xs={12} md={6} lg={6} sx={{ mb: 1, }}>
@@ -205,9 +234,11 @@ const ApplicationDetailCard = ({ formData, }) => {
<Grid item xs={12} sm={12} md={6} lg={6} sx={{ mb: 1 }}> <Grid item xs={12} sm={12} md={6} lg={6} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}> <Grid container alignItems={"center"}>
<Grid item xs={12} sm={12} md={12} lg={12} sx={{ alignItems: 'center', wordBreak: 'break-word' }}> <Grid item xs={12} sm={12} md={12} lg={12} sx={{ alignItems: 'center', wordBreak: 'break-word' }}>
<Typography><Typography variant="pnspsFormParagraph">
<FormattedMessage id="pleaseCheckReminder" />:
</Typography></Typography>
<Typography>
<Typography variant="pnspsFormParagraph">
<FormattedMessage id="pleaseCheckReminder" />:
</Typography>
</Typography>
</Grid> </Grid>
<Grid item xs={12} sm={12} md={12} lg={12} sx={{ width: '95%', maxWidth: { xs: '70vw', sm: '72vw', md: '75vw', lg: '80vw' } }}> <Grid item xs={12} sm={12} md={12} lg={12} sx={{ width: '95%', maxWidth: { xs: '70vw', sm: '72vw', md: '75vw', lg: '80vw' } }}>
<FileList <FileList
@@ -223,11 +254,14 @@ const ApplicationDetailCard = ({ formData, }) => {
/> />
</Grid> </Grid>
</Grid> </Grid>

</Grid> </Grid>


<Grid item xs={12} md={5} lg={5} sx={{ mb: 1, }}> <Grid item xs={12} md={5} lg={5} sx={{ mb: 1, }}>
<Grid container alignItems={"center"}> <Grid container alignItems={"center"}>
{
data.creditor == true ?
<>
<Grid item xs={12} md={12} lg={12} <Grid item xs={12} md={12} lg={12}
sx={{ display: 'flex', alignItems: 'center' }}> sx={{ display: 'flex', alignItems: 'center' }}>
<Typography variant="h5" display="inline"> <Typography variant="h5" display="inline">
@@ -240,7 +274,7 @@ const ApplicationDetailCard = ({ formData, }) => {
{locale === 'en' ? {locale === 'en' ?
`${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` `${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} `
: :
`${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ${intl.formatMessage({ id: 'before' })}`
`${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "上午")?.replace("pm", "下午")}${intl.formatMessage({ id: 'before' })}`
} }
</Typography> </Typography>
</Grid> </Grid>
@@ -256,15 +290,21 @@ const ApplicationDetailCard = ({ formData, }) => {
{locale === 'en' ? {locale === 'en' ?
`${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` `${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} `
: :
`${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ${intl.formatMessage({ id: 'before' })}`
`${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "上午")?.replace("pm", "下午")}${intl.formatMessage({ id: 'before' })}`
} }
</Typography> </Typography>
</Grid> </Grid>
</>
:
<></>
}


<Grid item xs={12} sm={3} md={3} lg={3} <Grid item xs={12} sm={3} md={3} lg={3}
sx={{ mb: 1, display: 'flex', alignItems: 'center' }}> sx={{ mb: 1, display: 'flex', alignItems: 'center' }}>
<Typography variant="pnspsFormParagraph">
<FormattedMessage id="payFeeFor" />:
<Typography>
<Typography variant="pnspsFormParagraph">
<FormattedMessage id="payFeeFor" />:
</Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} sm={9} md={9} lg={9} sx={{ mb: 1, display: 'flex', alignItems: 'center' }}> <Grid item xs={12} sm={9} md={9} lg={9} sx={{ mb: 1, display: 'flex', alignItems: 'center' }}>
@@ -274,11 +314,16 @@ const ApplicationDetailCard = ({ formData, }) => {
{ {
formik.values.groupType === "Private Bill" formik.values.groupType === "Private Bill"
? ?
<Typography variant="pnspsFormParagraph">( {data.noOfPages} {intl.formatMessage({ id: 'page' })} x $6,552 )</Typography>
<Typography>
<Typography variant="pnspsFormParagraph">( {data.noOfPages} {intl.formatMessage({ id: 'page' })} x $6,552 )</Typography>
</Typography>
: :
<Typography variant="pnspsFormParagraph">( {data.length} cm x {data.colCount === 2 ?
"$364 " + intl.formatMessage({ id: 'doubleCol' }) :
"$182 " + intl.formatMessage({ id: 'singleCol' })} )</Typography>
<Typography>
<Typography variant="pnspsFormParagraph">( {data.length} cm x {data.colCount === 2 ?
"$364 " + intl.formatMessage({ id: 'doubleCol' }) :
"$182 " + intl.formatMessage({ id: 'singleCol' })} )
</Typography>
</Typography>
} }
</Grid> </Grid>
</Grid> </Grid>


+ 175
- 141
src/pages/Proof/Reply_Public/ProofForm.js 查看文件

@@ -49,6 +49,7 @@ const FormPanel = ({ formData }) => {


const navigate = useNavigate() const navigate = useNavigate()
const params = useParams(); const params = useParams();
const dft = locale === 'en' ? "DD MMMM YYYY" : "YYYY年MM月DD日";


const tabelStyle = { const tabelStyle = {
border: "2px solid gray", border: "2px solid gray",
@@ -120,7 +121,7 @@ const FormPanel = ({ formData }) => {
}, },
files: attachments ? attachments : [], files: attachments ? attachments : [],
onSuccess: function (responseData) { onSuccess: function (responseData) {
console.log(responseData)
// console.log(responseData)
if (responseData.success === false) { if (responseData.success === false) {
navigate("/publicNotice/" + responseData.id); navigate("/publicNotice/" + responseData.id);
} else { } else {
@@ -236,7 +237,7 @@ const FormPanel = ({ formData }) => {
<FormattedMessage id="proofReplyDate" /> :&nbsp; <FormattedMessage id="proofReplyDate" /> :&nbsp;
{ {
locale === 'en' ? locale === 'en' ?
DateUtils.dateValue(formik.values.replyDate)
DateUtils.datetimeStr(formik.values.replyDate)
: :
DateUtils.datetimeStr_Cht(formik.values.replyDate) DateUtils.datetimeStr_Cht(formik.values.replyDate)
} }
@@ -319,138 +320,29 @@ const FormPanel = ({ formData }) => {
isDummyLoggedIn() ? isDummyLoggedIn() ?
<Grid item xs={12} sx={{ mb: 1, }}> <Grid item xs={12} sx={{ mb: 1, }}>
<table style={tabelStyle}> <table style={tabelStyle}>
<tr style={tabelStyle}>
<th style={tabelStyle} width="50" align="left"></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="paymentMeans" /></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="confirmingDealine" /></th>
<th style={tabelStyle} width="400" align="left"><FormattedMessage id="PaymentCoonpletDealine" /></th>
</tr>
<tr>
<td style={tabelStyle}>
<Checkbox
checked={paymentMethod == "demandNote"}
onChange={() => {
set_paymentMethod("demandNote")
}}
/>
</td>
<td style={tabelStyle}>
<FormattedMessage id="payDn" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "payDn" }))
setWarningText(
<><FormattedMessage id="paymentMethodMeans" />
<ul>
<li><FormattedMessage id="atm" /></li>
<li><FormattedMessage id="pps" /></li>
<li><FormattedMessage id="eBank" /></li>
<li><FormattedMessage id="phoneBank" /></li>
<li><FormattedMessage id="eCheque" /></li>
<li><FormattedMessage id="fps" /></li>
<li><FormattedMessage id="hkpo" /></li>
<li><FormattedMessage id="store" /></li>
<li><FormattedMessage id="post" /></li>
</ul>
</>
);
setIsWarningPopUp(true);
}}><FormattedMessage id="viewDetail" /></a>
</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} 5:00 p.m.</td>
<td style={tabelStyle}>
<FormattedMessage id="payDnRemark" values={{
date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:00 p.m."
}} />
</td>
</tr>
<tr>
<td style={tabelStyle}>
<Checkbox
checked={paymentMethod == "office"}
onChange={() => {
set_paymentMethod("office")
}}
/>
</td>
<td style={tabelStyle}>
<FormattedMessage id="payNPGO" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "payNPGO" }))
setWarningText(
<><FormattedMessage id="paymentMethodMeans" />
<ul>
<li><FormattedMessage id="cheque" /></li>
<li><FormattedMessage id="cash" /></li>
</ul>
</>
);
setIsWarningPopUp(true);
}}><FormattedMessage id="viewDetail" /></a>
</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 12:00 p.m.</td>
<td style={tabelStyle}>
<FormattedMessage id="payNPGORemark" values={{
date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:30 p.m."
}} />
</td>
</tr>
</table>
</Grid> :
<>
<Grid item xs={12} sx={{ mb: 1, }}>
<table style={tabelStyle}>
<tbody>
<tr style={tabelStyle}> <tr style={tabelStyle}>
<th style={tabelStyle} width="50" align="left"></th> <th style={tabelStyle} width="50" align="left"></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="paymentMeans" /></th> <th style={tabelStyle} width="300" align="left"><FormattedMessage id="paymentMeans" /></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="commentDeadline" /></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="confirmingDealine" /></th> <th style={tabelStyle} width="300" align="left"><FormattedMessage id="confirmingDealine" /></th>
<th style={tabelStyle} width="400" align="left"><FormattedMessage id="PaymentCoonpletDealine" /></th> <th style={tabelStyle} width="400" align="left"><FormattedMessage id="PaymentCoonpletDealine" /></th>
</tr> </tr>
<tr> <tr>
<td style={tabelStyle}> <td style={tabelStyle}>
<Checkbox <Checkbox
checked={paymentMethod == "online"}
checked={paymentMethod == "demandNote"}
onChange={() => { onChange={() => {
set_paymentMethod("online")
set_paymentMethod("demandNote")
}} }}
/> />
</td> </td>
<td style={tabelStyle}> <td style={tabelStyle}>
<FormattedMessage id="payOnline" />
<FormattedMessage id="paymentMeans" />: <FormattedMessage id="payDn" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => { <br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "payOnline" }))
setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payDn" }))
setWarningText( setWarningText(
<><FormattedMessage id="paymentMethodMeans" />
<ul>
<li><FormattedMessage id="fps" /></li>
<li><FormattedMessage id="card" /></li>
<li><FormattedMessage id="pps" /></li>
</ul>
</>
);
setIsWarningPopUp(true);
}}><FormattedMessage id="viewDetail" /></a>
</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")}</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.expiryDate, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")}</td>
</tr>
<tr>
<td style={tabelStyle}>
{isOverDnReviseDeadline() ?
<></> :
<Checkbox
checked={paymentMethod == "demandNote"}
onChange={() => {
set_paymentMethod("demandNote")
}}
/>
}
</td>
<td style={tabelStyle}>
<FormattedMessage id="payDn" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "payDn" }))
setWarningText(
<><FormattedMessage id="paymentMethodMeans" />
<><FormattedMessage id="paymentMethodMeans" />:
<ul> <ul>
<li><FormattedMessage id="atm" /></li> <li><FormattedMessage id="atm" /></li>
<li><FormattedMessage id="pps" /></li> <li><FormattedMessage id="pps" /></li>
@@ -462,64 +354,206 @@ const FormPanel = ({ formData }) => {
<li><FormattedMessage id="store" /></li> <li><FormattedMessage id="store" /></li>
<li><FormattedMessage id="post" /></li> <li><FormattedMessage id="post" /></li>
</ul> </ul>
<Typography variant="h6">
<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} />
</Typography>
</> </>
); );
setIsWarningPopUp(true); setIsWarningPopUp(true);
}}><FormattedMessage id="viewDetail" /></a>
}}><u><FormattedMessage id="viewDetail" /></u></a>
</td> </td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} 5:00 p.m.</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} 5:00 p.m.</td> <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} 5:00 p.m.</td>
<td style={tabelStyle}> <td style={tabelStyle}>
<FormattedMessage id="payDnRemark" values={{ <FormattedMessage id="payDnRemark" values={{
date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:00 p.m."
date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))
}} /> }} />
</td> </td>
</tr> </tr>

<tr> <tr>
<td style={tabelStyle}> <td style={tabelStyle}>
{
isOverNpgoReviseDeadline() ?
<></> :
<Checkbox
checked={paymentMethod == "office"}
onChange={() => {
set_paymentMethod("office")
}}
/>
}
<Checkbox
checked={paymentMethod == "office"}
onChange={() => {
set_paymentMethod("office")
}}
/>
</td> </td>
<td style={tabelStyle}> <td style={tabelStyle}>
<FormattedMessage id="payNPGO" /> <FormattedMessage id="payNPGO" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => { <br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "payNPGO" }))
setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payNPGOPopUpTitle" }))
setWarningText( setWarningText(
<><FormattedMessage id="paymentMethodMeans" />
<><FormattedMessage id="paymentMethodMeans" />:
<ul> <ul>
<li><FormattedMessage id="cheque" /></li> <li><FormattedMessage id="cheque" /></li>
<li><FormattedMessage id="drafts" /></li>
<li><FormattedMessage id="cashierOrders" /></li>
<li><FormattedMessage id="cash" /></li> <li><FormattedMessage id="cash" /></li>
</ul> </ul>
</> </>
); );
setIsWarningPopUp(true); setIsWarningPopUp(true);
}}><FormattedMessage id="viewDetail" /></a>
}}><u><FormattedMessage id="viewDetail" /></u></a>
</td> </td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 11:30 a.m.</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 12:00 p.m.</td> <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 12:00 p.m.</td>
<td style={tabelStyle}> <td style={tabelStyle}>
<FormattedMessage id="payNPGORemark" values={{ <FormattedMessage id="payNPGORemark" values={{
date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:30 p.m."
date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))
}} /> }} />
</td> </td>
</tr> </tr>

</tbody>
</table>
</Grid> :
<>
<Grid item xs={12} sx={{ mb: 1, }}>
<table style={tabelStyle}>
<tbody>
<tr style={tabelStyle}>
<th style={tabelStyle} width="50" align="left"></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="paymentMeans" /></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="commentDeadline" /></th>
<th style={tabelStyle} width="300" align="left"><FormattedMessage id="confirmingDealine" /></th>
<th style={tabelStyle} width="400" align="left"><FormattedMessage id="PaymentCoonpletDealine" /></th>
</tr>
<tr>
<td style={tabelStyle}>
<Checkbox
checked={paymentMethod == "online"}
onChange={() => {
set_paymentMethod("online")
}}
/>
</td>
<td style={tabelStyle}>
<FormattedMessage id="payOnline" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payOnline" }))
setWarningText(
<><FormattedMessage id="paymentMethodMeans" />:
<ul>
<li><FormattedMessage id="fps" /></li>
<li><FormattedMessage id="card" /></li>
<li><FormattedMessage id="pps" /></li>
</ul>
</>
);
setIsWarningPopUp(true);
}}><u><FormattedMessage id="viewDetail" /></u></a>
</td>
<td style={tabelStyle}>{
locale === 'en' ?
`${DateUtils.dateFormat(formData.reviseDeadline, intl.formatMessage({ id: "datetimeFormate" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")}`
:
`${DateUtils.dateFormat(formData.reviseDeadline, intl.formatMessage({ id: "datetimeFormate" }))?.replace("am", "上午")?.replace("pm", "下午").replace("00分", "")}`
}</td>
<td style={tabelStyle}>{
locale === 'en' ?
`${DateUtils.dateFormat(formData.proofPaymentDeadline, intl.formatMessage({ id: "datetimeFormate" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")}`
:
`${DateUtils.dateFormat(formData.proofPaymentDeadline, intl.formatMessage({ id: "datetimeFormate" }))?.replace("am", "上午")?.replace("pm", "下午").replace("00分", "")}`
}</td>
<td style={tabelStyle}>
<FormattedMessage id="payOnlineRemark" values={{
date: DateUtils.dateFormat(formData.proofPaymentDeadline, dft)
}} />
</td>
</tr>
<tr>
<td style={tabelStyle}>
{isOverDnReviseDeadline() ?
<></> :
<Checkbox
checked={paymentMethod == "demandNote"}
onChange={() => {
set_paymentMethod("demandNote")
}}
/>
}
</td>
<td style={tabelStyle}>
<FormattedMessage id="payDn" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payDn" }))
setWarningText(
<><FormattedMessage id="paymentMethodMeans" />:
<ul>
<li><FormattedMessage id="atm" /></li>
<li><FormattedMessage id="pps" /></li>
<li><FormattedMessage id="eBank" /></li>
<li><FormattedMessage id="phoneBank" /></li>
<li><FormattedMessage id="eCheque" /></li>
<li><FormattedMessage id="fps" /></li>
<li><FormattedMessage id="hkpo" /></li>
<li><FormattedMessage id="store" /></li>
<li><FormattedMessage id="post" /></li>
</ul>
<Typography variant="h6">
<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} />
</Typography>
</>
);
setIsWarningPopUp(true);
}}><u><FormattedMessage id="viewDetail" /></u></a>
</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} {locale ==='en'?"5:00 p.m.":"下午5時"}</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} {locale ==='en'?"5:00 p.m.":"下午5時"}</td>
<td style={tabelStyle}>
<FormattedMessage id="payDnRemark" values={{
date: DateUtils.dateFormat(formData.proofPaymentDeadline, intl.formatMessage({ id: "dateStrFormat" }))
}} />
</td>
</tr>

<tr>
<td style={tabelStyle}>
{
isOverNpgoReviseDeadline() ?
<></> :
<Checkbox
checked={paymentMethod == "office"}
onChange={() => {
set_paymentMethod("office")
}}
/>
}
</td>
<td style={tabelStyle}>
<FormattedMessage id="payNPGO" />
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => {
setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payNPGOPopUpTitle" }))
setWarningText(
<><FormattedMessage id="paymentMethodMeans" />:
<ul>
<li><FormattedMessage id="cheque" /></li>
<li><FormattedMessage id="drafts" /></li>
<li><FormattedMessage id="cashierOrders" /></li>
<li><FormattedMessage id="cash" /></li>
</ul>
</>
);
setIsWarningPopUp(true);
}}><u><FormattedMessage id="viewDetail" /></u></a>
</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} {locale ==='en'?"11:30 a.m.":"上午11時30分"}</td>
<td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} {locale ==='en'?"12:00 p.m.":"下午12時"}</td>
<td style={tabelStyle}>
<FormattedMessage id="payNPGORemark" values={{
date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))
}} />
</td>
</tr>
</tbody>


</table> </table>
</Grid> </Grid>
<Grid item xs={12}>
{/* <Grid item xs={12}>
<Typography variant="h6" height="100%" > <Typography variant="h6" height="100%" >
<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} /> <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} />
</Typography> </Typography>
</Grid>
</Grid> */}


<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="h6" height="100%" > <Typography variant="h6" height="100%" >
@@ -662,10 +696,10 @@ const FormPanel = ({ formData }) => {
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button <Button
aria-label={intl.formatMessage({ id: 'ok' })}
aria-label={intl.formatMessage({ id: 'close' })}
onClick={() => setIsWarningPopUp(false)} onClick={() => setIsWarningPopUp(false)}
> >
OK
<FormattedMessage id="close" />
</Button> </Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>


+ 4
- 4
src/pages/Proof/Reply_Public/UploadFileTable.js 查看文件

@@ -46,10 +46,10 @@ export default function UploadFileTable({recordList, setRecordList,}) {
...rowModesModel, ...rowModesModel,
[id]: { mode: GridRowModes.View, ignoreModifications: true }, [id]: { mode: GridRowModes.View, ignoreModifications: true },
}); });
console.log("Starting Delete")
const editedRow = rows.find((row) => row.id === id);
console.log(editedRow)
console.log(editedRow.isNew)
// console.log("Starting Delete")
// const editedRow = rows.find((row) => row.id === id);
// console.log(editedRow)
// console.log(editedRow.isNew)
setRecordList(rows.filter((row) => row.id !== id)); setRecordList(rows.filter((row) => row.id !== id));
setRows(rows.filter((row) => row.id !== id)); setRows(rows.filter((row) => row.id !== id));
} }


+ 14
- 5
src/pages/Proof/Search_GLD/DataGrid.js 查看文件

@@ -9,11 +9,11 @@ import { FiDataGrid } from "components/FiDataGrid";
import { clickableLink } from 'utils/CommonFunction'; import { clickableLink } from 'utils/CommonFunction';
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchPublicNoticeTable({searchCriteria}) {
export default function SearchPublicNoticeTable({searchCriteria, applyGridOnReady,applySearch}) {


const navigate = useNavigate() const navigate = useNavigate()


const [_searchCriteria, set_searchCriteria] = React.useState({});
const [_searchCriteria, set_searchCriteria] = React.useState({searchCriteria});


React.useEffect(() => { React.useEffect(() => {
set_searchCriteria(searchCriteria); set_searchCriteria(searchCriteria);
@@ -83,6 +83,9 @@ export default function SearchPublicNoticeTable({searchCriteria}) {
renderCell: (params) => { renderCell: (params) => {
let company = params.row.enCompanyName != null?params.row.enCompanyName: params.row.chCompanyName; let company = params.row.enCompanyName != null?params.row.enCompanyName: params.row.chCompanyName;
company = company != null ? company : ""; company = company != null ? company : "";
if (company == "GLD"){
company = company + ": " + params.row.appCustName
}
return (<> return (<>
{params?.value}<br />{company} {params?.value}<br />{company}
</>); </>);
@@ -119,12 +122,18 @@ export default function SearchPublicNoticeTable({searchCriteria}) {
<FiDataGrid <FiDataGrid
columns={columns} columns={columns}
customPageSize={10} customPageSize={10}
onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'} getRowHeight={() => 'auto'}
doLoad={{
onRowDoubleClick={handleRowDoubleClick}
applyGridOnReady={applyGridOnReady}
applySearch = {applySearch}
// doLoad={{
// url: LIST_PROOF,
// params: _searchCriteria,
// }}
doLoad={React.useMemo(() => ({
url: LIST_PROOF, url: LIST_PROOF,
params: _searchCriteria, params: _searchCriteria,
}}
}), [_searchCriteria])}
/> />
</div> </div>
); );


+ 71
- 12
src/pages/Proof/Search_GLD/SearchForm.js 查看文件

@@ -21,22 +21,34 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, issueComboData
const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, issueComboData, onGridReady
}) => { }) => {


const [type, setType] = React.useState([]); const [type, setType] = React.useState([]);
const [status, setStatus] = React.useState(ComboData.proofStatus[0]);
const [status, setStatus] = React.useState(searchCriteria.statusKey!=undefined?ComboData.proofStatus_GLD[searchCriteria.statusKey]:ComboData.proofStatus_GLD[0]);
const [orgSelected, setOrgSelected] = React.useState({}); const [orgSelected, setOrgSelected] = React.useState({});
const [orgCombo, setOrgCombo] = React.useState(); const [orgCombo, setOrgCombo] = React.useState();
const [issueSelected, setIssueSelected] = React.useState({}); const [issueSelected, setIssueSelected] = React.useState({});
const [issueCombo, setIssueCombo] = React.useState([]); const [issueCombo, setIssueCombo] = React.useState([]);
const [groupSelected, setGroupSelected] = React.useState({});
const [groupSelected, setGroupSelected] = React.useState(searchCriteria.gazettGroup!=undefined?ComboData.groupTitle.find(item => item.code === searchCriteria.gazettGroup):{});


const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy");
const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy");


// React.useEffect(() => {
// if(searchCriteria.status!=undefined){
// if(searchCriteria.status === ""){
// ComboData.proofStatus_GLD[0]
// }else{
// setSelectedStatus(ComboData.proofStatus_GLD.find(item => item.type === searchCriteria.status))
// }
// }else{
// setSelectedStatus(ComboData.proofStatus_GLD[0])
// }
// }, [searchCriteria]);
React.useEffect(() => { React.useEffect(() => {
setFromDateValue(minDate); setFromDateValue(minDate);
}, [minDate]); }, [minDate]);
@@ -68,26 +80,56 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
refNo: data.refNo, refNo: data.refNo,
code: data.code, code: data.code,
issueId: issueSelected?.id, issueId: issueSelected?.id,
gazettGroup: groupSelected?.type,
gazettGroup: groupSelected?.code,
dateFrom: sentDateFrom, dateFrom: sentDateFrom,
dateTo: sentDateTo, dateTo: sentDateTo,
contact: data.contact, contact: data.contact,
replyed: (status?.type && status?.type != 'all') ? status?.type : "",
orgId: (orgSelected?.key && orgSelected?.key > 0) ? orgSelected?.key : "", orgId: (orgSelected?.key && orgSelected?.key > 0) ? orgSelected?.key : "",
statusKey:status?.key,


}; };


if(status?.type && status?.type != 'all'){
if (status?.type == "Confirmed"){
temp["replyed"] = "T";
temp["action"] = true;
temp["cancelled"] = false;
}else if(status?.type == "Re-proofing"){
temp["replyed"] = "T";
temp["action"] = false;
temp["cancelled"] = false;
}else if(status?.type == "No Reply"){
temp["replyed"] = "F";
temp["timeOut"] = "T";
temp["cancelled"] = false;
}else if(status?.type == "Cancelled"){
temp["cancelled"] = true;
} else{
temp["replyed"] = "F";
temp["timeOut"] = "F";
temp["cancelled"] = false;
}
}

applySearch(temp); applySearch(temp);
}; };


React.useEffect(() => { React.useEffect(() => {
if (orgComboData && orgComboData.length > 0) { if (orgComboData && orgComboData.length > 0) {
setOrgCombo(orgComboData); setOrgCombo(orgComboData);
if(searchCriteria.orgId!=undefined){
setOrgSelected(orgComboData.find(item => item.key === searchCriteria.orgId))
}
} }
}, [orgComboData]); }, [orgComboData]);


React.useEffect(() => { React.useEffect(() => {
if (issueComboData && issueComboData.length > 0) { if (issueComboData && issueComboData.length > 0) {
setIssueCombo(issueComboData); setIssueCombo(issueComboData);
if(searchCriteria.issueId!=undefined){
setIssueSelected(issueComboData.find(item => item.id === searchCriteria.issueId))
}
} }
}, [issueComboData]); }, [issueComboData]);


@@ -99,7 +141,12 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
setGroupSelected({}); setGroupSelected({});
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
reset();
reset({
refNo:"",
code:"",
contact:""
});
localStorage.setItem('searchCriteria',"")
} }


function getIssueLabel(data) { function getIssueLabel(data) {
@@ -299,9 +346,10 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
id="status" id="status"
size="small" size="small"
filterOptions={(options) => options} filterOptions={(options) => options}
options={ComboData.proofStatus}
options={ComboData.proofStatus_GLD}
value={status} value={status}
inputValue={status?.label ? status?.label : ""}
getOptionLabel={(option) => option.type? intl.formatMessage({ id: option.i18nLabel }) : ""}
inputValue={status? intl.formatMessage({id: status.i18nLabel}):""}
onChange={(event, newValue) => { onChange={(event, newValue) => {
if (newValue !== null) { if (newValue !== null) {
setStatus(newValue); setStatus(newValue);
@@ -323,13 +371,15 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
<Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
<Autocomplete <Autocomplete
{...register("orgId")} {...register("orgId")}
disablePortal={false}
disablePortal
id="orgId" id="orgId"
size="small"
options={orgCombo} options={orgCombo}
groupBy={(option) => option.groupType}
size="small"
value={orgSelected} value={orgSelected}
getOptionLabel={(option) => option.name? option.name : ""} getOptionLabel={(option) => option.name? option.name : ""}
inputValue={orgSelected ? orgSelected.name : ""}
inputValue={orgSelected ? orgSelected.name!=undefined?orgSelected.name:"" : ""}

onChange={(event, newValue) => { onChange={(event, newValue) => {
if (newValue !== null) { if (newValue !== null) {
setOrgSelected(newValue); setOrgSelected(newValue);
@@ -345,6 +395,14 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
}} }}
/> />
)} )}
renderGroup={(params) => (
<Grid item key={params.key}>
<Typography fontSize={20} fontStyle="italic" p={1}>
{params.group}
</Typography>
{params.children}
</Grid>
)}
/> />
</Grid> </Grid>
: <></> : <></>
@@ -371,7 +429,8 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
<Button <Button
variant="contained" variant="contained"
type="submit" type="submit"
>
disabled={onGridReady}
>
Submit Submit
</Button> </Button>
</Grid> </Grid>


+ 22
- 5
src/pages/Proof/Search_GLD/index.js 查看文件

@@ -10,6 +10,7 @@ import * as React from "react";
import * as HttpUtils from "utils/HttpUtils"; import * as HttpUtils from "utils/HttpUtils";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import {GET_ORG_COMBO, GET_ISSUE_COMBO} from "utils/ApiPathConst"; import {GET_ORG_COMBO, GET_ISSUE_COMBO} from "utils/ApiPathConst";
import { getSearchCriteria } from "auth/utils";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
@@ -32,15 +33,22 @@ const BackgroundHead = {
const UserSearchPage_Individual = () => { const UserSearchPage_Individual = () => {
const [orgCombo, setOrgCombo] = React.useState([]); const [orgCombo, setOrgCombo] = React.useState([]);
const [issueCombo, setIssueCombo] = React.useState([]); const [issueCombo, setIssueCombo] = React.useState([]);
const [searchCriteria, setSearchCriteria] = React.useState({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14)),
});
const [searchCriteria, setSearchCriteria] = React.useState({});
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => {
React.useEffect(() => {
getOrgCombo(); getOrgCombo();
getIssueCombo(); getIssueCombo();
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
setSearchCriteria({
dateTo: DateUtils.dateValue(new Date()),
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
})
}
}, []); }, []);


React.useEffect(() => { React.useEffect(() => {
@@ -69,7 +77,13 @@ const UserSearchPage_Individual = () => {
} }


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -95,6 +109,7 @@ const UserSearchPage_Individual = () => {
orgComboData={orgCombo} orgComboData={orgCombo}
issueComboData={issueCombo} issueComboData={issueCombo}
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -107,6 +122,8 @@ const UserSearchPage_Individual = () => {
> >
<EventTable <EventTable
searchCriteria={searchCriteria} searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


+ 32
- 21
src/pages/Proof/Search_Public/DataGrid.js 查看文件

@@ -11,13 +11,14 @@ import { useNavigate } from "react-router-dom";
import { FiDataGrid } from "components/FiDataGrid"; import { FiDataGrid } from "components/FiDataGrid";
import { import {
isORGLoggedIn, isORGLoggedIn,
} from "utils/Utils";
import {useTheme} from "@emotion/react";
import {useIntl} from "react-intl";
isDummyLoggedIn,
} from "utils/Utils";
import { useTheme } from "@emotion/react";
import { useIntl } from "react-intl";
import { clickableLink } from 'utils/CommonFunction'; import { clickableLink } from 'utils/CommonFunction';
// ==============================|| EVENT TABLE ||============================== // // ==============================|| EVENT TABLE ||============================== //


export default function SearchPublicNoticeTable({ searchCriteria }) {
export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnReady, applySearch }) {


const navigate = useNavigate() const navigate = useNavigate()
const theme = useTheme(); const theme = useTheme();
@@ -44,7 +45,15 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
'& .MuiDataGrid-footerContainer': { '& .MuiDataGrid-footerContainer': {
border: 1, border: 1,
borderColor: "#EEE" borderColor: "#EEE"
}
},
"& .MuiDataGrid-columnHeaderTitle": {
whiteSpace: "normal",
lineHeight: "normal"
},
"& .MuiDataGrid-columnHeader": {
// Forced to use important since overriding inline styles
height: "unset !important"
},
} }




@@ -66,7 +75,7 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
} }
}*/ }*/


const getIssueLabel=(data) =>{
const getIssueLabel = (data) => {
let issueYear = data.row.issueYear let issueYear = data.row.issueYear
let volume = data.row.issueVolume; let volume = data.row.issueVolume;
let issueNo = data.row.issueNo; let issueNo = data.row.issueNo;
@@ -90,22 +99,22 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
+ ", " + DateUtils.dateFormat(issueDate, "D MMM YYYY (ddd)"); + ", " + DateUtils.dateFormat(issueDate, "D MMM YYYY (ddd)");
} }


const columns = [ const columns = [
{ {
field: 'actions', field: 'actions',
headerName: intl.formatMessage({id: 'proofId'}),
headerName: intl.formatMessage({ id: 'proofId' }),
width: isMdOrLg ? 'auto' : 200, width: isMdOrLg ? 'auto' : 200,
flex: isMdOrLg ? 1.5 : undefined, flex: isMdOrLg ? 1.5 : undefined,
cellClassName: 'actions', cellClassName: 'actions',
renderCell: (params) => { renderCell: (params) => {
return clickableLink('/proof/reply/' + params.row.id,params.row.refNo);
return clickableLink('/proof/reply/' + params.row.id, params.row.refNo);
}, },
}, },
{ {
id: 'appId', id: 'appId',
field: 'appId', field: 'appId',
headerName: isORGLoggedIn()?intl.formatMessage({id: 'gazetteCount3'}):intl.formatMessage({id: 'gazetteCount2'}),
headerName: isORGLoggedIn() ? intl.formatMessage({ id: 'gazetteCount3' }) : intl.formatMessage({ id: 'gazetteCount2' }),
width: isMdOrLg ? 'auto' : 330, width: isMdOrLg ? 'auto' : 330,
flex: isMdOrLg ? 2 : undefined, flex: isMdOrLg ? 2 : undefined,
renderCell: (params) => { renderCell: (params) => {
@@ -114,13 +123,13 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
let isssue = getIssueLabel(params); let isssue = getIssueLabel(params);


// return <div style={{ margin: 4 }}>{appNo}<br />{isssue}<br />{params.row.appRemarks}</div> // return <div style={{ margin: 4 }}>{appNo}<br />{isssue}<br />{params.row.appRemarks}</div>
return <div style={{ margin: 4 }}>{isssue}<br />{isORGLoggedIn()?<>{params.row.appCareOf}<br /></>:null}{params.row.appRemarks}</div>
return <div style={{ margin: 4 }}>{isssue}<br />{isORGLoggedIn() ? isDummyLoggedIn()?<><>GLD: {params.row.applicant}<br /></><>{params.row.appCareOf}<br /></></>:<>{params.row.appCareOf}<br /></> : null}{params.row.appRemarks}</div>
}, },
}, },
{ {
id: 'created', id: 'created',
field: 'created',
headerName: intl.formatMessage({id: 'proofDate'}),
field: 'reviseDeadline',
headerName: intl.formatMessage({ id: 'proofDate' }),
width: isMdOrLg ? 'auto' : 200, width: isMdOrLg ? 'auto' : 200,
flex: isMdOrLg ? 1.5 : undefined, flex: isMdOrLg ? 1.5 : undefined,
valueGetter: (params) => { valueGetter: (params) => {
@@ -130,7 +139,7 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
{ {
id: 'proofPaymentDeadline', id: 'proofPaymentDeadline',
field: 'proofPaymentDeadline', field: 'proofPaymentDeadline',
headerName: intl.formatMessage({id: 'replyBefore'}),
headerName: intl.formatMessage({ id: 'replyBefore' }),
width: isMdOrLg ? 'auto' : 200, width: isMdOrLg ? 'auto' : 200,
flex: isMdOrLg ? 1.5 : undefined, flex: isMdOrLg ? 1.5 : undefined,
valueGetter: (params) => { valueGetter: (params) => {
@@ -142,7 +151,7 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
{ {
id: 'replyDate', id: 'replyDate',
field: 'replyDate', field: 'replyDate',
headerName: intl.formatMessage({id: 'replyDate'}),
headerName: intl.formatMessage({ id: 'replyDate' }),
width: isMdOrLg ? 'auto' : 200, width: isMdOrLg ? 'auto' : 200,
flex: isMdOrLg ? 1.5 : undefined, flex: isMdOrLg ? 1.5 : undefined,
valueGetter: (params) => { valueGetter: (params) => {
@@ -151,17 +160,17 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
}, },
{ {
id: 'actions', id: 'actions',
headerName: intl.formatMessage({id: 'status'}),
headerName: intl.formatMessage({ id: 'status' }),
width: isMdOrLg ? 'auto' : 160, width: isMdOrLg ? 'auto' : 160,
flex: isMdOrLg ? 1 : undefined, flex: isMdOrLg ? 1 : undefined,
renderCell: (params) => { renderCell: (params) => {
return locale === 'en' ? ProofStatus.getStatus_Eng(params) : ProofStatus.getStatus_Cht(params);
return locale === 'en' ? ProofStatus.getStatus_Eng(params) : locale === 'zh-HK' ? ProofStatus.getStatus_Cht(params) : ProofStatus.getStatus_Cn(params);
}, },
}, },
{ {
id: 'fee', id: 'fee',
field: 'fee', field: 'fee',
headerName: intl.formatMessage({id: 'fee'}),
headerName: intl.formatMessage({ id: 'fee' }),
width: isMdOrLg ? 'auto' : 160, width: isMdOrLg ? 'auto' : 160,
flex: isMdOrLg ? 1 : undefined, flex: isMdOrLg ? 1 : undefined,
valueGetter: (params) => { valueGetter: (params) => {
@@ -175,7 +184,7 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
} }


return ( return (
<div style={{ width: '100%', overflowX: 'auto'}}>
<div style={{ width: '100%', overflowX: 'auto' }}>


<FiDataGrid <FiDataGrid
sx={_sx} sx={_sx}
@@ -183,10 +192,12 @@ export default function SearchPublicNoticeTable({ searchCriteria }) {
customPageSize={10} customPageSize={10}
getRowHeight={() => "auto"} getRowHeight={() => "auto"}
onRowDoubleClick={handleRowDoubleClick} onRowDoubleClick={handleRowDoubleClick}
doLoad={{
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
doLoad={React.useMemo(() => ({
url: LIST_PROOF, url: LIST_PROOF,
params: _searchCriteria, params: _searchCriteria,
}}
}), [_searchCriteria])}
/> />
</div> </div>
); );

+ 32
- 8
src/pages/Proof/Search_Public/SearchForm.js 查看文件

@@ -22,16 +22,16 @@ import {DemoItem} from "@mui/x-date-pickers/internals/demo";
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
// ==============================|| DASHBOARD - DEFAULT ||============================== // // ==============================|| DASHBOARD - DEFAULT ||============================== //
const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData
const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, onGridReady
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
const { locale } = intl; const { locale } = intl;
const [type, setType] = React.useState([]); const [type, setType] = React.useState([]);
const [status, setStatus] = React.useState(ComboData.proofStatus[0]);
const [status, setStatus] = React.useState(searchCriteria.statusKey!=undefined?ComboData.proofStatusFull[searchCriteria.statusKey]:ComboData.proofStatusFull[0]);
const [issueSelected, setIssueSelected] = React.useState({}); const [issueSelected, setIssueSelected] = React.useState({});
const [issueCombo, setIssueCombo] = React.useState([]); const [issueCombo, setIssueCombo] = React.useState([]);
const [groupSelected, setGroupSelected] = React.useState({});
const [groupSelected, setGroupSelected] = React.useState(searchCriteria.gazettGroup!=undefined?ComboData.groupTitle.find(item => item.code === searchCriteria.gazettGroup):{});


const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
@@ -84,9 +84,24 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData
gazettGroup: groupSelected?.type, gazettGroup: groupSelected?.type,
dateFrom: sentDateFrom, dateFrom: sentDateFrom,
dateTo: sentDateTo, dateTo: sentDateTo,
//contact: data.contact,
replyed: (status?.type && status?.type != 'all') ? status?.type : "",
statusKey:status?.key,
}; };
if(status?.type && status?.type != 'all'){
if (status?.type == "Confirmed"){
temp["replyed"] = "T";
temp["action"] = true;
}else if(status?.type == "Re-proofing"){
temp["replyed"] = "T";
temp["action"] = false;
}else if(status?.type == "No Reply"){
temp["replyed"] = "F";
temp["timeOut"] = "T";
}else{
temp["replyed"] = "F";
temp["timeOut"] = "F";
}
}
applySearch(temp); applySearch(temp);
}; };


@@ -94,17 +109,24 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData
React.useEffect(() => { React.useEffect(() => {
if (issueComboData && issueComboData.length > 0) { if (issueComboData && issueComboData.length > 0) {
setIssueCombo(issueComboData); setIssueCombo(issueComboData);
if(searchCriteria.issueId!=undefined){
setIssueSelected(issueComboData.find(item => item.id === searchCriteria.issueId))
}
} }
}, [issueComboData]); }, [issueComboData]);


function resetForm() { function resetForm() {
setType([]); setType([]);
setStatus(ComboData.proofStatus[0]);
setStatus(ComboData.proofStatusFull[0]);
setIssueSelected({}); setIssueSelected({});
setGroupSelected({}); setGroupSelected({});
setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14))) setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
setMaxDate(DateUtils.dateValue(new Date())) setMaxDate(DateUtils.dateValue(new Date()))
reset();
reset({
refNo:"",
code:"",
});
localStorage.setItem('searchCriteria',"")
} }


function getIssueLabel(data) { function getIssueLabel(data) {
@@ -300,8 +322,9 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData
disablePortal={false} disablePortal={false}
size="small" size="small"
id="status" id="status"
disableClearable
filterOptions={(options) => options} filterOptions={(options) => options}
options={ComboData.proofStatus}
options={ComboData.proofStatusFull}
value={status} value={status}
getOptionLabel={(option) => option.type? intl.formatMessage({ id: option.i18nLabel }) : ""} getOptionLabel={(option) => option.type? intl.formatMessage({ id: option.i18nLabel }) : ""}
inputValue={status? intl.formatMessage({ id: status.i18nLabel }) : ""} inputValue={status? intl.formatMessage({ id: status.i18nLabel }) : ""}
@@ -345,6 +368,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData
variant="contained" variant="contained"
type="submit" type="submit"
aria-label={intl.formatMessage({id: 'submit'})} aria-label={intl.formatMessage({id: 'submit'})}
disabled={onGridReady}
> >
<FormattedMessage id="submit"/> <FormattedMessage id="submit"/>
</Button> </Button>


+ 20
- 4
src/pages/Proof/Search_Public/index.js 查看文件

@@ -9,6 +9,7 @@ import * as UrlUtils from "utils/ApiPathConst";
import * as React from "react"; import * as React from "react";
import * as HttpUtils from "utils/HttpUtils"; import * as HttpUtils from "utils/HttpUtils";
import * as DateUtils from "utils/DateUtils"; import * as DateUtils from "utils/DateUtils";
import { getSearchCriteria } from "auth/utils";


import Loadable from 'components/Loadable'; import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
@@ -37,9 +38,15 @@ const UserSearchPage_Individual = () => {
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)), dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)),
}); });
const [onReady, setOnReady] = React.useState(false); const [onReady, setOnReady] = React.useState(false);
const [onGridReady, setGridOnReady] = React.useState(false);


React.useEffect(() => { React.useEffect(() => {
getIssueCombo(); getIssueCombo();
if (Object.keys(getSearchCriteria(window.location.pathname)).length>0){
setSearchCriteria(getSearchCriteria(window.location.pathname))
}else{
localStorage.setItem('searchCriteria',"")
}
}, []); }, []);


React.useEffect(() => { React.useEffect(() => {
@@ -59,7 +66,13 @@ const UserSearchPage_Individual = () => {


function applySearch(input) { function applySearch(input) {
setGridOnReady(true)
setSearchCriteria(input); setSearchCriteria(input);
localStorage.setItem('searchCriteria', JSON.stringify({path:window.location.pathname,data:input}))
}

function applyGridOnReady(input) {
setGridOnReady(input);
} }


return ( return (
@@ -83,9 +96,10 @@ const UserSearchPage_Individual = () => {
{/*row 1*/} {/*row 1*/}
<Grid item xs={12} md={12} lg={12}> <Grid item xs={12} md={12} lg={12}>
<SearchForm <SearchForm
applySearch={applySearch}
issueComboData={issueCombo}
searchCriteria={searchCriteria}
applySearch={applySearch}
issueComboData={issueCombo}
searchCriteria={searchCriteria}
onGridReady={onGridReady}
/> />
</Grid> </Grid>
{/*row 2*/} {/*row 2*/}
@@ -96,7 +110,9 @@ const UserSearchPage_Individual = () => {
sx={{width: "-webkit-fill-available"}} sx={{width: "-webkit-fill-available"}}
> >
<EventTable <EventTable
searchCriteria={searchCriteria}
searchCriteria={searchCriteria}
applyGridOnReady={applyGridOnReady}
applySearch={applySearch}
/> />
</MainCard> </MainCard>
</Grid> </Grid>


部分文件因文件數量過多而無法顯示

Loading…
取消
儲存