Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

6 місяці тому
3 роки тому
3 роки тому
7 місяці тому
3 роки тому
3 роки тому
1 тиждень тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
2 місяці тому
7 місяці тому
2 роки тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
3 роки тому
3 роки тому
6 місяці тому
6 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
7 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
5 місяці тому
2 роки тому
2 роки тому
2 роки тому
5 місяці тому
2 роки тому
2 роки тому
5 місяці тому
2 роки тому
3 роки тому
2 роки тому
3 роки тому
5 місяці тому
2 місяці тому
5 місяці тому
5 місяці тому
5 місяці тому
2 роки тому
3 роки тому
3 роки тому
3 роки тому
3 місяці тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
3 роки тому
3 роки тому
3 місяці тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
2 місяці тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
1 рік тому
2 роки тому
1 рік тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
3 роки тому
2 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
5 місяці тому
2 місяці тому
5 місяці тому
5 місяці тому
3 роки тому
3 роки тому
6 місяці тому
2 роки тому
6 місяці тому
2 місяці тому
2 роки тому
2 місяці тому
2 роки тому
2 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 місяці тому
2 роки тому
7 місяці тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
7 місяці тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
3 місяці тому
7 місяці тому
2 роки тому
7 місяці тому
2 місяці тому
2 роки тому
2 роки тому
2 роки тому
7 місяці тому
3 роки тому
3 роки тому
3 роки тому
7 місяці тому
3 місяці тому
7 місяці тому
2 роки тому
3 роки тому
2 роки тому
2 місяці тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
2 місяці тому
2 роки тому
2 роки тому
2 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
7 місяці тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
3 роки тому
7 місяці тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
3 роки тому
7 місяці тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
2 роки тому
3 роки тому
7 місяці тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
7 місяці тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
3 роки тому
7 місяці тому
2 місяці тому
3 роки тому
2 роки тому
2 роки тому
7 місяці тому
2 місяці тому
3 роки тому
2 роки тому
2 роки тому
7 місяці тому
2 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
7 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
7 місяці тому
2 роки тому
2 роки тому
2 місяці тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
7 місяці тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
3 роки тому
7 місяці тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
3 роки тому
7 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
3 роки тому
2 роки тому
7 місяці тому
2 роки тому
2 роки тому
7 місяці тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
7 місяці тому
2 роки тому
7 місяці тому
3 роки тому
3 роки тому
2 роки тому
7 місяці тому
3 роки тому
2 роки тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
7 місяці тому
3 роки тому
2 роки тому
2 роки тому
7 місяці тому
2 роки тому
7 місяці тому
3 роки тому
2 роки тому
7 місяці тому
2 роки тому
3 роки тому
2 місяці тому
2 роки тому
2 місяці тому
2 роки тому
2 місяці тому
2 роки тому
6 місяці тому
6 місяці тому
6 місяці тому
2 роки тому
2 місяці тому
5 місяці тому
2 місяці тому
2 роки тому
2 місяці тому
1 тиждень тому
11 місяці тому
7 місяці тому
2 роки тому
11 місяці тому
2 роки тому
2 роки тому
2 роки тому
7 місяці тому
2 роки тому
3 роки тому
2 місяці тому
2 роки тому
3 роки тому
2 роки тому
7 місяці тому
3 роки тому
3 роки тому
6 місяці тому
6 місяці тому
6 місяці тому
2 місяці тому
6 місяці тому
3 місяці тому
6 місяці тому
7 місяці тому
3 роки тому
2 місяці тому
2 роки тому
2 місяці тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 місяці тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 місяці тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
3 роки тому
2 роки тому
3 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 роки тому
2 місяці тому
2 роки тому
5 місяці тому
3 роки тому
3 роки тому
2 місяці тому
2 роки тому
2 місяці тому
2 роки тому
2 роки тому
3 роки тому
3 роки тому
2 місяці тому
2 роки тому
3 роки тому
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981
  1. import { useEffect, useState, useRef } from 'react';
  2. // material-ui
  3. import {
  4. Box,
  5. Button,
  6. FormControl,
  7. FormHelperText,
  8. Grid, IconButton,
  9. InputAdornment,
  10. InputLabel, OutlinedInput,
  11. Stack,
  12. Typography,
  13. FormGroup,
  14. TextField,
  15. Checkbox
  16. // MenuItem
  17. } from '@mui/material';
  18. import { useForm, } from 'react-hook-form'
  19. import Autocomplete from "@mui/material/Autocomplete";
  20. // third party
  21. import { useFormik, FormikProvider } from 'formik';
  22. import * as yup from 'yup';
  23. // import axios from "axios";
  24. // project import
  25. // import AnimateButton from 'components/@extended/AnimateButton';
  26. import { strengthColorChi, strengthIndicator } from 'utils/password-strength';
  27. // import {apiPath} from "auth/utils";
  28. import axios from "axios";
  29. import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, POST_USERNAME, POST_USER_EMAIL, POST_CAPTCHA_AUDIO} from "utils/ApiPathConst";
  30. // import * as HttpUtils from 'utils/HttpUtils';
  31. import * as ComboData from "utils/ComboData";
  32. import Loadable from 'components/Loadable';
  33. import SafeHtml from 'components/SafeHtml';
  34. import { lazy } from 'react';
  35. const UploadFileTable = Loadable(lazy(() => import('./UploadFileTable')));
  36. const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent')));
  37. const PreviewUploadFileTable = Loadable(lazy(() => import('./PreviewUploadFileTable')));
  38. // import UploadFileTable from './UploadFileTable';
  39. // import LoadingComponent from "../../extra-pages/LoadingComponent";
  40. // assets
  41. import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
  42. import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
  43. import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
  44. import { Link } from 'react-router-dom';
  45. import * as HttpUtils from "../../../utils/HttpUtils"
  46. import LoopIcon from '@mui/icons-material/Loop';
  47. import { useTheme } from '@mui/material/styles';
  48. import {PNSPS_LONG_BUTTON_THEME} from "../../../themes/buttonConst";
  49. import {ThemeProvider} from "@emotion/react";
  50. import {FormattedMessage, useIntl} from "react-intl";
  51. //import { Invaild } from 'utils/IconUtils';
  52. import { handleActionKeyDown, notifyActionError } from 'utils/CommonFunction';
  53. import { ADDRESS_LINE_MAX_LENGTH, isAddressLineWithinLimit, isRegisterAddressValid } from 'utils/registerValidation';
  54. // ============================|| FIREBASE - REGISTER ||============================ //
  55. const BusCustomFormWizard = (props) => {
  56. const intl = useIntl();
  57. const { locale } = intl;
  58. const theme = useTheme()
  59. const [level, setLevel] = useState();
  60. const [showPassword, setShowPassword] = useState(false);
  61. const [showConfirmPassword, setshowConfirmPassword] = useState(false);
  62. const [fileList, setFileList] = useState([]);
  63. const [fileListData, setFileListData] = useState([]);
  64. const [checkUpload, setCheckUpload] = useState(false);
  65. const [isLoading, setLoding] = useState(true);
  66. const [updateRows, setUpdateRows] = useState([]);
  67. // const [userNameList, setUserNameList] = useState([]);
  68. const [captchaImg, setCaptchaImage] = useState("");
  69. const [base64Url, setBase64Url] = useState("")
  70. const [checkCode, setCheckCode] = useState("")
  71. const handleClickShowPassword = () => {
  72. setShowPassword(!showPassword);
  73. };
  74. const handleClickShowConfirmPassword = () => {
  75. setshowConfirmPassword(!showConfirmPassword);
  76. };
  77. const handleMouseDownPassword = (event) => {
  78. event.preventDefault();
  79. };
  80. const changePassword = (value) => {
  81. const temp = strengthIndicator(value);
  82. setLevel(strengthColorChi(temp));
  83. };
  84. const [selectedAddress4, setSelectedAddress4] = useState(null);
  85. const [selectedAddress5, setSelectedAddress5] = useState(ComboData.country[0]);
  86. const [termsAndConAccept, setTermsAndConAccept] = useState(false);
  87. const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false);
  88. const [isValid, setisValid] = useState(false);
  89. const [checkCountry, setCheckCountry] = useState(false);
  90. // eslint-disable-next-line no-unused-vars -- used as ref for hidden file input (ref={fileInputRef}) and in click handlers
  91. const fileInputRef = useRef(null);
  92. const username = document.getElementById("username-login")
  93. const [checkUsername, setCheckUsername] = useState(false);
  94. const [checkUsernameBlur, setCheckUsernameBlur] = useState(false)
  95. const email = document.getElementById("email-login")
  96. const [checkEmail, setCheckEmail] = useState(false)
  97. const [checkEmailBlur, setCheckEmailBlur] = useState(false)
  98. const district = document.getElementById("address4-combo")
  99. const [checkDistrict, setCheckDistrict] = useState(false)
  100. const [checkDistrictBlur, setCheckDistrictBlur] = useState(false)
  101. const [districtErrStr, setDistrictErrStr] = useState("")
  102. const address4ComboList = ComboData.district;
  103. const address5ComboList = ComboData.country;
  104. const refType = "identification";
  105. useEffect(() => {
  106. changePassword('');
  107. }, []);
  108. const playCaptchaAudio = async () => {
  109. try {
  110. const resp = await axios.post(
  111. `${POST_CAPTCHA_AUDIO}`,
  112. { base64Url, lang: intl.locale },
  113. { responseType: "arraybuffer" }
  114. );
  115. const blob = new Blob([resp.data], { type: "audio/wav" });
  116. const url = URL.createObjectURL(blob);
  117. const audio = new Audio(url);
  118. await audio.play();
  119. } catch (error) {
  120. let message = intl.formatMessage({ id: "captchaAudioError" });
  121. if (error.response) {
  122. if (error.response.status === 404) {
  123. message = intl.formatMessage({ id: "captchaExpired" });
  124. } else if (error.response.status === 500) {
  125. message = intl.formatMessage({ id: "captchaAudioServerError" });
  126. }
  127. } else if (error.request) {
  128. message = intl.formatMessage({ id: "connectionError" });
  129. }
  130. notifyActionError(message);
  131. }
  132. };
  133. const handleCheckUsername = async () => {
  134. if (values?.username) {
  135. const response = await axios.post(`${POST_USERNAME}`, {
  136. u1: values.username,
  137. })
  138. setCheckUsername((Number(response.data[0]) > 0))
  139. return Number(response.data[0]) > 0
  140. }
  141. }
  142. /** POST /user/checkE1 — returns true if email is already registered */
  143. const checkEmailRegistered = async (emailStr) => {
  144. const em = emailStr?.trim();
  145. if (!em) return false;
  146. const response = await axios.post(`${POST_USER_EMAIL}`, { e1: em });
  147. return Number(response.data[0]) > 0;
  148. };
  149. const handleCheckEmail = async () => {
  150. if (!values?.email) return false;
  151. try {
  152. const taken = await checkEmailRegistered(values.email);
  153. setCheckEmail(taken);
  154. return taken;
  155. } catch (error) {
  156. notifyActionError(intl.formatMessage({ id: 'connectionError' }));
  157. return false;
  158. }
  159. };
  160. useEffect(() => {
  161. if (username) {
  162. username.addEventListener("blur", function () {
  163. setCheckUsernameBlur(true)
  164. })
  165. }
  166. }, [username])
  167. useEffect(() => {
  168. if (checkUsernameBlur) {
  169. handleCheckUsername()
  170. setCheckUsernameBlur(false)
  171. }
  172. }, [checkUsernameBlur])
  173. useEffect(() => {
  174. if (email) {
  175. email.addEventListener("blur", function () {
  176. setCheckEmailBlur(true)
  177. })
  178. }
  179. }, [email])
  180. useEffect(() => {
  181. if (checkEmailBlur) {
  182. handleCheckEmail()
  183. setCheckEmailBlur(false)
  184. }
  185. }, [checkEmailBlur])
  186. useEffect(() => {
  187. if (district) {
  188. district.addEventListener("blur", function () {
  189. setCheckDistrictBlur(true)
  190. })
  191. }
  192. }, [district])
  193. useEffect(() => {
  194. if (checkDistrictBlur) {
  195. handleCheckDistrict()
  196. setCheckDistrictBlur(false)
  197. }
  198. }, [checkDistrictBlur])
  199. const isDistrictSelectionValid = () => {
  200. if (selectedAddress5?.type !== "hongKong") {
  201. return true;
  202. }
  203. return !(selectedAddress4 == null || selectedAddress4 === "");
  204. };
  205. const handleCheckDistrict = () => {
  206. setDistrictErrStr("");
  207. if (selectedAddress5?.type === "hongKong") {
  208. if (selectedAddress4 == null || selectedAddress4 == "" || selectedAddress4 == {}){
  209. setCheckDistrict(true)
  210. setDistrictErrStr(getRequiredErrStr("district"))
  211. }else {
  212. setCheckDistrict(false)
  213. }
  214. } else {
  215. setCheckDistrict(false);
  216. }
  217. }
  218. useEffect(() => {
  219. handleCheckDistrict();
  220. }, [selectedAddress4, selectedAddress5]);
  221. function getRequiredErrStr(fieldname){
  222. return displayErrorMsg(intl.formatMessage({ id: 'require'},{fieldname:fieldname?intl.formatMessage({ id: fieldname}):""}));
  223. }
  224. function getMaxErrStr(num, fieldname){
  225. return displayErrorMsg(intl.formatMessage({ id: 'noMoreThenNWords' },{num:num, fieldname:fieldname?intl.formatMessage({ id: fieldname})+": ":""}));
  226. }
  227. const onCaptchaChange = () => {
  228. HttpUtils.post({
  229. url: POST_CAPTCHA,
  230. params: { width: 130, height: 40, captcha: captchaImg},
  231. onSuccess: (responseData) => {
  232. props.setBase64Url(responseData.base64Url)
  233. setBase64Url(responseData.base64Url)
  234. localStorage.setItem("base64Url", responseData.base64Url);
  235. setCaptchaImage(localStorage.getItem('base64Url'));
  236. }
  237. });
  238. }
  239. /** Step-0 validity excluding duplicate-email result from /checkE1 (see checkEmail state). */
  240. const computeStep0ValidSync = (data) => (
  241. handleCaptcha(data.captchaField) &&
  242. data.username !== "" &&
  243. data.password !== "" &&
  244. data.confirmPassword !== "" &&
  245. data.password === data.confirmPassword &&
  246. (data.chCompanyName !== "" || data.enCompanyName !== "") &&
  247. data.enName !== "" &&
  248. data.chName !== "" &&
  249. isRegisterAddressValid(data) &&
  250. data.email !== "" &&
  251. data.emailConfirm !== "" &&
  252. data.email === data.emailConfirm &&
  253. data.phone !== "" &&
  254. data.phoneCountryCode !== "" &&
  255. termsAndConAccept === true &&
  256. fileList.length !== 0 &&
  257. data.brNo !== "" &&
  258. data.brExpiryDate !== "" &&
  259. handlePassword(data.password) &&
  260. handleEmail(data.email) &&
  261. handlePhone(data.phone) &&
  262. handleUserName(data.username) &&
  263. handleBrNo(data.brNo) &&
  264. isDistrictSelectionValid() &&
  265. !checkUsername
  266. );
  267. const computeStep0Valid = (data) => computeStep0ValidSync(data) && !checkEmail;
  268. const checkDataField = (data) => {
  269. const can = computeStep0Valid(data);
  270. setisValid(can);
  271. return can;
  272. };
  273. const handleCheckBoxChange = (event) => {
  274. // console.log(event.target)
  275. if (event.target.name == 'termsAndConAccept') {
  276. setTermsAndConAccept(event.target.checked)
  277. setTermsAndConNotAccept(!event.target.checked)
  278. }
  279. if (event.target.name == 'termsAndConNotAccept') {
  280. setTermsAndConNotAccept(event.target.checked)
  281. setTermsAndConAccept(!event.target.checked)
  282. }
  283. };
  284. useEffect(() => {
  285. let updateRowList = new DataTransfer();
  286. var updateRowsIndex = updateRows.length;
  287. const saveFileList = [];
  288. if (updateRowsIndex != null) {
  289. for (let i = 0; i < updateRowsIndex; i++) {
  290. const file = updateRows[i]
  291. file.id = i;
  292. updateRowList.items.add(file);
  293. saveFileList.push(file);
  294. }
  295. let updatedFileList = updateRowList.files;
  296. setFileList(updatedFileList);
  297. setFileListData(saveFileList)
  298. }
  299. if (fileInputRef.current) {
  300. fileInputRef.current.value = '';
  301. }
  302. }, [updateRows]);
  303. const handleBrNo = (brNo) => {
  304. var brNo_pattern = /[0-9]{8}/
  305. if (brNo !== undefined) {
  306. if (brNo.match(brNo_pattern)) {
  307. return true
  308. } else {
  309. return false
  310. }
  311. }
  312. }
  313. const handleFileUpload = (event) => {
  314. let updateList = new DataTransfer();
  315. let currentFileList = fileListData;
  316. const uploadFileList = event.target.files;
  317. const saveFileList = [];
  318. var currentIndex = 0;
  319. if (currentFileList.length != null) {
  320. currentIndex = currentFileList.length;
  321. for (let i = 0; i < currentIndex; i++) {
  322. const file = currentFileList[i]
  323. // file.id = currentIndex;
  324. updateList.items.add(file);
  325. saveFileList.push(file);
  326. }
  327. }
  328. for (let i = 0; i < uploadFileList.length && currentIndex < 5; i++) {
  329. const file = event.target.files[i]
  330. let isDuplicate = false;
  331. // Check if the file name already exists in saveFileList
  332. for (let j = 0; j < saveFileList.length; j++) {
  333. if (saveFileList[j].name === file.name) {
  334. isDuplicate = true;
  335. break;
  336. }
  337. }
  338. if (!isDuplicate && i + currentIndex < 5) {
  339. file.id = currentIndex + i
  340. saveFileList.push(file)
  341. updateList.items.add(file);
  342. }
  343. // console.log("currentIndex")
  344. // console.log(currentIndex)
  345. }
  346. let updatedFileList = updateList.files;
  347. setFileListData(saveFileList)
  348. setFileList(updatedFileList);
  349. setUpdateRows(saveFileList);
  350. event.target.value = '';
  351. };
  352. useEffect(() => {
  353. props.setUpdateValid(isValid)
  354. }, [isValid])
  355. useEffect(() => {
  356. checkDataField(values)
  357. }, [selectedAddress4, selectedAddress5,
  358. termsAndConAccept, termsAndConNotAccept, fileList])
  359. useEffect(() => {
  360. props.step == 2 ? _onSubmit() : null;
  361. if(captchaImg=="")
  362. onCaptchaChange();
  363. checkDataField(values)
  364. }, [props.step])
  365. const { handleSubmit } = useForm({})
  366. const _onSubmit = () => {
  367. setLoding(true);
  368. values.address4 = selectedAddress4==null?"":selectedAddress4.type
  369. values.address5 = selectedAddress5.type
  370. // console.log(values)
  371. const busUserAddress = {
  372. "addressLine1": "",
  373. "addressLine2": "",
  374. "addressLine3": "",
  375. "district": "",
  376. "country": ""
  377. };
  378. busUserAddress.addressLine1 = values.address1
  379. busUserAddress.addressLine2 = values.address2
  380. busUserAddress.addressLine3 = values.address3
  381. busUserAddress.district = values.address4
  382. busUserAddress.country = values.address5
  383. const userFaxNo = {
  384. "countryCode": values.faxCountryCode,
  385. "faxNumber": values.fax,
  386. };
  387. const busUserContactTel = {
  388. "countryCode": values.phoneCountryCode,
  389. "phoneNumber": values.phone,
  390. };
  391. let tncFlag = false;
  392. if (termsAndConAccept) {
  393. tncFlag = true
  394. }
  395. if (termsAndConNotAccept) {
  396. tncFlag = false
  397. }
  398. const preferLocale = locale === 'en' ? 'en': locale === 'zh-HK' ? 'zh_HK': 'zh-CN'
  399. const user = {
  400. username: values.username,
  401. password: values.password,
  402. name: values.username,
  403. enCompanyName: values.enCompanyName,
  404. chCompanyName: values.chCompanyName,
  405. emailBus: values.email,
  406. brNo: values.brNo,
  407. brExpiryDate: values.brExpiryDate,
  408. contactPerson: values.enName,
  409. tncFlag: tncFlag,
  410. type: "ORG",
  411. captcha: base64Url,
  412. checkCode: checkCode,
  413. preferLocale:preferLocale
  414. };
  415. var formData = new FormData();
  416. for (let i = 0; i < fileListData.length; i++) {
  417. const file = fileListData[i]
  418. formData.append("multipartFileList", file);
  419. }
  420. formData.append("refType", refType);
  421. for (const [key, value] of Object.entries(user)) {
  422. formData.append(key, value);
  423. }
  424. formData.append("userFaxNo", JSON.stringify(userFaxNo));
  425. formData.append("busUserContactTel", JSON.stringify(busUserContactTel));
  426. formData.append("busUserAddress", JSON.stringify(busUserAddress));
  427. // formData.append("preferLocale", "en");
  428. if (isValid) {
  429. axios.post(POST_PUBLIC_USER_REGISTER, formData, {
  430. headers: {
  431. "Content-Type": "multipart/form-data"
  432. }
  433. })
  434. .then((
  435. // response
  436. ) => {
  437. // console.log(response)
  438. setCheckUpload(true)
  439. props.onRegistrationComplete?.();
  440. setLoding(false);
  441. })
  442. .catch(error => {
  443. console.error(error);
  444. setLoding(false);
  445. });
  446. } else {
  447. setLoding(false);
  448. }
  449. }
  450. function handlePhone(phone) {
  451. if (phone.length < 8) {
  452. return false;
  453. } else {
  454. return true;
  455. }
  456. }
  457. function handleUserName(username) {
  458. var symbol = /^(?=.*\W)/;
  459. var space = /\s/;
  460. if (username.length < 6) {
  461. return false;
  462. } else if (username.match(symbol)) {
  463. return false;
  464. } else if (username.match(space)) {
  465. return false;
  466. } else {
  467. return true;
  468. }
  469. }
  470. function handleCaptcha(captchaField) {
  471. if (captchaField.length == 5 ){
  472. return true
  473. } else {
  474. return false
  475. }
  476. }
  477. function handlePassword(password) {
  478. let new_pass = password;
  479. // regular expressions to validate password
  480. var lowerCase = /[a-z]/g;
  481. var upperCase = /[A-Z]/g;
  482. var numbers = /[0-9]/g;
  483. var symbol = /^(?=.*\W)/;
  484. var space = /\s/;
  485. if (!new_pass.match(lowerCase)) {
  486. return false;
  487. } else if (!new_pass.match(upperCase)) {
  488. return false;
  489. } else if (!new_pass.match(numbers)) {
  490. return false;
  491. } else if (!new_pass.match(symbol)) {
  492. return false;
  493. } else if (new_pass.length < 8) {
  494. return false;
  495. }
  496. else if (new_pass.match(space)) {
  497. return false;
  498. } else {
  499. // console.log("password true")
  500. return true;
  501. }
  502. }
  503. function handleEmail(email) {
  504. var validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
  505. if (!email.match(validRegex)) {
  506. return false;
  507. } else {
  508. return true;
  509. }
  510. }
  511. function displayErrorMsg(errorMsg) {
  512. return <Typography variant="errorMessage1">{errorMsg}</Typography>
  513. }
  514. const formik = useFormik({
  515. initialValues: ({
  516. username: '',
  517. enName: '',
  518. enCompanyName: '',
  519. chCompanyName: '',
  520. email: '',
  521. address1: '',
  522. address2: '',
  523. address3: '',
  524. password: '',
  525. confirmPassword: '',
  526. phone: '',
  527. phoneCountryCode: '852',
  528. submit: null,
  529. fax: '',
  530. faxCountryCode: '852',
  531. brExpiryDate: '',
  532. brNo: '',
  533. emailConfirm: '',
  534. captchaField: ''
  535. }),
  536. validationSchema: yup.object().shape({
  537. username: yup.string().min(6, displayErrorMsg(intl.formatMessage({id: 'atLeast6CharAccount'}))).max(30,getMaxErrStr(30)).required(displayErrorMsg(intl.formatMessage({id: 'requireUsername'})))
  538. .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(intl.formatMessage({id: 'noSpecialCharAccount'})) })
  539. .matches(/^\S*$/, { message: displayErrorMsg(intl.formatMessage({id: 'noSpaceAccount'})) }),
  540. password: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'atLeast8CharPassword'}))).max(60,getMaxErrStr(60)).required(displayErrorMsg(intl.formatMessage({id: 'requirePassword'})))
  541. .matches(/^\S*$/, { message: displayErrorMsg(intl.formatMessage({id: 'noSpacePassword'})) })
  542. .matches(/^(?=.*[a-z])/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeastOneSmallLetter'})) })
  543. .matches(/^(?=.*[A-Z])/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeastOneCapLetter'})) })
  544. .matches(/^(?=.*[0-9])/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeast1Number'})) })
  545. .matches(/^(?=.*\W)/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeast1SpecialChar'})) }),
  546. confirmPassword: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'atLeast8CharPassword'}))).required(displayErrorMsg(intl.formatMessage({id: 'pleaseConfirmPassword'}))).oneOf([yup.ref('password'), null], displayErrorMsg(intl.formatMessage({id: 'samePassword'}))),
  547. enName: yup.string().max(40,getMaxErrStr(40)).required(displayErrorMsg(intl.formatMessage({id: 'userRequireEnglishName'}))),
  548. enCompanyName: yup.string().matches(/^[^$^*]+$/, { message: displayErrorMsg('No special characters $/^/*') }).when('chCompanyName', {
  549. is: (chCompanyName) => !chCompanyName || chCompanyName.length === 0,
  550. then: yup.string().required(displayErrorMsg('Please enter either English or Chinese name')),
  551. }),
  552. chCompanyName: yup.string().matches(/^[^$^*]+$/, { message: displayErrorMsg(intl.formatMessage({id: 'notContainSpecialChar'})) }).when('enCompanyName', {
  553. is: (enCompanyName) => !enCompanyName || enCompanyName.length === 0,
  554. then: yup.string().required(displayErrorMsg(intl.formatMessage({id: 'validateEngOrChiName'}))),
  555. }),
  556. chName: yup.string().max(6, getMaxErrStr(6)).required(displayErrorMsg(intl.formatMessage({id: 'userRequireChineseName'}))),
  557. address1: yup.string().max(40, getMaxErrStr(40)).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine1'}))),
  558. address2: yup.string().max(40, getMaxErrStr(40)),
  559. address3: yup.string().max(40, getMaxErrStr(40)),
  560. email: yup.string().email(displayErrorMsg(intl.formatMessage({id: 'validEmailFormat'}))).max(128, getMaxErrStr(128)).required(displayErrorMsg(intl.formatMessage({id: 'requireEmail'}))),
  561. emailConfirm: yup.string().email(displayErrorMsg(intl.formatMessage({id: 'validEmailFormat'}))).max(128, getMaxErrStr(128)).required(displayErrorMsg(intl.formatMessage({id: 'requireEmail'}))).oneOf([yup.ref('email'), null], displayErrorMsg(intl.formatMessage({id: 'validSameEmail'}))),
  562. phoneCountryCode: yup.string().min(2, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast2Number'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireDialingCode'}))),
  563. faxCountryCode: yup.string().min(2, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast2Number'}))),
  564. phone: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast8Number'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireContactNumber'}))),
  565. fax: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast8Number'}))),
  566. brExpiryDate: yup.date().min(new Date().toISOString().split("T")[0], displayErrorMsg(intl.formatMessage({id: 'pleaseFillInBusinessRegCertValidityDate'})))
  567. .max("2099-12-31", displayErrorMsg(intl.formatMessage({id: 'pleaseFillInBusinessRegCertValidityDate'}))).
  568. required(displayErrorMsg(intl.formatMessage({id: 'pleaseFillInBusinessRegCertValidityDate'}))),
  569. brNo: yup.string().max(8, getMaxErrStr(8)).required(displayErrorMsg(intl.formatMessage({id: 'pleaseFillInBusinessRegCertNumber'}))).test('checkBrNoFormat', displayErrorMsg(`${intl.formatMessage({id: 'pleaseFillInValidBusinessRegCertNumber'})} (e.g. 12341234)`), function (value) {
  570. // var brNo_pattern = /[0-9]{8}-[0-9]{3}-(0[1-9]|1[012])-[0-9]{2}-[0-9A-Z]{1}/
  571. var brNo_pattern = /[0-9]{8}/
  572. if (value !== undefined) {
  573. if (value.match(brNo_pattern)) {
  574. return true
  575. } else {
  576. return false
  577. }
  578. }
  579. }),
  580. captchaField: yup.string().max(5, getMaxErrStr(5)).required(displayErrorMsg(intl.formatMessage({ id: 'requireVerify' }))).min(5, displayErrorMsg(intl.formatMessage({ id: 'requireVerify' }))),//.oneOf([captcha], displayErrorMsg('請輸入有效驗證')),
  581. }, ['enCompanyName', 'chCompanyName']),
  582. });
  583. const handleReset = (resetForm) => {
  584. resetForm();
  585. setSelectedAddress4("")
  586. setSelectedAddress5(ComboData.country[0])
  587. setCheckCountry(false)
  588. setFileList([])
  589. setFileListData([])
  590. onCaptchaChange()
  591. };
  592. const handleCCPChange = (e) => {
  593. e.preventDefault();
  594. };
  595. const { values } = formik
  596. useEffect(() => {
  597. if (!props.step0GuardRef) return;
  598. props.step0GuardRef.current = async () => {
  599. const syncOk = computeStep0ValidSync(values);
  600. if (!syncOk) {
  601. setisValid(false);
  602. if (!isRegisterAddressValid(values)) {
  603. if (values.address1 === '') {
  604. notifyActionError(intl.formatMessage({ id: 'validateAddressLine1' }));
  605. } else if (!isAddressLineWithinLimit(values.address1)) {
  606. notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine1' }) + ": " }));
  607. } else if (!isAddressLineWithinLimit(values.address2)) {
  608. notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine2' }) + ": " }));
  609. } else if (!isAddressLineWithinLimit(values.address3)) {
  610. notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine3' }) + ": " }));
  611. }
  612. } else if (!isDistrictSelectionValid()) {
  613. setDistrictErrStr(getRequiredErrStr("district"));
  614. setCheckDistrict(true);
  615. notifyActionError(intl.formatMessage({ id: 'require' }, { fieldname: intl.formatMessage({ id: 'district' }) }));
  616. }
  617. return false;
  618. }
  619. try {
  620. const taken = await checkEmailRegistered(values.email);
  621. setCheckEmail(taken);
  622. if (taken) {
  623. setisValid(false);
  624. notifyActionError(intl.formatMessage({ id: 'emailUsed' }));
  625. return false;
  626. }
  627. } catch (error) {
  628. notifyActionError(intl.formatMessage({ id: 'connectionError' }));
  629. return false;
  630. }
  631. setisValid(true);
  632. return true;
  633. };
  634. }, [values, selectedAddress4, selectedAddress5, termsAndConAccept, fileList, checkUsername, checkEmail]);
  635. useEffect(() => {
  636. checkDataField(values)
  637. }, [values])
  638. return (
  639. <FormikProvider value={formik}>
  640. <form onSubmit={handleSubmit(_onSubmit)}>
  641. {/* Input Form */}
  642. <FormGroup id={"inputForm"} sx={{ display: props.step === 0 ? "" : "none" }}>
  643. <Grid container spacing={3}>
  644. <Grid item xs={12} md={12}>
  645. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  646. <Button
  647. variant="outlined"
  648. type="reset"
  649. onClick={handleReset.bind(null, formik.resetForm)}
  650. sx={{
  651. height: '40px',
  652. borderColor: '#616161',
  653. color: '#424242',
  654. '&:hover': { borderColor: '#424242', backgroundColor: 'rgba(97,97,97,0.08)' },
  655. }}
  656. >
  657. <Typography variant="pnspsFormHeader">
  658. <FormattedMessage id="reset"/>
  659. </Typography>
  660. </Button>
  661. <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}>
  662. <Typography display="inline" variant="h3" component="h1" sx={{ color: '#1A4399' }}>
  663. <FormattedMessage id="becomeNewBusinessUser"/>
  664. </Typography>
  665. </div>
  666. <Typography mt={0.25} variant="h6" component="span" sx={{ color: '#B00020' }}>
  667. <FormattedMessage id="requireString"/>
  668. </Typography>
  669. <Typography mt={0.25} variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  670. <FormattedMessage id="yourLoginInformation"/>
  671. </Typography>
  672. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  673. Already have an account?
  674. </Typography> */}
  675. </Stack>
  676. </Grid>
  677. <Grid item xs={12} md={12}>
  678. <Grid container spacing={1}>
  679. <Grid item xs={12} md={12} >
  680. <Stack spacing={1}>
  681. <InputLabel htmlFor="username-signup">
  682. <Typography variant="pnspsFormHeader">
  683. <FormattedMessage id="userLoginName"/>
  684. <span style={{ color: '#B00020' }}>*</span>
  685. {/* <Button
  686. variant="contained"
  687. onClick={handleCheckUsername}
  688. sx={{ ml: 2, height: "40px" }}>
  689. <Typography variant="h6" component="span">檢查是否重覆</Typography>
  690. </Button> */}
  691. </Typography>
  692. </InputLabel>
  693. <OutlinedInput
  694. id="username-signup"
  695. type="text"
  696. value={formik.values.username.trim()}
  697. name="username"
  698. onChange={(e) => {
  699. setCheckUsername(false)
  700. props.setUsername(e.target.value)
  701. formik.handleChange(e)
  702. }}
  703. placeholder={intl.formatMessage({id: 'userLoginName'})}
  704. fullWidth
  705. autoFocus
  706. error={Boolean((formik.touched.username && formik.errors.username) || checkUsername)}
  707. onBlur={formik.handleBlur}
  708. inputProps={{
  709. "aria-label": intl.formatMessage({ id: "userLoginName" }),
  710. "aria-describedby": 'helper-text-username-login',
  711. onKeyDown: (e) => {
  712. if (e.key === 'Enter') {
  713. e.preventDefault();
  714. }
  715. },
  716. }}
  717. />
  718. {formik.touched.username && formik.errors.username && (
  719. <FormHelperText error id="helper-text-username-signup">
  720. {formik.errors.username}
  721. </FormHelperText>
  722. )}
  723. {checkUsername && (
  724. <FormHelperText error id="helper-text-username-signup">
  725. <FormattedMessage id="usernameTaken"/>
  726. </FormHelperText>
  727. )}
  728. </Stack>
  729. </Grid>
  730. <Grid item xs={12} md={12}>
  731. <Grid container>
  732. <Grid item xs={12} md={6} >
  733. <Stack spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  734. <Stack direction="row" justifyContent="space-between">
  735. <InputLabel htmlFor="password-signup">
  736. <Typography variant="pnspsFormHeader">
  737. <FormattedMessage id="userPassword"/>
  738. <span style={{ color: '#B00020' }}>*</span>
  739. </Typography>
  740. </InputLabel>
  741. </Stack>
  742. <OutlinedInput
  743. fullWidth
  744. error={Boolean(formik.touched.password && formik.errors.password)}
  745. id="password-signup"
  746. type={showPassword ? 'text' : 'password'}
  747. value={formik.values.password.trim()}
  748. name="password"
  749. onChange={(e) => {
  750. formik.handleChange(e);
  751. changePassword(e.target.value);
  752. }}
  753. endAdornment={
  754. <InputAdornment position="end">
  755. <IconButton
  756. role="button"
  757. tabIndex={0}
  758. aria-label={intl.formatMessage({
  759. id: showPassword ? "ariaHidePassword" : "ariaShowPassword"
  760. })}
  761. onClick={handleClickShowPassword}
  762. onKeyDown={(event) => handleActionKeyDown(event, handleClickShowPassword)}
  763. onMouseDown={handleMouseDownPassword}
  764. edge="end"
  765. size="large"
  766. >
  767. {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  768. </IconButton>
  769. </InputAdornment>
  770. }
  771. placeholder={intl.formatMessage({id: 'userPassword'})}
  772. onBlur={formik.handleBlur}
  773. inputProps={{
  774. "aria-label": intl.formatMessage({ id: "userPassword" }),
  775. "aria-describedby": 'helper-text-password-signup',
  776. onKeyDown: (e) => {
  777. if (e.key === 'Enter') {
  778. e.preventDefault();
  779. }
  780. },
  781. }}
  782. />
  783. {formik.touched.password && formik.errors.password && (
  784. <FormHelperText error id="helper-text-password-signup">
  785. {formik.errors.password}
  786. </FormHelperText>
  787. )}
  788. </Stack>
  789. <FormControl fullWidth sx={{ mt: 2 }}>
  790. <Grid container spacing={2} alignItems="center">
  791. <Grid item>
  792. <Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
  793. </Grid>
  794. <Grid item>
  795. <Typography component="span" variant="subtitle1" sx={{ display: 'block' }}>
  796. <FormattedMessage id={level ? level?.label : "pwWeak" }/>
  797. </Typography>
  798. </Grid>
  799. </Grid>
  800. </FormControl>
  801. </Grid>
  802. <Grid item xs={12} md={6} >
  803. <Stack spacing={1}>
  804. <InputLabel htmlFor="confirmPassword-signup">
  805. <Typography variant="pnspsFormHeader">
  806. <FormattedMessage id="confirmPassword"/>
  807. <span style={{ color: '#B00020' }}>*</span>
  808. </Typography>
  809. </InputLabel>
  810. <OutlinedInput
  811. id="confirmPassword-signup"
  812. type={showConfirmPassword ? 'text' : 'password'}
  813. value={formik.values.confirmPassword.trim()}
  814. name="confirmPassword"
  815. onBlur={formik.handleBlur}
  816. onCut={handleCCPChange}
  817. onCopy={handleCCPChange}
  818. onPaste={handleCCPChange}
  819. onChange={(e) => {
  820. formik.handleChange(e);
  821. // changePassword(e.target.value);
  822. }}
  823. inputProps={{
  824. "aria-label": intl.formatMessage({ id: "confirmPassword" }),
  825. "aria-describedby": 'helper-text-confirmPassword-signup',
  826. onKeyDown: (e) => {
  827. if (e.key === 'Enter') {
  828. e.preventDefault();
  829. }
  830. },
  831. }}
  832. endAdornment={
  833. <InputAdornment position="end">
  834. <IconButton
  835. role="button"
  836. tabIndex={0}
  837. aria-label={intl.formatMessage({
  838. id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword"
  839. })}
  840. onClick={handleClickShowConfirmPassword}
  841. onKeyDown={(event) => handleActionKeyDown(event, handleClickShowConfirmPassword)}
  842. onMouseDown={handleMouseDownPassword}
  843. edge="end"
  844. size="large"
  845. >
  846. {showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  847. </IconButton>
  848. </InputAdornment>
  849. }
  850. placeholder={intl.formatMessage({id: 'confirmPassword'})}
  851. fullWidth
  852. error={Boolean(formik.touched.confirmPassword && formik.errors.confirmPassword)}
  853. />
  854. {formik.touched.confirmPassword && formik.errors.confirmPassword && (
  855. <FormHelperText error id="helper-text-confirmPassword-signup">
  856. {formik.errors.confirmPassword}
  857. </FormHelperText>
  858. )}
  859. </Stack>
  860. <Grid container spacing={2} alignItems="center">
  861. <Grid item sx={{mt:1}}>
  862. <Typography component="span" variant="subtitle1" sx={{ display: 'block' }}>
  863. •<FormattedMessage id="pwRemark1"/><br />
  864. •<FormattedMessage id="pwRemark2"/><br />
  865. •<FormattedMessage id="pwRemark3"/><br />
  866. •<FormattedMessage id="pwRemark4"/><br />
  867. •<FormattedMessage id="pwRemark5"/>
  868. </Typography>
  869. </Grid>
  870. </Grid>
  871. </Grid>
  872. </Grid>
  873. </Grid>
  874. <Grid item xs={12} mt={1} mb={1}>
  875. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  876. <Typography display="inline" variant="h4" component="h2" /*sx={{ color: '#1A4399' }}*/>
  877. <FormattedMessage id="yourBusinessInformation"/>
  878. </Typography>
  879. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  880. Already have an account?
  881. </Typography> */}
  882. </Stack>
  883. </Grid>
  884. <Grid item xs={12} md={12}>
  885. <Typography component="span" variant="subtitle1" sx={{ display: 'block' }}>
  886. •<FormattedMessage id="pleaseEnterOrgOrCompName"/>
  887. </Typography>
  888. </Grid>
  889. <Grid item xs={12} md={6}>
  890. <Stack spacing={1}>
  891. <InputLabel htmlFor="enCompanyName-signup">
  892. <Typography variant="pnspsFormHeader">
  893. <FormattedMessage id="businessEngName"/>
  894. </Typography>
  895. </InputLabel>
  896. <OutlinedInput
  897. id="enCompanyName-signup"
  898. type="enCompanyName"
  899. value={formik.values.enCompanyName}
  900. name="enCompanyName"
  901. onChange={formik.handleChange}
  902. placeholder={intl.formatMessage({id: 'sameAsBusinessRegistrationCert'})}
  903. fullWidth
  904. error={Boolean(formik.touched.enCompanyName && formik.errors.enCompanyName && selectedAddress5 !== "內地")}
  905. onBlur={formik.handleBlur}
  906. inputProps={{
  907. "aria-label": intl.formatMessage({ id: "businessEngName" }),
  908. "aria-describedby": 'helper-text-enCompanyName-signup',
  909. onKeyDown: (e) => {
  910. if (e.key === 'Enter') {
  911. e.preventDefault();
  912. }
  913. },
  914. }}
  915. />
  916. {formik.touched.enCompanyName && formik.errors.enCompanyName && selectedAddress5 !== "內地" && (
  917. <FormHelperText error id="helper-text-enCompanyName-signup">
  918. {formik.errors.enCompanyName}
  919. </FormHelperText>
  920. )}
  921. </Stack>
  922. </Grid>
  923. <Grid item xs={12} md={6}>
  924. <Stack spacing={1}>
  925. <InputLabel htmlFor="chCompanyName-signup">
  926. <Typography variant="pnspsFormHeader">
  927. <FormattedMessage id="businessChName"/>
  928. </Typography>
  929. </InputLabel>
  930. <OutlinedInput
  931. fullWidth
  932. error={Boolean(formik.touched.chCompanyName && formik.errors.chCompanyName)}
  933. id="chCompanyName-signup"
  934. type="text"
  935. value={formik.values.chCompanyName.trim()}
  936. name="chCompanyName"
  937. onChange={formik.handleChange}
  938. placeholder={intl.formatMessage({id: 'sameAsBusinessRegistrationCert'})}
  939. onBlur={formik.handleBlur}
  940. inputProps={{
  941. "aria-label": intl.formatMessage({ id: "businessChName" }),
  942. "aria-describedby": 'helper-text-chCompanyName-signup',
  943. onKeyDown: (e) => {
  944. if (e.key === 'Enter') {
  945. e.preventDefault();
  946. }
  947. },
  948. }}
  949. />
  950. {formik.touched.chCompanyName && formik.errors.chCompanyName && (
  951. <FormHelperText error id="helper-text-chCompanyName-signup">
  952. {formik.errors.chCompanyName}
  953. </FormHelperText>
  954. )}
  955. </Stack>
  956. </Grid>
  957. <Grid item xs={12} md={6}>
  958. <Stack spacing={1}>
  959. <InputLabel htmlFor="brNo-signup" sx={{ whiteSpace: 'pre-wrap', wordWrap: 'break-word' }}>
  960. <Typography variant="pnspsFormHeader">
  961. <FormattedMessage id="businessRegCertNumber"/> (e.g. 12341234)
  962. <span style={{ color: '#B00020' }}>*</span>
  963. </Typography>
  964. </InputLabel>
  965. <OutlinedInput
  966. fullWidth
  967. error={Boolean(formik.touched.brNo && formik.errors.brNo)}
  968. id="brNo-signup"
  969. type="text"
  970. value={formik.values.brNo.trim()}
  971. name="brNo"
  972. onChange={formik.handleChange}
  973. onBlur={formik.handleBlur}
  974. placeholder={intl.formatMessage({id: 'sameAsBusinessRegistrationCert'})}
  975. inputProps={{
  976. "aria-label": intl.formatMessage({ id: "businessRegCertNumber" }),
  977. "aria-describedby": 'helper-text-brNo-signup',
  978. onKeyDown: (e) => {
  979. if (e.key === 'Enter') {
  980. e.preventDefault();
  981. }
  982. },
  983. }}
  984. />
  985. {formik.touched.brNo && formik.errors.brNo && (
  986. <FormHelperText error id="helper-text-brNo-signup">
  987. {formik.errors.brNo}
  988. </FormHelperText>
  989. )}
  990. </Stack>
  991. </Grid>
  992. <Grid item xs={12} md={6}>
  993. <Stack spacing={1}>
  994. <InputLabel htmlFor="brExpiryDate-signup">
  995. <Typography variant="pnspsFormHeader">
  996. <FormattedMessage id="businessRegCertValidityDate"/>
  997. <span style={{ color: '#B00020' }}>*</span>
  998. </Typography>
  999. </InputLabel>
  1000. <OutlinedInput
  1001. fullWidth
  1002. error={Boolean(formik.touched.brExpiryDate && formik.errors.brExpiryDate)}
  1003. id="brExpiryDate-signup"
  1004. type="date"
  1005. value={formik.values.brExpiryDate}
  1006. name="brExpiryDate"
  1007. onChange={formik.handleChange}
  1008. onBlur={formik.handleBlur}
  1009. placeholder={intl.formatMessage({id: 'sameAsBusinessRegistrationCert'})}
  1010. inputProps={{
  1011. "aria-label": intl.formatMessage({ id: "businessRegCertExpiryDate" }),
  1012. "aria-describedby": 'helper-text-brExpiryDate-signup',
  1013. max: "2099-12-31",
  1014. min: new Date().toISOString().split("T")[0],
  1015. onKeyDown: (e) => {
  1016. if (e.key === 'Enter') {
  1017. e.preventDefault();
  1018. }
  1019. },
  1020. }}
  1021. />
  1022. {formik.touched.brExpiryDate && formik.errors.brExpiryDate && (
  1023. <FormHelperText error id="helper-text-brExpiryDate-signup">
  1024. {formik.errors.brExpiryDate}
  1025. </FormHelperText>
  1026. )}
  1027. </Stack>
  1028. </Grid>
  1029. <Grid item xs={12}>
  1030. <Stack spacing={1}>
  1031. <InputLabel htmlFor="address1-signup">
  1032. <Typography variant="pnspsFormHeader">
  1033. <FormattedMessage id="formAddress"/>
  1034. <span style={{ color: '#B00020' }}>*</span>
  1035. </Typography>
  1036. </InputLabel>
  1037. <OutlinedInput
  1038. fullWidth
  1039. error={Boolean(formik.touched.address1 && formik.errors.address1)}
  1040. id="address1-signup"
  1041. value={formik.values.address1}
  1042. name="address1"
  1043. onChange={formik.handleChange}
  1044. placeholder={intl.formatMessage({id: 'addressLine1'})}
  1045. onBlur={formik.handleBlur}
  1046. inputProps={{
  1047. "aria-label": intl.formatMessage({ id: "addressLine1" }),
  1048. maxLength: ADDRESS_LINE_MAX_LENGTH,
  1049. onKeyDown: (e) => {
  1050. if (e.key === 'Enter') {
  1051. e.preventDefault();
  1052. }
  1053. },
  1054. }}
  1055. />
  1056. <OutlinedInput
  1057. fullWidth
  1058. error={Boolean(formik.touched.address2 && formik.errors.address2)}
  1059. id="address2-signup"
  1060. value={formik.values.address2}
  1061. name="address2"
  1062. onBlur={formik.handleBlur}
  1063. onChange={formik.handleChange}
  1064. placeholder={intl.formatMessage({id: 'addressLine2'})}
  1065. inputProps={{
  1066. "aria-label": intl.formatMessage({ id: "addressLine2" }),
  1067. maxLength: ADDRESS_LINE_MAX_LENGTH,
  1068. onKeyDown: (e) => {
  1069. if (e.key === 'Enter') {
  1070. e.preventDefault();
  1071. }
  1072. },
  1073. }}
  1074. />
  1075. <OutlinedInput
  1076. fullWidth
  1077. error={Boolean(formik.touched.address3 && formik.errors.address3)}
  1078. id="address3-signup"
  1079. value={formik.values.address3}
  1080. name="address3"
  1081. onBlur={formik.handleBlur}
  1082. onChange={formik.handleChange}
  1083. placeholder={intl.formatMessage({id: 'addressLine3'})}
  1084. inputProps={{
  1085. "aria-label": intl.formatMessage({ id: "addressLine3" }),
  1086. maxLength: ADDRESS_LINE_MAX_LENGTH,
  1087. onKeyDown: (e) => {
  1088. if (e.key === 'Enter') {
  1089. e.preventDefault();
  1090. }
  1091. },
  1092. }}
  1093. />
  1094. <Autocomplete
  1095. disablePortal
  1096. id="address4-combo"
  1097. value={selectedAddress4}
  1098. options={address4ComboList}
  1099. disabled={checkCountry}
  1100. // error={Boolean(districtErrStr!="")}
  1101. // onBlur={formik.handleBlur}
  1102. getOptionLabel={(option) => option.type? intl.formatMessage({ id: option.type }) : ""}
  1103. onChange={(event, newValue) => {
  1104. setSelectedAddress4(newValue);
  1105. }}
  1106. sx={{
  1107. '& .MuiInputBase-root': { alignItems: 'center' },
  1108. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  1109. '& .MuiOutlinedInput-root': { height: 40 }
  1110. }}
  1111. renderInput={(params) => <TextField error={checkDistrict} {...params} placeholder={intl.formatMessage({id: 'region'})}
  1112. />}
  1113. clearText={intl.formatMessage({ id: "muiClear" })}
  1114. closeText={intl.formatMessage({ id: "muiClose" })}
  1115. openText={intl.formatMessage({ id: "muiOpen" })}
  1116. noOptionsText={intl.formatMessage({ id: "muiNoOptions" })}
  1117. />
  1118. <Autocomplete
  1119. disablePortal
  1120. id="address5-combo"
  1121. value={selectedAddress5}
  1122. options={address5ComboList}
  1123. disabled= {true}
  1124. getOptionLabel={(option) => option.type? intl.formatMessage({ id: option.type }) : ""}
  1125. onChange={(event, newValue) => {
  1126. if (newValue !== null) {
  1127. setSelectedAddress5(newValue);
  1128. if (newValue.type === 'hongKong') {
  1129. setCheckCountry(false)
  1130. if(formik.values.phone==""){
  1131. formik.values.phoneCountryCode = "852";
  1132. }
  1133. if(formik.values.fax==""){
  1134. formik.values.faxCountryCode = "852";
  1135. }
  1136. } else {
  1137. if (newValue.type === 'mainland'){
  1138. if(formik.values.phone==""){
  1139. formik.values.phoneCountryCode = "86";
  1140. }
  1141. if(formik.values.fax==""){
  1142. formik.values.faxCountryCode = "86";
  1143. }
  1144. }else if(newValue.type === 'macau'){
  1145. if(formik.values.phone==""){
  1146. formik.values.phoneCountryCode = "853";
  1147. }
  1148. if(formik.values.fax==""){
  1149. formik.values.faxCountryCode = "853";
  1150. }
  1151. }
  1152. setSelectedAddress4("");
  1153. setCheckCountry(true)
  1154. }
  1155. } else {
  1156. setSelectedAddress4("");
  1157. setCheckCountry(true)
  1158. }
  1159. }}
  1160. sx={{
  1161. '& .MuiInputBase-root': { alignItems: 'center' },
  1162. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  1163. '& .MuiOutlinedInput-root': { height: 40 }
  1164. }}
  1165. renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({id: 'regionOrCountry'})} />}
  1166. clearText={intl.formatMessage({ id: "muiClear" })}
  1167. closeText={intl.formatMessage({ id: "muiClose" })}
  1168. openText={intl.formatMessage({ id: "muiOpen" })}
  1169. noOptionsText={intl.formatMessage({ id: "muiNoOptions" })}
  1170. />
  1171. {formik.touched.address1 && formik.errors.address1 && (
  1172. <FormHelperText error id="helper-text-address1-signup">
  1173. {formik.errors.address1}
  1174. </FormHelperText>
  1175. )}
  1176. {formik.touched.address2 && formik.errors.address2 && (
  1177. <FormHelperText error id="helper-text-address2-signup">
  1178. {formik.errors.address2}
  1179. </FormHelperText>
  1180. )}
  1181. {formik.touched.address3 && formik.errors.address3 && (
  1182. <FormHelperText error id="helper-text-address3-signup">
  1183. {formik.errors.address3}
  1184. </FormHelperText>
  1185. )}
  1186. {checkDistrict && (
  1187. <FormHelperText error >
  1188. {districtErrStr}
  1189. </FormHelperText>
  1190. )}
  1191. </Stack>
  1192. </Grid>
  1193. <Grid item xs={12} mt={1} mb={1}>
  1194. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1195. <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  1196. <FormattedMessage id="yourContact"/>
  1197. </Typography>
  1198. </Stack>
  1199. </Grid>
  1200. <Grid item xs={12} md={12}>
  1201. <Stack spacing={1}>
  1202. <InputLabel htmlFor="enName-signup">
  1203. <Typography variant="pnspsFormHeader">
  1204. <FormattedMessage id="userContactName"/>
  1205. <span style={{ color: '#B00020' }}>*</span>
  1206. </Typography>
  1207. </InputLabel>
  1208. <OutlinedInput
  1209. id="enName-signup"
  1210. type="enName"
  1211. value={formik.values.enName}
  1212. name="enName"
  1213. onChange={formik.handleChange}
  1214. placeholder=""
  1215. fullWidth
  1216. error={Boolean(formik.touched.enName && formik.errors.enName)}
  1217. onBlur={formik.handleBlur}
  1218. inputProps={{
  1219. "aria-label": intl.formatMessage({ id: "userContactName" }),
  1220. "aria-describedby": 'helper-text-enName-signup',
  1221. onKeyDown: (e) => {
  1222. if (e.key === 'Enter') {
  1223. e.preventDefault();
  1224. }
  1225. },
  1226. }}
  1227. />
  1228. {formik.touched.enName && formik.errors.enName && (
  1229. <FormHelperText error id="helper-text-enName-signup">
  1230. {formik.errors.enName}
  1231. </FormHelperText>
  1232. )}
  1233. </Stack>
  1234. </Grid>
  1235. <Grid item xs={12} md={12}>
  1236. <Grid container>
  1237. <Grid item xs={12} md={6}>
  1238. <Stack spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  1239. <InputLabel htmlFor="email-login">
  1240. <Typography variant="pnspsFormHeader">
  1241. <FormattedMessage id="userContactEmail"/>
  1242. <span style={{ color: '#B00020' }}>*</span>
  1243. </Typography>
  1244. </InputLabel>
  1245. <OutlinedInput
  1246. fullWidth
  1247. error={Boolean((formik.touched.email && formik.errors.email) || checkEmail)}
  1248. id="email-login"
  1249. type="email"
  1250. value={formik.values.email.trim()}
  1251. name="email"
  1252. onChange={formik.handleChange}
  1253. placeholder={intl.formatMessage({id: 'userContactEmail'})}
  1254. onBlur={formik.handleBlur}
  1255. inputProps={{
  1256. "aria-label": intl.formatMessage({ id: "userContactEmail" }),
  1257. "aria-describedby": 'helper-text-email-signup',
  1258. onKeyDown: (e) => {
  1259. if (e.key === 'Enter') {
  1260. e.preventDefault();
  1261. }
  1262. },
  1263. }}
  1264. />
  1265. {formik.touched.email && formik.errors.email && (
  1266. <FormHelperText error id="helper-text-email-signup">
  1267. {formik.errors.email}
  1268. </FormHelperText>
  1269. )}
  1270. {checkEmail && (
  1271. <FormHelperText error id="helper-text-email-signup">
  1272. <FormattedMessage id="emailUsed"/>
  1273. </FormHelperText>
  1274. )}
  1275. </Stack>
  1276. </Grid>
  1277. <Grid item xs={12} md={6}>
  1278. <Stack spacing={1} >
  1279. <InputLabel htmlFor="emailConfirm-login">
  1280. <Typography variant="pnspsFormHeader">
  1281. <FormattedMessage id="confirmEmail"/>
  1282. <span style={{ color: '#B00020' }}>*</span>
  1283. </Typography>
  1284. </InputLabel>
  1285. <OutlinedInput
  1286. fullWidth
  1287. error={Boolean(formik.touched.emailConfirm && formik.errors.emailConfirm)}
  1288. id="emailConfirm-login"
  1289. type="email"
  1290. value={formik.values.emailConfirm.trim()}
  1291. name="emailConfirm"
  1292. // onBlur={formik.handleBlur}
  1293. onChange={formik.handleChange}
  1294. placeholder={intl.formatMessage({id: 'confirmEmail'})}
  1295. onBlur={formik.handleBlur}
  1296. onCut={handleCCPChange}
  1297. onCopy={handleCCPChange}
  1298. onPaste={handleCCPChange}
  1299. inputProps={{
  1300. "aria-label": intl.formatMessage({ id: "confirmEmail" }),
  1301. "aria-describedby": 'helper-text-emailConfirm-signup',
  1302. onKeyDown: (e) => {
  1303. if (e.key === 'Enter') {
  1304. e.preventDefault();
  1305. }
  1306. },
  1307. }}
  1308. />
  1309. {formik.touched.emailConfirm && formik.errors.emailConfirm && (
  1310. <FormHelperText error id="helper-text-emailConfirm-signup">
  1311. {formik.errors.emailConfirm}
  1312. </FormHelperText>
  1313. )}
  1314. </Stack>
  1315. </Grid>
  1316. </Grid>
  1317. </Grid>
  1318. <Grid item xs={12} md={12}>
  1319. <Grid container>
  1320. <Grid item xs={12} md={6}>
  1321. <Grid container>
  1322. <Grid item xs={12} md={12}>
  1323. <Stack direction="column" spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  1324. <InputLabel htmlFor="phone-signup">
  1325. <Typography variant="pnspsFormHeader">
  1326. <FormattedMessage id="userContactNumber"/>
  1327. <span style={{ color: '#B00020' }}>*</span>
  1328. </Typography>
  1329. </InputLabel>
  1330. <Stack direction="row">
  1331. <OutlinedInput
  1332. id="phoneCountryCode-signup"
  1333. type="phoneCountryCode"
  1334. value={formik.values.phoneCountryCode.trim()}
  1335. name="phoneCountryCode"
  1336. // onBlur={formik.handleBlur}
  1337. // onChange={formik.handleChange}
  1338. onChange={(event) => {
  1339. const value = event.target.value;
  1340. if (value.match(/[^0-9]/)) {
  1341. return event.preventDefault();
  1342. }
  1343. formik.setFieldValue("phoneCountryCode", value);
  1344. }}
  1345. endAdornment={<InputAdornment position="end">-</InputAdornment>}
  1346. placeholder={intl.formatMessage({id: 'dialingCode'})}
  1347. error={Boolean(formik.touched.phone && formik.errors.phone)}
  1348. onBlur={formik.handleBlur}
  1349. inputProps={{
  1350. "aria-label": intl.formatMessage({ id: "phoneCountryCode" }),
  1351. maxLength: 3,
  1352. onKeyDown: (e) => {
  1353. if (e.key === 'Enter') {
  1354. e.preventDefault();
  1355. }
  1356. },
  1357. }}
  1358. sx={{ width: '33%', mr:1 }}
  1359. />
  1360. <OutlinedInput
  1361. id="phone-signup"
  1362. type="phone"
  1363. value={formik.values.phone.trim()}
  1364. name="phone"
  1365. onBlur={formik.handleBlur}
  1366. // onChange={formik.handleChange}
  1367. onChange={(event) => {
  1368. const value = event.target.value;
  1369. if (value.match(/[^0-9]/)) {
  1370. return event.preventDefault();
  1371. }
  1372. formik.setFieldValue("phone", value);
  1373. }}
  1374. placeholder={intl.formatMessage({id: 'userContactNumber'})}
  1375. error={Boolean(formik.touched.phone && formik.errors.phone)}
  1376. inputProps={{
  1377. "aria-label": intl.formatMessage({ id: "userContactNumber" }),
  1378. "aria-describedby": 'helper-text-phone-signup',
  1379. maxLength: 11,
  1380. onKeyDown: (e) => {
  1381. if (e.key === 'Enter') {
  1382. e.preventDefault();
  1383. }
  1384. },
  1385. }}
  1386. sx={{ width: '66%' }}
  1387. />
  1388. </Stack>
  1389. {formik.touched.phone && formik.errors.phone && (
  1390. <FormHelperText error id="helper-text-phone-signup">
  1391. {formik.errors.phone}
  1392. </FormHelperText>
  1393. )}
  1394. </Stack>
  1395. </Grid>
  1396. </Grid>
  1397. </Grid>
  1398. <Grid item xs={12} md={6}>
  1399. <Grid container>
  1400. <Grid item xs={12} md={12}>
  1401. <Stack spacing={1} direction="column">
  1402. <InputLabel htmlFor="fax-signup">
  1403. <Typography variant="pnspsFormHeader">
  1404. <FormattedMessage id="userFaxNumber"/>
  1405. </Typography>
  1406. </InputLabel>
  1407. <Stack direction="row">
  1408. <OutlinedInput
  1409. error={Boolean(formik.touched.fax && formik.errors.fax)}
  1410. id="faxCountryCode-signup"
  1411. type="faxCountryCode"
  1412. value={formik.values.faxCountryCode.trim()}
  1413. name="faxCountryCode"
  1414. // onBlur={formik.handleBlur}
  1415. // onChange={formik.handleChange}
  1416. onChange={(event) => {
  1417. const value = event.target.value;
  1418. if (value.match(/[^0-9]/)) {
  1419. return event.preventDefault();
  1420. }
  1421. formik.setFieldValue("faxCountryCode", value);
  1422. }}
  1423. placeholder={intl.formatMessage({id: 'dialingCode'})}
  1424. endAdornment={<InputAdornment position="end">-</InputAdornment>}
  1425. inputProps={{
  1426. "aria-label": intl.formatMessage({ id: "faxCountryCode" }),
  1427. maxLength: 3,
  1428. onKeyDown: (e) => {
  1429. if (e.key === 'Enter') {
  1430. e.preventDefault();
  1431. }
  1432. },
  1433. }}
  1434. sx={{ width: '33%', mr:1 }}
  1435. />
  1436. <OutlinedInput
  1437. id="fax-signup"
  1438. type="fax"
  1439. value={formik.values.fax.trim()}
  1440. name="fax"
  1441. // onBlur={formik.handleBlur}
  1442. // onChange={formik.handleChange}
  1443. onChange={(event) => {
  1444. const value = event.target.value;
  1445. if (value.match(/[^0-9]/)) {
  1446. return event.preventDefault();
  1447. }
  1448. formik.setFieldValue("fax", value);
  1449. }}
  1450. placeholder={intl.formatMessage({id: 'userFaxNumber'})}
  1451. inputProps={{
  1452. "aria-label": intl.formatMessage({ id: "userFaxNumber" }),
  1453. maxLength: 8,
  1454. onKeyDown: (e) => {
  1455. if (e.key === 'Enter') {
  1456. e.preventDefault();
  1457. }
  1458. },
  1459. }}
  1460. sx={{ width: '66%' }}
  1461. />
  1462. </Stack>
  1463. </Stack>
  1464. </Grid>
  1465. </Grid>
  1466. </Grid>
  1467. </Grid>
  1468. </Grid>
  1469. <Grid item xs={12} md={12} mt={1} mb={1}>
  1470. <Grid container>
  1471. <Grid item xs={12} md={12}>
  1472. <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1473. <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  1474. <FormattedMessage id="businessRegCertAndDoc"/>
  1475. <span style={{ color: '#B00020' }}>*</span>
  1476. </Typography>
  1477. <Typography display="inline" variant="h6" component="span" sx={{ color: 'primary.primary' }}>
  1478. <FormattedMessage id="pleaseUploadDoc"/>
  1479. </Typography>
  1480. {/* <Typography display="inline" variant="h6" component="span" sx={{ fontSize: 12,color: 'primary.primary'}}>如: 香港身份證; 護照; 中國內地身份證等</Typography> */}
  1481. <Stack mt={1} direction="row" justifyContent="flex-start" alignItems="center" spacing={2}>
  1482. <ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
  1483. <Button
  1484. variant="contained"
  1485. sx={{ height: '40px' }}
  1486. type="button"
  1487. tabIndex={0}
  1488. onClick={() => {
  1489. if (fileInputRef.current) {
  1490. fileInputRef.current.click();
  1491. }
  1492. }}
  1493. onKeyDown={(event) => {
  1494. if (event.key === 'Enter' || event.key === ' ') {
  1495. event.preventDefault();
  1496. if (fileInputRef.current) {
  1497. fileInputRef.current.click();
  1498. }
  1499. }
  1500. }}
  1501. >
  1502. <FormattedMessage id="uploadFile" />
  1503. </Button>
  1504. <input
  1505. accept="image/png, .jpg, .bmp, .pdf"
  1506. //className={classes.input}
  1507. id="contained-button-file"
  1508. multiple
  1509. type="file"
  1510. onChange={handleFileUpload}
  1511. ref={fileInputRef}
  1512. style={{ display: 'none' }}
  1513. />
  1514. </ThemeProvider>
  1515. {/* <Typography display="inline" variant="h6" component="span" sx={{ fontSize: 12, color: 'primary.primary'}}></Typography> */}
  1516. </Stack>
  1517. {fileList != null && props.step === 0 ?
  1518. <UploadFileTable key="uploadTable" recordList={fileListData} setUpdateRows={setUpdateRows} /> : null}
  1519. {/* <Stack mt={1} direction="row" justifyContent="flex-start" alignItems="center" spacing={2}>
  1520. <Button variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button>
  1521. <Button disabled={!formik.isValid} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button>
  1522. </Stack> */}
  1523. </Stack>
  1524. </Grid>
  1525. </Grid>
  1526. </Grid>
  1527. </Grid>
  1528. <Grid item xs={12} md={12}>
  1529. <Grid container>
  1530. <Grid item xs={12} md={12}>
  1531. <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  1532. <FormattedMessage id="termsAndCondition"/>
  1533. <span style={{ color: '#B00020' }}>*</span>
  1534. </Typography>
  1535. </Grid>
  1536. <Grid item xs={12} md={12}>
  1537. <Grid container>
  1538. <Grid item xs={12} md={12}>
  1539. <Typography component="span" variant="h6" height="100%" sx={{ textAlign: "left", /*overflow: "scroll",*/ borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0c489e", display: "block" }}>
  1540. <SafeHtml html={intl.formatMessage({id: "termsAndCon"})} style={{padding: 12}} />
  1541. </Typography>
  1542. </Grid>
  1543. </Grid>
  1544. <Grid item xs={12} s={12} md={12} lg={12}>
  1545. <Grid container>
  1546. <Grid item xs={6} s={6} md={11} lg={11}>
  1547. <Grid container>
  1548. <Grid item sx={{ display: 'flex', alignItems: 'center' }}>
  1549. <Checkbox
  1550. checked={termsAndConAccept}
  1551. onChange={handleCheckBoxChange}
  1552. name="termsAndConAccept"
  1553. color="primary"
  1554. size="small"
  1555. inputProps={{
  1556. "aria-label": intl.formatMessage({ id: "iConfirm" })
  1557. }}
  1558. />
  1559. <Typography variant="pnspsFormHeader">
  1560. <FormattedMessage id="iConfirm"/>
  1561. </Typography>
  1562. </Grid>
  1563. </Grid>
  1564. </Grid>
  1565. <Grid item xs={6} s={6} md={3} lg={3}>
  1566. <Grid container style={{ display: "none" }}>
  1567. <Grid item sx={{ display: 'flex', alignItems: 'center' }}>
  1568. <Checkbox
  1569. checked={termsAndConNotAccept}
  1570. onChange={handleCheckBoxChange}
  1571. name="termsAndConNotAccept"
  1572. color="primary"
  1573. size="small"
  1574. inputProps={{
  1575. "aria-label": intl.formatMessage({ id: "rejectTerms" })
  1576. }}
  1577. />
  1578. <Typography variant="pnspsFormHeader">
  1579. <FormattedMessage id="rejectTerms"/>
  1580. </Typography>
  1581. </Grid>
  1582. </Grid>
  1583. </Grid>
  1584. </Grid>
  1585. </Grid>
  1586. </Grid>
  1587. </Grid>
  1588. </Grid>
  1589. <Grid item xs={12} lg={12}>
  1590. <Grid container>
  1591. <Stack direction="column">
  1592. <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  1593. <FormattedMessage id="verify"/>
  1594. <span style={{ color: '#B00020' }}>*</span>
  1595. </Typography>
  1596. <Stack spacing={1} direction="row">
  1597. <Grid item xs={5} lg={5} style={{ "border": "1px solid black" }}>
  1598. <img src={captchaImg} alt="" />
  1599. </Grid>
  1600. <Grid item xs={1} lg={1} style={{ "border": "0px solid black" }}>
  1601. <IconButton
  1602. role="button"
  1603. tabIndex={0}
  1604. aria-label={intl.formatMessage({ id: 'ariaRefreshCaptcha' })}
  1605. size="large"
  1606. onClick={() => { onCaptchaChange() }}
  1607. onKeyDown={(event) => handleActionKeyDown(event, () => onCaptchaChange())}
  1608. >
  1609. <LoopIcon fontSize="inherit" />
  1610. </IconButton>
  1611. </Grid>
  1612. <Grid item xs={6} lg={6}>
  1613. <OutlinedInput
  1614. fullWidth
  1615. id="captchaField"
  1616. type="text"
  1617. value={formik.values.captchaField.trim()}
  1618. onBlur={formik.handleBlur}
  1619. error={Boolean(formik.touched.captchaField && formik.errors.captchaField)}
  1620. name="captchaField"
  1621. onChange={(event) => {
  1622. const value = event.target.value;
  1623. props.setCheckCode(event.target.value);
  1624. setCheckCode(event.target.value);
  1625. formik.setFieldValue("captchaField", value);
  1626. }}
  1627. sx={{ width: '75%' }}
  1628. inputProps={{
  1629. "aria-label": intl.formatMessage({ id: "verify" }),
  1630. "aria-describedby": 'helper-text-captcha-signup'
  1631. }}
  1632. />
  1633. </Grid>
  1634. </Stack>
  1635. {formik.touched.captchaField && formik.errors.captchaField && (
  1636. <FormHelperText error id="helper-text-captcha-signup">
  1637. {formik.errors.captchaField}
  1638. </FormHelperText>
  1639. )}
  1640. <Stack spacing={1} direction="row" sx={{ mt: 0.25 }}>
  1641. <Button
  1642. variant="contained"
  1643. onClick={playCaptchaAudio}
  1644. aria-label={intl.formatMessage({ id: "captchaPlayAudio" })}
  1645. sx={{
  1646. backgroundColor: '#0c489e',
  1647. color: '#FFFFFF',
  1648. '&:hover': { backgroundColor: '#1565c0' },
  1649. }}
  1650. >
  1651. <FormattedMessage id="captchaPlayAudio" />
  1652. </Button>
  1653. </Stack>
  1654. </Stack>
  1655. </Grid>
  1656. </Grid>
  1657. </Grid>
  1658. </Grid>
  1659. </FormGroup>
  1660. {/* Preview Form */}
  1661. <FormGroup id={"previewForm"} sx={{ display: props.step === 1 ? "" : "none" }}>
  1662. <Grid container spacing={2}>
  1663. <Grid item xs={12}>
  1664. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1665. <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}>
  1666. <Typography display="inline" variant="h3" component="h1" sx={{ color: '#1A4399' }}>
  1667. <FormattedMessage id="becomeNewBusinessUser"/>
  1668. </Typography>
  1669. </div>
  1670. {/* <Typography mt={0.25} variant="h6" component="span" sx={{ fontSize: 12,color: '#B00020'}}>註有*的項目必須輸入資料</Typography> */}
  1671. <Typography mt={0.25} variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  1672. <FormattedMessage id="yourLoginInformation"/>
  1673. </Typography>
  1674. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  1675. Already have an account?
  1676. </Typography> */}
  1677. </Stack>
  1678. </Grid>
  1679. <Grid item xs={12}>
  1680. <Grid container spacing={1}>
  1681. <Grid item xs={12} >
  1682. <Stack spacing={1} direction="row">
  1683. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1684. {intl.formatMessage({id: 'userLoginName'})}:
  1685. </Typography>
  1686. <Typography variant="pnspsFormHeader" id="preview-username-login">
  1687. {formik.values.username}
  1688. </Typography>
  1689. </Stack>
  1690. </Grid>
  1691. <Grid item xs={12} mt={1} mb={1}>
  1692. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1693. <Typography display="inline" variant="h4" component="h2" /*sx={{ color: '#1A4399' }}*/>
  1694. <FormattedMessage id="yourBusinessInformation"/>
  1695. </Typography>
  1696. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  1697. Already have an account?
  1698. </Typography> */}
  1699. </Stack>
  1700. </Grid>
  1701. <Grid item xs={12} md={6}>
  1702. <Stack spacing={1} direction="row">
  1703. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1704. <FormattedMessage id="businessEngName"/>:
  1705. </Typography>
  1706. <Typography variant="pnspsFormHeader" id="preview-enCompanyName-signup">
  1707. {formik.values.enCompanyName}
  1708. </Typography>
  1709. </Stack>
  1710. </Grid>
  1711. <Grid item xs={12} md={6}>
  1712. <Stack spacing={1} direction="row">
  1713. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1714. <FormattedMessage id="businessChName"/>:
  1715. </Typography>
  1716. <Typography variant="pnspsFormHeader" id="preview-chCompanyName-signup">
  1717. {formik.values.chCompanyName}
  1718. </Typography>
  1719. </Stack>
  1720. </Grid>
  1721. <Grid item xs={12} md={12} >
  1722. <Stack spacing={1}>
  1723. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1724. <FormattedMessage id="businessRegCert"/>
  1725. </Typography>
  1726. </Stack>
  1727. </Grid>
  1728. <Grid item xs={12} md={6}>
  1729. <Stack spacing={1} direction="row">
  1730. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1731. <FormattedMessage id="businessRegCertNumber"/>:
  1732. </Typography>
  1733. <Typography variant="pnspsFormHeader" id="brNo-login">
  1734. {formik.values.brNo}
  1735. </Typography>
  1736. </Stack>
  1737. </Grid>
  1738. <Grid item xs={12} md={6}>
  1739. <Stack spacing={1} direction="row">
  1740. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1741. <FormattedMessage id="businessRegCertValidityDate"/>:
  1742. </Typography>
  1743. <Typography variant="pnspsFormHeader" id="brExpiryDate-login">
  1744. {formik.values.brExpiryDate}
  1745. </Typography>
  1746. </Stack>
  1747. </Grid>
  1748. <Grid item xs={12}>
  1749. <Stack spacing={1} direction="column">
  1750. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1751. <FormattedMessage id="formAddress"/>:
  1752. </Typography>
  1753. <Stack spacing={1} direction="column">
  1754. <Typography variant="pnspsFormHeader" id="preview-address1-signup">
  1755. {formik.values.address1}
  1756. </Typography>
  1757. {formik.values.address2 != null ?
  1758. <Typography variant="pnspsFormHeader" id="preview-address2-signup">
  1759. {formik.values.address2}
  1760. </Typography>
  1761. : null}
  1762. {formik.values.address3 != null ?
  1763. <Typography variant="pnspsFormHeader" id="preview-address3-signup">
  1764. {formik.values.address3}
  1765. </Typography>
  1766. : null}
  1767. {selectedAddress5.type === "hongKong" ?
  1768. <Stack direction="column">
  1769. {/* <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]} id="preview-address4-signup">
  1770. <FormattedMessage id="region"/>:
  1771. </Typography> */}
  1772. <Typography variant="pnspsFormHeader">
  1773. {!selectedAddress4? "" : intl.formatMessage({id: selectedAddress4.type})}
  1774. </Typography>
  1775. </Stack>
  1776. : null}
  1777. <Stack direction="column">
  1778. {/* <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]} id="preview-address5-signup">
  1779. <FormattedMessage id="regionOrCountry"/>:
  1780. </Typography> */}
  1781. <Typography variant="pnspsFormHeader">
  1782. {intl.formatMessage({id: selectedAddress5.type})}
  1783. </Typography>
  1784. </Stack>
  1785. </Stack>
  1786. </Stack>
  1787. </Grid>
  1788. <Grid item xs={12} mt={1} mb={1}>
  1789. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1790. <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  1791. <FormattedMessage id="yourContact"/>
  1792. </Typography>
  1793. </Stack>
  1794. </Grid>
  1795. <Grid item xs={12} md={12}>
  1796. <Stack spacing={1} direction="row">
  1797. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1798. <FormattedMessage id="userEnglishName"/>
  1799. </Typography>
  1800. <Typography variant="pnspsFormHeader" id="preview-enName-signup">
  1801. {formik.values.enName}
  1802. </Typography>
  1803. </Stack>
  1804. </Grid>
  1805. <Grid item xs={12} md={12}>
  1806. <Stack spacing={1} direction="row">
  1807. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1808. <FormattedMessage id="userContactEmail"/>:
  1809. </Typography>
  1810. <Typography variant="pnspsFormHeader" id="preview-email-signup">
  1811. {formik.values.email}
  1812. </Typography>
  1813. </Stack>
  1814. </Grid>
  1815. <Grid item xs={12} md={6}>
  1816. <Stack spacing={1} direction="row">
  1817. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1818. <FormattedMessage id="userContactNumber"/>:
  1819. </Typography>
  1820. <Typography variant="pnspsFormHeader" id="preview-phone-signup">
  1821. +{formik.values.phoneCountryCode} {formik.values.phone}
  1822. </Typography>
  1823. </Stack>
  1824. </Grid>
  1825. <Grid item xs={12} md={6}>
  1826. <Stack spacing={1} direction="row">
  1827. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1828. <FormattedMessage id="userFaxNumber"/>:
  1829. </Typography>
  1830. <Typography variant="pnspsFormHeader" id="preview-fax-signup">
  1831. +{formik.values.faxCountryCode} {formik.values.fax}
  1832. </Typography>
  1833. </Stack>
  1834. </Grid>
  1835. <Grid item xs={12} md={12} mt={1} mb={1}>
  1836. <Grid container>
  1837. <Grid item xs={12} md={12}>
  1838. <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1839. <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}>
  1840. <FormattedMessage id="businessRegCertAndDoc"/>
  1841. </Typography>
  1842. {fileList != null && props.step === 1 ?
  1843. <PreviewUploadFileTable key="previewTable" recordList={fileListData} /> : null}
  1844. </Stack>
  1845. </Grid>
  1846. </Grid>
  1847. </Grid>
  1848. </Grid>
  1849. </Grid>
  1850. </Grid>
  1851. </FormGroup>
  1852. {/* Submit page */}
  1853. <FormGroup id={"submitForm"} sx={{ display: props.step === 2 ? "" : "none" }}>
  1854. <Grid container spacing={3}>
  1855. {isLoading ?
  1856. <LoadingComponent /> :
  1857. <Grid item xs={12}>
  1858. {checkUpload ?
  1859. // SUCCESS page
  1860. <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
  1861. <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
  1862. <Typography display="inline" variant="h4" component="span">
  1863. <FormattedMessage id="registerSubmitted"/>
  1864. </Typography>
  1865. <Typography display="inline" variant="h4" component="span">
  1866. <FormattedMessage id="emailSent"/>
  1867. </Typography>
  1868. <Button variant="outlined" component={Link} to="/login" >
  1869. <Typography variant="pnspsFormHeader">
  1870. <FormattedMessage id="backToLogin"/>
  1871. </Typography></Button>
  1872. </Stack>
  1873. :
  1874. // ERROR page
  1875. <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
  1876. {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
  1877. <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
  1878. <Typography display="inline" variant="h4" component="span">
  1879. <FormattedMessage id="registerFail" />
  1880. </Typography>
  1881. <Button color="error" variant="outlined" component={Link} to="/login" ><Typography variant="pnspsFormHeader">
  1882. <FormattedMessage id="backToLogin"/>
  1883. </Typography></Button>
  1884. </Stack>
  1885. }
  1886. </Grid>
  1887. }
  1888. </Grid>
  1889. </FormGroup>
  1890. </form>
  1891. </FormikProvider>
  1892. );
  1893. }
  1894. export default BusCustomFormWizard;