diff --git a/src/layout/MainLayout/Header/index.js b/src/layout/MainLayout/Header/index.js index 2fbc26f..58f66ad 100644 --- a/src/layout/MainLayout/Header/index.js +++ b/src/layout/MainLayout/Header/index.js @@ -74,62 +74,62 @@ function Header(props) { isGLDLoggedIn() ?
  • - Dashboard + Dashboard
  • - Application + Application
  • - Proof + Proof
  • - Payment + Payment
  • - Client + Client
    • - Users (GLD) + Users (GLD)
    • - Users (Individual) + Users (Individual)
    • - Users (Organization) + Users (Organization)
    • - Organization + Organization
    • - User Group + User Group
  • - Logout + Logout
  • :
  • - 主頁 + 主頁
  • - 我的公共啟事 + 我的公共啟事
  • - 校對記錄 + 校對記錄
  • - 付款記錄 + 付款記錄
  • - 設定 + 設定 {isPrimaryLoggedIn() ?
    • - 公司/機構用戶記錄 + 公司/機構用戶記錄
    : @@ -137,7 +137,7 @@ function Header(props) { }
  • - 登出 + 登出
  • ); @@ -145,10 +145,10 @@ function Header(props) { const logoutContent = (
  • - 登入 + 登入
  • - 申請 + 申請
  • ); diff --git a/src/pages/authentication/AuthWrapper.js b/src/pages/authentication/AuthWrapper.js index c96d079..fe37dd3 100644 --- a/src/pages/authentication/AuthWrapper.js +++ b/src/pages/authentication/AuthWrapper.js @@ -44,8 +44,8 @@ const AuthWrapper = ({ children }) => ( alignItems="center" spacing={2}> - 香港特別行政區政府 - 憲報 + 香港特別行政區政府 + 憲報 import('./auth-forms/BusCustomFormWizard'))); - const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); - // import CustomFormWizard from './auth-forms/BusCustomFormWizard'; - // import AuthWrapper from './AuthWrapperCustom'; - - // ================================|| REGISTER ||================================ // - const stepStyle = { - width:"40%", - boxShadow: 2, - backgroundColor: "#FFFFFF", - padding: 2, - "& .Mui-active": { - "&.MuiStepIcon-root": { - color: "warning.main", - fontSize: "2rem", - }, - "& .MuiStepConnector-line": { - borderColor: "warning.main" - } +// import { Link } from 'react-router-dom'; +import React, { useState } from 'react'; + +// material-ui +import { + Stepper, + Step, + StepButton, + // Grid, + Stack, + Typography, + Button, + +} from '@mui/material'; +import VisibilityIcon from '@mui/icons-material/Visibility'; + +// project import +import Loadable from 'components/Loadable'; +import { lazy } from 'react'; +const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/BusCustomFormWizard'))); +const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); +// import CustomFormWizard from './auth-forms/BusCustomFormWizard'; +// import AuthWrapper from './AuthWrapperCustom'; + +// ================================|| REGISTER ||================================ // +const stepStyle = { + width: "40%", + boxShadow: 2, + backgroundColor: "#FFFFFF", + padding: 2, + "& .Mui-active": { + "&.MuiStepIcon-root": { + color: "warning.main", + fontSize: "2rem", }, - "& .Mui-completed": { - "&.MuiStepIcon-root": { - color: "secondary.main", - fontSize: "2rem", - }, - "& .MuiStepConnector-line": { - borderColor: "secondary.main" - } + "& .MuiStepConnector-line": { + borderColor: "warning.main" + } + }, + "& .Mui-completed": { + "&.MuiStepIcon-root": { + color: "secondary.main", + fontSize: "2rem", + }, + "& .MuiStepConnector-line": { + borderColor: "secondary.main" } } - const steps = ['個人資料', '預覽', '完成提交']; +} +const steps = ['個人資料', '預覽', '完成提交']; - const BusRegister = () => { - const [activeStep, setActiveStep] = useState(0); - const [completed, setCompleted] = useState([false]); - const [updateValid, setUpdateValid] = useState(false); +const BusRegister = () => { + const [activeStep, setActiveStep] = useState(0); + const [completed, setCompleted] = useState([false]); + const [updateValid, setUpdateValid] = useState(false); - const totalSteps = () => { - return steps.length; - }; + const totalSteps = () => { + return steps.length; + }; - const completedSteps = () => { - return Object.keys(completed).length; - }; + const completedSteps = () => { + return Object.keys(completed).length; + }; - const isLastStep = () => { - return activeStep === totalSteps() - 1; - }; + const isLastStep = () => { + return activeStep === totalSteps() - 1; + }; - const allStepsCompleted = () => { - return completedSteps() === totalSteps(); - }; + const allStepsCompleted = () => { + return completedSteps() === totalSteps(); + }; - const handleNext = () => { - const newActiveStep = + const handleNext = () => { + const newActiveStep = isLastStep() && !allStepsCompleted() - ? // It's the last step, but not all steps have been completed, - // find the first step that has been completed - steps.findIndex((step, i) => !(i in completed)) - : activeStep + 1; - setActiveStep(newActiveStep); - scrollToTop(); - }; - - const handleBack = () => { - scrollToTop(); - setActiveStep((prevActiveStep) => prevActiveStep - 1); - }; - - const scrollToTop = () => { - window.scrollTo(0,0); - }; - - const handleReset = () => { - setActiveStep(0); - setCompleted({}); - }; - - return( - // - - - {steps.map((label, index) => ( - - { - index < 2 ? - ( - {label} - ) : - (} - // onClick={handleStep(index)} - > - {label} - ) - } - - - ))} - - {allStepsCompleted() ? ( - - - All steps completed - you're finished - - - - - - - ) : ( - - - - {/* */} - - - { activeStep === totalSteps() - 1 ? ( - - ):( - + + + ) : ( + + + + {/* */} + + + {activeStep === totalSteps() - 1 ? ( + + ) : ( + + ) + } + + {activeStep === totalSteps() - 2 ? + ( + - ) - } - - {activeStep === totalSteps() - 2 ? + ) : (activeStep === totalSteps() - 1 ? ( - - ) : ( activeStep === totalSteps() - 1 ? - ( - - ): - ( - // - ) + ) : + ( + // + ) )} - {/* {activeStep !== steps.length && + {/* {activeStep !== steps.length && (completed[activeStep] ? ( Step {activeStep + 1} already completed @@ -189,12 +191,12 @@ : 'Complete Step'} ))} */} - - - )} - - // - ); - }; - - export default BusRegister; + + + )} + + // + ); +}; + +export default BusRegister; diff --git a/src/pages/authentication/Register.js b/src/pages/authentication/Register.js index 1f5f133..1d1efa8 100644 --- a/src/pages/authentication/Register.js +++ b/src/pages/authentication/Register.js @@ -1,182 +1,182 @@ - // import { Link } from 'react-router-dom'; - import React,{useState - // ,useEffect - } from 'react'; +// import { Link } from 'react-router-dom'; +import React, { + useState + // ,useEffect +} from 'react'; - // material-ui - import { - Stepper, - Step, - StepButton, - // Grid, - Stack, - Typography, - Button, +// material-ui +import { + Stepper, + Step, + StepButton, + // Grid, + Stack, + Typography, + Button, +} from '@mui/material'; +import VisibilityIcon from '@mui/icons-material/Visibility'; - } from '@mui/material'; - import VisibilityIcon from '@mui/icons-material/Visibility'; - - // project import - import Loadable from 'components/Loadable'; - import { lazy } from 'react'; - const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/CustomFormWizard'))); - const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); - // ================================|| REGISTER ||================================ // - const stepStyle = { - width:"40%", - boxShadow: 1, - backgroundColor: "#FFFFFF", - padding: 2, - "& .Mui-active": { - "&.MuiStepIcon-root": { - color: "warning.main", - fontSize: "2rem", - }, - "& .MuiStepConnector-line": { - borderColor: "warning.main" - } +// project import +import Loadable from 'components/Loadable'; +import { lazy } from 'react'; +const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/CustomFormWizard'))); +const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); +// ================================|| REGISTER ||================================ // +const stepStyle = { + width: "40%", + boxShadow: 1, + backgroundColor: "#FFFFFF", + padding: 2, + "& .Mui-active": { + "&.MuiStepIcon-root": { + color: "warning.main", + fontSize: "2rem", + }, + "& .MuiStepConnector-line": { + borderColor: "warning.main" + } + }, + "& .Mui-completed": { + "&.MuiStepIcon-root": { + color: "secondary.main", + fontSize: "2rem", }, - "& .Mui-completed": { - "&.MuiStepIcon-root": { - color: "secondary.main", - fontSize: "2rem", - }, - "& .MuiStepConnector-line": { - borderColor: "secondary.main" - } + "& .MuiStepConnector-line": { + borderColor: "secondary.main" } } - const steps = ['個人資料', '預覽', '完成提交']; +} +const steps = ['個人資料', '預覽', '完成提交']; - const Register = () => { - const [activeStep, setActiveStep] = useState(0); - const [completed, setCompleted] = useState([false]); - const [updateValid, setUpdateValid] = useState(false); +const Register = () => { + const [activeStep, setActiveStep] = useState(0); + const [completed, setCompleted] = useState([false]); + const [updateValid, setUpdateValid] = useState(false); - const totalSteps = () => { - return steps.length; - }; + const totalSteps = () => { + return steps.length; + }; - const completedSteps = () => { - return Object.keys(completed).length; - }; + const completedSteps = () => { + return Object.keys(completed).length; + }; - const isLastStep = () => { - return activeStep === totalSteps() - 1; - }; + const isLastStep = () => { + return activeStep === totalSteps() - 1; + }; - const allStepsCompleted = () => { - return completedSteps() === totalSteps(); - }; + const allStepsCompleted = () => { + return completedSteps() === totalSteps(); + }; - const handleNext = () => { - const newActiveStep = + const handleNext = () => { + const newActiveStep = isLastStep() && !allStepsCompleted() - ? // It's the last step, but not all steps have been completed, - // find the first step that has been completed - steps.findIndex((step, i) => !(i in completed)) - : activeStep + 1; - setActiveStep(newActiveStep); - scrollToTop(); - }; - - const handleBack = () => { - scrollToTop(); - setActiveStep((prevActiveStep) => prevActiveStep - 1); - }; + ? // It's the last step, but not all steps have been completed, + // find the first step that has been completed + steps.findIndex((step, i) => !(i in completed)) + : activeStep + 1; + setActiveStep(newActiveStep); + scrollToTop(); + }; - const scrollToTop = () => { - window.scrollTo(0,0); - }; + const handleBack = () => { + scrollToTop(); + setActiveStep((prevActiveStep) => prevActiveStep - 1); + }; - const handleReset = () => { - setActiveStep(0); - setCompleted({}); - }; + const scrollToTop = () => { + window.scrollTo(0, 0); + }; - return( - // - - - {steps.map((label, index) => ( - - { - index < 2 ? - ( - {label} - ) : - (} - // onClick={handleStep(index)} - > - {label} - ) - } + const handleReset = () => { + setActiveStep(0); + setCompleted({}); + }; - - ))} - - {allStepsCompleted() ? ( - - - All steps completed - you're finished - - - - - - - ) : ( - - - - {/* */} - - - { activeStep === 2|| activeStep === 0? ( - - ):( - + + + ) : ( + + + + {/* */} + + + {activeStep === 2 || activeStep === 0 ? ( + + ) : ( + + ) + } + + {activeStep === totalSteps() - 2 ? + ( + - ) - } - - {activeStep === totalSteps() - 2 ? + ) : (activeStep === totalSteps() - 1 ? + ( + + ) : ( - - ) : ( activeStep === totalSteps() - 1 ? - ( - - ): - ( - // - ) + ) )} - {/* {activeStep !== steps.length && + {/* {activeStep !== steps.length && (completed[activeStep] ? ( Step {activeStep + 1} already completed @@ -188,12 +188,12 @@ : 'Complete Step'} ))} */} - - - )} - - // - ); - }; + + + )} + + // + ); +}; - export default Register; +export default Register; diff --git a/src/pages/authentication/RegisterCustom.js b/src/pages/authentication/RegisterCustom.js index afed143..b478d0c 100644 --- a/src/pages/authentication/RegisterCustom.js +++ b/src/pages/authentication/RegisterCustom.js @@ -7,14 +7,11 @@ 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'; - // ================================|| LOGIN ||================================ // - - const RegisterCustom = () => ( - - + + banner
    ( '& > *': { flexGrow: 1, flexBasis: '50%' - } + }, + backgroundColor: "secondary" }} + > @@ -38,7 +37,7 @@ const RegisterCustom = () => ( 個人用戶 - + @@ -50,7 +49,7 @@ const RegisterCustom = () => ( - + 需上載身份證明文件數碼檔案以進行網上申請。 @@ -59,7 +58,7 @@ const RegisterCustom = () => ( 機構/公司用戶 - + 需上載以下任何一份證明文件以進行網上申請。
    如:商業登記證;專業執業證書 diff --git a/src/pages/authentication/auth-forms/AuthLoginCustom.js b/src/pages/authentication/auth-forms/AuthLoginCustom.js index 637f9e0..ff1400e 100644 --- a/src/pages/authentication/auth-forms/AuthLoginCustom.js +++ b/src/pages/authentication/auth-forms/AuthLoginCustom.js @@ -4,8 +4,8 @@ import React, { lazy } from 'react'; import { Link as RouterLink } from 'react-router-dom'; -import {useNavigate} from 'react-router-dom'; -import {useForm,} from 'react-hook-form' +import { useNavigate } from 'react-router-dom'; +import { useForm, } from 'react-hook-form' // material-ui import { @@ -26,7 +26,7 @@ import { // third party import * as yup from 'yup'; -import { useFormik,FormikProvider } from 'formik'; +import { useFormik, FormikProvider } from 'formik'; // project import //import FirebaseSocial from './FirebaseSocial'; @@ -38,8 +38,8 @@ const PasswordAlertDialog = Loadable(lazy(() => import('./PasswordAlertDialog')) import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; // import axios from "axios"; import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; -import {useDispatch} from "react-redux"; -import {handleLogin} from "auth/index"; +import { useDispatch } from "react-redux"; +import { handleLogin } from "auth/index"; import useJwt from "../../../auth/jwt/useJwt"; import { handleLogoutFunction } from 'auth/index'; // ============================|| FIREBASE - LOGIN ||============================ // @@ -64,11 +64,11 @@ const AuthLoginCustom = () => { }; const tryLogin = () => { - if(isValid){ - dispatch(handleLogoutFunction()); + if (isValid) { + dispatch(handleLogoutFunction()); // setSumitting(true) useJwt - .login({username: values.username, password: values.password}) + .login({ username: values.username, password: values.password }) .then((response) => { console.log(response) const userData = { @@ -82,7 +82,7 @@ const AuthLoginCustom = () => { creditor: response.data.creditor, //avatar: require('src/assets/images/users/avatar-3.png').default, } - const data = {...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken} + const data = { ...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken } // setSuccess(true) dispatch(handleLogin(data)) navigate('/dashboard'); @@ -96,42 +96,41 @@ const AuthLoginCustom = () => { setErrorMassage(error.response.data.error) setOpen(true) }); - }else{ + } else { setOpen(true) } } const formik = useFormik({ - initialValues:({ - username: '', - password: '', - submit: null + initialValues: ({ + username: '', + password: '', + submit: null }), - validationSchema:yup.object().shape({ - // username: yup.string().min(6,'用戶名稱最少6位').required('請輸入用戶名稱'), - username: yup.string().required('請輸入用戶名稱'), - password: yup.string().min(8,'請輸入最少8位密碼').required('請輸入密碼') - .matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') - .matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') - .matches(/^(?=.*[0-9])/, '請包括最少1個數字') - .matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), + validationSchema: yup.object().shape({ + // username: yup.string().min(6,'用戶名稱最少6位').required('請輸入用戶名稱'), + username: yup.string().required('請輸入用戶名稱'), + password: yup.string().min(8, '請輸入最少8位密碼').required('請輸入密碼') + .matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') + .matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') + .matches(/^(?=.*[0-9])/, '請包括最少1個數字') + .matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), }), }); - const checkDataField = (data)=> { - if (data.username !==""&& - data.password !==""&& - handlePassword(data.password) - // &&handle6Digi(data.username) - ) - { - setisValid(true) - setIsButtonDisabled(false); - return isValid - }else{ - setisValid(false) - setIsButtonDisabled(true); - return isValid + const checkDataField = (data) => { + if (data.username !== "" && + data.password !== "" && + handlePassword(data.password) + // &&handle6Digi(data.username) + ) { + setisValid(true) + setIsButtonDisabled(false); + return isValid + } else { + setisValid(false) + setIsButtonDisabled(true); + return isValid } }; @@ -143,17 +142,17 @@ const AuthLoginCustom = () => { var numbers = /[0-9]/g; var symbol = /^(?=.*[!@#%&])/; if (!new_pass.match(lowerCase)) { - return false; + return false; } else if (!new_pass.match(upperCase)) { - return false; + return false; } else if (!new_pass.match(numbers)) { - return false; + return false; } else if (!new_pass.match(symbol)) { - return false; + return false; } else if (new_pass.length < 8) { return false; } else { - return true; + return true; } } @@ -162,123 +161,123 @@ const AuthLoginCustom = () => { }; const { values } = formik - useEffect(() => { - checkDataField(values) - }, [values]) + useEffect(() => { + checkDataField(values) + }, [values]) - const {handleSubmit} = useForm({}) + const { handleSubmit } = useForm({}) return ( - -
    - - - - 用戶登入名稱 - { - if (e.key === 'Enter') { - e.preventDefault(); - } - }, + + + + + + 用戶登入名稱 + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, }} - /> - {formik.touched.username && formik.errors.username && ( - - {formik.errors.username} - - )} - - - - - 密碼 - - - {showPassword ? : } - - - } - placeholder="" - /> - {formik.touched.password && formik.errors.password && ( - - {formik.errors.password} - - )} - - + /> + {formik.touched.username && formik.errors.username && ( + + {formik.errors.username} + + )} + + + + + 密碼 + + + {showPassword ? : } + + + } + placeholder="" + /> + {formik.touched.password && formik.errors.password && ( + + {formik.errors.password} + + )} + + - - - - - - - - - + + + + + + + + + 忘記密碼? - - - - - - - - - - - - 了解更多智方便 - - - - - - - + + + + + + + + + + + + 了解更多智方便 + + + + + + - - -
    +
    + + + ); }; diff --git a/src/pages/authentication/auth-forms/BusCustomFormWizard.js b/src/pages/authentication/auth-forms/BusCustomFormWizard.js index 907ae7d..9a3e264 100644 --- a/src/pages/authentication/auth-forms/BusCustomFormWizard.js +++ b/src/pages/authentication/auth-forms/BusCustomFormWizard.js @@ -1,26 +1,26 @@ -import { useEffect, useState, } from 'react'; +import { useEffect, useState, } from 'react'; // material-ui import { - Box, - Button, - FormControl, - FormHelperText, - Grid, IconButton, - InputAdornment, - InputLabel, OutlinedInput, - Stack, - Typography, - FormGroup, - TextField, - Checkbox - // MenuItem + Box, + Button, + FormControl, + FormHelperText, + Grid, IconButton, + InputAdornment, + InputLabel, OutlinedInput, + Stack, + Typography, + FormGroup, + TextField, + Checkbox + // MenuItem } from '@mui/material'; -import {useForm,} from 'react-hook-form' +import { useForm, } from 'react-hook-form' import Autocomplete from "@mui/material/Autocomplete"; // third party -import { useFormik,FormikProvider } from 'formik'; +import { useFormik, FormikProvider } from 'formik'; import * as yup from 'yup'; // import axios from "axios"; @@ -30,7 +30,7 @@ import * as yup from 'yup'; import { strengthColorChi, strengthIndicator } from 'utils/password-strength'; // import {apiPath} from "auth/utils"; import axios from "axios"; -import {POST_PUBLIC_USER_REGISTER, POST_CAPTCHA} from "utils/ApiPathConst"; +import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, GET_USERNAME } from "utils/ApiPathConst"; // import * as HttpUtils from 'utils/HttpUtils'; import * as ComboData from "utils/ComboData"; @@ -50,11 +50,13 @@ import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; import { Link } from 'react-router-dom'; import * as HttpUtils from "../../../utils/HttpUtils" import LoopIcon from '@mui/icons-material/Loop'; +import { useTheme } from '@mui/material/styles'; //import { Invaild } from 'utils/IconUtils'; // ============================|| FIREBASE - REGISTER ||============================ // const BusCustomFormWizard = (props) => { - + + const theme = useTheme() const [level, setLevel] = useState(); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setshowConfirmPassword] = useState(false); @@ -63,6 +65,7 @@ const BusCustomFormWizard = (props) => { const [checkUpload, setCheckUpload] = useState(false); const [isLoading, setLoding] = useState(true); const [updateRows, setUpdateRows] = useState([]); + const [userNameList, setUserNameList] = useState([]); const [captcha, setCaptcha] = useState([]); const [captchaImg, setCaptchaImage] = useState([]); @@ -89,17 +92,17 @@ const BusCustomFormWizard = (props) => { const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false); const [isValid, setisValid] = useState(false); const [checkCountry, setCheckCountry] = useState(false); - + const address4ComboList = ComboData.district; const address5ComboList = ComboData.country; const termsAndCon = "此網址由香港特別行政區政府物流服務署製作及管理。本署會盡力確保網址上的資料無誤,\n" - + "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址" - + "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評" - + "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港" - + "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限" - + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" - + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" - + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" + + "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址" + + "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評" + + "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港" + + "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限" + + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" + + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" + + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" const refType = "identification"; useEffect(() => { @@ -111,68 +114,76 @@ const BusCustomFormWizard = (props) => { // localStorage.setItem("checkCode",null); // localStorage.setItem("base64Url",null); // }else{ - onCaptchaChange(); + onCaptchaChange(); // } - - + axios.get(`${GET_USERNAME}`) + .then((response) => { + if (response.status === 200) { + setUserNameList(response.data); + } + + }) + .catch(error => { + console.log(error); + return false; + }); }, []); - const onCaptchaChange = ()=>{ + const onCaptchaChange = () => { HttpUtils.post({ url: POST_CAPTCHA, - params:{width: 130, height: 40}, - onSuccess:(responseData)=>{ - localStorage.setItem("checkCode",responseData.checkCode); - localStorage.setItem("base64Url",responseData.base64Url); + params: { width: 130, height: 40 }, + onSuccess: (responseData) => { + localStorage.setItem("checkCode", responseData.checkCode); + localStorage.setItem("base64Url", responseData.base64Url); setCaptcha(localStorage.getItem('checkCode')); setCaptchaImage(localStorage.getItem('base64Url')); } }); } - const checkDataField = (data)=> { + const checkDataField = (data) => { // console.log(data.brExpiryDate) - if (data.username !==""&& - data.password !==""&& - data.confirmPassword !==""&& - data.password == data.confirmPassword&& + if (data.username !== "" && + data.password !== "" && + data.confirmPassword !== "" && + data.password == data.confirmPassword && // (data.enCompanyName !=="" || selectedAddress5 ==="內地")&& - (data.chCompanyName !=="" || data.enCompanyName !== "")&& - data.enName !==""&& - data.chName !==""&& - data.address1 !==""&& - data.email !==""&& - data.emailConfirm !==""&& - data.email == data.emailConfirm&& - data.phone !==""&& - data.phoneCountryCode !==""&& - termsAndConAccept == true&& - fileList.length!==0&& - data.captchaField&& - data.brNo!==""&& - data.brExpiryDate!==""&& - handlePassword(data.password)&& - handleEmail(data.email)&& - handlePhone(data.phone)&& - handleUserName(data.username)&& + (data.chCompanyName !== "" || data.enCompanyName !== "") && + data.enName !== "" && + data.chName !== "" && + data.address1 !== "" && + data.email !== "" && + data.emailConfirm !== "" && + data.email == data.emailConfirm && + data.phone !== "" && + data.phoneCountryCode !== "" && + termsAndConAccept == true && + fileList.length !== 0 && + data.captchaField && + data.brNo !== "" && + data.brExpiryDate !== "" && + handlePassword(data.password) && + handleEmail(data.email) && + handlePhone(data.phone) && + handleUserName(data.username) && handleCaptcha(data.captchaField) - ) - { + ) { setisValid(true) return isValid - }else{ + } else { setisValid(false) return isValid } }; const handleCheckBoxChange = (event) => { - console.log (event.target) - if(event.target.name == 'termsAndConAccept'){ + console.log(event.target) + if (event.target.name == 'termsAndConAccept') { setTermsAndConAccept(event.target.checked) setTermsAndConNotAccept(!event.target.checked) } - if(event.target.name == 'termsAndConNotAccept'){ + if (event.target.name == 'termsAndConNotAccept') { setTermsAndConNotAccept(event.target.checked) setTermsAndConAccept(!event.target.checked) } @@ -183,8 +194,8 @@ const BusCustomFormWizard = (props) => { var updateRowsIndex = updateRows.length; const saveFileList = []; - if (updateRowsIndex!=null){ - for (let i = 0; i < updateRowsIndex; i++){ + if (updateRowsIndex != null) { + for (let i = 0; i < updateRowsIndex; i++) { const file = updateRows[i] file.id = i; updateRowList.items.add(file); @@ -193,21 +204,21 @@ const BusCustomFormWizard = (props) => { let updatedFileList = updateRowList.files; setFileList(updatedFileList); setFileListData(saveFileList) - + } }, [updateRows]); - const handleFileUpload = (event)=>{ + const handleFileUpload = (event) => { let updateList = new DataTransfer(); let currentFileList = fileListData; const uploadFileList = event.target.files; const saveFileList = []; var currentIndex = 0; - if (currentFileList.length!=null){ + if (currentFileList.length != null) { currentIndex = currentFileList.length; - for (let i = 0; i < currentIndex; i++){ + for (let i = 0; i < currentIndex; i++) { const file = currentFileList[i] // file.id = currentIndex; updateList.items.add(file); @@ -215,7 +226,7 @@ const BusCustomFormWizard = (props) => { } } - for (let i = 0; i < uploadFileList.length && currentIndex<5; i++){ + for (let i = 0; i < uploadFileList.length && currentIndex < 5; i++) { const file = event.target.files[i] let isDuplicate = false; @@ -226,8 +237,8 @@ const BusCustomFormWizard = (props) => { break; } } - if (!isDuplicate && i+currentIndex<5) { - file.id = currentIndex+i + if (!isDuplicate && i + currentIndex < 5) { + file.id = currentIndex + i saveFileList.push(file) updateList.items.add(file); } @@ -246,27 +257,27 @@ const BusCustomFormWizard = (props) => { useEffect(() => { checkDataField(values) - }, [selectedAddress4,selectedAddress5, - termsAndConAccept,termsAndConNotAccept,fileList]) + }, [selectedAddress4, selectedAddress5, + termsAndConAccept, termsAndConNotAccept, fileList]) useEffect(() => { - props.step ==2?_onSubmit():null; + props.step == 2 ? _onSubmit() : null; onCaptchaChange(); checkDataField(values) }, [props.step]) - const {handleSubmit} = useForm({}) + const { handleSubmit } = useForm({}) const _onSubmit = () => { setLoding(true); values.address4 = selectedAddress4 values.address5 = selectedAddress5 // console.log(values) - const busUserAddress = { - "addressLine1":"", - "addressLine2":"", - "addressLine3":"", - "district":"", - "country":"" + const busUserAddress = { + "addressLine1": "", + "addressLine2": "", + "addressLine3": "", + "district": "", + "country": "" }; busUserAddress.addressLine1 = values.address1 busUserAddress.addressLine2 = values.address2 @@ -275,66 +286,66 @@ const BusCustomFormWizard = (props) => { busUserAddress.country = values.address5 const userFaxNo = { - "countryCode":values.faxCountryCode, - "faxNumber":values.fax, + "countryCode": values.faxCountryCode, + "faxNumber": values.fax, }; const busUserContactTel = { - "countryCode":values.phoneCountryCode, - "phoneNumber":values.phone, + "countryCode": values.phoneCountryCode, + "phoneNumber": values.phone, }; let tncFlag = false; - if (termsAndConAccept){ + if (termsAndConAccept) { tncFlag = true } - if (termsAndConNotAccept){ + if (termsAndConNotAccept) { tncFlag = false } const user = { username: values.username, - password: values.password, - name: values.username, - enCompanyName: values.enCompanyName, - chCompanyName: values.chCompanyName, - emailBus: values.email, - brNo:values.brNo, - brExpiryDate:values.brExpiryDate, - contactPerson: values.enName, - tncFlag:tncFlag, - type:"ORG" + password: values.password, + name: values.username, + enCompanyName: values.enCompanyName, + chCompanyName: values.chCompanyName, + emailBus: values.email, + brNo: values.brNo, + brExpiryDate: values.brExpiryDate, + contactPerson: values.enName, + tncFlag: tncFlag, + type: "ORG" }; var formData = new FormData(); - for (let i = 0; i < fileListData.length; i++){ + for (let i = 0; i < fileListData.length; i++) { const file = fileListData[i] formData.append("multipartFileList", file); } formData.append("refType", refType); - + for (const [key, value] of Object.entries(user)) { formData.append(key, value); } - + formData.append("userFaxNo", JSON.stringify(userFaxNo)); formData.append("busUserContactTel", JSON.stringify(busUserContactTel)); formData.append("busUserAddress", JSON.stringify(busUserAddress)); - if (isValid){ - axios.post(POST_PUBLIC_USER_REGISTER, formData,{ + if (isValid) { + axios.post(POST_PUBLIC_USER_REGISTER, formData, { headers: { - "Content-Type":"multipart/form-data" + "Content-Type": "multipart/form-data" } }) - .then((response) => { - console.log(response) - setCheckUpload(true) - setLoding(false); - }) - .catch(error => { - console.error(error); - setLoding(false); - }); - }else{ + .then((response) => { + console.log(response) + setCheckUpload(true) + setLoding(false); + }) + .catch(error => { + console.error(error); + setLoding(false); + }); + } else { setLoding(false); } } @@ -354,7 +365,7 @@ const BusCustomFormWizard = (props) => { return false; } else if (username.match(symbol)) { return false; - }else if (username.match(space)) { + } else if (username.match(space)) { return false; } else { return true; @@ -383,10 +394,10 @@ const BusCustomFormWizard = (props) => { return false; } else if (new_pass.length < 8) { return false; - } + } else if (new_pass.match(space)) { return false; - }else { + } else { // console.log("password true") return true; } @@ -396,15 +407,18 @@ const BusCustomFormWizard = (props) => { var validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; if (!email.match(validRegex)) { return false; - }else{ + } else { return true; } } - + + function displayErrorMsg(errorMsg) { + return {errorMsg} + } const formik = useFormik({ - initialValues:({ - username:'', + initialValues: ({ + username: '', enName: '', enCompanyName: '', chCompanyName: '', @@ -414,52 +428,62 @@ const BusCustomFormWizard = (props) => { address3: '', password: '', confirmPassword: '', - phone:'', - phoneCountryCode:'852', + phone: '', + phoneCountryCode: '852', submit: null, - fax:'', - faxCountryCode:'852', - brExpiryDate:'', - brNo:'', - emailConfirm:'', - captchaField:'' + fax: '', + faxCountryCode: '852', + brExpiryDate: '', + brNo: '', + emailConfirm: '', + captchaField: '' }), - - validationSchema:yup.object().shape({ - username: yup.string().min(6,'用戶名稱最少6位').required('請輸入用戶名稱') - .matches(/^[aA-zZ0-9\s]+$/, "用戶名稱不包含特殊字符") - .matches(/^\S*$/, '用戶名稱不包含空格'), - password: yup.string().min(8,'請輸入最少8位密碼').required('請輸入密碼') - .matches(/^\S*$/, '密碼不包含空格') - .matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') - .matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') - .matches(/^(?=.*[0-9])/, '請包括最少1個數字') - .matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), - confirmPassword: yup.string().min(8,'請最少輸入8位密碼').required('請確認密碼').oneOf([yup.ref('password'), null], '請輸入相同密碼'), - enName: yup.string().max(255).required('請輸入英文姓名'), - enCompanyName: yup.string().matches(/^[^$^*()]+$/, 'No special characters $/^/*/(/)').when('chCompanyName', { + + validationSchema: yup.object().shape({ + username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg('請輸入用戶名稱')).test( + "checkUserNameUsed", + displayErrorMsg("此用戶登入名稱已被注冊,請使用其他用戶登入名稱"), + function (value) { + if (userNameList.some(item => item.username === value)) { + return false + } else { + return true + } + } + ) + .matches(/^[aA-zZ0-9\s]+$/, {message: displayErrorMsg("用戶名稱不包含特殊字符")}) + .matches(/^\S*$/, {message: displayErrorMsg('用戶名稱不包含空格')}), + password: yup.string().min(8, displayErrorMsg('請輸入最少8位密碼')).required(displayErrorMsg('請輸入密碼')) + .matches(/^\S*$/, {message: displayErrorMsg('密碼不包含空格')}) + .matches(/^(?=.*[a-z])/, {message: displayErrorMsg('請包括最少1個小寫字母')}) + .matches(/^(?=.*[A-Z])/, {message: displayErrorMsg('請包括最少1個大寫字母')}) + .matches(/^(?=.*[0-9])/, {message: displayErrorMsg('請包括最少1個數字')}) + .matches(/^(?=.*[!@#%&])/, {message: displayErrorMsg('請包括最少1個特殊字符')}), + confirmPassword: yup.string().min(8, displayErrorMsg('請最少輸入8位密碼')).required(displayErrorMsg('請確認密碼')).oneOf([yup.ref('password'), null], displayErrorMsg('請輸入相同密碼')), + enName: yup.string().max(255).required(displayErrorMsg('請輸入英文姓名')), + enCompanyName: yup.string().matches(/^[^$^*()]+$/, {message: displayErrorMsg('No special characters $/^/*/(/)')}).when('chCompanyName', { is: (chCompanyName) => !chCompanyName || chCompanyName.length === 0, - then: yup.string().required('Please enter either English or Chinese name'), - }), - chCompanyName: yup.string().matches(/^[^$^*()]+$/, '不包含特殊字符 $/^/*/(/)').when('enCompanyName', { - is: (enCompanyName) => !enCompanyName || enCompanyName.length === 0, - then: yup.string().required('請輸入英文或中文名稱'), + then: yup.string().required(displayErrorMsg('Please enter either English or Chinese name')), + }), + chCompanyName: yup.string().matches(/^[^$^*()]+$/, {message: displayErrorMsg('不包含特殊字符 $/^/*/(/)')}).when('enCompanyName', { + is: (enCompanyName) => !enCompanyName || enCompanyName.length === 0, + then: yup.string().required(displayErrorMsg('請輸入英文或中文名稱')), }), - chName: yup.string().max(255).required('請輸入中文姓名'), - address1: yup.string().max(255).required('請輸入第一行地址'), - address2: yup.string().max(255).required('請輸入第二行地址'), - address3: yup.string().max(255).required('請輸入第三行地址'), - email: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵'), - emailConfirm: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵').oneOf([yup.ref('email'), null], '請輸入相同電郵'), - phoneCountryCode: yup.string().min(2,'請輸入最少2位數字').required('請輸入國際區號'), - faxCountryCode: yup.string().min(2,'請輸入最少2位數字'), - phone: yup.string().min(8,'請輸入最少8位數字').required('請輸入聯絡電話'), - fax: yup.string().min(8,'請輸入最少8位數字'), - brExpiryDate: yup.date().min(new Date().toISOString().split("T")[0], '請輸入商業登記證有效日期').max("2099-12-31", '請輸入商業登記證有效日期').required('請輸入商業登記證有效日期'), - brNo: yup.string().min(8,'請輸入商業登記證號碼').required('請輸入商業登記證號碼'), - captchaField: yup.string().required('請輸入驗證').oneOf([captcha], '請輸入有效驗證'), + chName: yup.string().max(255).required(displayErrorMsg('請輸入中文姓名')), + address1: yup.string().max(255).required(displayErrorMsg('請輸入第一行地址')), + address2: yup.string().max(255).required(displayErrorMsg('請輸入第二行地址')), + address3: yup.string().max(255).required(displayErrorMsg('請輸入第三行地址')), + email: yup.string().email(displayErrorMsg('請輸入電郵格式')).max(255).required(displayErrorMsg('請輸入電郵')), + emailConfirm: yup.string().email(displayErrorMsg('請輸入電郵格式')).max(255).required(displayErrorMsg('請輸入電郵')).oneOf([yup.ref('email'), null], displayErrorMsg('請輸入相同電郵')), + phoneCountryCode: yup.string().min(2, displayErrorMsg('請輸入最少2位數字')).required(displayErrorMsg('請輸入國際區號')), + faxCountryCode: yup.string().min(2, displayErrorMsg('請輸入最少2位數字')), + phone: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')).required(displayErrorMsg('請輸入聯絡電話')), + fax: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')), + brExpiryDate: yup.date().min(new Date().toISOString().split("T")[0], displayErrorMsg('請輸入商業登記證有效日期')).max("2099-12-31", displayErrorMsg('請輸入商業登記證有效日期')).required(displayErrorMsg('請輸入商業登記證有效日期')), + brNo: yup.string().min(8, displayErrorMsg('請輸入商業登記證號碼')).required(displayErrorMsg('請輸入商業登記證號碼')), + captchaField: yup.string().required(displayErrorMsg('請輸入驗證')).oneOf([captcha], displayErrorMsg('請輸入有效驗證')), }, ['enCompanyName', 'chCompanyName']), - + }); const handleReset = (resetForm) => { @@ -475,22 +499,22 @@ const BusCustomFormWizard = (props) => { const { values } = formik useEffect(() => { checkDataField(values) - }, [values]) + }, [values]) return (
    - {/* Input Form */} + {/* Input Form */} - -
    - 成為新的機構/公司用戶 + +
    + 成為新的機構/公司用戶
    - 註有*的項目必須輸入資料 - 你的登入資料 + 註有*的項目必須輸入資料 + 你的登入資料 {/* Already have an account? */} @@ -500,8 +524,11 @@ const BusCustomFormWizard = (props) => { - 用戶登入名稱 - * + + + 用戶登入名稱 + * + { /> {formik.touched.username && formik.errors.username && ( - {formik.errors.username} + {formik.errors.username} )} @@ -531,10 +558,13 @@ const BusCustomFormWizard = (props) => { - + - 密碼 - * + + + 密碼 + * + { changePassword(e.target.value); }} endAdornment={ - - - {showPassword ? : } - - + + + {showPassword ? : } + + } placeholder="密碼" onBlur={formik.handleBlur} @@ -573,27 +603,30 @@ const BusCustomFormWizard = (props) => { /> {formik.touched.password && formik.errors.password && ( - {formik.errors.password} + {formik.errors.password} )} - - - - - - - {level?.label} - + + + + + + + {level?.label} + + - - 確認密碼 - * + + + 確認密碼 + * + { }, }} endAdornment={ - - - {showConfirmPassword ? : } - - + + + {showConfirmPassword ? : } + + } placeholder="確認密碼" fullWidth @@ -631,43 +664,46 @@ const BusCustomFormWizard = (props) => { /> {formik.touched.confirmPassword && formik.errors.confirmPassword && ( - {formik.errors.confirmPassword} + {formik.errors.confirmPassword} )} - -
    - •至少8個字元,字元越多越好
    - •字母和數字的混合
    - •英文字母大寫與小寫的混合
    - •至少包含一個特殊符號,例如,@ # ? + +
    + •至少8個字元,字元越多越好
    + •字母和數字的混合
    + •英文字母大寫與小寫的混合
    + •至少包含一個特殊符號,例如,@ # ?
    -
    +
    - 你的機構/公司資料 + 你的機構/公司資料 {/* Already have an account? */} - + - -
    - •請輸入機構/公司英文名稱或中文名稱
    - •Please enter the English/Chinese name of the organisation/company -
    + +
    + •請輸入機構/公司英文名稱或中文名稱
    + •Please enter the English/Chinese name of the organisation/company +
    - 機構/公司英文名稱 + + + 機構/公司英文名稱 + { /> {formik.touched.enCompanyName && formik.errors.enCompanyName && selectedAddress5 !== "內地" && ( - {formik.errors.enCompanyName} + {formik.errors.enCompanyName} )} - 機構/公司中文名稱 + + + 機構/公司中文名稱 + { /> {formik.touched.chCompanyName && formik.errors.chCompanyName && ( - {formik.errors.chCompanyName} + {formik.errors.chCompanyName} )} - 商業登記證號碼 - * + + + 商業登記證號碼 + * + { /> {formik.touched.brNo && formik.errors.brNo && ( - {formik.errors.brNo} + {formik.errors.brNo} )} - 商業登記證有效日期 - * + + + 商業登記證有效日期 + * + { /> {formik.touched.brExpiryDate && formik.errors.brExpiryDate && ( - {formik.errors.brExpiryDate} + {formik.errors.brExpiryDate} )} - 地址 - * + + + 地址 + * + { }} /> { - setSelectedAddress4(newValue); - }} - sx={{"& .MuiInputBase-root": { height: "41px" },"#address4-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} - renderInput={(params) => } + disablePortal + id="address4-combo" + value={selectedAddress4} + options={address4ComboList} + disabled={checkCountry} + onChange={(event, newValue) => { + setSelectedAddress4(newValue); + }} + sx={{ "& .MuiInputBase-root": { height: "41px" }, "#address4-combo": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }} + renderInput={(params) => } /> { - if (newValue !== null){ - setSelectedAddress5(newValue); - if(newValue=='香港'){ - setCheckCountry(false) - }else{ - setSelectedAddress4(""); - setCheckCountry(true) - } - }else{ - setSelectedAddress4(""); - setCheckCountry(true) - } - }} - - sx={{"& .MuiInputBase-root": { height: "41px" },"#address5-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} - renderInput={(params) => } + disablePortal + id="address5-combo" + value={selectedAddress5} + options={address5ComboList} + onChange={(event, newValue) => { + if (newValue !== null) { + setSelectedAddress5(newValue); + if (newValue == '香港') { + setCheckCountry(false) + } else { + setSelectedAddress4(""); + setCheckCountry(true) + } + } else { + setSelectedAddress4(""); + setCheckCountry(true) + } + }} + + sx={{ "& .MuiInputBase-root": { height: "41px" }, "#address5-combo": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }} + renderInput={(params) => } /> {formik.touched.address1 && formik.errors.address1 && ( - {formik.errors.address1} + {formik.errors.address1} )} {formik.touched.address2 && formik.errors.address2 && ( - {formik.errors.address2} + {formik.errors.address2} )} {formik.touched.address3 && formik.errors.address3 && ( - {formik.errors.address3} + {formik.errors.address3} )} - 你的聯絡資料 + 你的聯絡資料 - 姓名 - * + + + 姓名 + * + { /> {formik.touched.enName && formik.errors.enName && ( - {formik.errors.enName} + {formik.errors.enName} )} @@ -929,9 +980,12 @@ const BusCustomFormWizard = (props) => { - - 電郵 - * + + + + 電郵 + * + { /> {formik.touched.email && formik.errors.email && ( - {formik.errors.email} + {formik.errors.email} )} - 確認電郵 - * + + + 確認電郵 + * + { /> {formik.touched.emailConfirm && formik.errors.emailConfirm && ( - {formik.errors.emailConfirm} + {formik.errors.emailConfirm} )} - + - + - - 聯絡電話 - * + + + + 聯絡電話 + * + { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("phoneCountryCode",value); + formik.setFieldValue("phoneCountryCode", value); }} placeholder="國際區號" error={Boolean(formik.touched.phone && formik.errors.phone)} @@ -1026,7 +1086,7 @@ const BusCustomFormWizard = (props) => { } }, }} - sx={{width:'25%'}} + sx={{ width: '25%' }} /> { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("phone",value); + formik.setFieldValue("phone", value); }} placeholder="聯絡電話" error={Boolean(formik.touched.phone && formik.errors.phone)} @@ -1052,23 +1112,27 @@ const BusCustomFormWizard = (props) => { } }, }} - sx={{width:'75%'}} + sx={{ width: '75%' }} /> {formik.touched.phone && formik.errors.phone && ( - {formik.errors.phone} + {formik.errors.phone} )} - + - 傳真號碼 + + + 傳真號碼 + + { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("faxCountryCode",value); + formik.setFieldValue("faxCountryCode", value); }} placeholder="國際區號" inputProps={{ @@ -1094,7 +1158,7 @@ const BusCustomFormWizard = (props) => { } }, }} - sx={{width:'25%'}} + sx={{ width: '25%' }} /> { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("fax",value); + formik.setFieldValue("fax", value); }} placeholder="傳真號碼" inputProps={{ @@ -1119,12 +1183,12 @@ const BusCustomFormWizard = (props) => { } }, }} - sx={{width:'75%'}} + sx={{ width: '75%' }} /> - + @@ -1132,27 +1196,27 @@ const BusCustomFormWizard = (props) => { - 商業登記證及其他文件 - * - - 請上傳你的 有效商業登記證及其他文件 的數碼檔案,以驗證你的身份。 + 商業登記證及其他文件 + * + + 請上傳你的 有效商業登記證及其他文件 的數碼檔案,以驗證你的身份。 {/* 如: 香港身份證; 護照; 中國內地身份證等 */} - {/* */} - {fileList !=null? - :null} + {fileList != null ? + : null} {/* @@ -1165,15 +1229,15 @@ const BusCustomFormWizard = (props) => { - + 條款和條件 - * + * - + {termsAndCon} @@ -1182,7 +1246,7 @@ const BusCustomFormWizard = (props) => { - + { color="primary" size="small" /> - 我接受 + 我接受 - + - 我不接受 + /> + 我不接受 - + - + 驗證 - * + * - - - - - - {onCaptchaChange()}}> - - - - - { - const value = event.target.value; - formik.setFieldValue("captchaField",value); - }} - sx={{width:'75%'}} - /> - - + + + + + + { onCaptchaChange() }}> + + + + + { + const value = event.target.value; + formik.setFieldValue("captchaField", value); + }} + sx={{ width: '75%' }} + /> + + {formik.touched.captchaField && formik.errors.captchaField && ( - {formik.errors.captchaField} + {formik.errors.captchaField} )} @@ -1257,16 +1321,16 @@ const BusCustomFormWizard = (props) => { - {/* Preview Form */} - + {/* Preview Form */} + -
    - 成為新的機構/公司用戶 +
    + 成為新的機構/公司用戶
    {/* 註有*的項目必須輸入資料 */} - 你的登入資料 + 你的登入資料 {/* Already have an account? */} @@ -1276,18 +1340,18 @@ const BusCustomFormWizard = (props) => { - - 用戶登入名稱: + + 用戶登入名稱: - + {formik.values.username} - 你的機構/公司資料 - {/* + 你的機構/公司資料 + {/* Already have an account? */} @@ -1295,20 +1359,20 @@ const BusCustomFormWizard = (props) => { - - 機構/公司英文名稱: + + 機構/公司英文名稱: - + {formik.values.enCompanyName} - - 機構/公司中文名稱: + + 機構/公司中文名稱: - + {formik.values.chCompanyName} @@ -1316,7 +1380,7 @@ const BusCustomFormWizard = (props) => { - + 商業登記證 @@ -1324,96 +1388,106 @@ const BusCustomFormWizard = (props) => { - - 商業登記證號碼: + + 商業登記證號碼: - + {formik.values.brNo} - - 商業登記證有效日期: + + 商業登記證有效日期: - + {formik.values.brExpiryDate} - + - + 地址: - + {formik.values.address1} - {formik.values.address2!=null? - + {formik.values.address2 != null ? + {formik.values.address2} - :null} - {formik.values.address3!=null? - - {formik.values.address3} - - :null} - {selectedAddress5==("香港")? - - 區域 (只適用於香港): {selectedAddress4} + : null} + {formik.values.address3 != null ? + + {formik.values.address3} - :null} - - 國家/地區: {selectedAddress5} - + : null} + {selectedAddress5 == ("香港") ? + + + 區域 (只適用於香港): + + + {selectedAddress4} + + + : null} + + + 國家/地區: + + + {selectedAddress5} + + - 你的聯絡資料 + 你的聯絡資料 - + 英文名稱: - + {formik.values.enName} - + 電郵: - + {formik.values.email} - + 聯絡電話: - + +{formik.values.phoneCountryCode} {formik.values.phone} - + 傳真號碼: - + +{formik.values.faxCountryCode} {formik.values.fax} @@ -1422,9 +1496,9 @@ const BusCustomFormWizard = (props) => { - 身份證明文件 - {fileList !=null? - :null} + 身份證明文件 + {fileList != null ? + : null} @@ -1434,26 +1508,26 @@ const BusCustomFormWizard = (props) => { {/* Submit page */} - + - {isLoading ? - : + {isLoading ? + : - {checkUpload? - // SUCCESS page + {checkUpload ? + // SUCCESS page - + 帳戶申請已成功提交。 驗證電郵將發送到你的電郵地址,請要指示完成驗證及登入系統。 - + - : - // ERROR page + : + // ERROR page {/* */} - + 申請失敗,請稍後嘗試 - + } diff --git a/src/pages/authentication/auth-forms/CustomFormWizard.js b/src/pages/authentication/auth-forms/CustomFormWizard.js index bd5cd0f..50f33d3 100644 --- a/src/pages/authentication/auth-forms/CustomFormWizard.js +++ b/src/pages/authentication/auth-forms/CustomFormWizard.js @@ -1,26 +1,26 @@ -import { useEffect, useState, } from 'react'; +import { useEffect, useState, } from 'react'; // material-ui import { - Box, - Button, - FormControl, - FormHelperText, - Grid, IconButton, - InputAdornment, - InputLabel, OutlinedInput, - Stack, - Typography, - FormGroup, - TextField, - Checkbox - // MenuItem + Box, + Button, + FormControl, + FormHelperText, + Grid, IconButton, + InputAdornment, + InputLabel, OutlinedInput, + Stack, + Typography, + FormGroup, + TextField, + Checkbox + // MenuItem } from '@mui/material'; -import {useForm,} from 'react-hook-form' +import { useForm, } from 'react-hook-form' import Autocomplete from "@mui/material/Autocomplete"; // third party -import { useFormik,FormikProvider } from 'formik'; +import { useFormik, FormikProvider } from 'formik'; import * as yup from 'yup'; // import axios from "axios"; @@ -29,7 +29,7 @@ import * as yup from 'yup'; import { strengthColorChi, strengthIndicator } from 'utils/password-strength'; // import {apiPath} from "auth/utils"; import axios from "axios"; -import {POST_PUBLIC_USER_REGISTER,POST_CAPTCHA, GET_USERNAME} from "utils/ApiPathConst"; +import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, GET_USERNAME } from "utils/ApiPathConst"; // import * as HttpUtils from 'utils/HttpUtils'; import * as ComboData from "utils/ComboData"; @@ -49,11 +49,13 @@ import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; import { Link } from 'react-router-dom'; import * as HttpUtils from "../../../utils/HttpUtils"; import LoopIcon from '@mui/icons-material/Loop'; +import { useTheme } from '@mui/material/styles'; // ============================|| FIREBASE - REGISTER ||============================ // const CustomFormWizard = (props) => { - + + const theme = useTheme() const [level, setLevel] = useState(); const [showPassword, setShowPassword] = useState(false); const [showConfirmPassword, setshowConfirmPassword] = useState(false); @@ -67,7 +69,6 @@ const CustomFormWizard = (props) => { const [captcha, setCaptcha] = useState([]); const [captchaImg, setCaptchaImage] = useState([]); - const handleClickShowPassword = () => { setShowPassword(!showPassword); }; @@ -98,13 +99,13 @@ const CustomFormWizard = (props) => { const address4ComboList = ComboData.district; const address5ComboList = ComboData.country; const termsAndCon = "此網址由香港特別行政區政府物流服務署製作及管理。本署會盡力確保網址上的資料無誤,\n" - + "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址" - + "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評" - + "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港" - + "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限" - + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" - + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" - + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" + + "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址" + + "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評" + + "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港" + + "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限" + + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" + + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" + + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" const refType = "identification"; useEffect(() => { @@ -115,7 +116,7 @@ const CustomFormWizard = (props) => { if (response.status === 200) { setUserNameList(response.data); } - + }) .catch(error => { console.log(error); @@ -123,13 +124,13 @@ const CustomFormWizard = (props) => { }); }, []); - const onCaptchaChange = ()=>{ + const onCaptchaChange = () => { HttpUtils.post({ url: POST_CAPTCHA, - params:{width: 130, height: 40}, - onSuccess:(responseData)=>{ - localStorage.setItem("checkCode",responseData.checkCode); - localStorage.setItem("base64Url",responseData.base64Url); + params: { width: 130, height: 40 }, + onSuccess: (responseData) => { + localStorage.setItem("checkCode", responseData.checkCode); + localStorage.setItem("base64Url", responseData.base64Url); setCaptcha(localStorage.getItem('checkCode')); setCaptchaImage(localStorage.getItem('base64Url')); } @@ -137,46 +138,45 @@ const CustomFormWizard = (props) => { } - const checkDataField = (data)=> { - if (data.username !==""&& - data.password !==""&& - data.confirmPassword !==""&& - data.password == data.confirmPassword&& - selectedIdDocType.type !==""&& - data.idNo !==""&& - (data.enName !=="" || selectedIdDocType.type === "CNID")&& - data.chName !==""&& - data.address1 !==""&& - data.email !==""&& - data.emailConfirm !==""&& - data.email == data.emailConfirm&& - data.phone !==""&& - data.phoneCountryCode !==""&& - termsAndConAccept == true&& - fileList.length!==0&& - data.captchaField&& - handlePassword(data.password)&& - handleEmail(data.email)&& - handleIdNo(data.idNo,selectedIdDocType.type,data.checkDigit)&& - handlePhone(data.phone)&& - handleUsername(data.username)&& + const checkDataField = (data) => { + if (data.username !== "" && + data.password !== "" && + data.confirmPassword !== "" && + data.password == data.confirmPassword && + selectedIdDocType.type !== "" && + data.idNo !== "" && + (data.enName !== "" || selectedIdDocType.type === "CNID") && + data.chName !== "" && + data.address1 !== "" && + data.email !== "" && + data.emailConfirm !== "" && + data.email == data.emailConfirm && + data.phone !== "" && + data.phoneCountryCode !== "" && + termsAndConAccept == true && + fileList.length !== 0 && + data.captchaField && + handlePassword(data.password) && + handleEmail(data.email) && + handleIdNo(data.idNo, selectedIdDocType.type, data.checkDigit) && + handlePhone(data.phone) && + handleUsername(data.username) && handleCaptcha(data.captchaField) - ) - { + ) { setisValid(true) return isValid - }else{ + } else { setisValid(false) return isValid } }; const handleCheckBoxChange = (event) => { - if(event.target.name == 'termsAndConAccept'){ + if (event.target.name == 'termsAndConAccept') { setTermsAndConAccept(event.target.checked) setTermsAndConNotAccept(!event.target.checked) } - if(event.target.name == 'termsAndConNotAccept'){ + if (event.target.name == 'termsAndConNotAccept') { setTermsAndConNotAccept(event.target.checked) setTermsAndConAccept(!event.target.checked) } @@ -187,8 +187,8 @@ const CustomFormWizard = (props) => { var updateRowsIndex = updateRows.length; const saveFileList = []; - if (updateRowsIndex!=null){ - for (let i = 0; i < updateRowsIndex; i++){ + if (updateRowsIndex != null) { + for (let i = 0; i < updateRowsIndex; i++) { const file = updateRows[i] file.id = i; updateRowList.items.add(file); @@ -197,21 +197,21 @@ const CustomFormWizard = (props) => { let updatedFileList = updateRowList.files; setFileList(updatedFileList); setFileListData(saveFileList) - + } }, [updateRows]); - const handleFileUpload = (event)=>{ + const handleFileUpload = (event) => { let updateList = new DataTransfer(); let currentFileList = fileListData; const uploadFileList = event.target.files; const saveFileList = []; var currentIndex = 0; - if (currentFileList.length!=null){ + if (currentFileList.length != null) { currentIndex = currentFileList.length; - for (let i = 0; i < currentIndex; i++){ + for (let i = 0; i < currentIndex; i++) { const file = currentFileList[i] // file.id = currentIndex; updateList.items.add(file); @@ -219,7 +219,7 @@ const CustomFormWizard = (props) => { } } - for (let i = 0; i < uploadFileList.length && currentIndex<5; i++){ + for (let i = 0; i < uploadFileList.length && currentIndex < 5; i++) { const file = event.target.files[i] let isDuplicate = false; @@ -230,12 +230,12 @@ const CustomFormWizard = (props) => { break; } } - if (!isDuplicate && i+currentIndex<5) { - file.id = currentIndex+i + if (!isDuplicate && i + currentIndex < 5) { + file.id = currentIndex + i saveFileList.push(file) updateList.items.add(file); } - + } let updatedFileList = updateList.files; @@ -251,47 +251,47 @@ const CustomFormWizard = (props) => { checkDataField(values) }, [ selectedIdDocType, - selectedAddress4,selectedAddress5, - termsAndConAccept,termsAndConNotAccept,fileList]) + selectedAddress4, selectedAddress5, + termsAndConAccept, termsAndConNotAccept, fileList]) useEffect(() => { - props.step ==2?_onSubmit():null; + props.step == 2 ? _onSubmit() : null; onCaptchaChange(); checkDataField(values) }, [props.step]) - const {handleSubmit} = useForm({}) + const { handleSubmit } = useForm({}) const _onSubmit = () => { setLoding(true); values.idDocType = selectedIdDocType.type values.address4 = selectedAddress4 values.address5 = selectedAddress5 - const userAddress = { - "addressLine1":"", - "addressLine2":"", - "addressLine3":"", - "district":"", - "country":"" + const userAddress = { + "addressLine1": "", + "addressLine2": "", + "addressLine3": "", + "district": "", + "country": "" }; userAddress.addressLine1 = values.address1 userAddress.addressLine2 = values.address2 userAddress.addressLine3 = values.address3 userAddress.district = values.address4 userAddress.country = values.address5 - + const userFaxNo = { - "countryCode":values.faxCountryCode, - "faxNumber":values.fax, + "countryCode": values.faxCountryCode, + "faxNumber": values.fax, }; const userMobileNumber = { - "countryCode":values.phoneCountryCode, - "phoneNumber":values.phone, + "countryCode": values.phoneCountryCode, + "phoneNumber": values.phone, }; let tncFlag = false; - if (termsAndConAccept){ + if (termsAndConAccept) { tncFlag = true } - if (termsAndConNotAccept){ + if (termsAndConNotAccept) { tncFlag = false } @@ -302,24 +302,24 @@ const CustomFormWizard = (props) => { enName: values.enName, chName: values.chName, emailAddress: values.email, - idDocType:values.idDocType, - identification:values.idNo, - checkDigit:values.checkDigit, - tncFlag:tncFlag, - type:"IND", + idDocType: values.idDocType, + identification: values.idNo, + checkDigit: values.checkDigit, + tncFlag: tncFlag, + type: "IND", }; var formData = new FormData(); - for (let i = 0; i < fileListData.length; i++){ + for (let i = 0; i < fileListData.length; i++) { const file = fileListData[i] formData.append("multipartFileList", file); } formData.append("refType", refType); - + for (const [key, value] of Object.entries(user)) { formData.append(key, value); } - + formData.append("userFaxNo", JSON.stringify(userFaxNo)); formData.append("userMobileNumber", JSON.stringify(userMobileNumber)); formData.append("userAddress", JSON.stringify(userAddress)); @@ -328,22 +328,22 @@ const CustomFormWizard = (props) => { // formData.append("refCode", refCode); // } - if (isValid){ - axios.post(POST_PUBLIC_USER_REGISTER, formData,{ + if (isValid) { + axios.post(POST_PUBLIC_USER_REGISTER, formData, { headers: { - "Content-Type":"multipart/form-data" + "Content-Type": "multipart/form-data" } }) - .then((response) => { - console.log(response) - setCheckUpload(true) - setLoding(false); - }) - .catch(error => { - console.error(error); - setLoding(false); - }); - }else{ + .then((response) => { + console.log(response) + setCheckUpload(true) + setLoding(false); + }) + .catch(error => { + console.error(error); + setLoding(false); + }); + } else { setLoding(false); } } @@ -364,7 +364,7 @@ const CustomFormWizard = (props) => { return false; } else if (username.match(symbol)) { return false; - }else if (username.match(space)) { + } else if (username.match(space)) { return false; } else { return true; @@ -375,7 +375,7 @@ const CustomFormWizard = (props) => { return captchaField == captcha; } - function handleIdNo(idNo,selectedIdDocType,checkDigit) { + function handleIdNo(idNo, selectedIdDocType, checkDigit) { // var pattern = /^[A-Z][0-9]*$/; var pattern_HKIDv1 = /^[A-Z]{1}[0-9]{6}$/; var pattern_HKIDv2 = /^[A-Z]{2}[0-9]{6}$/; @@ -416,7 +416,7 @@ const CustomFormWizard = (props) => { const subStr_year = idNo.substring(6, 10) const subStr_month = idNo.substring(10, 12) const subStr_date = idNo.substring(12, 14) - + const today = new Date() const inputDate = new Date(`${subStr_year}-${subStr_month}-${subStr_date}`) @@ -457,10 +457,10 @@ const CustomFormWizard = (props) => { return false; } else if (new_pass.length < 8) { return false; - } + } else if (new_pass.match(space)) { return false; - }else { + } else { // console.log("password true") return true; } @@ -470,14 +470,18 @@ const CustomFormWizard = (props) => { var validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; if (!email.match(validRegex)) { return false; - }else{ + } else { return true; } } + function displayErrorMsg(errorMsg) { + return {errorMsg} + } + const formik = useFormik({ - initialValues:({ - username:'', + initialValues: ({ + username: '', enName: '', chName: '', email: '', @@ -487,55 +491,55 @@ const CustomFormWizard = (props) => { address3: '', password: '', confirmPassword: '', - phone:'', - phoneCountryCode:'852', - idNo:'', - checkDigit:'', + phone: '', + phoneCountryCode: '852', + idNo: '', + checkDigit: '', submit: null, - fax:'', - faxCountryCode:'852', - idDocType:'', - captchaField:'' + fax: '', + faxCountryCode: '852', + idDocType: '', + captchaField: '' }), - validationSchema:yup.object().shape({ - username: yup.string().min(6,'用戶名稱最少6位').required('請輸入用戶名稱').test( + validationSchema: yup.object().shape({ + username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg("請輸入用戶登入名稱")).test( "checkUserNameUsed", - "此用戶登入名稱已被注冊,請使用其他用戶登入名稱", - function(value) { + displayErrorMsg("此用戶登入名稱已被注冊,請使用其他用戶登入名稱"), + function (value) { if (userNameList.some(item => item.username === value)) { return false } else { return true } } - ) - .matches(/^[aA-zZ0-9\s]+$/, "用戶名稱不包含特殊字符") - .matches(/^\S*$/, '用戶名稱不包含空格'), - password: yup.string().min(8,'請輸入最少8位密碼').required('請輸入密碼') - .matches(/^\S*$/, '密碼不包含空格') - .matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') - .matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') - .matches(/^(?=.*[0-9])/, '請包括最少1個數字') - .matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), - confirmPassword: yup.string().min(8,'請最少輸入8位密碼').required('請確認密碼').oneOf([yup.ref('password'), null], '請輸入相同密碼'), - enName: yup.string().max(255).required('請輸入英文姓名'), - chName: yup.string().max(6).required('請輸入中文姓名'), - address1: yup.string().max(255).required('請輸入第一行地址'), - address2: yup.string().max(255).required('請輸入第二行地址'), - address3: yup.string().max(255).required('請輸入第三行地址'), - email: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵'), - emailConfirm: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵').oneOf([yup.ref('email'), null], '請輸入相同電郵'), - idNo: yup.string().required(`請輸入${selectedIdDocInputType}號碼`) - .matches(/^[aA-zZ0-9\s]+$/, `${selectedIdDocInputType}號碼不包含特殊字符`) - .matches(/^\S*$/, `${selectedIdDocInputType}號碼不包含空格`) - .test('checkIDCardFormat', `請輸入有效的${selectedIdDocInputType}號碼`, function(value) { + ) + .matches(/^[aA-zZ0-9\s]+$/, {message: displayErrorMsg("用戶名稱不包含特殊字符")}) + .matches(/^\S*$/, {message: displayErrorMsg("用戶名稱不包含空格")}), + password: yup.string().min(8, displayErrorMsg('請輸入最少8位密碼')).required(displayErrorMsg('請輸入密碼')) + .matches(/^\S*$/, {message: displayErrorMsg('密碼不包含空格')}) + .matches(/^(?=.*[a-z])/, {message: displayErrorMsg('請包括最少1個小寫字母')}) + .matches(/^(?=.*[A-Z])/, {message: displayErrorMsg('請包括最少1個大寫字母')}) + .matches(/^(?=.*[0-9])/, {message: displayErrorMsg('請包括最少1個數字')}) + .matches(/^(?=.*[!@#%&])/, {message: displayErrorMsg('請包括最少1個特殊字符')}), + confirmPassword: yup.string().min(8, displayErrorMsg('請最少輸入8位密碼')).required(displayErrorMsg('請確認密碼')).oneOf([yup.ref('password'), null], displayErrorMsg('請輸入相同密碼')), + enName: yup.string().max(255).required(displayErrorMsg('請輸入英文姓名')), + chName: yup.string().max(6).required(displayErrorMsg('請輸入中文姓名')), + address1: yup.string().max(255).required(displayErrorMsg('請輸入第一行地址')), + address2: yup.string().max(255).required(displayErrorMsg('請輸入第二行地址')), + address3: yup.string().max(255).required(displayErrorMsg('請輸入第三行地址')), + email: yup.string().email(displayErrorMsg('請輸入電郵格式')).max(255).required(displayErrorMsg('請輸入電郵')), + emailConfirm: yup.string().email(displayErrorMsg('請輸入電郵格式')).max(255).required(displayErrorMsg('請輸入電郵')).oneOf([yup.ref('email'), null], displayErrorMsg('請輸入相同電郵')), + idNo: yup.string().required(displayErrorMsg(`請輸入${selectedIdDocInputType}號碼`)) + .matches(/^[aA-zZ0-9\s]+$/, {message: displayErrorMsg(`${selectedIdDocInputType}號碼不包含特殊字符`)}) + .matches(/^\S*$/, {message: displayErrorMsg(`${selectedIdDocInputType}號碼不包含空格`)}) + .test('checkIDCardFormat', displayErrorMsg(`請輸入有效的${selectedIdDocInputType}號碼`), function (value) { const idDocType = selectedIdDocType.type; var pattern_HKIDv1 = /^[A-Z]{1}[0-9]{6}$/; var pattern_HKIDv2 = /^[A-Z]{2}[0-9]{6}$/; var pattern_passport = /^[A-Z]{1}[0-9]{8}$/; var pattern_CHID = /^[0-9]{6}(20|19)[0-9]{2}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]{1}/; var pattern_otherCert = /^[A-Z]{1}[0-9]{5,}/; - if(value!==undefined){ + if (value !== undefined) { switch (idDocType) { case "HKID": if (value.match(pattern_HKIDv1)) { @@ -556,7 +560,7 @@ const CustomFormWizard = (props) => { const subStr_year = value.substring(6, 10) const subStr_month = value.substring(10, 12) const subStr_date = value.substring(12, 14) - + const today = new Date() const inputDate = new Date(`${subStr_year}-${subStr_month}-${subStr_date}`) @@ -579,13 +583,13 @@ const CustomFormWizard = (props) => { } } }), - checkDigit:yup.string().max(1).required('請輸入括號內的數字或字母'), - idDocType: yup.string().max(255).required('請輸入證件類別'), - phoneCountryCode: yup.string().min(2,'請輸入最少2位數字').required('請輸入國際區號'), + checkDigit: yup.string().max(1).required(displayErrorMsg('請輸入括號內的數字或字母')), + idDocType: yup.string().max(255).required(displayErrorMsg('請輸入證件類別')), + phoneCountryCode: yup.string().min(2, displayErrorMsg('請輸入最少2位數字')).required(displayErrorMsg('請輸入國際區號')), // faxCountryCode: yup.string().min(3,'請輸入3位數字'), - phone: yup.string().min(8,'請輸入最少8位數字').required('請輸入聯絡電話'), + phone: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')).required(displayErrorMsg('請輸入聯絡電話')), // fax: yup.string().min(8,'請輸入8位數字'), - captchaField: yup.string().required('請輸入驗證').oneOf([captcha], '請輸入有效驗證'), + captchaField: yup.string().required(displayErrorMsg('請輸入驗證')).oneOf([captcha], displayErrorMsg('請輸入有效驗證')), }), }); @@ -610,25 +614,28 @@ const CustomFormWizard = (props) => { return ( - {/* Input Form */} + {/* Input Form */} - -
    - 成為新的個人用戶 + +
    + 成為新的個人用戶
    - 註有*的項目必須輸入資料 - 你的登入資料 + 註有*的項目必須輸入資料 + 你的登入資料 - 用戶登入名稱 - * + + + 用戶登入名稱 + * + { /> {formik.touched.username && formik.errors.username && ( - {formik.errors.username} + {formik.errors.username} )} @@ -658,10 +665,13 @@ const CustomFormWizard = (props) => { - + - 密碼 - * + + + 密碼 + * + { changePassword(e.target.value); }} endAdornment={ - - - {showPassword ? : } - - + + + {showPassword ? : } + + } placeholder="密碼" onBlur={formik.handleBlur} @@ -700,7 +710,7 @@ const CustomFormWizard = (props) => { /> {formik.touched.password && formik.errors.password && ( - {formik.errors.password} + {formik.errors.password} )} @@ -710,7 +720,7 @@ const CustomFormWizard = (props) => { - + {level?.label} @@ -719,8 +729,11 @@ const CustomFormWizard = (props) => { - 確認密碼 - * + + + 確認密碼 + * + { }, }} endAdornment={ - - - {showConfirmPassword ? : } - - + + + {showConfirmPassword ? : } + + } placeholder="確認密碼" fullWidth @@ -758,37 +771,40 @@ const CustomFormWizard = (props) => { /> {formik.touched.confirmPassword && formik.errors.confirmPassword && ( - {formik.errors.confirmPassword} + {formik.errors.confirmPassword} )} - - -
    - •至少8個字元,字元越多越好
    - •字母和數字的混合
    - •英文字母大寫與小寫的混合
    + + +
    + •至少8個字元,字元越多越好
    + •字母和數字的混合
    + •英文字母大寫與小寫的混合
    •至少包含一個特殊符號,例如,@ # ? -
    -
    +
    -
    +
    +
    - 你的個人資料 + 你的個人資料 {/* Already have an account? */} - + - 身份證明文件 - * + + + 身份證明文件 + * + {/* {formik.touched.enName && formik.errors.enName && ( @@ -800,7 +816,7 @@ const CustomFormWizard = (props) => { - + { options={idDocTypeComboList} // getOptionLabel={(idDocTypeComboList) => idDocTypeComboList.label} onBlur={formik.handleBlur} - filterOptions={(options)=>options} + filterOptions={(options) => options} inputValue={selectedIdDocInputType} onChange={(event, newValue) => { - if (newValue!=null && newValue != {}){ + if (newValue != null && newValue != {}) { setSelectedIdDocInputType(newValue.label); setSelectedIdDocType(newValue); - if (newValue.type!="HKID"){ - formik.setFieldValue("checkDigit","") + if (newValue.type != "HKID") { + formik.setFieldValue("checkDigit", "") } - }else{ + } else { setSelectedIdDocInputType(""); } }} - sx={{"& .MuiInputBase-root": { height: "41px" },"#idDocType":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} - renderInput={(params) => } + sx={{ "& .MuiInputBase-root": { height: "41px" }, "#idDocType": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }} + renderInput={(params) => } /> {formik.touched.idDocType && ( - selectedIdDocType===null? - - 請輸入證件類別 - :'' + selectedIdDocType === null ? + + 請輸入證件類別 + : '' )} - {selectedIdDocType.type=="HKID"? + {selectedIdDocType.type == "HKID" ? <> @@ -841,7 +857,7 @@ const CustomFormWizard = (props) => { type="text" name="idNo" value={formik.values.idNo} - onChange={async (e)=>{ + onChange={async (e) => { const ele = document.getElementById('idNo-login') const startPos = ele.selectionStart if (e.type === "change") { @@ -851,17 +867,17 @@ const CustomFormWizard = (props) => { ele.setSelectionRange(startPos, startPos) } else { await formik.setFieldValue("idNo", formik.values.idNo) - ele.setSelectionRange(startPos-1, startPos-1) + ele.setSelectionRange(startPos - 1, startPos - 1) } } }} placeholder="證件號碼" fullWidth - sx={{mr:1}} + sx={{ mr: 1 }} error={Boolean(formik.touched.idNo && formik.errors.idNo)} onBlur={formik.handleBlur} inputProps={{ - maxLength: selectedIdDocType.type =='HKID'?8:18, + maxLength: selectedIdDocType.type == 'HKID' ? 8 : 18, onKeyDown: (e) => { console.log(e) if (e.key === 'Enter') { @@ -872,12 +888,12 @@ const CustomFormWizard = (props) => { /> {formik.touched.idNo && formik.errors.idNo && ( - {formik.errors.idNo} + {formik.errors.idNo} )} {formik.touched.checkDigit && formik.errors.checkDigit && ( - {formik.errors.checkDigit} + {formik.errors.checkDigit} )} @@ -906,7 +922,7 @@ const CustomFormWizard = (props) => { /> - : + : { type="text" value={formik.values.idNo} name="idNo" - onChange={async (e)=>{ + onChange={async (e) => { const ele = document.getElementById('idNo-login') const startPos = ele.selectionStart if (e.type === "change") { @@ -924,13 +940,13 @@ const CustomFormWizard = (props) => { ele.setSelectionRange(startPos, startPos) } else { await formik.setFieldValue("idNo", formik.values.idNo) - ele.setSelectionRange(startPos-1, startPos-1) + ele.setSelectionRange(startPos - 1, startPos - 1) } } }} placeholder="證件號碼" fullWidth - sx={{mr:1}} + sx={{ mr: 1 }} error={Boolean(formik.touched.idNo && formik.errors.idNo)} onBlur={formik.handleBlur} inputProps={{ @@ -944,7 +960,7 @@ const CustomFormWizard = (props) => { /> {formik.touched.idNo && formik.errors.idNo && ( - {formik.errors.idNo} + {formik.errors.idNo} )} @@ -954,8 +970,11 @@ const CustomFormWizard = (props) => { - 英文姓名 - {selectedIdDocType.type === "CNID" ? "" : *} + + + 英文姓名 + {selectedIdDocType.type === "CNID" ? "" : *} + { /> {formik.touched.enName && formik.errors.enName && selectedIdDocType.type !== "CNID" && ( - {formik.errors.enName} + {formik.errors.enName} )} @@ -985,8 +1004,10 @@ const CustomFormWizard = (props) => { - 中文姓名 - * + + 中文姓名 + * + { /> {formik.touched.chName && formik.errors.chName && ( - {formik.errors.chName} + {formik.errors.chName} )} - 地址 - * + + + 地址 + * + { }} /> { - setSelectedAddress4(newValue); - }} - sx={{"& .MuiInputBase-root": { height: "41px" },"#address4-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} - renderInput={(params) => } + disablePortal + id="address4-combo" + value={selectedAddress4} + options={address4ComboList} + disabled={checkCountry} + onChange={(event, newValue) => { + setSelectedAddress4(newValue); + }} + sx={{ "& .MuiInputBase-root": { height: "41px" }, "#address4-combo": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }} + renderInput={(params) => } /> { - if (newValue !== null){ - setSelectedAddress5(newValue); - if(newValue=='香港'){ - setCheckCountry(false) - }else{ - setSelectedAddress4(""); - setCheckCountry(true) - } - }else{ - setSelectedAddress4(""); - setCheckCountry(true) - } - }} - - sx={{"& .MuiInputBase-root": { height: "41px" },"#address5-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} - renderInput={(params) => } + disablePortal + id="address5-combo" + value={selectedAddress5} + options={address5ComboList} + onChange={(event, newValue) => { + if (newValue !== null) { + setSelectedAddress5(newValue); + if (newValue == '香港') { + setCheckCountry(false) + } else { + setSelectedAddress4(""); + setCheckCountry(true) + } + } else { + setSelectedAddress4(""); + setCheckCountry(true) + } + }} + + sx={{ "& .MuiInputBase-root": { height: "41px" }, "#address5-combo": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }} + renderInput={(params) => } /> {formik.touched.address1 && formik.errors.address1 && ( - {formik.errors.address1} + {formik.errors.address1} )} {formik.touched.address2 && formik.errors.address2 && ( - {formik.errors.address2} + {formik.errors.address2} )} {formik.touched.address3 && formik.errors.address3 && ( - {formik.errors.address3} + {formik.errors.address3} )} - 你的聯絡資料 + 你的聯絡資料 - - 電郵 - * + + + + 電郵 + * + { /> {formik.touched.email && formik.errors.email && ( - {formik.errors.email} + {formik.errors.email} )} - 確認電郵 - * + + + 確認電郵 + * + { /> {formik.touched.emailConfirm && formik.errors.emailConfirm && ( - {formik.errors.emailConfirm} + {formik.errors.emailConfirm} )} - + - + - - 聯絡電話 - * + + + + 聯絡電話 + * + { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("phoneCountryCode",value); + formik.setFieldValue("phoneCountryCode", value); }} placeholder="國際區號" error={Boolean(formik.touched.phone && formik.errors.phone)} @@ -1225,7 +1258,7 @@ const CustomFormWizard = (props) => { } }, }} - sx={{width:'25%'}} + sx={{ width: '25%' }} /> { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("phone",value); + formik.setFieldValue("phone", value); }} placeholder="聯絡電話" error={Boolean(formik.touched.phone && formik.errors.phone)} @@ -1252,23 +1285,27 @@ const CustomFormWizard = (props) => { } }, }} - sx={{width:'75%'}} + sx={{ width: '75%' }} /> {formik.touched.phone && formik.errors.phone && ( - {formik.errors.phone} + {formik.errors.phone} )} - + - 傳真號碼 + + + 傳真號碼 + + { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("faxCountryCode",value); + formik.setFieldValue("faxCountryCode", value); }} placeholder="國際區號" onBlur={formik.handleBlur} @@ -1294,7 +1331,7 @@ const CustomFormWizard = (props) => { } }, }} - sx={{width:'25%'}} + sx={{ width: '25%' }} /> { if (value.match(/[^0-9]/)) { return event.preventDefault(); } - formik.setFieldValue("fax",value); + formik.setFieldValue("fax", value); }} placeholder="傳真號碼" inputProps={{ @@ -1319,38 +1356,41 @@ const CustomFormWizard = (props) => { } }, }} - sx={{width:'75%'}} + sx={{ width: '75%' }} /> - + - 身份證明文件* - 請上傳你的 有效身份證明文件 的數碼檔案,以驗證你的身份。 - 如: 香港身份證; 護照; 中國內地身份證; 專業執業証書等 + 身份證明文件* + 請上傳你的 有效身份證明文件 的數碼檔案,以驗證你的身份。 + 如: 香港身份證; 護照; 中國內地身份證; 專業執業証書等 - - 如: 香港身份證; 護照; 中國內地身份證等 + 如: 香港身份證; 護照; 中國內地身份證等 - {fileList !=null? - :null} + {fileList != null ? + : null} {/* @@ -1363,15 +1403,15 @@ const CustomFormWizard = (props) => { - + 條款和條件 - * + * - + {termsAndCon} @@ -1380,7 +1420,7 @@ const CustomFormWizard = (props) => { - + { color="primary" size="small" /> - 我接受 + 我接受 - + - 我不接受 + /> + 我不接受 - + - + 驗證 - * + * - - - - - - {onCaptchaChange()}}> - - - - - { - const value = event.target.value; - formik.setFieldValue("captchaField",value); - }} - sx={{width:'75%'}} - /> - - + + + + + + { onCaptchaChange() }}> + + + + + { + const value = event.target.value; + formik.setFieldValue("captchaField", value); + }} + sx={{ width: '75%' }} + /> + + {formik.touched.captchaField && formik.errors.captchaField && ( - {formik.errors.captchaField} + {formik.errors.captchaField} )} @@ -1455,16 +1495,16 @@ const CustomFormWizard = (props) => { - {/* Preview Form */} - + {/* Preview Form */} + -
    - 成為新的個人用戶 +
    + 成為新的個人用戶
    {/* 註有*的項目必須輸入資料 */} - 你的登入資料 + 你的登入資料 {/* Already have an account? */} @@ -1474,145 +1514,151 @@ const CustomFormWizard = (props) => { - - 用戶登入名稱: + + 用戶登入名稱: - + {formik.values.username} - 你的個人資料 - {/* + 你的個人資料 + {/* Already have an account? */} - + 身份證明文件 - - + + 證件類別: - + {selectedIdDocType.label} - + 證件號碼: - - {formik.values.idNo} {selectedIdDocType.type=="HKID"?'('+formik.values.checkDigit+')':null} + + {formik.values.idNo} {selectedIdDocType.type == "HKID" ? '(' + formik.values.checkDigit + ')' : null} - + - + 英文姓名: - + {formik.values.enName} - + 中文姓名: - + {formik.values.chName} - + 地址: - + {formik.values.address1} - {formik.values.address2!=null? - + {formik.values.address2 != null ? + {formik.values.address2} - :null} - {formik.values.address3!=null? - - {formik.values.address3} - - :null} - {selectedAddress5==("香港")? - - 區域 (只適用於香港): {selectedAddress4} + : null} + {formik.values.address3 != null ? + + {formik.values.address3} - :null} - - 國家/地區: {selectedAddress5} - + : null} + {selectedAddress5 == ("香港") ? + + + 區域 (只適用於香港): + + {selectedAddress4} + + : null} + + + 國家/地區: + + {selectedAddress5} + - 你的聯絡資料 + 你的聯絡資料 - + 電郵: - + {formik.values.email} - + 聯絡電話: - + +{formik.values.phoneCountryCode} {formik.values.phone} - {formik.values.faxCountryCode!=""&&formik.values.fax!=""? + {formik.values.faxCountryCode != "" && formik.values.fax != "" ? - + 傳真號碼: - + +{formik.values.faxCountryCode} {formik.values.fax} - :null} + : null} - 身份證明文件 - {fileList !=null? - :null} + 身份證明文件 + {fileList != null ? + : null} @@ -1621,31 +1667,31 @@ const CustomFormWizard = (props) => { - {/* Submit page */} - + {/* Submit page */} + - {isLoading ? - : - - {checkUpload? - // SUCCESS page - - + {isLoading ? + : + + {checkUpload ? + // SUCCESS page + + 帳戶申請已成功提交。 驗證電郵將發送到你的電郵地址,請要指示完成驗證及登入系統。 - - - : - // ERROR page - - {/* */} - - 申請失敗,請稍後嘗試 - - - } - - } + + + : + // ERROR page + + {/* */} + + 申請失敗,請稍後嘗試 + + + } + + } diff --git a/src/pages/authentication/auth-forms/PreviewUploadFileTable.js b/src/pages/authentication/auth-forms/PreviewUploadFileTable.js index 7c70087..779a7b6 100644 --- a/src/pages/authentication/auth-forms/PreviewUploadFileTable.js +++ b/src/pages/authentication/auth-forms/PreviewUploadFileTable.js @@ -6,17 +6,18 @@ import { // GridRowModes } from "@mui/x-data-grid"; // import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; -import {useEffect} from "react"; +import { useEffect } from "react"; // import {useNavigate} from "react-router-dom"; // import { useTheme } from '@mui/material/styles'; import { Box, - Stack + Stack, + Typography } from '@mui/material'; // ==============================|| EVENT TABLE ||============================== // -export default function PreviewUploadFileTable({recordList,}) { - +export default function PreviewUploadFileTable({ recordList, }) { + const [rows, setRows] = React.useState(recordList); const [rowModesModel] = React.useState({}); // const theme = useTheme(); @@ -30,8 +31,10 @@ export default function PreviewUploadFileTable({recordList,}) { function NoRowsOverlay() { return ( - 沒有上傳檔案 - {/*
    (rows={[]})
    */} + + 沒有上傳檔案 + + {/*
    (rows={[]})
    */}
    ); } @@ -71,17 +74,17 @@ export default function PreviewUploadFileTable({recordList,}) { { id: 'name', field: 'name', - headerName: '檔案名稱', + headerName: 檔案名稱, flex: 1, }, { id: 'size', field: 'size', - headerName: '檔案大小', + headerName: 檔案大小, valueGetter: (params) => { // console.log(params) - return Math.ceil(params.value/1024)+" KB"; - }, + return Math.ceil(params.value / 1024) + " KB"; + }, flex: 1, }, ]; @@ -92,7 +95,7 @@ export default function PreviewUploadFileTable({recordList,}) { rows={rows} columns={columns} editMode="row" - sx={{border:1}} + sx={{ border: 1 }} rowModesModel={rowModesModel} disablePagination components={{ NoRowsOverlay, }} diff --git a/src/pages/authentication/auth-forms/UploadFileTable.js b/src/pages/authentication/auth-forms/UploadFileTable.js index 3755f2e..2b295e2 100644 --- a/src/pages/authentication/auth-forms/UploadFileTable.js +++ b/src/pages/authentication/auth-forms/UploadFileTable.js @@ -6,19 +6,20 @@ import { GridRowModes } from "@mui/x-data-grid"; import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; -import {useEffect} from "react"; +import { useEffect } from "react"; // import {useNavigate} from "react-router-dom"; // import { useTheme } from '@mui/material/styles'; import { Box, - Stack + Stack, + Typography } from '@mui/material'; // ==============================|| EVENT TABLE ||============================== // -export default function UploadFileTable({recordList, setUpdateRows,}) { - +export default function UploadFileTable({ recordList, setUpdateRows, }) { + const [rows, setRows] = React.useState(recordList); - const [rowModesModel,setRowModesModel] = React.useState({}); + const [rowModesModel, setRowModesModel] = React.useState({}); // const theme = useTheme(); // const navigate = useNavigate() @@ -31,8 +32,10 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { function NoRowsOverlay() { return ( - 沒有上傳檔案 - {/*
    (rows={[]})
    */} + + 沒有上傳檔案 + + {/*
    (rows={[]})
    */}
    ); } @@ -58,11 +61,11 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { width: 30, cellClassName: 'actions', // hide:true, - getActions: ({id}) => { + getActions: ({ id }) => { return [ } + icon={} label="delete" className="textPrimary" onClick={handleCancelClick(id)} @@ -73,17 +76,17 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { { id: 'name', field: 'name', - headerName: '檔案名稱', + headerName: 檔案名稱, flex: 1, }, { id: 'size', field: 'size', - headerName: '檔案大小', + headerName: 檔案大小, valueGetter: (params) => { // console.log(params) - return Math.ceil(params.value/1024)+" KB"; - }, + return Math.ceil(params.value / 1024) + " KB"; + }, flex: 1, }, ]; @@ -94,7 +97,7 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { rows={rows} columns={columns} editMode="row" - sx={{border:1}} + sx={{ border: 1 }} rowModesModel={rowModesModel} disablePagination components={{ NoRowsOverlay, }} diff --git a/src/themes/palette.js b/src/themes/palette.js index 7812d99..635de12 100644 --- a/src/themes/palette.js +++ b/src/themes/palette.js @@ -83,6 +83,9 @@ const Palette = (mode) => { dark: '#b0671e', contrastText: '#fff', }, + backgroundColor: { + default: '#F2F2F2' + } } }); }; diff --git a/src/themes/typography.js b/src/themes/typography.js index d6dd849..3220607 100644 --- a/src/themes/typography.js +++ b/src/themes/typography.js @@ -9,30 +9,35 @@ const Typography = (fontFamily) => ({ fontWeightBold: 600, h1: { fontWeight: 600, - fontSize: '2.375rem', + fontSize: '2.5rem', lineHeight: 1.21 }, h2: { fontWeight: 600, - fontSize: '1.875rem', + fontSize: '2.375rem', lineHeight: 1.27 }, h3: { fontWeight: 600, - fontSize: '1.5rem', + fontSize: '1.875rem', lineHeight: 1.33 }, h4: { fontWeight: 600, - fontSize: '1.25rem', + fontSize: '1.5rem', lineHeight: 1.4 }, h5: { fontWeight: 600, - fontSize: '1rem', - lineHeight: 1.5 + fontSize: '1.275rem', + lineHeight: 1.66 }, h6: { + fontWeight: 600, + fontSize: '1.1rem', + lineHeight: 1.57 + }, + h7: { fontWeight: 400, fontSize: '0.875rem', lineHeight: 1.57 @@ -43,23 +48,39 @@ const Typography = (fontFamily) => ({ lineHeight: 1.66 }, body1: { - fontSize: '0.875rem', + fontSize: '1.1rem', + fontWeight: 600, lineHeight: 1.57 }, body2: { - fontSize: '0.75rem', + fontSize: '1.2rem', lineHeight: 1.66 }, subtitle1: { - fontSize: '0.875rem', + fontSize: '1rem', fontWeight: 600, lineHeight: 1.57 }, subtitle2: { - fontSize: '0.75rem', + fontSize: '0.8rem', fontWeight: 500, lineHeight: 1.66 }, + headerTitle1: { + fontSize: '1.5rem', + fontWeight: 600, + lineHeight: 1.66 + }, + errorMessage1: { + fontSize: '1rem', + fontWeight: 600, + lineHeight: 1 + }, + step1: { + fontSize: '1.4rem', + fontWeight: 600, + lineHeight: 1 + }, overline: { lineHeight: 1.66 }, @@ -68,4 +89,4 @@ const Typography = (fontFamily) => ({ } }); -export default Typography; +export default Typography; \ No newline at end of file