diff --git a/src/assets/style/navbarStyles.css b/src/assets/style/navbarStyles.css index be5f102..d71cd84 100644 --- a/src/assets/style/navbarStyles.css +++ b/src/assets/style/navbarStyles.css @@ -26,7 +26,7 @@ text-decoration: none; font-size: 1.2rem; font-weight: 600; - font-family: 微軟正黑體; + /* font-family: 微軟正黑體; */ color: black; transition: 0.3s ease-in-out; } @@ -76,7 +76,7 @@ font-weight: 600; color: #0C489E; transition: 0.3s ease-in-out; - font-family: 微軟正黑體; + /* font-family: 微軟正黑體; */ text-align: center; } #mobileTitle{ @@ -85,13 +85,13 @@ font-weight: 600; color: #0C489E; transition: 0.3s ease-in-out; - font-family: 微軟正黑體; + /* font-family: 微軟正黑體; */ text-align: center; } #sidebar{ font-size: 1.3rem; font-weight: 600; - font-family: 微軟正黑體; + /* font-family: 微軟正黑體; */ } #sidebartop{ align-items: center; @@ -115,7 +115,7 @@ text-decoration: none; font-size: 1.3rem; font-weight: 600; - font-family: 微軟正黑體; + /* font-family: 微軟正黑體; */ color: black; transition: 0.3s ease-in-out; } diff --git a/src/assets/style/styles.css b/src/assets/style/styles.css index 0a6da19..b10e4ff 100644 --- a/src/assets/style/styles.css +++ b/src/assets/style/styles.css @@ -1,7 +1,20 @@ -body{ +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+HK|Noto+Sans+SC&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC&display=swap'); + +html, +body, +#root, +.app, +.content { + height: 100%; + width: 100%; + font-family: "Noto Sans HK", "Noto Sans SC"; +} + +/* body{ padding-top: 53px; font-family: 微軟正黑體; -} +} */ /* main{ padding-top: 43px; } */ \ No newline at end of file diff --git a/src/auth/utils.js b/src/auth/utils.js index 9c99e55..c37cbb6 100644 --- a/src/auth/utils.js +++ b/src/auth/utils.js @@ -13,9 +13,38 @@ export const hostPath = `http://${hostname}:${hostPort}`; export const apiPath = `${hostPath}/api`; // export const apiPath = `/api`; export const paymentPath = `http://pnspsdev.gld.gov.hk/payment`; + export const iAmSmartPath = `https://apigw-isit.staging-eid.gov.hk`; +export const clientId = "cf61fa7c121e4869966f69c8694b1cd2"; +export const getBowerType=()=>{ + console.log(navigator.userAgent) + // const regex = /Mobi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Mi|huawei|Opera Mini|SAMSUNG|Samsung|SGH-[I|N|T]|GT-[I|N]|SM-[A|N|P|T|Z]|SHV-E|SCH-[I|J|R|S]|SPH-L/i; + // if(!regex.test(navigator.userAgent)) -// clientId : cf61fa7c121e4869966f69c8694b1cd2 + if (navigator.userAgent.indexOf("Edg") != -1) { + if(navigator.userAgent.match(/Android/i)) return "Android_Edge" + if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Edge" + return "PC_Browser" + }else if(navigator.userAgent.indexOf("Chrome") != -1){ + if(navigator.userAgent.match(/Android/i)) return "Android_Chrome" + if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Chrome" + return "PC_Browser" + }else if(navigator.userAgent.indexOf("Safari") != -1){ + if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Safari" + return "PC_Browser" + }else if(navigator.userAgent.indexOf("Firefox") != -1){ + if(navigator.userAgent.match(/Android/i)) return "Android_Firefox" + if(navigator.userAgent.match(/iPhone|iPad|iPod/i)) return "iOS_Firefox" + return "PC_Browser" + }else if(navigator.userAgent.match(/SAMSUNG|Samsung|SGH-[I|N|T]|GT-[I|N]|SM-[A|N|P|T|Z]|SHV-E|SCH-[I|J|R|S]|SPH-L/i)){ + return "Android_Samsung" + }else if(navigator.userAgent.match(/huawei/i)){ + return "Android_Huawei" + }else if(navigator.userAgent.match(/Mi/i)){ + return "Android_Xiaomi" + } + return "PC_Browser"; +} diff --git a/src/index.js b/src/index.js index 4465d65..5efaa37 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; +import "./assets/style/styles.css" // scroll bar import 'simplebar/src/simplebar.css'; diff --git a/src/layout/MainLayout/Header/HeaderContent/Profile/index.js b/src/layout/MainLayout/Header/HeaderContent/Profile/index.js index 239eda5..aa5e13c 100644 --- a/src/layout/MainLayout/Header/HeaderContent/Profile/index.js +++ b/src/layout/MainLayout/Header/HeaderContent/Profile/index.js @@ -109,7 +109,7 @@ const Profile = () => { > - {userData == null ? "" : (userData.fullenName?userData.fullenName: userData.fullchName)} + {userData == null ? "" : (userData.fullenName?userData.fullenName: userData.fullchName)} { - {userData == null ? "" : (userData.fullenName?userData.fullenName: userData.fullchName)} + {userData == null ? "" : (userData.fullenName?userData.fullenName: userData.fullchName)} {/* {userData == null ? "" : userData.fullenName} */} diff --git a/src/pages/Proof/Create_FromApp/ProofForm.js b/src/pages/Proof/Create_FromApp/ProofForm.js index fb40ee1..10a09c1 100644 --- a/src/pages/Proof/Create_FromApp/ProofForm.js +++ b/src/pages/Proof/Create_FromApp/ProofForm.js @@ -10,6 +10,7 @@ import { FormLabel, Button } from '@mui/material'; + import * as UrlUtils from "utils/ApiPathConst"; import * as HttpUtils from "utils/HttpUtils"; import MainCard from "components/MainCard"; @@ -20,8 +21,6 @@ import { useNavigate } from "react-router-dom"; import Loadable from 'components/Loadable'; import { notifySaveSuccess } from 'utils/CommonFunction'; const UploadFileTable = Loadable(React.lazy(() => import('./UploadFileTable'))); -// ==============================|| DASHBOARD - DEFAULT ||============================== // - const FormPanel = ({ formData }) => { @@ -239,12 +238,13 @@ const FormPanel = ({ formData }) => { size="small" type="text" onChange={(event) => { - const value = event.target.value; - formik.setFieldValue("length", value); - formik.setFieldValue("fee", 6552 * value); + const re = /^[0-9\b]+$/; + if (event.target.value === '' || re.test(event.target.value)) { + const value = event.target.value; + formik.setFieldValue("length", value); + formik.setFieldValue("fee", 6552 * value); + } }} - name="noOfPages" - value={formik.values["noOfPages"]} variant="outlined" sx={ { @@ -275,9 +275,13 @@ const FormPanel = ({ formData }) => { size="small" type="text" onChange={(event) => { - const value = event.target.value; - formik.setFieldValue("length", value); - formik.setFieldValue("fee", columnPrice.value * value); + const re = /^[0-9\b]+$/; + if (event.target.value === '' || re.test(event.target.value)) { + const value = event.target.value; + formik.setFieldValue("length", value); + formik.setFieldValue("fee", columnPrice.value * value); + } + }} name="length" value={formik.values["length"]} diff --git a/src/pages/Proof/Reply_Public/ApplicationDetails.js b/src/pages/Proof/Reply_Public/ApplicationDetails.js index 7ffa56c..71996ef 100644 --- a/src/pages/Proof/Reply_Public/ApplicationDetails.js +++ b/src/pages/Proof/Reply_Public/ApplicationDetails.js @@ -204,19 +204,20 @@ const ApplicationDetailCard = ({ formData, }) => { - 繳費及返稿最後限期: + 繳費及返稿最後限期: - {DateUtils.dateStr_Cht(data.returnBeforeDate)} 下午 2:00前 +  {DateUtils.dateStr_Cht(data.returnBeforeDate)} 下午 2:00前 應繳費用: - {FormatUtils.currencyFormat(data.fee)} + {FormatUtils.currencyFormat(data.fee)} - + + { formik.values.groupType == "A" ? diff --git a/src/pages/Proof/Search_GLD/SearchForm.js b/src/pages/Proof/Search_GLD/SearchForm.js index 4bbb7b6..d803a2c 100644 --- a/src/pages/Proof/Search_GLD/SearchForm.js +++ b/src/pages/Proof/Search_GLD/SearchForm.js @@ -91,7 +91,7 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss >
- + {/*row 1*/} @@ -282,7 +282,7 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss {/*last row*/} - + @@ -480,7 +481,7 @@ const ApplicationDetailCard = ( - + - + diff --git a/src/pages/User/SearchPage/UserSearchForm.js b/src/pages/User/SearchPage/UserSearchForm.js index c393d05..a2949d7 100644 --- a/src/pages/User/SearchPage/UserSearchForm.js +++ b/src/pages/User/SearchPage/UserSearchForm.js @@ -41,7 +41,7 @@ const UserSearchForm = ({ applySearch }) => { const temp = { username: data.userName, - fullenName: data.fullenName, + enName: data.fullenName, post: data.post, email: data.email, phone: data.phone, diff --git a/src/pages/User/SearchPage_Individual/UserSearchForm_Individual.js b/src/pages/User/SearchPage_Individual/UserSearchForm_Individual.js index b7b1de2..28a9ceb 100644 --- a/src/pages/User/SearchPage_Individual/UserSearchForm_Individual.js +++ b/src/pages/User/SearchPage_Individual/UserSearchForm_Individual.js @@ -29,7 +29,7 @@ const UserSearchForm_Individual = ({ applySearch }) => { const temp = { username: data.userName, - fullenName: data.fullenName, + fullName: data.fullenName, email: data.email, phone: data.phone, accountFilter: accountFilter, diff --git a/src/pages/authentication/AuthWrapper.js b/src/pages/authentication/AuthWrapper.js index fe37dd3..2b18b90 100644 --- a/src/pages/authentication/AuthWrapper.js +++ b/src/pages/authentication/AuthWrapper.js @@ -44,8 +44,8 @@ const AuthWrapper = ({ children }) => ( alignItems="center" spacing={2}> - 香港特別行政區政府 - 憲報 + 香港特別行政區政府 + 憲報 { setIsPopUp(true); } + const getQRWithIAmSmart = () => { + let url = iAmSmartPath + "/api/v1/auth/getQR" + + "?clientID=" + clientId + + "&responseType=code" + +"&source=" + getBowerType() + +"&redirectURI=" + +"&scope=eidapi_formFilling" + +"&lang=zh-HK"//en-US, zh-HK, or zh-CN + //+"&state=" + +"&brokerPage=false" + window.location.assign(url); + } + return ( @@ -58,7 +72,7 @@ const RegisterCustom = () => { 你可點擊「智方便」按鈕,系統會自動輸入個人資料,或自行輸入個人資料,以即時啟動憲報刊登公告帳戶。
如欲使用「智方便」提供個人資料,請先下載「智方便」流動應用程式並登記成為「智方便」用戶。 - 了解更多 + 了解更多 @@ -105,29 +119,25 @@ const RegisterCustom = () => { - 身份證號碼 - - - 性別 -
- - 中文姓名 - - - - 英文姓名 + - 電郵地址 - - 身份證號碼 + - 手機號碼 - - 性別 + - 住宅地址
- - - + + +
+ 了解更多 +
); diff --git a/src/pages/authentication/Verify.js b/src/pages/authentication/Verify.js new file mode 100644 index 0000000..dbcd8aa --- /dev/null +++ b/src/pages/authentication/Verify.js @@ -0,0 +1,74 @@ +// material-ui +import { Button, Grid } from '@mui/material'; +import { Link } from 'react-router-dom'; +import Typography from '@mui/material/Typography'; +// import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; +// import banner from 'assets/images/bg_ml.jpg'; +import { Stack } from '../../../node_modules/@mui/material/index'; +import { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import axios from 'axios'; +import { GET_VERIFY_USER_ACCOUNT } from 'utils/ApiPathConst'; +import Loadable from 'components/Loadable'; +import { lazy } from 'react'; + +const LoadingComponent = Loadable(lazy(() => import('../extra-pages/LoadingComponent'))); +const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); +import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; +import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; + +export default function Verify() { + + const [isLoading, setIsLoading] = useState(true) + const [verifyState, setVerifyState] = useState(null) + + const params = useParams() + const handleVerify = async () => { + const response = await axios.get(GET_VERIFY_USER_ACCOUNT, { + params: { + email: decodeURIComponent(params.email), + emailVerifyHash: decodeURIComponent(params.verifyCode) + } + }) + if (response.status === 200 && response.data) { + setVerifyState(true) + } else { + setVerifyState(false) + } + setIsLoading(false) + } + + let enterUseEffect = false + useEffect(() => { + if (enterUseEffect) handleVerify() + enterUseEffect = true + }, []) + + return ( + + + {isLoading || verifyState == null ? + : + + {verifyState ? + // SUCCESS page + + + 帳戶已成功驗證。 + + + : + // ERROR page + + {/* */} + + 驗證失敗,請聯絡相關的系統管理員協助。 + + + } + + } + + + ) +} \ No newline at end of file diff --git a/src/pages/authentication/auth-forms/PasswordAlertDialog.js b/src/pages/authentication/auth-forms/PasswordAlertDialog.js index 60ef811..33b83b3 100644 --- a/src/pages/authentication/auth-forms/PasswordAlertDialog.js +++ b/src/pages/authentication/auth-forms/PasswordAlertDialog.js @@ -19,41 +19,45 @@ import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; const PasswordAlertDialog = (props) => { return ( - - - - - {props.errorMassage==='ACCOUNT_LOCKED_ERROR'? - - - 帳戶將被封鎖 - - - 帳戶連續五次登入錯誤,請與系統管理員聯絡 - - : - - 用戶名或密碼錯誤 - - } - - - - - {""} - - - - - - + > + + + + {props.errorMassage === 'ACCOUNT_LOCKED_ERROR' ? + + + 帳戶將被封鎖 + + + 帳戶連續五次登入錯誤,請與系統管理員聯絡 + + : + props.errorMassage === 'ACCOUNT_VERIFIED_ERROR' ? + + 帳戶尚未驗證 + : + + 用戶名或密碼錯誤 + + } + + + + + {""} + + + + + + ); }; diff --git a/src/routes/LoginRoutes.js b/src/routes/LoginRoutes.js index 99c9bc4..87f0fc9 100644 --- a/src/routes/LoginRoutes.js +++ b/src/routes/LoginRoutes.js @@ -16,6 +16,7 @@ const IAmSmart_SuccessCallback = Loadable(lazy(() => import('pages/iAmSmart/Succ //TODO: this page for testing only, please remove at prod const TestMailPage = Loadable(lazy(() => import('pages/pnspsNotifyTest'))); +const VerifyPage = Loadable(lazy(() => import('pages/authentication/Verify'))); // ==============================|| AUTH ROUTING ||============================== // @@ -54,6 +55,14 @@ const LoginRoutes = { { path: 'iamsmart/logincallback', element: + }, + { + path: 'testMailPage', + element: + }, + { + path: 'verify/:verifyCode/:email', + element: } ] }; diff --git a/src/themes/index.js b/src/themes/index.js index 728f01a..22ee02a 100644 --- a/src/themes/index.js +++ b/src/themes/index.js @@ -17,7 +17,7 @@ export default function ThemeCustomization({ children }) { const theme = Palette('light', 'default'); // eslint-disable-next-line react-hooks/exhaustive-deps - const themeTypography = Typography(`微軟正黑體`); + const themeTypography = Typography(``); const themeCustomShadows = useMemo(() => CustomShadows(theme), [theme]); const themeOptions = useMemo( diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index b6523a6..b90fce1 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -45,6 +45,7 @@ export const POST_CAPTCHA = apiPath+'/captcha'; export const POST_PUBLIC_USER_REGISTER = apiPath+'/user/register'; export const GET_USERNAME = apiPath+'/user/username'; export const GET_USER_EMAIL = apiPath+'/user/email'; +export const GET_VERIFY_USER_ACCOUNT = apiPath+'/user/verifyEmail'; //Public export const GET_PUBLIC_ORG_USER_LIST = apiPath+'/user/listOrg';