From ccbeeab0fd43118bd997bbc4fe73f6940bc71a5f Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 4 Dec 2023 11:46:44 +0800 Subject: [PATCH] iamSmart --- src/pages/authentication/IAmSmartRegister.js | 217 ++++ .../auth-forms/IAmSmartFormWizard.js | 1020 +++++++++++++++++ src/pages/iAmSmart/AuthCallback/index.js | 187 +-- src/routes/LoginRoutes.js | 5 + 4 files changed, 1259 insertions(+), 170 deletions(-) create mode 100644 src/pages/authentication/IAmSmartRegister.js create mode 100644 src/pages/authentication/auth-forms/IAmSmartFormWizard.js diff --git a/src/pages/authentication/IAmSmartRegister.js b/src/pages/authentication/IAmSmartRegister.js new file mode 100644 index 0000000..ec59c4c --- /dev/null +++ b/src/pages/authentication/IAmSmartRegister.js @@ -0,0 +1,217 @@ +// import { Link } from 'react-router-dom'; +import React, { + useState + // ,useEffect +} from 'react'; + +// material-ui +import { + Stepper, + Step, + StepButton, + // Grid, + Stack, + Typography, + Button, +} from '@mui/material'; +import VisibilityIcon from '@mui/icons-material/Visibility'; +import { GET_USERNAME } from "utils/ApiPathConst"; + +// project import +import Loadable from 'components/Loadable'; +import { lazy } from 'react'; +import { notifyActionError } from 'utils/CommonFunction'; +import axios from "axios"; +const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/IAmSmartFormWizard'))); +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", + }, + "& .MuiStepConnector-line": { + borderColor: "secondary.main" + } + } +} +const steps = ['個人資料', '預覽', '完成提交']; + +const Register = () => { + const [activeStep, setActiveStep] = useState(0); + const [completed, setCompleted] = useState([false]); + const [updateValid, setUpdateValid] = useState(false); + const [username, setUsername] = useState(""); + + const totalSteps = () => { + return steps.length; + }; + + const completedSteps = () => { + return Object.keys(completed).length; + }; + + const isLastStep = () => { + return activeStep === totalSteps() - 1; + }; + + const allStepsCompleted = () => { + return completedSteps() === totalSteps(); + }; + + const handleCheckUsername = async () => { + const response = await axios.get(`${GET_USERNAME}`, { + params: { + username: username, + } + }) + return Number(response.data[0]) === 1 + } + + const handleNext = async () => { + const test = await handleCheckUsername() + if (test) { + notifyActionError("此用戶登入名稱已被注冊,請使用其他用戶登入名稱") + } else { + 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 === 2 || activeStep === 0 ? ( + + ) : ( + + ) + } + + {activeStep === totalSteps() - 2 ? + ( + + ) : (activeStep === totalSteps() - 1 ? + ( + + ) : + ( + // + ) + )} + {/* {activeStep !== steps.length && + (completed[activeStep] ? ( + + Step {activeStep + 1} already completed + + ) : ( + + ))} */} + + + )} + + // + ); +}; + +export default Register; diff --git a/src/pages/authentication/auth-forms/IAmSmartFormWizard.js b/src/pages/authentication/auth-forms/IAmSmartFormWizard.js new file mode 100644 index 0000000..eb6b26e --- /dev/null +++ b/src/pages/authentication/auth-forms/IAmSmartFormWizard.js @@ -0,0 +1,1020 @@ +import { useEffect, useState, } from 'react'; + +// material-ui +import { + Button, + FormHelperText, + Grid, IconButton, + InputLabel, OutlinedInput, + Stack, + Typography, + FormGroup, + TextField, + Checkbox + // MenuItem +} from '@mui/material'; +import { useForm, } from 'react-hook-form' +import Autocomplete from "@mui/material/Autocomplete"; + +// third party +import { useFormik, FormikProvider } from 'formik'; +import * as yup from 'yup'; + +import axios from "axios"; +import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, GET_USER_EMAIL } from "utils/ApiPathConst"; + +import * as ComboData from "utils/ComboData"; + +import Loadable from 'components/Loadable'; +import { lazy } from 'react'; +const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent'))); + +import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; +import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined'; +import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; + +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 { useLocation } from "react-router-dom"; + +// ============================|| FIREBASE - REGISTER ||============================ // + +const CustomFormWizard = (props) => { + const location = useLocation(); + const theme = useTheme(); + + const [iAmSmartData, setIAmSmartData] = useState({}); + + const [checkUpload, setCheckUpload] = useState(false); + const [isLoading, setLoding] = useState(true); + + const [captcha, setCaptcha] = useState([]); + const [captchaImg, setCaptchaImage] = useState([]); + + const [selectedAddress4, setSelectedAddress4] = useState(null); + const [selectedAddress5, setSelectedAddress5] = useState(ComboData.country[0]); + const [termsAndConAccept, setTermsAndConAccept] = useState(false); + const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false); + const [isValid, setisValid] = useState(false); + const [checkCountry, setCheckCountry] = useState(false); + const email = document.getElementById("email-login") + const [checkEmail, setCheckEmail] = useState(false) + const [checkEmailBlur, setCheckEmailBlur] = useState(false) + + const address4ComboList = ComboData.district; + const address5ComboList = ComboData.country; + const termsAndCon = "此網址由香港特別行政區政府物流服務署製作及管理。本署會盡力確保網址上的資料無誤,\n" + + "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址" + + "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評" + + "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港" + + "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限" + + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" + + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" + + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" + + + const dataStr = "{\"emailAddress\":\"test@gmail.com\",\"postalAddress\":{\"EngPremisesAddress\":{\"EngDistrict\":{\"DcDistrict\":\"KC\",\"Sub-district\":\"TSING YI\"},\"EngEstate\":{\"EstateName\":\"Cheung Hang Estate\",\"EngPhase\":{\"PhaseName\":\"N/A\"}},\"BuildingName\":\"Hang Lai House\",\"EngBlock\":{\"BlockDescriptor\":\"Block\",\"BlockNo\":\"2\"},\"Region\":\"NT\",\"EngStreet\":{\"StreetName\":\"Liu To Road\",\"BuildingNoFrom\":\"6\"},\"Eng3dAddress\":{\"EngFloor\":{\"FloorNum\":\"33\"},\"EngUnit\":{\"UnitDescriptor\":\"Room\",\"UnitNo\":\"3301\"}}}},\"mobileNumber\":{\"CountryCode\":\"852\",\"SubscriberNumber\":\"99999999\"},\"residentialAddress\":{\"ChiPremisesAddress\":{\"Chi3dAddress\":{\"ChiUnit\":{\"UnitDescriptor\":\"室\",\"UnitNo\":\"1010\"},\"ChiFloor\":{\"FloorNum\":\"10\"}},\"ChiBlock\":{\"BlockDescriptor\":\"座\",\"BlockNo\":\"2\"},\"BuildingName\":\"亨麗樓(第2座)\",\"ChiDistrict\":{\"DcDistrict\":\"KC\",\"Sub-district\":\"青衣\"},\"Region\":\"新界\",\"ChiEstate\":{\"EstateName\":\"長亨邨\"},\"ChiStreet\":{\"StreetName\":\"寮肚路\",\"BuildingNoFrom\":\"6\"}}},\"enName\":{\"UnstructuredName\":\"Testing Co One\"},\"idNo\":{\"Identification\":\"G561107\",\"CheckDigit\":\"4\"},\"chName\":{\"ChineseName\":\"測試商一\"}}"; + + useEffect(() => { + location.state?.responseData ?? {} + onCaptchaChange(); + responseToData(); + }, []); + + const responseToData = () => { + let rd = JSON.parse(dataStr); + let data = { + "enName": rd.enName?.UnstructuredName ?? "", + "chName": rd.chName?.ChineseName ?? "", + "idNo": rd.idNo?.Identification ?? "", + "checkDigit": rd.idNo?.CheckDigit ?? "", + "email": rd.emailAddress ?? "", + "phone": rd.mobileNumber?.SubscriberNumber ?? "", + "phoneCountryCode": rd.mobileNumber?.CountryCode ?? "", + }; + + if (rd.postalAddress) { + if (rd.postalAddress.EngPremisesAddress) { + data["address1"] = getAddressEng(rd.postalAddress.EngPremisesAddress); + } else if (rd.postalAddress.ChiPremisesAddress) { + data["address1"] = getAddressChi(rd.postalAddress.ChiPremisesAddress); + } + } else if (rd.residentialAddress) { + if (rd.residentialAddress.EngPremisesAddress) { + data["address1"] = getAddressEng(rd.residentialAddress.EngPremisesAddress); + } else if (rd.residentialAddress.ChiPremisesAddress) { + data["address1"] = getAddressChi(rd.residentialAddress.ChiPremisesAddress); + } + } + + setIAmSmartData(data); + + } + + + const getAddressEng = (pAdd) => { + let unit = (pAdd.Eng3dAddress?.EngUnit?.UnitDescriptor ?? "") + " " + (pAdd.Eng3dAddress?.EngUnit?.UnitNo ?? ""); + let block = (pAdd.EngBlock?.BlockDescriptor ?? "") + " " + (pAdd.EngBlock?.BlockNo ?? ""); + let floor = pAdd.Eng3dAddress?.EngFloor?.FloorNum ? pAdd.Eng3dAddress?.EngFloor?.FloorNum + "/F " : ""; + let street = (pAdd.EngStreet?.EngUnit?.UnitDescriptor ?? "") + " " + (pAdd.Eng3dAddress?.EngUnit?.UnitNo ?? ""); + //let region = pAdd.Region ?? ""; + let buildingName = pAdd.BuildingName ?? ""; + let estate = pAdd.EngEstate?.EstateName ?? ""; + let district = pAdd.EngDistrict["Sub - district"] ?? ""; + return getAddressStr([unit, block, floor, buildingName, estate, street, district]); + } + + const getAddressChi = (pAdd) => { + let unit = (pAdd.Chi3dAddress?.ChiUnit?.UnitDescriptor ?? "") + " " + (pAdd.Chi3dAddress?.ChiUnit?.UnitNo ?? ""); + let block = (pAdd.ChiBlock?.BlockDescriptor ?? "") + " " + (pAdd.ChiBlock?.BlockNo ?? ""); + let floor = pAdd.Chi3dAddress?.ChiFloor?.FloorNum ? pAdd.Chi3dAddress?.ChiFloor?.FloorNum + "樓 " : ""; + let street = (pAdd.ChiStreet?.ChiUnit?.UnitDescriptor ?? "") + " " + (pAdd.Chi3dAddress?.ChiUnit?.UnitNo ?? ""); + //let region = pAdd.Region ?? ""; + let buildingName = pAdd.BuildingName ?? ""; + let estate = pAdd.ChiEstate?.EstateName ?? ""; + let district = pAdd.ChiDistrict["Sub - district"] ?? ""; + return getAddressStr([district, street, estate, buildingName, street, floor, block, unit ]); + } + + const getAddressStr = (strs) => { + let add = "" + strs.forEach(str => { + add += str ? str + ", " : ""; + }); + add = add.trim(); + if (add.slice(- 1) == ",") { + add = add.substring(0, add.length - 1); + } + return add; + } + + const handleCheckEmail = async () => { + if (values?.email) { + const response = await axios.get(`${GET_USER_EMAIL}`, { + params: { + email: values.email, + } + }) + setCheckEmail((Number(response.data[0]) === 1)) + return Number(response.data[0]) === 1 + } + } + + useEffect(() => { + if (email) { + email.addEventListener("blur", function () { + setCheckEmailBlur(true) + }) + } + }, [email]) + + useEffect(() => { + if (checkEmailBlur) { + handleCheckEmail() + setCheckEmailBlur(false) + } + }, [checkEmailBlur]) + + const onCaptchaChange = () => { + HttpUtils.post({ + url: POST_CAPTCHA, + 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) => { + if (data.address1 !== "" && + data.email !== "" && + data.emailConfirm !== "" && + data.email == data.emailConfirm && + data.phone !== "" && + data.phoneCountryCode !== "" && + termsAndConAccept == true && + data.captchaField && + handleEmail(data.email) && + handlePhone(data.phone) && + handleCaptcha(data.captchaField) && + !checkEmail + ) { + setisValid(true) + return isValid + } else { + setisValid(false) + return isValid + } + }; + + const handleCheckBoxChange = (event) => { + if (event.target.name == 'termsAndConAccept') { + setTermsAndConAccept(event.target.checked) + setTermsAndConNotAccept(!event.target.checked) + } + if (event.target.name == 'termsAndConNotAccept') { + setTermsAndConNotAccept(event.target.checked) + setTermsAndConAccept(!event.target.checked) + } + }; + + useEffect(() => { + props.setUpdateValid(isValid) + }, [isValid]) + + useEffect(() => { + checkDataField(values) + }, [ + selectedAddress4, selectedAddress5, + termsAndConAccept, termsAndConNotAccept]) + + useEffect(() => { + props.step == 2 ? _onSubmit() : null; + onCaptchaChange(); + checkDataField(values) + }, [props.step]) + + const { handleSubmit } = useForm({}) + const _onSubmit = () => { + setLoding(true); + values.address4 = selectedAddress4 + values.address5 = selectedAddress5 + 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, + }; + const userMobileNumber = { + "countryCode": values.phoneCountryCode, + "phoneNumber": values.phone, + }; + let tncFlag = false; + if (termsAndConAccept) { + tncFlag = true + } + if (termsAndConNotAccept) { + tncFlag = false + } + + const user = { + enName: values.enName, + chName: values.chName, + emailAddress: values.email, + idDocType: values.idDocType, + identification: values.idNo, + checkDigit: values.checkDigit, + tncFlag: tncFlag, + type: "IND", + }; + + 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)); + + if (isValid) { + axios.post(POST_PUBLIC_USER_REGISTER, formData, { + headers: { + "Content-Type": "multipart/form-data" + } + }) + .then((response) => { + console.log(response) + setCheckUpload(true) + setLoding(false); + }) + .catch(error => { + console.error(error); + setLoding(false); + }); + } else { + setLoding(false); + } + } + + function handlePhone(phone) { + if (phone.length < 8) { + return false; + } else { + return true; + } + } + + function handleCaptcha(captchaField) { + return captchaField == captcha; + } + + function handleEmail(email) { + var validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; + if (!email.match(validRegex)) { + return false; + } else { + return true; + } + } + + function displayErrorMsg(errorMsg) { + return {errorMsg} + } + + const formik = useFormik({ + initialValues: ({ + email: '', + emailConfirm: '', + address1: '', + address2: '', + address3: '', + phone: '', + phoneCountryCode: '852', + submit: null, + fax: '', + faxCountryCode: '852', + captchaField: '' + }), + validationSchema: yup.object().shape({ + 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('請輸入國際區號')), + phone: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')).required(displayErrorMsg('請輸入聯絡電話')), + captchaField: yup.string().required(displayErrorMsg('請輸入驗證')).oneOf([captcha], displayErrorMsg('請輸入有效驗證')), + }), + }); + + + const { values } = formik + + useEffect(() => { + checkDataField(values) + }, [values]) + + return ( + +
+ {/* Input Form */} + + + + + + +
+ 成為新的個人用戶iAM Smart +
+ + 註有*的項目必須輸入資料。 + iAM Smart: 表示該項由「智方便」提供。 + +
+
+ + + + + 你的個人資料 + + + + + + + + 香港身份證: {iAmSmartData.idNo+"("+iAmSmartData.checkDigit+")"} + + + + + + + + + + 英文姓名: {iAmSmartData.enName} + + + + + + + + + + 中文姓名: {iAmSmartData.chName} + + + + + + + + + 地址 + * + + + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + /> + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + /> + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + /> + { + 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) => } + /> + {formik.touched.address1 && formik.errors.address1 && ( + + {formik.errors.address1} + + )} + {formik.touched.address2 && formik.errors.address2 && ( + + {formik.errors.address2} + + )} + {formik.touched.address3 && formik.errors.address3 && ( + + {formik.errors.address3} + + )} + + + + + 你的聯絡資料 + + + + + + + + + 電郵 + * + + + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + /> + {formik.touched.email && formik.errors.email && ( + + {formik.errors.email} + + )} + {checkEmail && ( + + 此電郵已被注冊,請使用其他電郵 + + )} + + + + + + + 確認電郵 + * + + + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + /> + {formik.touched.emailConfirm && formik.errors.emailConfirm && ( + + {formik.errors.emailConfirm} + + )} + + + + + + + + + + + + + 聯絡電話 + * + + + + { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("phoneCountryCode", value); + }} + placeholder="國際區號" + error={Boolean(formik.touched.phone && formik.errors.phone)} + onBlur={formik.handleBlur} + inputProps={{ + maxLength: 3, + onKeyDown: (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + sx={{ width: '25%' }} + /> + { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("phone", value); + }} + placeholder="聯絡電話" + error={Boolean(formik.touched.phone && formik.errors.phone)} + onBlur={formik.handleBlur} + inputProps={{ + maxLength: 11, + onKeyDown: (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + sx={{ width: '75%' }} + /> + + {formik.touched.phone && formik.errors.phone && ( + + {formik.errors.phone} + + )} + + + + + + + + + + + 傳真號碼 + + + + { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("faxCountryCode", value); + }} + placeholder="國際區號" + onBlur={formik.handleBlur} + inputProps={{ + maxLength: 3, + onKeyDown: (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + sx={{ width: '25%' }} + /> + { + const value = event.target.value; + if (value.match(/[^0-9]/)) { + return event.preventDefault(); + } + formik.setFieldValue("fax", value); + }} + placeholder="傳真號碼" + inputProps={{ + maxLength: 8, + onKeyDown: (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + sx={{ width: '75%' }} + /> + + + + + + + + + + + + + 條款和條件 + * + + + + + + + {termsAndCon} + + + + + + + + + + 我接受 + + + + + + + + 我不接受 + + + + + + + + + + + + + 驗證 + * + + + + + + + { onCaptchaChange() }}> + + + + + { + const value = event.target.value; + formik.setFieldValue("captchaField", value); + }} + sx={{ width: '75%' }} + /> + + + {formik.touched.captchaField && formik.errors.captchaField && ( + + {formik.errors.captchaField} + + )} + + + + +
+
+ {/* Preview Form */} + + + + +
+ 成為新的個人用戶 +
+
+
+ + + + + 你的個人資料 + {/* + Already have an account? + */} + + + + + + 身份證明文件 + + + {formik.values.enName} + + + + + + + + 英文姓名: + + + {formik.values.enName} + + + + + + + 中文姓名: + + + {formik.values.chName} + + + + + + + 地址: + + + + {formik.values.address1} + + {formik.values.address2 != null ? + + {formik.values.address2} + + : null} + {formik.values.address3 != null ? + + {formik.values.address3} + + : 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} + + + + : null} + + +
+
+ {/* Submit page */} + + + {isLoading ? + : + + {checkUpload ? + // SUCCESS page + + + 帳戶申請已成功提交。 + 驗證電郵將發送到你的電郵地址,請依指示完成驗證及登入系統。 + + + : + // ERROR page + + {/* */} + + 申請失敗,請稍後嘗試 + + + } + + } + + +
+
+ ); +} + +export default CustomFormWizard; diff --git a/src/pages/iAmSmart/AuthCallback/index.js b/src/pages/iAmSmart/AuthCallback/index.js index aa61a40..0c03fbe 100644 --- a/src/pages/iAmSmart/AuthCallback/index.js +++ b/src/pages/iAmSmart/AuthCallback/index.js @@ -1,195 +1,42 @@ -// material-ui -import { - Grid, - Typography, - Stack, - Card, - FormHelperText, - InputLabel, OutlinedInput, -} from '@mui/material'; + import * as React from "react"; -import { useFormik, FormikProvider } from 'formik'; -import * as yup from 'yup'; -import { useParams } from "react-router-dom"; import * as HttpUtils from "utils/HttpUtils"; import * as UrlUtils from "utils/ApiPathConst"; -//import { iAmSmartPath, clientId, getBowerType , iAmSmartCallbackPath} from 'auth/utils' - +import { useNavigate } from "react-router-dom"; import Loadable from 'components/Loadable'; const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); -import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' -const BackgroundHead = { - backgroundImage: `url(${titleBackgroundImg})`, - width: '100%', - height: '100%', - backgroundSize: 'contain', - backgroundRepeat: 'no-repeat', - backgroundColor: '#0C489E', - backgroundPosition: 'right' -} // ==============================|| DASHBOARD - DEFAULT ||============================== // const Index = () => { - const params = useParams(); - const [onReady, setOnReady] = React.useState(false); - const [checkUsername, setCheckUsername] = React.useState(false); - const [props, setProps] = React.useState({}); + const navigate = useNavigate() React.useEffect(() => { - if(params.code){ - setOnReady(true); - setProps({}); - getPrfile(); - } + getPrfile(); }, []); function getPrfile(){ - HttpUtils.post({ - url: UrlUtils.GET_SMART_PROFILE, - params:{ - code: params.code - }, - onSuccess: () => { - - } - }); - } - - function displayErrorMsg(errorMsg) { - return {errorMsg} + let params = new URLSearchParams(window.location.search) + if(params.get("code")){ + HttpUtils.post({ + url: UrlUtils.GET_SMART_PROFILE, + params:{ + code: params.get("code") + }, + onSuccess: (responseData) => { + navigate('/iAmSmartRegisterFrom', { state: { responseData: responseData } }); + } + }); + } } - const formik = useFormik({ - initialValues: ({ - username: '', - enName: '', - email: '', - address1: '', - address2: '', - address3: '', - password: '', - phone: '', - phoneCountryCode: '852', - }), - - validationSchema: yup.object().shape({ - username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg('請輸入用戶名稱')) - .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg("用戶名稱不包含特殊字符") }) - .matches(/^\S*$/, { message: displayErrorMsg('用戶名稱不包含空格') }), - enName: yup.string().max(255).required(displayErrorMsg('請輸入英文姓名')), - 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('請輸入電郵')), - phoneCountryCode: yup.string().min(2, displayErrorMsg('請輸入最少2位數字')).required(displayErrorMsg('請輸入國際區號')), - phone: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')).required(displayErrorMsg('請輸入聯絡電話')), - }, ['username']), - - }); + return ( - !onReady ? - : - - - -
- - iAmSmart 登記 - -
-
- {/*row 1*/} - - - *': { - flexGrow: 1, - flexBasis: '50%' - }, - backgroundColor: "secondary", - p:8, - pl:16, - pr:16 - }} - > - - - -
- 成為個人用戶 -
- 註有*的項目必須輸入資料 - 用戶資料 - {/* - Already have an account? - */} -
-
- - - - - - - 用戶登入名稱 - * - - - { - setCheckUsername(false) - props.username = e.target.value - formik.handleChange(e) - }} - placeholder="用戶登入名稱" - fullWidth - error={Boolean((formik.touched.username && formik.errors.username) || checkUsername)} - onBlur={formik.handleBlur} - inputProps={{ - onKeyDown: (e) => { - if (e.key === 'Enter') { - e.preventDefault(); - } - }, - }} - /> - {formik.touched.username && formik.errors.username && ( - - {formik.errors.username} - - )} - {checkUsername && ( - - 此用戶登入名稱已被注冊,請使用其他用戶登入名稱 - - )} - - - - - -
-
-
-
- {/*row 2*/} -
-
- ); }; diff --git a/src/routes/LoginRoutes.js b/src/routes/LoginRoutes.js index d0adeb1..f32edfe 100644 --- a/src/routes/LoginRoutes.js +++ b/src/routes/LoginRoutes.js @@ -10,6 +10,7 @@ const AuthLogin = Loadable(lazy(() => import('pages/authentication/Login'))); const AuthRegister = Loadable(lazy(() => import('pages/authentication/RegisterCustom'))); const RegisterForm = Loadable(lazy(() => import('pages/authentication/Register'))); const BusRegisterForm = Loadable(lazy(() => import('pages/authentication/BusRegister'))); +const IAmSmartRegister = Loadable(lazy(() => import('pages/authentication/IAmSmartRegister'))); const ErrorPage = Loadable(lazy(() => import('pages/extra-pages/ErrorPage'))); const IAmSmart_FailCallback = Loadable(lazy(() => import('pages/iAmSmart/FailCallback'))); const IAmSmart_SuccessCallback = Loadable(lazy(() => import('pages/iAmSmart/SuccessCallback'))); @@ -45,6 +46,10 @@ const LoginRoutes = { path: 'registerFromOrganization', element: }, + { + path: 'iAmSmartRegisterFrom', + element: + }, { path: 'error', element: