You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

1071 regels
66 KiB

  1. import { useEffect, useState, } from 'react';
  2. // material-ui
  3. import {
  4. Button,
  5. FormHelperText,
  6. Grid, IconButton,
  7. InputLabel, OutlinedInput,
  8. Stack,
  9. Typography,
  10. FormGroup,
  11. TextField,
  12. Checkbox
  13. // MenuItem
  14. } from '@mui/material';
  15. import { useForm, } from 'react-hook-form'
  16. import Autocomplete from "@mui/material/Autocomplete";
  17. // third party
  18. import { useFormik, FormikProvider } from 'formik';
  19. import * as yup from 'yup';
  20. import axios from "axios";
  21. import { POST_IAMSMART_USER_REGISTER, POST_CAPTCHA, GET_USER_EMAIL } from "utils/ApiPathConst";
  22. import * as ComboData from "utils/ComboData";
  23. import Loadable from 'components/Loadable';
  24. import { lazy } from 'react';
  25. const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent')));
  26. import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
  27. import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
  28. import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png';
  29. import { Link } from 'react-router-dom';
  30. import * as HttpUtils from "../../../utils/HttpUtils";
  31. import LoopIcon from '@mui/icons-material/Loop';
  32. import { useTheme } from '@mui/material/styles';
  33. import { useLocation } from "react-router-dom";
  34. import {FormattedMessage, useIntl} from "react-intl";
  35. // ============================|| FIREBASE - REGISTER ||============================ //
  36. const CustomFormWizard = (props) => {
  37. const location = useLocation();
  38. const theme = useTheme();
  39. const intl = useIntl();
  40. const [iAmSmartData, setIAmSmartData] = useState({});
  41. const [checkUpload, setCheckUpload] = useState(false);
  42. const [isLoading, setLoding] = useState(true);
  43. const [captchaImg, setCaptchaImage] = useState("");
  44. const [selectedAddress4, setSelectedAddress4] = useState(null);
  45. const [selectedAddress5, setSelectedAddress5] = useState(ComboData.country[0]);
  46. const [termsAndConAccept, setTermsAndConAccept] = useState(false);
  47. const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false);
  48. const [isValid, setisValid] = useState(false);
  49. const [checkCountry, setCheckCountry] = useState(false);
  50. const email = document.getElementById("email-login")
  51. const [checkEmail, setCheckEmail] = useState(false)
  52. const [checkEmailBlur, setCheckEmailBlur] = useState(false)
  53. const address4ComboList = ComboData.district;
  54. const address5ComboList = ComboData.country;
  55. const termsAndCon = "此網址由香港特別行政區政府物流服務署製作及管理。本署會盡力確保網址上的資料無誤,\n"
  56. + "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址"
  57. + "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評"
  58. + "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港"
  59. + "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限"
  60. + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香"
  61. + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面"
  62. + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。"
  63. useEffect(() => {
  64. location.state?.responseData ?? {}
  65. if(captchaImg=="")
  66. onCaptchaChange();
  67. responseToData();
  68. }, []);
  69. const responseToData = () => {
  70. //let rd = JSON.parse("{\"emailAddress\":\"[email protected]\",\"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\":\"測試商一\"}}");
  71. let rd = JSON.parse(location.state?.responseData.data);
  72. let data = {
  73. "enName": rd?.enName?.UnstructuredName ?? "",
  74. "chName": rd?.chName?.ChineseName ?? "",
  75. "idNo": rd?.idNo?.Identification ?? "",
  76. "checkDigit": rd?.idNo?.CheckDigit ?? "",
  77. "email": rd?.emailAddress ?? "",
  78. "phone": rd?.mobileNumber?.SubscriberNumber ?? "",
  79. "phoneCountryCode": rd?.mobileNumber?.CountryCode ?? "",
  80. };
  81. if (rd?.postalAddress) {
  82. if (rd?.postalAddress?.EngPremisesAddress) {
  83. data["address1"] = getAddressEng(rd?.postalAddress?.EngPremisesAddress);
  84. } else if (rd.postalAddress.ChiPremisesAddress) {
  85. data["address1"] = getAddressChi(rd?.postalAddress?.ChiPremisesAddress);
  86. }
  87. } else if (rd?.residentialAddress) {
  88. if (rd?.residentialAddress?.EngPremisesAddress) {
  89. data["address1"] = getAddressEng(rd?.residentialAddress?.EngPremisesAddress);
  90. } else if (rd?.residentialAddress?.ChiPremisesAddress) {
  91. data["address1"] = getAddressChi(rd?.residentialAddress?.ChiPremisesAddress);
  92. }
  93. }
  94. setIAmSmartData(data);
  95. }
  96. const getAddressEng = (pAdd) => {
  97. let unit = (pAdd.Eng3dAddress?.EngUnit?.UnitDescriptor ?? "") + " " + (pAdd.Eng3dAddress?.EngUnit?.UnitNo ?? "");
  98. let block = (pAdd.EngBlock?.BlockDescriptor ?? "") + " " + (pAdd.EngBlock?.BlockNo ?? "");
  99. let floor = pAdd.Eng3dAddress?.EngFloor?.FloorNum ? pAdd.Eng3dAddress?.EngFloor?.FloorNum + "/F " : "";
  100. let street = (pAdd.EngStreet?.EngUnit?.UnitDescriptor ?? "") + " " + (pAdd.Eng3dAddress?.EngUnit?.UnitNo ?? "");
  101. //let region = pAdd.Region ?? "";
  102. let buildingName = pAdd.BuildingName ?? "";
  103. let estate = pAdd.EngEstate?.EstateName ?? "";
  104. let district = pAdd.EngDistrict["Sub - district"] ?? "";
  105. return getAddressStr([unit, block, floor, buildingName, estate, street, district]);
  106. }
  107. const getAddressChi = (pAdd) => {
  108. let unit = (pAdd.Chi3dAddress?.ChiUnit?.UnitDescriptor ?? "") + " " + (pAdd.Chi3dAddress?.ChiUnit?.UnitNo ?? "");
  109. let block = (pAdd.ChiBlock?.BlockDescriptor ?? "") + " " + (pAdd.ChiBlock?.BlockNo ?? "");
  110. let floor = pAdd.Chi3dAddress?.ChiFloor?.FloorNum ? pAdd.Chi3dAddress?.ChiFloor?.FloorNum + "樓 " : "";
  111. let street = (pAdd.ChiStreet?.ChiUnit?.UnitDescriptor ?? "") + " " + (pAdd.Chi3dAddress?.ChiUnit?.UnitNo ?? "");
  112. //let region = pAdd.Region ?? "";
  113. let buildingName = pAdd.BuildingName ?? "";
  114. let estate = pAdd.ChiEstate?.EstateName ?? "";
  115. let district = pAdd.ChiDistrict["Sub - district"] ?? "";
  116. return getAddressStr([district, street, estate, buildingName, street, floor, block, unit ]);
  117. }
  118. const getAddressStr = (strs) => {
  119. let add = ""
  120. strs.forEach(str => {
  121. add += str.trim() ? str.trim() + ", " : "";
  122. });
  123. add = add.trim();
  124. if (add.slice(- 1) == ",") {
  125. add = add.substring(0, add.length - 1);
  126. }
  127. return add;
  128. }
  129. const handleCheckEmail = async () => {
  130. if (values?.email) {
  131. const response = await axios.get(`${GET_USER_EMAIL}`, {
  132. params: {
  133. email: values.email,
  134. }
  135. })
  136. setCheckEmail((Number(response.data[0]) === 1))
  137. return Number(response.data[0]) === 1
  138. }
  139. }
  140. useEffect(() => {
  141. if (email) {
  142. email.addEventListener("blur", function () {
  143. setCheckEmailBlur(true)
  144. })
  145. }
  146. }, [email])
  147. useEffect(() => {
  148. if (checkEmailBlur) {
  149. handleCheckEmail()
  150. setCheckEmailBlur(false)
  151. }
  152. }, [checkEmailBlur])
  153. useEffect(() => {
  154. if (iAmSmartData) {
  155. formik.setFieldValue("enName", iAmSmartData.enName??"");
  156. formik.setFieldValue("chName", iAmSmartData.chName??"");
  157. formik.setFieldValue("idNo", iAmSmartData.idNo??"");
  158. formik.setFieldValue("checkDigit", iAmSmartData.checkDigit??"");
  159. formik.setFieldValue("email", iAmSmartData.email??"");
  160. formik.setFieldValue("phone", iAmSmartData.phone??"");
  161. formik.setFieldValue("phoneCountryCode", iAmSmartData.phoneCountryCode??"");
  162. formik.setFieldValue("address1", iAmSmartData.address1??"");
  163. props.setIdNo(iAmSmartData.idNo??"");
  164. }
  165. }, [iAmSmartData])
  166. const onCaptchaChange = () => {
  167. HttpUtils.post({
  168. url: POST_CAPTCHA,
  169. params: { width: 130, height: 40, captcha: captchaImg},
  170. onSuccess: (responseData) => {
  171. props.setBase64Url(responseData.base64Url)
  172. localStorage.setItem("base64Url", responseData.base64Url);
  173. setCaptchaImage(localStorage.getItem('base64Url'));
  174. }
  175. });
  176. }
  177. const checkDataField = (data) => {
  178. if (data.address1 !== "" &&
  179. data.email !== "" &&
  180. data.emailConfirm !== "" &&
  181. data.email == data.emailConfirm &&
  182. data.phone !== "" &&
  183. data.phoneCountryCode !== "" &&
  184. termsAndConAccept == true &&
  185. data.captchaField &&
  186. handleEmail(data.email) &&
  187. handlePhone(data.phone) &&
  188. handleCaptcha(data.captchaField) &&
  189. !checkEmail
  190. ) {
  191. setisValid(true)
  192. return isValid
  193. } else {
  194. setisValid(false)
  195. return isValid
  196. }
  197. };
  198. const handleCheckBoxChange = (event) => {
  199. if (event.target.name == 'termsAndConAccept') {
  200. setTermsAndConAccept(event.target.checked)
  201. setTermsAndConNotAccept(!event.target.checked)
  202. }
  203. if (event.target.name == 'termsAndConNotAccept') {
  204. setTermsAndConNotAccept(event.target.checked)
  205. setTermsAndConAccept(!event.target.checked)
  206. }
  207. };
  208. useEffect(() => {
  209. props.setUpdateValid(isValid)
  210. }, [isValid])
  211. useEffect(() => {
  212. checkDataField(values)
  213. }, [
  214. selectedAddress4, selectedAddress5,
  215. termsAndConAccept, termsAndConNotAccept])
  216. useEffect(() => {
  217. props.step == 2 ? _onSubmit() : null;
  218. if(captchaImg=="")
  219. onCaptchaChange();
  220. checkDataField(values)
  221. }, [props.step])
  222. const { handleSubmit } = useForm({})
  223. const _onSubmit = () => {
  224. setLoding(true);
  225. values.address4 = selectedAddress4
  226. values.address5 = selectedAddress5
  227. const userAddress = {
  228. "addressLine1": "",
  229. "addressLine2": "",
  230. "addressLine3": "",
  231. "district": "",
  232. "country": ""
  233. };
  234. userAddress.addressLine1 = values.address1
  235. userAddress.addressLine2 = values.address2
  236. userAddress.addressLine3 = values.address3
  237. userAddress.district = values.address4
  238. userAddress.country = values.address5
  239. const userFaxNo = {
  240. "countryCode": values.faxCountryCode,
  241. "faxNumber": values.fax,
  242. };
  243. const userMobileNumber = {
  244. "countryCode": values.phoneCountryCode,
  245. "phoneNumber": values.phone,
  246. };
  247. let tncFlag = false;
  248. if (termsAndConAccept) {
  249. tncFlag = true
  250. }
  251. if (termsAndConNotAccept) {
  252. tncFlag = false
  253. }
  254. const formData = {
  255. enName: iAmSmartData.enName,
  256. chName: iAmSmartData.chName,
  257. emailAddress: values.email,
  258. idDocType: "HKID",
  259. identification: iAmSmartData.idNo,
  260. checkDigit: iAmSmartData.checkDigit,
  261. tncFlag: tncFlag,
  262. type: "IND",
  263. userFaxNo: JSON.stringify(userFaxNo),
  264. userMobileNumber: JSON.stringify(userMobileNumber),
  265. userAddress: JSON.stringify(userAddress)
  266. };
  267. if (isValid) {
  268. axios.post(POST_IAMSMART_USER_REGISTER, formData, {
  269. headers: {
  270. "Content-Type": "multipart/form-data"
  271. }
  272. })
  273. .then((response) => {
  274. console.log(response)
  275. setCheckUpload(true)
  276. setLoding(false);
  277. })
  278. .catch(error => {
  279. console.error(error);
  280. setLoding(false);
  281. });
  282. } else {
  283. setLoding(false);
  284. }
  285. }
  286. function handlePhone(phone) {
  287. if (phone.length < 8) {
  288. return false;
  289. } else {
  290. return true;
  291. }
  292. }
  293. function handleCaptcha(captchaField) {
  294. return captchaField;
  295. }
  296. function handleEmail(email) {
  297. var validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
  298. if (!email.match(validRegex)) {
  299. return false;
  300. } else {
  301. return true;
  302. }
  303. }
  304. function displayErrorMsg(errorMsg) {
  305. return <Typography variant="errorMessage1">{errorMsg}</Typography>
  306. }
  307. const formik = useFormik({
  308. initialValues: ({
  309. email: iAmSmartData.email??"",
  310. emailConfirm: iAmSmartData.email??"",
  311. address1: iAmSmartData.address1??"",
  312. address2: '',
  313. address3: '',
  314. phone: iAmSmartData.phone??"",
  315. phoneCountryCode: iAmSmartData.phoneCountryCode??"852",
  316. submit: null,
  317. fax: '',
  318. faxCountryCode: '852',
  319. captchaField: ''
  320. }),
  321. validationSchema: yup.object().shape({
  322. address1: yup.string().max(40).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine1'}))),
  323. address2: yup.string().max(40).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine2'}))),
  324. address3: yup.string().max(40).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine3'}))),
  325. email: yup.string().email(displayErrorMsg(intl.formatMessage({id: 'validEmailFormat'}))).max(255).required(displayErrorMsg(intl.formatMessage({id: 'requireEmail'}))),
  326. emailConfirm: yup.string().email(displayErrorMsg(intl.formatMessage({id: 'validEmailFormat'}))).max(255).required(displayErrorMsg(intl.formatMessage({id: 'requireEmail'}))).oneOf([yup.ref('email'), null], displayErrorMsg(intl.formatMessage({id: 'validSameEmail'}))),
  327. phoneCountryCode: yup.string().min(2, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast2Number'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireDialingCode'}))),
  328. phone: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast8Number'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireContactNumber'}))),
  329. captchaField: yup.string().required(displayErrorMsg(intl.formatMessage({id: 'requireVerify'}))),//.oneOf([captcha], displayErrorMsg('請輸入有效驗證')),
  330. }),
  331. });
  332. const { values } = formik
  333. useEffect(() => {
  334. checkDataField(values)
  335. }, [values])
  336. return (
  337. <FormikProvider value={formik}>
  338. <form onSubmit={handleSubmit(_onSubmit)}>
  339. {/* Input Form */}
  340. <FormGroup id={"inputForm"} sx={{ display: props.step === 0 ? "" : "none" }}>
  341. <Grid container spacing={3}>
  342. <Grid item xs={12} md={12}>
  343. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  344. <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}>
  345. <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}>
  346. <FormattedMessage id="becomeNewPersonalUser"/>
  347. </Typography><img src={iAmSmartICon} alt="iAM Smart" width="50" />
  348. </div>
  349. <Typography mt={0.25} variant="h6" sx={{ color: '#f10000' }}>
  350. <FormattedMessage id="requireString"/>。
  351. </Typography>
  352. <Stack mt={1} direction="row" style={{ alignItems: "center" }}><img src={iAmSmartICon} alt="iAM Smart" width="25" /><Typography mt={0.25} variant="h6" >: 表示該項由「智方便」提供。</Typography></Stack>
  353. </Stack>
  354. </Grid>
  355. <Grid item xs={12} md={12}>
  356. <Grid container spacing={1}>
  357. <Grid item xs={12} mt={1} mb={1}>
  358. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  359. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  360. <FormattedMessage id="yourPersonalInformation"/>
  361. </Typography>
  362. </Stack>
  363. </Grid>
  364. <Grid item xs={12} md={12} >
  365. <Grid container sx={{ mb: 1 }}>
  366. <Stack spacing={1}>
  367. <InputLabel htmlFor="idDocType-signup">
  368. <Typography variant="h5">
  369. 香港身份證: {iAmSmartData.idNo+"("+iAmSmartData.checkDigit+")"}
  370. </Typography>
  371. </InputLabel>
  372. </Stack>
  373. </Grid>
  374. </Grid>
  375. <Grid item xs={12} md={6}>
  376. <Stack spacing={1}>
  377. <InputLabel htmlFor="enName-signup">
  378. <Typography variant="h5">
  379. <FormattedMessage id="userEnglishName"/>: {iAmSmartData.enName}
  380. </Typography>
  381. </InputLabel>
  382. </Stack>
  383. </Grid>
  384. <Grid item xs={12} md={6}>
  385. <Stack spacing={1}>
  386. <InputLabel htmlFor="chName-signup">
  387. <Typography variant="h5">
  388. {intl.formatMessage({id: 'userChineseName'})}: {iAmSmartData.chName}
  389. </Typography>
  390. </InputLabel>
  391. </Stack>
  392. </Grid>
  393. <Grid item xs={12}>
  394. <Stack spacing={1}>
  395. <InputLabel htmlFor="address1-signup">
  396. <Typography variant="h5">
  397. <FormattedMessage id="formAddress"/>
  398. <span style={{ color: '#f10000' }}>*</span>
  399. {iAmSmartData.address1?<img src={iAmSmartICon} alt="iAM Smart" width="25" />:null}
  400. </Typography>
  401. </InputLabel>
  402. <OutlinedInput
  403. fullWidth
  404. error={Boolean(formik.touched.address1 && formik.errors.address1)}
  405. id="address1-signup"
  406. value={formik.values.address1}
  407. name="address1"
  408. onChange={formik.handleChange}
  409. placeholder={intl.formatMessage({id: 'addressLine1'})}
  410. onBlur={formik.handleBlur}
  411. inputProps={{
  412. onKeyDown: (e) => {
  413. if (e.key === 'Enter') {
  414. e.preventDefault();
  415. }
  416. },
  417. }}
  418. />
  419. <OutlinedInput
  420. fullWidth
  421. error={Boolean(formik.touched.address2 && formik.errors.address2)}
  422. id="address2-signup"
  423. value={formik.values.address2}
  424. name="address2"
  425. onChange={formik.handleChange}
  426. placeholder={intl.formatMessage({id: 'addressLine2'})}
  427. inputProps={{
  428. onKeyDown: (e) => {
  429. if (e.key === 'Enter') {
  430. e.preventDefault();
  431. }
  432. },
  433. }}
  434. />
  435. <OutlinedInput
  436. fullWidth
  437. error={Boolean(formik.touched.address3 && formik.errors.address3)}
  438. id="address3-signup"
  439. value={formik.values.address3}
  440. name="address3"
  441. onChange={formik.handleChange}
  442. placeholder={intl.formatMessage({id: 'addressLine3'})}
  443. inputProps={{
  444. onKeyDown: (e) => {
  445. if (e.key === 'Enter') {
  446. e.preventDefault();
  447. }
  448. },
  449. }}
  450. />
  451. <Autocomplete
  452. disablePortal
  453. id="address4-combo"
  454. value={selectedAddress4}
  455. options={address4ComboList}
  456. disabled={checkCountry}
  457. getOptionLabel={(option) => option.type? intl.formatMessage({ id: option.type }) : ""}
  458. onChange={(event, newValue) => {
  459. setSelectedAddress4(newValue);
  460. }}
  461. sx={{ "& .MuiInputBase-root": { height: "41px" }, "#address4-combo": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }}
  462. renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({id: 'region'})}
  463. />}
  464. />
  465. <Autocomplete
  466. disablePortal
  467. id="address5-combo"
  468. value={selectedAddress5}
  469. options={address5ComboList}
  470. getOptionLabel={(option) => option.type? intl.formatMessage({ id: option.type }) : ""}
  471. onChange={(event, newValue) => {
  472. if (newValue !== null) {
  473. setSelectedAddress5(newValue);
  474. if (newValue.type === 'hongKong') {
  475. setCheckCountry(false)
  476. } else {
  477. setSelectedAddress4("");
  478. setCheckCountry(true)
  479. }
  480. } else {
  481. setSelectedAddress4("");
  482. setCheckCountry(true)
  483. }
  484. }}
  485. sx={{ "& .MuiInputBase-root": { height: "41px" }, "#address5-combo": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }}
  486. renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({id: 'regionOrCountry'})} />}
  487. />
  488. {formik.touched.address1 && formik.errors.address1 && (
  489. <FormHelperText error id="helper-text-address1-signup">
  490. {formik.errors.address1}
  491. </FormHelperText>
  492. )}
  493. {formik.touched.address2 && formik.errors.address2 && (
  494. <FormHelperText error id="helper-text-address2-signup">
  495. {formik.errors.address2}
  496. </FormHelperText>
  497. )}
  498. {formik.touched.address3 && formik.errors.address3 && (
  499. <FormHelperText error id="helper-text-address3-signup">
  500. {formik.errors.address3}
  501. </FormHelperText>
  502. )}
  503. </Stack>
  504. </Grid>
  505. <Grid item xs={12} mt={1} mb={1}>
  506. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  507. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  508. <FormattedMessage id="yourContact"/>
  509. </Typography>
  510. </Stack>
  511. </Grid>
  512. <Grid item xs={12} md={12}>
  513. <Grid container>
  514. <Grid item xs={12} md={6}>
  515. <Stack spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  516. <InputLabel htmlFor="email-signup">
  517. <Typography variant="h5">
  518. <FormattedMessage id="userContactEmail"/>
  519. <span style={{ color: '#f10000' }}>*</span>
  520. {iAmSmartData.email?<img src={iAmSmartICon} alt="iAM Smart" width="25" />:null}
  521. </Typography>
  522. </InputLabel>
  523. <OutlinedInput
  524. fullWidth
  525. error={Boolean((formik.touched.email && formik.errors.email) || checkEmail)}
  526. id="email-login"
  527. type="email"
  528. value={formik.values.email.trim()}
  529. name="email"
  530. onChange={formik.handleChange}
  531. placeholder={intl.formatMessage({id: 'userContactEmail'})}
  532. onBlur={formik.handleBlur}
  533. inputProps={{
  534. onKeyDown: (e) => {
  535. if (e.key === 'Enter') {
  536. e.preventDefault();
  537. }
  538. },
  539. }}
  540. />
  541. {formik.touched.email && formik.errors.email && (
  542. <FormHelperText error id="helper-text-email-signup">
  543. {formik.errors.email}
  544. </FormHelperText>
  545. )}
  546. {checkEmail && (
  547. <FormHelperText error id="helper-text-email-signup">
  548. <FormattedMessage id="emailUsed"/>
  549. </FormHelperText>
  550. )}
  551. </Stack>
  552. </Grid>
  553. <Grid item xs={12} md={6}>
  554. <Stack spacing={1} >
  555. <InputLabel htmlFor="emailConfirm-signup">
  556. <Typography variant="h5">
  557. <FormattedMessage id="userContactEmail"/>
  558. <span style={{ color: '#f10000' }}>*</span>
  559. </Typography>
  560. </InputLabel>
  561. <OutlinedInput
  562. fullWidth
  563. error={Boolean(formik.touched.emailConfirm && formik.errors.emailConfirm)}
  564. id="emailConfirm-login"
  565. type="email"
  566. value={formik.values.emailConfirm.trim()}
  567. name="emailConfirm"
  568. // onBlur={formik.handleBlur}
  569. onChange={formik.handleChange}
  570. placeholder={intl.formatMessage({id: 'confirmEmail'})}
  571. onBlur={formik.handleBlur}
  572. inputProps={{
  573. onKeyDown: (e) => {
  574. if (e.key === 'Enter') {
  575. e.preventDefault();
  576. }
  577. },
  578. }}
  579. />
  580. {formik.touched.emailConfirm && formik.errors.emailConfirm && (
  581. <FormHelperText error id="helper-text-emailConfirm-signup">
  582. {formik.errors.emailConfirm}
  583. </FormHelperText>
  584. )}
  585. </Stack>
  586. </Grid>
  587. </Grid>
  588. </Grid>
  589. <Grid item xs={12} md={12}>
  590. <Grid container>
  591. <Grid item xs={12} md={6}>
  592. <Grid container>
  593. <Grid item xs={12} md={12}>
  594. <Stack direction="column" spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  595. <InputLabel htmlFor="phone-signup">
  596. <Typography variant="h5">
  597. <FormattedMessage id="userContactNumber"/>
  598. <span style={{ color: '#f10000' }}>*</span>
  599. {iAmSmartData.phone?<img src={iAmSmartICon} alt="iAM Smart" width="25" />:null}
  600. </Typography>
  601. </InputLabel>
  602. <Stack direction="row">
  603. <OutlinedInput
  604. id="phoneCountryCode-login"
  605. type="phoneCountryCode"
  606. value={formik.values.phoneCountryCode.trim()}
  607. name="phoneCountryCode"
  608. // onBlur={formik.handleBlur}
  609. // onChange={formik.handleChange}
  610. onChange={(event) => {
  611. const value = event.target.value;
  612. if (value.match(/[^0-9]/)) {
  613. return event.preventDefault();
  614. }
  615. formik.setFieldValue("phoneCountryCode", value);
  616. }}
  617. placeholder={intl.formatMessage({id: 'dialingCode'})}
  618. error={Boolean(formik.touched.phone && formik.errors.phone)}
  619. onBlur={formik.handleBlur}
  620. inputProps={{
  621. maxLength: 3,
  622. onKeyDown: (e) => {
  623. if (e.key === 'Enter') {
  624. e.preventDefault();
  625. }
  626. },
  627. }}
  628. sx={{ width: '25%' }}
  629. />
  630. <OutlinedInput
  631. id="phone-login"
  632. type="phone"
  633. value={formik.values.phone.trim()}
  634. name="phone"
  635. // onBlur={formik.handleBlur}
  636. // onChange={formik.handleChange}
  637. onChange={(event) => {
  638. const value = event.target.value;
  639. if (value.match(/[^0-9]/)) {
  640. return event.preventDefault();
  641. }
  642. formik.setFieldValue("phone", value);
  643. }}
  644. placeholder={intl.formatMessage({id: 'userContactNumber'})}
  645. error={Boolean(formik.touched.phone && formik.errors.phone)}
  646. onBlur={formik.handleBlur}
  647. inputProps={{
  648. maxLength: 11,
  649. onKeyDown: (e) => {
  650. if (e.key === 'Enter') {
  651. e.preventDefault();
  652. }
  653. },
  654. }}
  655. sx={{ width: '75%' }}
  656. />
  657. </Stack>
  658. {formik.touched.phone && formik.errors.phone && (
  659. <FormHelperText error id="helper-text-phone-signup">
  660. {formik.errors.phone}
  661. </FormHelperText>
  662. )}
  663. </Stack>
  664. </Grid>
  665. </Grid>
  666. </Grid>
  667. <Grid item xs={12} md={6}>
  668. <Grid container>
  669. <Grid item xs={12} md={12}>
  670. <Stack spacing={1} direction="column">
  671. <InputLabel htmlFor="fax-signup">
  672. <Typography variant="h5">
  673. <FormattedMessage id="userFaxNumber"/>
  674. </Typography>
  675. </InputLabel>
  676. <Stack direction="row">
  677. <OutlinedInput
  678. error={Boolean(formik.touched.fax && formik.errors.fax)}
  679. id="faxCountryCode-login"
  680. type="faxCountryCode"
  681. value={formik.values.faxCountryCode.trim()}
  682. name="faxCountryCode"
  683. // onChange={formik.handleChange}
  684. onChange={(event) => {
  685. const value = event.target.value;
  686. if (value.match(/[^0-9]/)) {
  687. return event.preventDefault();
  688. }
  689. formik.setFieldValue("faxCountryCode", value);
  690. }}
  691. placeholder={intl.formatMessage({id: 'dialingCode'})}
  692. onBlur={formik.handleBlur}
  693. inputProps={{
  694. maxLength: 3,
  695. onKeyDown: (e) => {
  696. if (e.key === 'Enter') {
  697. e.preventDefault();
  698. }
  699. },
  700. }}
  701. sx={{ width: '25%' }}
  702. />
  703. <OutlinedInput
  704. id="fax-login"
  705. type="fax"
  706. value={formik.values.fax.trim()}
  707. name="fax"
  708. onBlur={formik.handleBlur}
  709. // onChange={formik.handleChange}
  710. onChange={(event) => {
  711. const value = event.target.value;
  712. if (value.match(/[^0-9]/)) {
  713. return event.preventDefault();
  714. }
  715. formik.setFieldValue("fax", value);
  716. }}
  717. placeholder={intl.formatMessage({id: 'userFaxNumber'})}
  718. inputProps={{
  719. maxLength: 8,
  720. onKeyDown: (e) => {
  721. if (e.key === 'Enter') {
  722. e.preventDefault();
  723. }
  724. },
  725. }}
  726. sx={{ width: '75%' }}
  727. />
  728. </Stack>
  729. </Stack>
  730. </Grid>
  731. </Grid>
  732. </Grid>
  733. </Grid>
  734. </Grid>
  735. </Grid>
  736. <Grid item xs={12} md={12}>
  737. <Grid container>
  738. <Grid item xs={12} md={12}>
  739. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  740. <FormattedMessage id="termsAndCondition"/>
  741. <span style={{ color: '#f10000' }}>*</span>
  742. </Typography>
  743. </Grid>
  744. <Grid item xs={12} md={12}>
  745. <Grid container>
  746. <Grid item xs={12} md={12}>
  747. <Typography variant="h5" height="80%" sx={{ textAlign: "left", overflow: "scroll", borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0C489E" }}>
  748. {termsAndCon}
  749. </Typography>
  750. </Grid>
  751. </Grid>
  752. <Grid item xs={12} s={12} md={12} lg={12}>
  753. <Grid container>
  754. <Grid item xs={6} s={6} md={2} lg={2}>
  755. <Grid container>
  756. <Grid item sx={{ display: 'flex', alignItems: 'center' }}>
  757. <Checkbox
  758. checked={termsAndConAccept}
  759. onChange={handleCheckBoxChange}
  760. name="termsAndConAccept"
  761. color="primary"
  762. size="small"
  763. />
  764. <Typography variant="h5">
  765. <FormattedMessage id="acceptTerms"/>
  766. </Typography>
  767. </Grid>
  768. </Grid>
  769. </Grid>
  770. <Grid item xs={6} s={6} md={3} lg={3}>
  771. <Grid container>
  772. <Grid item sx={{ display: 'flex', alignItems: 'center' }}>
  773. <Checkbox
  774. checked={termsAndConNotAccept}
  775. onChange={handleCheckBoxChange}
  776. name="termsAndConNotAccept"
  777. color="primary"
  778. size="small"
  779. />
  780. <Typography variant="h5">
  781. <FormattedMessage id="rejectTerms"/>
  782. </Typography>
  783. </Grid>
  784. </Grid>
  785. </Grid>
  786. </Grid>
  787. </Grid>
  788. </Grid>
  789. </Grid>
  790. </Grid>
  791. <Grid item xs={12} lg={12}>
  792. <Grid container>
  793. <Stack direction="column">
  794. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  795. <FormattedMessage id="verify"/>
  796. <span style={{ color: '#f10000' }}>*</span>
  797. </Typography>
  798. <Stack spacing={1} direction="row">
  799. <Grid item xs={5} lg={5} style={{ "border": "1px solid black" }}>
  800. <img src={captchaImg} alt="" />
  801. </Grid>
  802. <Grid item xs={1} lg={1} style={{ "border": "0px solid black" }}>
  803. <IconButton aria-label="refrashCaptcha" size="large" onClick={() => { onCaptchaChange() }}>
  804. <LoopIcon fontSize="inherit" />
  805. </IconButton>
  806. </Grid>
  807. <Grid item xs={6} lg={6}>
  808. <OutlinedInput
  809. fullWidth
  810. id="captchaField"
  811. type="text"
  812. value={formik.values.captchaField.trim()}
  813. onBlur={formik.handleBlur}
  814. error={Boolean(formik.touched.captchaField && formik.errors.captchaField)}
  815. name="captchaField"
  816. onChange={(event) => {
  817. const value = event.target.value;
  818. props.setCheckCode(event.target.value);
  819. formik.setFieldValue("captchaField", value);
  820. }}
  821. sx={{ width: '75%' }}
  822. />
  823. </Grid>
  824. </Stack>
  825. {formik.touched.captchaField && formik.errors.captchaField && (
  826. <FormHelperText error id="helper-text-captcha-signup">
  827. {formik.errors.captchaField}
  828. </FormHelperText>
  829. )}
  830. </Stack>
  831. </Grid>
  832. </Grid>
  833. </Grid>
  834. </Grid>
  835. </FormGroup>
  836. {/* Preview Form */}
  837. <FormGroup id={"previewForm"} sx={{ display: props.step === 1 ? "" : "none" }}>
  838. <Grid container spacing={3}>
  839. <Grid item xs={12} md={12}>
  840. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  841. <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}>
  842. <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}>
  843. <FormattedMessage id="becomeNewPersonalUser"/>
  844. </Typography>
  845. </div>
  846. </Stack>
  847. </Grid>
  848. <Grid item xs={12} md={12}>
  849. <Grid container spacing={2}>
  850. <Grid item xs={12} mt={1} mb={1}>
  851. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  852. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  853. <FormattedMessage id="yourPersonalInformation"/>
  854. </Typography>
  855. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  856. Already have an account?
  857. </Typography> */}
  858. </Stack>
  859. </Grid>
  860. <Grid item xs={12} md={12} >
  861. <Stack spacing={1}>
  862. <Typography variant="h5" color={theme.palette.grey[600]}>
  863. <FormattedMessage id="userIdDoc"/>
  864. </Typography>
  865. <Typography variant="h5" name="preview-idDocType">
  866. {formik.values.idNo+"("+formik.values.checkDigit+")"}
  867. </Typography>
  868. </Stack>
  869. </Grid>
  870. <Grid item xs={12} md={6}>
  871. <Stack spacing={1} direction="row">
  872. <Typography variant="h5" color={theme.palette.grey[600]}>
  873. <FormattedMessage id="userEnglishName"/>:
  874. </Typography>
  875. <Typography variant="h5" id="preview-enName-signup">
  876. {formik.values.enName}
  877. </Typography>
  878. </Stack>
  879. </Grid>
  880. <Grid item xs={12} md={6}>
  881. <Stack spacing={1} direction="row">
  882. <Typography variant="h5" color={theme.palette.grey[600]}>
  883. <FormattedMessage id="userChineseName"/>:
  884. </Typography>
  885. <Typography variant="h5" id="preview-chName-signup">
  886. {formik.values.chName}
  887. </Typography>
  888. </Stack>
  889. </Grid>
  890. <Grid item xs={12}>
  891. <Stack spacing={1} direction="row">
  892. <Typography variant="h5" color={theme.palette.grey[600]}>
  893. <FormattedMessage id="formAddress"/>:
  894. </Typography>
  895. <Stack spacing={1} direction="column">
  896. <Typography variant="h5" id="preview-address1-signup">
  897. {formik.values.address1}
  898. </Typography>
  899. {formik.values.address2 != null ?
  900. <Typography variant="h5" id="preview-address2-signup">
  901. {formik.values.address2}
  902. </Typography>
  903. : null}
  904. {formik.values.address3 != null ?
  905. <Typography variant="h5" id="preview-address3-signup">
  906. {formik.values.address3}
  907. </Typography>
  908. : null}
  909. {selectedAddress5.type === "hongKong" ?
  910. <Stack direction="row">
  911. <Typography variant="h5" color={theme.palette.grey[600]} id="preview-address4-signup">
  912. <FormattedMessage id="region"/>:
  913. </Typography>
  914. <Typography variant="h5">
  915. {!selectedAddress4? "" : intl.formatMessage({id: selectedAddress4.type})}
  916. </Typography>
  917. </Stack>
  918. : null}
  919. <Stack direction="row">
  920. <Typography variant="h5" color={theme.palette.grey[600]} id="preview-address5-signup">
  921. <FormattedMessage id="regionOrCountry"/>:
  922. </Typography>
  923. <Typography variant="h5">
  924. {intl.formatMessage({id: selectedAddress5.type})}
  925. </Typography>
  926. </Stack>
  927. </Stack>
  928. </Stack>
  929. </Grid>
  930. <Grid item xs={12} mt={1} mb={1}>
  931. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  932. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  933. <FormattedMessage id="yourContact"/>
  934. </Typography>
  935. </Stack>
  936. </Grid>
  937. <Grid item xs={12} md={12}>
  938. <Stack spacing={1} direction="row">
  939. <Typography variant="h5" color={theme.palette.grey[600]}>
  940. <FormattedMessage id="userContactEmail"/>:
  941. </Typography>
  942. <Typography variant="h5" id="preview-email-signup">
  943. {formik.values.email}
  944. </Typography>
  945. </Stack>
  946. </Grid>
  947. <Grid item xs={12} md={6}>
  948. <Stack spacing={1} direction="row">
  949. <Typography variant="h5" color={theme.palette.grey[600]}>
  950. <FormattedMessage id="userContactNumber"/>:
  951. </Typography>
  952. <Typography variant="h5" id="preview-phone-signup">
  953. +{formik.values.phoneCountryCode} {formik.values.phone}
  954. </Typography>
  955. </Stack>
  956. </Grid>
  957. {formik.values.faxCountryCode != "" && formik.values.fax != "" ?
  958. <Grid item xs={12} md={6}>
  959. <Stack spacing={1} direction="row">
  960. <Typography variant="h5" color={theme.palette.grey[600]}>
  961. <FormattedMessage id="userFaxNumber"/>:
  962. </Typography>
  963. <Typography variant="h5" id="preview-fax-signup">
  964. +{formik.values.faxCountryCode} {formik.values.fax}
  965. </Typography>
  966. </Stack>
  967. </Grid>
  968. : null}
  969. </Grid>
  970. </Grid>
  971. </Grid>
  972. </FormGroup>
  973. {/* Submit page */}
  974. <FormGroup id={"submitForm"} sx={{ display: props.step === 2 ? "" : "none" }}>
  975. <Grid container spacing={3}>
  976. {isLoading ?
  977. <LoadingComponent /> :
  978. <Grid item xs={12}>
  979. {checkUpload ?
  980. // SUCCESS page
  981. <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
  982. <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
  983. <Typography display="inline" variant="h4">
  984. <FormattedMessage id="registerSubmitted"/>
  985. </Typography>
  986. <Typography display="inline" variant="h4">
  987. <FormattedMessage id="emailSent"/>
  988. </Typography>
  989. <Button variant="outlined" component={Link} to="/login" ><Typography variant="h5">
  990. <FormattedMessage id="backToLogin"/>
  991. </Typography></Button>
  992. </Stack>
  993. :
  994. // ERROR page
  995. <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
  996. {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
  997. <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
  998. <Typography display="inline" variant="h4">
  999. <FormattedMessage id="registerFail" />
  1000. </Typography>
  1001. <Button color="error" variant="outlined" component={Link} to="/login" ><Typography variant="h5">
  1002. <FormattedMessage id="backToLogin"/>
  1003. </Typography></Button>
  1004. </Stack>
  1005. }
  1006. </Grid>
  1007. }
  1008. </Grid>
  1009. </FormGroup>
  1010. </form>
  1011. </FormikProvider>
  1012. );
  1013. }
  1014. export default CustomFormWizard;