diff --git a/src/components/I18nProvider.js b/src/components/I18nProvider.js index fdcd9f0..c42cb2f 100644 --- a/src/components/I18nProvider.js +++ b/src/components/I18nProvider.js @@ -1,8 +1,8 @@ -import { useState, useEffect, createContext } from 'react'; +import { useState, useEffect, createContext, useMemo } from 'react'; import { IntlProvider } from 'react-intl'; -import enMessages from '../translations/en.json'; -import cnMessages from '../translations/zh-CN.json'; -import hkMessages from '../translations/zh-HK.json'; +import enBase from '../translations/en.json'; +import cnBase from '../translations/zh-CN.json'; +import hkBase from '../translations/zh-HK.json'; import { GET_COMBO, GET_CONTENT } from "utils/ApiPathConst"; import { get } from "utils/HttpUtils"; @@ -10,72 +10,106 @@ import { get } from "utils/HttpUtils"; const LocaleContext = createContext(); export const I18nProvider = ({ children }) => { - const systemMessages = { - "en": enMessages, - "zh": hkMessages, - "zh-HK": hkMessages, - "zh-CN": cnMessages - }; + const [locale, setLocale] = useState('en'); + + // keep base messages immutable + const [systemMessages, setSystemMessages] = useState({ + en: { ...enBase }, + zh: { ...hkBase }, + 'zh-HK': { ...hkBase }, + 'zh-CN': { ...cnBase } + }); + + const [loaded, setLoaded] = useState(false); + useEffect(() => { + const saved = localStorage.getItem('locale'); + if (!saved) localStorage.setItem('locale', 'en'); + else setLocale(saved); + }, []); - const [locale, setLocale] = useState('en'); // Default locale, you can change this as per your requirement - const [messages, setMessages] = useState(systemMessages[locale]); + useEffect(() => { + let alive = true; const loadTermsAndConditions = () => { + // load both endpoints then merge into state + const p1 = new Promise((resolve) => { get({ - url: GET_CONTENT, - onSuccess: (responseData) => { - for (const key in responseData) { - const value = responseData[key]; - enMessages[key] = value.en??""; - cnMessages[key] = value.cn??""; - hkMessages[key] = value.zh??""; - } - } + url: GET_CONTENT, + onSuccess: (resp) => resolve(resp || {}), + onError: () => resolve({}) }); + }); - + const p2 = new Promise((resolve) => { get({ - url: GET_COMBO, - onSuccess: (responseData) => { - for (let i = 0; i < responseData.length; i++) { - let item = responseData[i]; - enMessages[item.key] = item.en; - cnMessages[item.key] = item.cn; - hkMessages[item.key] = item.zh; - } - - } + url: GET_COMBO, + onSuccess: (resp) => resolve(resp || []), + onError: () => resolve([]) + }); + }); + + Promise.all([p1, p2]).then(([contentMap, comboList]) => { + if (!alive) return; + + setSystemMessages((prev) => { + // clone prev first (immutably) + const next = { + ...prev, + en: { ...prev.en }, + 'zh-CN': { ...prev['zh-CN'] }, + 'zh-HK': { ...prev['zh-HK'] }, + zh: { ...prev.zh } + }; + + // merge GET_CONTENT (object) + for (const key in contentMap) { + const v = contentMap[key] || {}; + next.en[key] = v.en ?? ""; + next['zh-CN'][key] = v.cn ?? ""; + next['zh-HK'][key] = v.zh ?? ""; + next.zh[key] = v.zh ?? ""; + } + + // merge GET_COMBO (array) + for (const item of comboList) { + if (!item?.key) continue; + next.en[item.key] = item.en ?? ""; + next['zh-CN'][item.key] = item.cn ?? ""; + next['zh-HK'][item.key] = item.zh ?? ""; + next.zh[item.key] = item.zh ?? ""; + } + + return next; }); - } - - useEffect(() => { - loadTermsAndConditions(); - if (localStorage.getItem('locale') === null) { - //no locale case - localStorage.setItem('locale', 'en'); - } - else { - setLocale(localStorage.getItem('locale')); - } - }, []); - - useEffect(() => { - // Load the messages for the selected locale - const fetchMessages = async () => { - setMessages(systemMessages[locale]); - }; - - fetchMessages(); - }, [locale]); - - return ( - - - {children} - - - ); -} - -export default LocaleContext; \ No newline at end of file + + setLoaded(true); + }); + }; + + loadTermsAndConditions(); + + return () => { + alive = false; + }; + }, []); + + const messages = useMemo(() => { + return systemMessages[locale] || systemMessages.en; + }, [systemMessages, locale]); + + return ( + + + {loaded ? children :
} + + + ); +}; + +export default LocaleContext; diff --git a/src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js b/src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js index a955469..56cc2d2 100644 --- a/src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js +++ b/src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js @@ -98,6 +98,7 @@ const LocaleSelector = () => { onClick={() => { setLocale("en") localStorage.setItem('locale','en'); + setOpen(false); }} > { { - setLocale("zh-HK") + setLocale("zh-HK"); localStorage.setItem('locale','zh-HK'); + setOpen(false); }} > { onClick={() => { setLocale("zh-CN") localStorage.setItem('locale','zh-CN'); + setOpen(false); }} > import('../../extra-pages/LoadingComponent'))); +import { checkPaymentSuspension } from "utils/Utils"; // ==============================|| DASHBOARD - DEFAULT ||============================== // @@ -372,8 +373,28 @@ const PublicNoticeApplyForm = ({ loadedData, _selections, gazetteIssueList }) => - + + {checkPaymentSuspension() && ( + + + + )}
{ setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payOnline" })) setWarningText( @@ -388,8 +409,8 @@ const PublicNoticeApplyForm = ({ loadedData, _selections, gazetteIssueList }) => setIsWarningPopUp(true); }}> - {DateUtils.dateFormat(closeDate, dft)} {locale==='en'?"2:00 p.m.":"下午2時"} - + {DateUtils.dateFormat(closeDate, dft)} {locale==='en'?"2:00 p.m.":"下午2時"} + diff --git a/src/pages/extra-pages/UserMenu1/index.js b/src/pages/extra-pages/UserMenu1/index.js new file mode 100644 index 0000000..b6ea85c --- /dev/null +++ b/src/pages/extra-pages/UserMenu1/index.js @@ -0,0 +1,178 @@ +import { Grid, Typography, Stack, } from '@mui/material'; +import { useState, useEffect, lazy } from "react"; + +import Loadable from 'components/Loadable'; +import { useIntl, FormattedMessage } from "react-intl"; + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' +const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: 'auto', + height: 'auto', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' +} + +const LoadingComponent = Loadable(lazy(() => import('pages/extra-pages/LoadingComponent'))); + +import DownloadIcon from '@mui/icons-material/Download'; + +const UserMenu1 = () => { + const intl = useIntl(); + const { locale } = intl; + const [onReady, setOnReady] = useState(false); + + const pnspsurl = "https://"+window.location.hostname; + + useEffect(() => { + setOnReady(true); + }, [locale]); + + const tableStyle = { + fontFamily: "arial, sans-serif", + borderCollapse: "collapse", + width: "100%", + } + + const cellStyle = { + border: "1px solid #dddddd", + textAlign: "left", + padding: "8px" + }; + + const getRow = ({ title, en, zh, cn }) => { + return <> + + {title} + + + + + + ; + } + + + return ( + !onReady ? + + + + + + : + ( + + +
+ + + + + +
+
+ + + +
+ +

+ + + + + + + + + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/01 - Create account - 1.pdf", + zh: pnspsurl + "/user-guide/cht/01c - Create account - 1.pdf", + cn: pnspsurl + "/user-guide/chs/01sc - Create account - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/02 - Login - 1.pdf", + zh: pnspsurl + "/user-guide/cht/02c - Login - 1.pdf", + cn: pnspsurl + "/user-guide/chs/02sc - Login - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/03 - Application for publishing a Public Notice in the Gazette - 1.pdf", + zh: pnspsurl + "/user-guide/cht/03c - Application for publishing a Public Notice in the Gazette - 1.pdf", + cn: pnspsurl + "/user-guide/chs/03sc - Application for publishing a Public Notice in the Gazette - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/04 - Proofreading reply (with correction) - 1.pdf", + zh: pnspsurl + "/user-guide/cht/04c - Proofreading reply (with correction) - 1.pdf", + cn: pnspsurl + "/user-guide/chs/04sc - Proofreading reply (with correction) - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/05 - Proofreading reply (pass for printing) - 1.pdf", + zh: pnspsurl + "/user-guide/cht/05c - Proofreading reply (pass for printing) - 1.pdf", + cn: pnspsurl + "/user-guide/chs/05sc - Proofreading reply (pass for printing) - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/06 - Cancellation of application for publishing a Public Notice in the Gazette - 1.pdf", + zh: pnspsurl + "/user-guide/cht/06c - Cancellation of application for publishing a Public Notice in the Gazette - 1.pdf", + cn: pnspsurl + "/user-guide/chs/06sc - Cancellation of application for publishing a Public Notice in the Gazette - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/07 - Forgot password - 1.pdf", + zh: pnspsurl + "/user-guide/cht/07c - Forgot password - 1.pdf", + cn: pnspsurl + "/user-guide/chs/07sc - Forgot password - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/08 - Change password - 1.pdf", + zh: pnspsurl + "/user-guide/cht/08c - Change password - 1.pdf", + cn: pnspsurl + "/user-guide/chs/08sc - Change password - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/09 - Language of email notification - 1.pdf", + zh: pnspsurl + "/user-guide/cht/09c - Language of email notification - 1.pdf", + cn: pnspsurl + "/user-guide/chs/09sc - Language of email notification - 1.pdf" + })} + + {getRow({ + title: , + en: pnspsurl + "/user-guide/eng/10 - Download General Demand Note for making payment(s) - 1.pdf", + zh: pnspsurl + "/user-guide/cht/10c - Download General Demand Note for making payment(s) - 1.pdf", + cn: pnspsurl + "/user-guide/chs/10sc - Download General Demand Note for making payment(s) - 1.pdf" + })} + + +
English繁體中文简体中文
+

+
+
+
+
+ ) + ); + +} + +export default UserMenu1; \ No newline at end of file diff --git a/src/pages/extra-pages/UserMenuPub/index.js b/src/pages/extra-pages/UserMenuPub/index.js index 1f9c3e7..414c2bb 100644 --- a/src/pages/extra-pages/UserMenuPub/index.js +++ b/src/pages/extra-pages/UserMenuPub/index.js @@ -19,7 +19,7 @@ const LoadingComponent = Loadable(lazy(() => import('pages/extra-pages/LoadingCo import DownloadIcon from '@mui/icons-material/Download'; -const UserMenu = () => { +const UserMenuPub = () => { const intl = useIntl(); const { locale } = intl; const [onReady, setOnReady] = useState(false); @@ -204,4 +204,4 @@ const UserMenu = () => { } -export default UserMenu; \ No newline at end of file +export default UserMenuPub; \ No newline at end of file diff --git a/src/pages/extra-pages/UserMenuPub1/index.js b/src/pages/extra-pages/UserMenuPub1/index.js new file mode 100644 index 0000000..21ef364 --- /dev/null +++ b/src/pages/extra-pages/UserMenuPub1/index.js @@ -0,0 +1,207 @@ +import { Grid, Typography, Stack, } from '@mui/material'; +import { useState, useEffect, lazy } from "react"; + +import Loadable from 'components/Loadable'; +import { useIntl, FormattedMessage } from "react-intl"; + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' +const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: 'auto', + height: 'auto', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' +} + +const LoadingComponent = Loadable(lazy(() => import('pages/extra-pages/LoadingComponent'))); + +import DownloadIcon from '@mui/icons-material/Download'; + +const UserMenuPub1 = () => { + const intl = useIntl(); + const { locale } = intl; + const [onReady, setOnReady] = useState(false); + + useEffect(() => { + setOnReady(true); + }, [locale]); + + const tableStyle = { + fontFamily: "arial, sans-serif", + borderCollapse: "collapse", + width: "100%", + } + + const cellStyle = { + border: "1px solid #dddddd", + textAlign: "left", + padding: "8px" + }; + + const getRow = ({ title, orgEn, orgZh, orgCn, indEn, indZh, indCn }) => { + + return <> + + {title} + + + + + ; + } + + const pnspsurl = "https://"+window.location.hostname; + + + return ( + !onReady ? + + + + + + : + ( + + +
+ + + + + +
+
+ + +
+ +

+ + + + + + + + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/01 - Create account - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/01c - Create account - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/01sc - Create account - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/01 - Create account - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/01c - Create account - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/01sc - Create account - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/02 - Login - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/02c - Login - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/02sc - Login - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/02 - Login - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/02c - Login - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/02sc - Login - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/03 - Application for publishing a Public Notice in the Gazette - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/03c - Application for publishing a Public Notice in the Gazette - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/03sc - Application for publishing a Public Notice in the Gazette - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/03 - Application for publishing a Public Notice in the Gazette - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/03c - Application for publishing a Public Notice in the Gazette - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/03sc - Application for publishing a Public Notice in the Gazette - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/04 - Proofreading reply (with correction) - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/04c - Proofreading reply (with correction) - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/04sc - Proofreading reply (with correction) - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/04 - Proofreading reply (with correction) - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/04c - Proofreading reply (with correction) - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/04sc - Proofreading reply (with correction) - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/05 - Proofreading reply (pass for printing) - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/05c - Proofreading reply (pass for printing) - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/05sc - Proofreading reply (pass for printing) - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/05 - Proofreading reply (pass for printing) - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/05c - Proofreading reply (pass for printing) - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/05sc - Proofreading reply (pass for printing) - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/06 - Cancellation of application for publishing a Public Notice in the Gazette - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/06c - Cancellation of application for publishing a Public Notice in the Gazette - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/06sc - Cancellation of application for publishing a Public Notice in the Gazette - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/06 - Cancellation of application for publishing a Public Notice in the Gazette - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/06c - Cancellation of application for publishing a Public Notice in the Gazette - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/06sc - Cancellation of application for publishing a Public Notice in the Gazette - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/07 - Forgot password - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/07c - Forgot password - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/07sc - Forgot password - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/07 - Forgot password - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/07c - Forgot password - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/07sc - Forgot password - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/08 - Change password - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/08c - Change password - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/08sc - Change password - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/08 - Change password - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/08c - Change password - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/08sc - Change password - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/09 - Language of email notification - c 1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/09c - Language of email notification - c 1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/09sc - Language of email notification - c 1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/09 - Language of email notification - p 1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/09c - Language of email notification - p 1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/09sc - Language of email notification - p 1.pdf" + })} + + {getRow({ + title: , + orgEn: pnspsurl + "/user-guide-pub/eng/10-Payment-c1.pdf", + orgZh: pnspsurl + "/user-guide-pub/cht/10c-Payment-c1.pdf", + orgCn: pnspsurl + "/user-guide-pub/chs/10sc-Payment-c1.pdf", + indEn: pnspsurl + "/user-guide-pub/eng/10-Payment-p1.pdf", + indZh: pnspsurl + "/user-guide-pub/cht/10c-Payment-p1.pdf", + indCn: pnspsurl + "/user-guide-pub/chs/10sc-Payment-p1.pdf" + })} + + +
+ +

+
+
+
+
+ ) + ); + +} + +export default UserMenuPub1; \ No newline at end of file diff --git a/src/routes/LoginRoutes.js b/src/routes/LoginRoutes.js index 76ead09..cf2a976 100644 --- a/src/routes/LoginRoutes.js +++ b/src/routes/LoginRoutes.js @@ -16,7 +16,9 @@ const PrivacyPolicyPage = Loadable(lazy(() => import('pages/extra-pages/PrivacyP const ImportantNoticePage = Loadable(lazy(() => import('pages/extra-pages/ImportantNoticePage'))); const AboutUsPage = Loadable(lazy(() => import('pages/extra-pages/AboutUs'))); const UserMenuPage = Loadable(lazy(() => import('pages/extra-pages/UserMenu'))); -// const UserMenuPubPage = Loadable(lazy(() => import('pages/extra-pages/UserMenuPub'))); +const UserMenuPubPage = Loadable(lazy(() => import('pages/extra-pages/UserMenuPub'))); +const UserMenu1Page = Loadable(lazy(() => import('pages/extra-pages/UserMenu1'))); +const UserMenuPub1Page = Loadable(lazy(() => import('pages/extra-pages/UserMenuPub1'))); const DatabaseHealthCheckPage = Loadable(lazy(() => import('pages/extra-pages/DatabaseHealthCheck'))); @@ -88,10 +90,18 @@ const LoginRoutes = { path: 'userGuide', element: }, - // { - // path: 'userGuidePub', - // element: - // }, + { + path: 'userGuidePub', + element: + }, + { + path: 'userGuide1', + element: + }, + { + path: 'userGuidePub1', + element: + }, { path: 'databaseHealthCheck', element: