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.
 
 

1810 line
112 KiB

  1. import { useEffect, useState, } 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, GET_USERNAME, GET_USER_EMAIL } 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 { lazy } from 'react';
  34. const UploadFileTable = Loadable(lazy(() => import('./UploadFileTable')));
  35. const PreviewUploadFileTable = Loadable(lazy(() => import('./PreviewUploadFileTable')));
  36. const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent')));
  37. // import UploadFileTable from './UploadFileTable';
  38. // import LoadingComponent from "../../extra-pages/LoadingComponent";
  39. // assets
  40. import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
  41. // import { Paper } from '../../../../node_modules/@mui/material/index';
  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. // ============================|| FIREBASE - REGISTER ||============================ //
  52. const CustomFormWizard = (props) => {
  53. const intl = useIntl();
  54. const theme = useTheme()
  55. const [level, setLevel] = useState();
  56. const [showPassword, setShowPassword] = useState(false);
  57. const [showConfirmPassword, setshowConfirmPassword] = useState(false);
  58. const [fileList, setFileList] = useState([]);
  59. const [fileListData, setFileListData] = useState([]);
  60. const [checkUpload, setCheckUpload] = useState(false);
  61. const [isLoading, setLoding] = useState(true);
  62. const [updateRows, setUpdateRows] = useState([]);
  63. const [captchaImg, setCaptchaImage] = useState("");
  64. const handleClickShowPassword = () => {
  65. setShowPassword(!showPassword);
  66. };
  67. const handleClickShowConfirmPassword = () => {
  68. setshowConfirmPassword(!showConfirmPassword);
  69. };
  70. const handleMouseDownPassword = (event) => {
  71. event.preventDefault();
  72. };
  73. const changePassword = (value) => {
  74. const temp = strengthIndicator(value);
  75. setLevel(strengthColorChi(temp));
  76. };
  77. const [selectedIdDocType, setSelectedIdDocType] = useState({});
  78. const [selectedIdDocInputType, setSelectedIdDocInputType] = useState("");
  79. // const [selectedIdDocLabel, setSelectedIdDocLabel] = useState(null);
  80. const [selectedAddress4, setSelectedAddress4] = useState(null);
  81. const [selectedAddress5, setSelectedAddress5] = useState(ComboData.country(intl)[0]);
  82. const [termsAndConAccept, setTermsAndConAccept] = useState(false);
  83. const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false);
  84. const [isValid, setisValid] = useState(false);
  85. const [checkCountry, setCheckCountry] = useState(false);
  86. const username = document.getElementById("username-login")
  87. const [checkUsername, setCheckUsername] = useState(false);
  88. const [checkUsernameBlur, setCheckUsernameBlur] = useState(false)
  89. const email = document.getElementById("email-login")
  90. const [checkEmail, setCheckEmail] = useState(false)
  91. const [checkEmailBlur, setCheckEmailBlur] = useState(false)
  92. const idDocTypeComboList = ComboData.idDocType;
  93. const address4ComboList = ComboData.district;
  94. const address5ComboList = ComboData.country(intl);
  95. const termsAndCon = "此網址由香港特別行政區政府物流服務署製作及管理。本署會盡力確保網址上的資料無誤,\n"
  96. + "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址"
  97. + "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評"
  98. + "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港"
  99. + "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限"
  100. + "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香"
  101. + "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面"
  102. + "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。"
  103. const refType = "identification";
  104. useEffect(() => {
  105. changePassword('');
  106. if(captchaImg=="")
  107. onCaptchaChange();
  108. }, []);
  109. const handleCheckUsername = async () => {
  110. if (values?.username) {
  111. const response = await axios.get(`${GET_USERNAME}`, {
  112. params: {
  113. username: values.username,
  114. }
  115. })
  116. setCheckUsername((Number(response.data[0]) === 1))
  117. return Number(response.data[0]) === 1
  118. }
  119. }
  120. const handleCheckEmail = async () => {
  121. if (values?.email) {
  122. const response = await axios.get(`${GET_USER_EMAIL}`, {
  123. params: {
  124. email: values.email,
  125. }
  126. })
  127. setCheckEmail((Number(response.data[0]) === 1))
  128. return Number(response.data[0]) === 1
  129. }
  130. }
  131. useEffect(() => {
  132. if (username) {
  133. username.addEventListener("blur", function () {
  134. setCheckUsernameBlur(true)
  135. })
  136. }
  137. }, [username])
  138. useEffect(() => {
  139. if (checkUsernameBlur) {
  140. handleCheckUsername()
  141. setCheckUsernameBlur(false)
  142. }
  143. }, [checkUsernameBlur])
  144. useEffect(() => {
  145. if (email) {
  146. email.addEventListener("blur", function () {
  147. setCheckEmailBlur(true)
  148. })
  149. }
  150. }, [email])
  151. useEffect(() => {
  152. if (checkEmailBlur) {
  153. handleCheckEmail()
  154. setCheckEmailBlur(false)
  155. }
  156. }, [checkEmailBlur])
  157. const onCaptchaChange = () => {
  158. HttpUtils.post({
  159. url: POST_CAPTCHA,
  160. params: { width: 130, height: 40, captcha: captchaImg},
  161. onSuccess: (responseData) => {
  162. props.setBase64Url(responseData.base64Url)
  163. localStorage.setItem("base64Url", responseData.base64Url);
  164. setCaptchaImage(localStorage.getItem('base64Url'));
  165. }
  166. });
  167. }
  168. const checkDataField = (data) => {
  169. if (data.username !== "" &&
  170. data.password !== "" &&
  171. data.confirmPassword !== "" &&
  172. data.password == data.confirmPassword &&
  173. selectedIdDocType.type !== "" &&
  174. data.idNo !== "" &&
  175. (data.enName !== "" || selectedIdDocType.type === "CNID") &&
  176. data.chName !== "" &&
  177. data.address1 !== "" &&
  178. data.email !== "" &&
  179. data.emailConfirm !== "" &&
  180. data.email == data.emailConfirm &&
  181. data.phone !== "" &&
  182. data.phoneCountryCode !== "" &&
  183. termsAndConAccept == true &&
  184. fileList.length !== 0 &&
  185. data.captchaField &&
  186. handlePassword(data.password) &&
  187. handleEmail(data.email) &&
  188. handleIdNo(data.idNo, selectedIdDocType.type, data.checkDigit) &&
  189. handlePhone(data.phone) &&
  190. handleUsername(data.username) &&
  191. handleCaptcha(data.captchaField) &&
  192. !checkUsername &&
  193. !checkEmail
  194. ) {
  195. setisValid(true)
  196. return isValid
  197. } else {
  198. setisValid(false)
  199. return isValid
  200. }
  201. };
  202. const handleCheckBoxChange = (event) => {
  203. if (event.target.name == 'termsAndConAccept') {
  204. setTermsAndConAccept(event.target.checked)
  205. setTermsAndConNotAccept(!event.target.checked)
  206. }
  207. if (event.target.name == 'termsAndConNotAccept') {
  208. setTermsAndConNotAccept(event.target.checked)
  209. setTermsAndConAccept(!event.target.checked)
  210. }
  211. };
  212. useEffect(() => {
  213. let updateRowList = new DataTransfer();
  214. var updateRowsIndex = updateRows.length;
  215. const saveFileList = [];
  216. if (updateRowsIndex != null) {
  217. for (let i = 0; i < updateRowsIndex; i++) {
  218. const file = updateRows[i]
  219. file.id = i;
  220. updateRowList.items.add(file);
  221. saveFileList.push(file);
  222. }
  223. let updatedFileList = updateRowList.files;
  224. setFileList(updatedFileList);
  225. setFileListData(saveFileList)
  226. }
  227. }, [updateRows]);
  228. const handleFileUpload = (event) => {
  229. let updateList = new DataTransfer();
  230. let currentFileList = fileListData;
  231. const uploadFileList = event.target.files;
  232. const saveFileList = [];
  233. var currentIndex = 0;
  234. if (currentFileList.length != null) {
  235. currentIndex = currentFileList.length;
  236. for (let i = 0; i < currentIndex; i++) {
  237. const file = currentFileList[i]
  238. // file.id = currentIndex;
  239. updateList.items.add(file);
  240. saveFileList.push(file);
  241. }
  242. }
  243. for (let i = 0; i < uploadFileList.length && currentIndex < 5; i++) {
  244. const file = event.target.files[i]
  245. let isDuplicate = false;
  246. // Check if the file name already exists in saveFileList
  247. for (let j = 0; j < saveFileList.length; j++) {
  248. if (saveFileList[j].name === file.name) {
  249. isDuplicate = true;
  250. break;
  251. }
  252. }
  253. if (!isDuplicate && i + currentIndex < 5) {
  254. file.id = currentIndex + i
  255. saveFileList.push(file)
  256. updateList.items.add(file);
  257. }
  258. }
  259. let updatedFileList = updateList.files;
  260. setFileListData(saveFileList)
  261. setFileList(updatedFileList);
  262. };
  263. useEffect(() => {
  264. props.setUpdateValid(isValid)
  265. }, [isValid])
  266. useEffect(() => {
  267. checkDataField(values)
  268. }, [
  269. selectedIdDocType,
  270. selectedAddress4, selectedAddress5,
  271. termsAndConAccept, termsAndConNotAccept, fileList])
  272. useEffect(() => {
  273. props.step == 2 ? _onSubmit() : null;
  274. if(captchaImg=="")
  275. onCaptchaChange();
  276. checkDataField(values)
  277. }, [props.step])
  278. const { handleSubmit } = useForm({})
  279. const _onSubmit = () => {
  280. setLoding(true);
  281. values.idDocType = selectedIdDocType.type
  282. values.address4 = selectedAddress4
  283. values.address5 = selectedAddress5
  284. const userAddress = {
  285. "addressLine1": "",
  286. "addressLine2": "",
  287. "addressLine3": "",
  288. "district": "",
  289. "country": ""
  290. };
  291. userAddress.addressLine1 = values.address1
  292. userAddress.addressLine2 = values.address2
  293. userAddress.addressLine3 = values.address3
  294. userAddress.district = values.address4
  295. userAddress.country = values.address5
  296. const userFaxNo = {
  297. "countryCode": values.faxCountryCode,
  298. "faxNumber": values.fax,
  299. };
  300. const userMobileNumber = {
  301. "countryCode": values.phoneCountryCode,
  302. "phoneNumber": values.phone,
  303. };
  304. let tncFlag = false;
  305. if (termsAndConAccept) {
  306. tncFlag = true
  307. }
  308. if (termsAndConNotAccept) {
  309. tncFlag = false
  310. }
  311. const user = {
  312. username: values.username,
  313. password: values.password,
  314. name: values.username,
  315. enName: values.enName,
  316. chName: values.chName,
  317. emailAddress: values.email,
  318. idDocType: values.idDocType,
  319. identification: values.idNo,
  320. checkDigit: values.checkDigit,
  321. tncFlag: tncFlag,
  322. type: "IND",
  323. };
  324. var formData = new FormData();
  325. for (let i = 0; i < fileListData.length; i++) {
  326. const file = fileListData[i]
  327. formData.append("multipartFileList", file);
  328. }
  329. formData.append("refType", refType);
  330. for (const [key, value] of Object.entries(user)) {
  331. formData.append(key, value);
  332. }
  333. formData.append("userFaxNo", JSON.stringify(userFaxNo));
  334. formData.append("userMobileNumber", JSON.stringify(userMobileNumber));
  335. formData.append("userAddress", JSON.stringify(userAddress));
  336. // formData.append("preferLocale", "en");
  337. // if(refCode){
  338. // formData.append("refCode", refCode);
  339. // }
  340. if (isValid) {
  341. axios.post(POST_PUBLIC_USER_REGISTER, formData, {
  342. headers: {
  343. "Content-Type": "multipart/form-data"
  344. }
  345. })
  346. .then((response) => {
  347. console.log(response)
  348. setCheckUpload(true)
  349. setLoding(false);
  350. })
  351. .catch(error => {
  352. console.error(error);
  353. setLoding(false);
  354. });
  355. } else {
  356. setLoding(false);
  357. }
  358. }
  359. function handlePhone(phone) {
  360. if (phone.length < 8) {
  361. return false;
  362. } else {
  363. // console.log("Phone true")
  364. return true;
  365. }
  366. }
  367. function handleUsername(username) {
  368. var symbol = /^(?=.*[!@#%&])/;
  369. var space = /\s/;
  370. if (username.length < 6) {
  371. return false;
  372. } else if (username.match(symbol)) {
  373. return false;
  374. } else if (username.match(space)) {
  375. return false;
  376. } else {
  377. return true;
  378. }
  379. }
  380. function handleCaptcha(captchaField) {
  381. return captchaField;
  382. }
  383. function handleIdNo(idNo, selectedIdDocType, checkDigit) {
  384. // var pattern = /^[A-Z][0-9]*$/;
  385. var pattern_HKIDv1 = /^[A-Z]{1}[0-9]{6}$/;
  386. var pattern_HKIDv2 = /^[A-Z]{2}[0-9]{6}$/;
  387. var pattern_passport = /^[A-Z]{1}[0-9]{8}$/;
  388. var pattern_CHID = /^[0-9]{6}(20|19)[0-9]{2}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]{1}/;
  389. var pattern_otherCert = /^[A-Z]{1}[0-9]{5,}/;
  390. // var space = /\s/;
  391. // if (!idNo.match(pattern)) {
  392. // return false;
  393. // } else if (selectedIdDocType=="HKID"&&checkDigit==""){
  394. // return false;
  395. // } else if (idNo.match(space)) {
  396. // return false;
  397. // } else if (idNo.length < 6) {
  398. // return false;
  399. // } else {
  400. // // console.log("IdNo true")
  401. // return true;
  402. // }
  403. switch (selectedIdDocType) {
  404. case "HKID":
  405. if (checkDigit === "") return false
  406. if (idNo.match(pattern_HKIDv1)) {
  407. return true
  408. } else if (idNo.match(pattern_HKIDv2)) {
  409. return true
  410. } else {
  411. return false
  412. }
  413. case "passport":
  414. if (idNo.match(pattern_passport)) {
  415. return true
  416. } else {
  417. return false
  418. }
  419. case "CNID":
  420. if (idNo.match(pattern_CHID)) {
  421. const subStr_year = idNo.substring(6, 10)
  422. const subStr_month = idNo.substring(10, 12)
  423. const subStr_date = idNo.substring(12, 14)
  424. const today = new Date()
  425. const inputDate = new Date(`${subStr_year}-${subStr_month}-${subStr_date}`)
  426. if (inputDate > today || inputDate === "Invalid Date" || inputDate.getFullYear().toString() !== subStr_year || (inputDate.getMonth() + 1).toString().padStart(2, "0") !== subStr_month || inputDate.getDate().toString().padStart(2, "0") !== subStr_date) {
  427. return false
  428. } else {
  429. return true
  430. }
  431. } else {
  432. return false
  433. }
  434. case "otherCert":
  435. if (idNo.match(pattern_otherCert)) {
  436. return true
  437. } else {
  438. return false
  439. }
  440. default:
  441. break;
  442. }
  443. }
  444. function handlePassword(password) {
  445. let new_pass = password;
  446. // regular expressions to validate password
  447. var lowerCase = /[a-z]/g;
  448. var upperCase = /[A-Z]/g;
  449. var numbers = /[0-9]/g;
  450. var symbol = /^(?=.*[!@#%&])/;
  451. var space = /\s/;
  452. if (!new_pass.match(lowerCase)) {
  453. return false;
  454. } else if (!new_pass.match(upperCase)) {
  455. return false;
  456. } else if (!new_pass.match(numbers)) {
  457. return false;
  458. } else if (!new_pass.match(symbol)) {
  459. return false;
  460. } else if (new_pass.length < 8) {
  461. return false;
  462. }
  463. else if (new_pass.match(space)) {
  464. return false;
  465. } else {
  466. // console.log("password true")
  467. return true;
  468. }
  469. }
  470. function handleEmail(email) {
  471. var validRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
  472. if (!email.match(validRegex)) {
  473. return false;
  474. } else {
  475. return true;
  476. }
  477. }
  478. function displayErrorMsg(errorMsg) {
  479. return <Typography variant="errorMessage1">{errorMsg}</Typography>
  480. }
  481. const formik = useFormik({
  482. initialValues: ({
  483. username: '',
  484. enName: '',
  485. chName: '',
  486. email: '',
  487. emailConfirm: '',
  488. address1: '',
  489. address2: '',
  490. address3: '',
  491. password: '',
  492. confirmPassword: '',
  493. phone: '',
  494. phoneCountryCode: '852',
  495. idNo: '',
  496. checkDigit: '',
  497. submit: null,
  498. fax: '',
  499. faxCountryCode: '852',
  500. idDocType: '',
  501. captchaField: ''
  502. }),
  503. validationSchema: yup.object().shape({
  504. username: yup.string().min(6, displayErrorMsg(intl.formatMessage({id: 'atLeast6CharAccount'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireUsername'})))
  505. .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(intl.formatMessage({id: 'noSpecialCharAccount'})) })
  506. .matches(/^\S*$/, { message: displayErrorMsg(intl.formatMessage({id: 'noSpaceAccount'})) }),
  507. password: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'atLeast8CharPassword'}))).required(displayErrorMsg(intl.formatMessage({id: 'requirePassword'})))
  508. .matches(/^\S*$/, { message: displayErrorMsg(intl.formatMessage({id: 'noSpacePassword'})) })
  509. .matches(/^(?=.*[a-z])/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeastOneSmallLetter'})) })
  510. .matches(/^(?=.*[A-Z])/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeastOneCapLetter'})) })
  511. .matches(/^(?=.*[0-9])/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeast1Number'})) })
  512. .matches(/^(?=.*[!@#%&])/, { message: displayErrorMsg(intl.formatMessage({id: 'atLeast1SpecialChar'})) }),
  513. 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'}))),
  514. enName: yup.string().max(255).required(displayErrorMsg(intl.formatMessage({id: 'userRequireEnglishName'}))),
  515. chName: yup.string().max(6).required(displayErrorMsg(intl.formatMessage({id: 'userRequireChineseName'}))),
  516. address1: yup.string().max(255).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine1'}))),
  517. address2: yup.string().max(255).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine2'}))),
  518. address3: yup.string().max(255).required(displayErrorMsg(intl.formatMessage({id: 'validateAddressLine3'}))),
  519. email: yup.string().email(displayErrorMsg(intl.formatMessage({id: 'validEmailFormat'}))).max(255).required(displayErrorMsg(intl.formatMessage({id: 'requireEmail'}))),
  520. 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'}))),
  521. idNo: yup.string().required(displayErrorMsg(`請輸入${selectedIdDocInputType}號碼`))
  522. .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}號碼不包含特殊字符`) })
  523. .matches(/^\S*$/, { message: displayErrorMsg(`${selectedIdDocInputType}號碼不包含空格`) })
  524. .test('checkIDCardFormat', displayErrorMsg(`請輸入有效的${selectedIdDocInputType}號碼`), function (value) {
  525. const idDocType = selectedIdDocType.type;
  526. var pattern_HKIDv1 = /^[A-Z]{1}[0-9]{6}$/;
  527. var pattern_HKIDv2 = /^[A-Z]{2}[0-9]{6}$/;
  528. var pattern_passport = /^[A-Z]{1}[0-9]{8}$/;
  529. var pattern_CHID = /^[0-9]{6}(20|19)[0-9]{2}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]{1}/;
  530. var pattern_otherCert = /^[A-Z]{1}[0-9]{5,}/;
  531. if (value !== undefined) {
  532. switch (idDocType) {
  533. case "HKID":
  534. if (value.match(pattern_HKIDv1)) {
  535. return true
  536. } else if (value.match(pattern_HKIDv2)) {
  537. return true
  538. } else {
  539. return false
  540. }
  541. case "passport":
  542. if (value.match(pattern_passport)) {
  543. return true
  544. } else {
  545. return false
  546. }
  547. case "CNID":
  548. if (value.match(pattern_CHID)) {
  549. const subStr_year = value.substring(6, 10)
  550. const subStr_month = value.substring(10, 12)
  551. const subStr_date = value.substring(12, 14)
  552. const today = new Date()
  553. const inputDate = new Date(`${subStr_year}-${subStr_month}-${subStr_date}`)
  554. if (inputDate > today || inputDate === "Invalid Date" || inputDate.getFullYear().toString() !== subStr_year || (inputDate.getMonth() + 1).toString().padStart(2, "0") !== subStr_month || inputDate.getDate().toString().padStart(2, "0") !== subStr_date) {
  555. return false
  556. } else {
  557. return true
  558. }
  559. } else {
  560. return false
  561. }
  562. case "otherCert":
  563. if (value.match(pattern_otherCert)) {
  564. return true
  565. } else {
  566. return false
  567. }
  568. default:
  569. break;
  570. }
  571. }
  572. }),
  573. checkDigit: yup.string().max(1).required(displayErrorMsg('請輸入括號內的數字或字母')),
  574. idDocType: yup.string().max(255).required(displayErrorMsg('請輸入證件類別')),
  575. phoneCountryCode: yup.string().min(2, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast2Number'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireDialingCode'}))),
  576. // faxCountryCode: yup.string().min(3,'請輸入3位數字'),
  577. phone: yup.string().min(8, displayErrorMsg(intl.formatMessage({id: 'requireAtLeast8Number'}))).required(displayErrorMsg(intl.formatMessage({id: 'requireContactNumber'}))),
  578. // fax: yup.string().min(8,'請輸入8位數字'),
  579. captchaField: yup.string().required(displayErrorMsg(intl.formatMessage({id: 'requireVerify'}))),//.oneOf([captcha], displayErrorMsg('請輸入有效驗證')),
  580. }),
  581. });
  582. const handleReset = (resetForm) => {
  583. resetForm();
  584. setSelectedAddress4("")
  585. setSelectedAddress5(ComboData.country(intl)[0])
  586. setCheckCountry(false)
  587. setSelectedIdDocType({})
  588. setSelectedIdDocInputType("");
  589. setFileList([])
  590. setFileListData([])
  591. onCaptchaChange()
  592. // setSelectedIdDocLabel("")
  593. };
  594. const { values } = formik
  595. useEffect(() => {
  596. checkDataField(values)
  597. }, [values])
  598. return (
  599. <FormikProvider value={formik}>
  600. <form onSubmit={handleSubmit(_onSubmit)}>
  601. {/* Input Form */}
  602. <FormGroup id={"inputForm"} sx={{ display: props.step === 0 ? "" : "none" }}>
  603. <Grid container spacing={3}>
  604. <Grid item xs={12} md={12}>
  605. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  606. <Button variant="outlined" type="reset" onClick={handleReset.bind(null, formik.resetForm)} sx={{ height: '40px' }}>
  607. <Typography variant="pnspsFormHeader">
  608. <FormattedMessage id="reset"/>
  609. </Typography>
  610. </Button>
  611. <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}>
  612. <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}>
  613. <FormattedMessage id="becomeNewPersonalUser"/>
  614. </Typography>
  615. </div>
  616. <Typography mt={0.25} variant="h6" sx={{ color: '#f10000' }}>
  617. <FormattedMessage id="requireString"/>
  618. </Typography>
  619. <Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary' }}>
  620. <FormattedMessage id="yourLoginInformation"/>
  621. </Typography>
  622. </Stack>
  623. </Grid>
  624. <Grid item xs={12} md={12}>
  625. <Grid container spacing={1}>
  626. <Grid item xs={12} md={12} >
  627. <Stack spacing={1}>
  628. <InputLabel htmlFor="username-signup">
  629. <Typography variant="pnspsFormHeader">
  630. <FormattedMessage id="userLoginName"/>
  631. <span style={{ color: '#f10000' }}>*</span>
  632. {/*<Button*/}
  633. {/* variant="contained"*/}
  634. {/* onClick={handleCheckUsername}*/}
  635. {/* sx={{ ml: 2, height: "40px" }}>*/}
  636. {/* <Typography variant="h6">檢查是否重覆</Typography>*/}
  637. {/*</Button> **/}
  638. </Typography>
  639. </InputLabel>
  640. <OutlinedInput
  641. id="username-login"
  642. type="text"
  643. value={formik.values.username.trim()}
  644. name="username"
  645. onChange={(e) => {
  646. setCheckUsername(false)
  647. props.setUsername(e.target.value)
  648. formik.handleChange(e)
  649. }}
  650. placeholder={intl.formatMessage({id: 'userLoginName'})}
  651. fullWidth
  652. error={Boolean((formik.touched.username && formik.errors.username) || checkUsername)}
  653. onBlur={formik.handleBlur}
  654. inputProps={{
  655. onKeyDown: (e) => {
  656. if (e.key === 'Enter') {
  657. e.preventDefault();
  658. }
  659. },
  660. }}
  661. />
  662. {formik.touched.username && formik.errors.username && (
  663. <FormHelperText error id="helper-text-username-signup">
  664. {formik.errors.username}
  665. </FormHelperText>
  666. )}
  667. {checkUsername && (
  668. <FormHelperText error id="helper-text-username-signup">
  669. 此用戶登入名稱已被注冊,請使用其他用戶登入名稱
  670. </FormHelperText>
  671. )}
  672. </Stack>
  673. </Grid>
  674. <Grid item xs={12} md={12}>
  675. <Grid container>
  676. <Grid item xs={12} md={6} >
  677. <Stack spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  678. <Stack direction="row" justifyContent="space-between">
  679. <InputLabel htmlFor="password-signup">
  680. <Typography variant="pnspsFormHeader">
  681. <FormattedMessage id="userPassword"/>
  682. <span style={{ color: '#f10000' }}>*</span>
  683. </Typography>
  684. </InputLabel>
  685. </Stack>
  686. <OutlinedInput
  687. fullWidth
  688. error={Boolean(formik.touched.password && formik.errors.password)}
  689. id="password-signup"
  690. type={showPassword ? 'text' : 'password'}
  691. value={formik.values.password.trim()}
  692. name="password"
  693. onChange={(e) => {
  694. formik.handleChange(e);
  695. changePassword(e.target.value);
  696. }}
  697. endAdornment={
  698. <InputAdornment position="end">
  699. <IconButton
  700. aria-label="toggle password visibility"
  701. onClick={handleClickShowPassword}
  702. onMouseDown={handleMouseDownPassword}
  703. edge="end"
  704. size="large"
  705. >
  706. {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  707. </IconButton>
  708. </InputAdornment>
  709. }
  710. placeholder={intl.formatMessage({id: 'userPassword'})}
  711. onBlur={formik.handleBlur}
  712. inputProps={{
  713. onKeyDown: (e) => {
  714. if (e.key === 'Enter') {
  715. e.preventDefault();
  716. }
  717. },
  718. }}
  719. />
  720. {formik.touched.password && formik.errors.password && (
  721. <FormHelperText error id="helper-text-password-signup">
  722. {formik.errors.password}
  723. </FormHelperText>
  724. )}
  725. </Stack>
  726. <FormControl fullWidth sx={{ mt: 2 }}>
  727. <Grid container spacing={2} alignItems="center">
  728. <Grid item>
  729. <Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
  730. </Grid>
  731. <Grid item>
  732. <Typography variant="subtitle1">
  733. {level?.label}
  734. </Typography>
  735. </Grid>
  736. </Grid>
  737. </FormControl>
  738. </Grid>
  739. <Grid item xs={12} md={6} >
  740. <Stack spacing={1}>
  741. <InputLabel htmlFor="confirmPassword-signup">
  742. <Typography variant="pnspsFormHeader">
  743. <FormattedMessage id="confirmPassword"/>
  744. <span style={{ color: '#f10000' }}>*</span>
  745. </Typography>
  746. </InputLabel>
  747. <OutlinedInput
  748. id="confirmPassword-login"
  749. type={showConfirmPassword ? 'text' : 'password'}
  750. value={formik.values.confirmPassword.trim()}
  751. name="confirmPassword"
  752. onBlur={formik.handleBlur}
  753. onChange={(e) => {
  754. formik.handleChange(e);
  755. // changePassword(e.target.value);
  756. }}
  757. inputProps={{
  758. onKeyDown: (e) => {
  759. if (e.key === 'Enter') {
  760. e.preventDefault();
  761. }
  762. },
  763. }}
  764. endAdornment={
  765. <InputAdornment position="end">
  766. <IconButton
  767. aria-label="toggle password visibility"
  768. onClick={handleClickShowConfirmPassword}
  769. onMouseDown={handleMouseDownPassword}
  770. edge="end"
  771. size="large"
  772. >
  773. {showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  774. </IconButton>
  775. </InputAdornment>
  776. }
  777. placeholder={intl.formatMessage({id: 'confirmPassword'})}
  778. fullWidth
  779. error={Boolean(formik.touched.confirmPassword && formik.errors.confirmPassword)}
  780. />
  781. {formik.touched.confirmPassword && formik.errors.confirmPassword && (
  782. <FormHelperText error id="helper-text-confirmPassword-signup">
  783. {formik.errors.confirmPassword}
  784. </FormHelperText>
  785. )}
  786. </Stack>
  787. <Grid container spacing={2} alignItems="center">
  788. <Grid item sx={{mt:1}}>
  789. <Typography variant="subtitle1">
  790. •至少8個字元,字元越多越好 <br />
  791. •字母和數字的混合<br />
  792. •英文字母大寫與小寫的混合<br />
  793. •至少包含一個特殊符號,例如,@ # ?
  794. </Typography>
  795. </Grid>
  796. </Grid>
  797. </Grid>
  798. </Grid>
  799. </Grid>
  800. <Grid item xs={12} mt={1} mb={1}>
  801. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  802. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  803. <FormattedMessage id="yourPersonalInformation"/>
  804. </Typography>
  805. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  806. Already have an account?
  807. </Typography> */}
  808. </Stack>
  809. </Grid>
  810. <Grid item xs={12} md={12} >
  811. <Grid container sx={{ mb: 1 }}>
  812. <Stack spacing={1}>
  813. <InputLabel htmlFor="idDocType-signup">
  814. <Typography variant="pnspsFormHeader">
  815. 身份證明文件
  816. <span style={{ color: '#f10000' }}>*</span>
  817. </Typography>
  818. </InputLabel>
  819. {/* {formik.touched.enName && formik.errors.enName && (
  820. <FormHelperText error id="helper-text-enName-signup">
  821. {formik.errors.enName}
  822. </FormHelperText>
  823. )} */}
  824. </Stack>
  825. </Grid>
  826. <Grid container>
  827. <Grid item xs={12} md={6} >
  828. <Stack spacing={1} sx={{ mr: { md: 1 } }}>
  829. <Autocomplete
  830. disablePortal
  831. id="idDocType"
  832. //value={selectedIdDocType}
  833. size="small"
  834. options={idDocTypeComboList}
  835. // getOptionLabel={(idDocTypeComboList) => idDocTypeComboList.label}
  836. onBlur={formik.handleBlur}
  837. filterOptions={(options) => options}
  838. inputValue={selectedIdDocInputType}
  839. onChange={(event, newValue) => {
  840. if (newValue != null ) {
  841. setSelectedIdDocInputType(newValue.label);
  842. setSelectedIdDocType(newValue);
  843. if (newValue.type !== "HKID") {
  844. formik.setFieldValue("checkDigit", "")
  845. }
  846. } else {
  847. setSelectedIdDocInputType("");
  848. }
  849. }}
  850. sx={{ "#address4-combo": { padding: "0px 0px 0px 0px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }}
  851. renderInput={(params) => <TextField
  852. {...params}
  853. placeholder="證件類別"
  854. />}
  855. />
  856. {formik.touched.idDocType && (
  857. selectedIdDocType === null ?
  858. <FormHelperText error id="helper-text-idDocType-signup">
  859. 請輸入證件類別
  860. </FormHelperText> : ''
  861. )}
  862. </Stack>
  863. </Grid>
  864. {selectedIdDocType.type === "HKID" ?
  865. <>
  866. <Grid item xs={10} md={5}>
  867. <Stack spacing={1} sx={{ mr: { md: 1 } }}>
  868. <OutlinedInput
  869. id="idNo-login"
  870. type="text"
  871. name="idNo"
  872. value={formik.values.idNo}
  873. onChange={async (e) => {
  874. const ele = document.getElementById('idNo-login')
  875. const startPos = ele.selectionStart
  876. if (e.type === "change") {
  877. if (!(e.target.value.match(/\s/g))) {
  878. const newValue = await e.target.value.toUpperCase()
  879. await formik.setFieldValue("idNo", newValue)
  880. ele.setSelectionRange(startPos, startPos)
  881. } else {
  882. await formik.setFieldValue("idNo", formik.values.idNo)
  883. ele.setSelectionRange(startPos - 1, startPos - 1)
  884. }
  885. }
  886. }}
  887. placeholder="證件號碼"
  888. fullWidth
  889. sx={{ mr: 1 }}
  890. error={Boolean(formik.touched.idNo && formik.errors.idNo)}
  891. onBlur={formik.handleBlur}
  892. inputProps={{
  893. maxLength: selectedIdDocType.type === 'HKID' ? 8 : 18,
  894. onKeyDown: (e) => {
  895. console.log(e)
  896. if (e.key === 'Enter') {
  897. e.preventDefault();
  898. }
  899. },
  900. }}
  901. />
  902. {formik.touched.idNo && formik.errors.idNo && (
  903. <FormHelperText error id="helper-text-idNo-signup">
  904. {formik.errors.idNo}
  905. </FormHelperText>
  906. )}
  907. {formik.touched.checkDigit && formik.errors.checkDigit && (
  908. <FormHelperText error id="helper-text-checkDigit-signup">
  909. {formik.errors.checkDigit}
  910. </FormHelperText>
  911. )}
  912. </Stack>
  913. </Grid>
  914. <Grid item xs={2} md={1}>
  915. <Stack spacing={1}>
  916. <OutlinedInput
  917. id="checkDigit-login"
  918. type="text"
  919. value={formik.values.checkDigit.trim()}
  920. name="checkDigit"
  921. onChange={formik.handleChange}
  922. //placeholder="( )"
  923. // sx={{height:"53px"}}
  924. startAdornment={<InputAdornment position="start">(</InputAdornment>}
  925. endAdornment={<InputAdornment position="end">)</InputAdornment>}
  926. sx={{
  927. '& .MuiOutlinedInput-input': {
  928. padding: '5px 5px 5px 5px', // Set the desired padding inline
  929. },
  930. }}
  931. inputProps={{
  932. maxLength: 1,
  933. onKeyDown: (e) => {
  934. if (e.key === 'Enter') {
  935. e.preventDefault();
  936. }
  937. },
  938. }}
  939. fullWidth
  940. error={Boolean(formik.touched.checkDigit && formik.errors.checkDigit)}
  941. onBlur={formik.handleBlur}
  942. />
  943. </Stack>
  944. </Grid>
  945. </> :
  946. <Grid item xs={12} md={6}>
  947. <Stack spacing={1}>
  948. <OutlinedInput
  949. id="idNo-login"
  950. type="text"
  951. value={formik.values.idNo}
  952. name="idNo"
  953. onChange={async (e) => {
  954. const ele = document.getElementById('idNo-login')
  955. const startPos = ele.selectionStart
  956. if (e.type === "change") {
  957. if (!(e.target.value.match(/\s/g))) {
  958. const newValue = await e.target.value.toUpperCase()
  959. await formik.setFieldValue("idNo", newValue)
  960. ele.setSelectionRange(startPos, startPos)
  961. } else {
  962. await formik.setFieldValue("idNo", formik.values.idNo)
  963. ele.setSelectionRange(startPos - 1, startPos - 1)
  964. }
  965. }
  966. }}
  967. placeholder="證件號碼"
  968. fullWidth
  969. sx={{ mr: 1 }}
  970. error={Boolean(formik.touched.idNo && formik.errors.idNo)}
  971. onBlur={formik.handleBlur}
  972. inputProps={{
  973. maxLength: 18,
  974. onKeyDown: (e) => {
  975. if (e.key === 'Enter') {
  976. e.preventDefault();
  977. }
  978. },
  979. }}
  980. />
  981. {formik.touched.idNo && formik.errors.idNo && (
  982. <FormHelperText error id="helper-text-idNo-signup">
  983. {formik.errors.idNo}
  984. </FormHelperText>
  985. )}
  986. </Stack>
  987. </Grid>
  988. }
  989. </Grid>
  990. </Grid>
  991. <Grid item xs={12} md={6}>
  992. <Stack spacing={1}>
  993. <InputLabel htmlFor="enName-signup">
  994. <Typography variant="pnspsFormHeader">
  995. <FormattedMessage id="userEnglishName"/>
  996. {selectedIdDocType.type === "CNID" ? "" : <span style={{ color: '#f10000' }}>*</span>}
  997. </Typography>
  998. </InputLabel>
  999. <OutlinedInput
  1000. id="enName-login"
  1001. type="enName"
  1002. value={formik.values.enName}
  1003. name="enName"
  1004. onChange={formik.handleChange}
  1005. placeholder="與你的身份證明文件相同"
  1006. fullWidth
  1007. error={Boolean(formik.touched.enName && formik.errors.enName && selectedIdDocType.type !== "CNID")}
  1008. onBlur={formik.handleBlur}
  1009. inputProps={{
  1010. onKeyDown: (e) => {
  1011. if (e.key === 'Enter') {
  1012. e.preventDefault();
  1013. }
  1014. },
  1015. }}
  1016. />
  1017. {formik.touched.enName && formik.errors.enName && selectedIdDocType.type !== "CNID" && (
  1018. <FormHelperText error id="helper-text-enName-signup">
  1019. {formik.errors.enName}
  1020. </FormHelperText>
  1021. )}
  1022. </Stack>
  1023. </Grid>
  1024. <Grid item xs={12} md={6}>
  1025. <Stack spacing={1}>
  1026. <InputLabel htmlFor="chName-signup">
  1027. <Typography variant="pnspsFormHeader">
  1028. <FormattedMessage id="userChineseName"/>
  1029. <span style={{ color: '#f10000' }}>*</span>
  1030. </Typography>
  1031. </InputLabel>
  1032. <OutlinedInput
  1033. fullWidth
  1034. error={Boolean(formik.touched.chName && formik.errors.chName)}
  1035. id="chName-signup"
  1036. type="text"
  1037. value={formik.values.chName.trim()}
  1038. name="chName"
  1039. onChange={formik.handleChange}
  1040. placeholder="與你的身份證明文件相同"
  1041. onBlur={formik.handleBlur}
  1042. inputProps={{
  1043. maxLength: 6,
  1044. onKeyDown: (e) => {
  1045. if (e.key === 'Enter') {
  1046. e.preventDefault();
  1047. }
  1048. },
  1049. }}
  1050. />
  1051. {formik.touched.chName && formik.errors.chName && (
  1052. <FormHelperText error id="helper-text-chName-signup">
  1053. {formik.errors.chName}
  1054. </FormHelperText>
  1055. )}
  1056. </Stack>
  1057. </Grid>
  1058. <Grid item xs={12}>
  1059. <Stack spacing={1}>
  1060. <InputLabel htmlFor="address1-signup">
  1061. <Typography variant="pnspsFormHeader">
  1062. <FormattedMessage id="formAddress"/>
  1063. <span style={{ color: '#f10000' }}>*</span>
  1064. </Typography>
  1065. </InputLabel>
  1066. <OutlinedInput
  1067. fullWidth
  1068. error={Boolean(formik.touched.address1 && formik.errors.address1)}
  1069. id="address1-signup"
  1070. value={formik.values.address1}
  1071. name="address1"
  1072. onChange={formik.handleChange}
  1073. placeholder={intl.formatMessage({id: 'addressLine1'})}
  1074. onBlur={formik.handleBlur}
  1075. inputProps={{
  1076. onKeyDown: (e) => {
  1077. if (e.key === 'Enter') {
  1078. e.preventDefault();
  1079. }
  1080. },
  1081. }}
  1082. />
  1083. <OutlinedInput
  1084. fullWidth
  1085. error={Boolean(formik.touched.address2 && formik.errors.address2)}
  1086. id="address2-signup"
  1087. value={formik.values.address2}
  1088. name="address2"
  1089. onChange={formik.handleChange}
  1090. placeholder={intl.formatMessage({id: 'addressLine2'})}
  1091. inputProps={{
  1092. onKeyDown: (e) => {
  1093. if (e.key === 'Enter') {
  1094. e.preventDefault();
  1095. }
  1096. },
  1097. }}
  1098. />
  1099. <OutlinedInput
  1100. fullWidth
  1101. error={Boolean(formik.touched.address3 && formik.errors.address3)}
  1102. id="address3-signup"
  1103. value={formik.values.address3}
  1104. name="address3"
  1105. onChange={formik.handleChange}
  1106. placeholder={intl.formatMessage({id: 'addressLine3'})}
  1107. inputProps={{
  1108. onKeyDown: (e) => {
  1109. if (e.key === 'Enter') {
  1110. e.preventDefault();
  1111. }
  1112. },
  1113. }}
  1114. />
  1115. <Autocomplete
  1116. disablePortal
  1117. id="address4-combo"
  1118. value={selectedAddress4}
  1119. options={address4ComboList}
  1120. disabled={checkCountry}
  1121. onChange={(event, newValue) => {
  1122. setSelectedAddress4(newValue);
  1123. }}
  1124. sx={{ "& .MuiInputBase-root": { height: "41px" },
  1125. "#address4-combo": { padding: "0px 0px 0px 3px" },
  1126. "& .MuiAutocomplete-endAdornment": { top: "auto" }, }}
  1127. renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({id: 'region'})}
  1128. />}
  1129. />
  1130. <Autocomplete
  1131. disablePortal
  1132. id="address5-combo"
  1133. value={selectedAddress5}
  1134. options={address5ComboList}
  1135. onChange={(event, newValue) => {
  1136. if (newValue !== null) {
  1137. setSelectedAddress5(newValue);
  1138. if (newValue === intl.formatMessage({id: 'hongKong'})) {
  1139. setCheckCountry(false)
  1140. } else {
  1141. setSelectedAddress4("");
  1142. setCheckCountry(true)
  1143. }
  1144. } else {
  1145. setSelectedAddress4("");
  1146. setCheckCountry(true)
  1147. }
  1148. }}
  1149. sx={{ "& .MuiInputBase-root": { height: "41px" }, "#address5-combo": { padding: "0px 0px 0px 3px" }, "& .MuiAutocomplete-endAdornment": { top: "auto" }, }}
  1150. renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({id: 'regionOrCountry'})} />}
  1151. />
  1152. {formik.touched.address1 && formik.errors.address1 && (
  1153. <FormHelperText error id="helper-text-address1-signup">
  1154. {formik.errors.address1}
  1155. </FormHelperText>
  1156. )}
  1157. {formik.touched.address2 && formik.errors.address2 && (
  1158. <FormHelperText error id="helper-text-address2-signup">
  1159. {formik.errors.address2}
  1160. </FormHelperText>
  1161. )}
  1162. {formik.touched.address3 && formik.errors.address3 && (
  1163. <FormHelperText error id="helper-text-address3-signup">
  1164. {formik.errors.address3}
  1165. </FormHelperText>
  1166. )}
  1167. </Stack>
  1168. </Grid>
  1169. <Grid item xs={12} mt={1} mb={1}>
  1170. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1171. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  1172. <FormattedMessage id="yourContact"/>
  1173. </Typography>
  1174. </Stack>
  1175. </Grid>
  1176. <Grid item xs={12} md={12}>
  1177. <Grid container>
  1178. <Grid item xs={12} md={6}>
  1179. <Stack spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  1180. <InputLabel htmlFor="email-signup">
  1181. <Typography variant="pnspsFormHeader">
  1182. <FormattedMessage id="userContactEmail"/>
  1183. <span style={{ color: '#f10000' }}>*</span>
  1184. </Typography>
  1185. </InputLabel>
  1186. <OutlinedInput
  1187. fullWidth
  1188. error={Boolean((formik.touched.email && formik.errors.email) || checkEmail)}
  1189. id="email-login"
  1190. type="email"
  1191. value={formik.values.email.trim()}
  1192. name="email"
  1193. onChange={formik.handleChange}
  1194. placeholder={intl.formatMessage({id: 'userContactEmail'})}
  1195. onBlur={formik.handleBlur}
  1196. inputProps={{
  1197. onKeyDown: (e) => {
  1198. if (e.key === 'Enter') {
  1199. e.preventDefault();
  1200. }
  1201. },
  1202. }}
  1203. />
  1204. {formik.touched.email && formik.errors.email && (
  1205. <FormHelperText error id="helper-text-email-signup">
  1206. {formik.errors.email}
  1207. </FormHelperText>
  1208. )}
  1209. {checkEmail && (
  1210. <FormHelperText error id="helper-text-email-signup">
  1211. <FormattedMessage id="emailUsed"/>
  1212. </FormHelperText>
  1213. )}
  1214. </Stack>
  1215. </Grid>
  1216. <Grid item xs={12} md={6}>
  1217. <Stack spacing={1} >
  1218. <InputLabel htmlFor="emailConfirm-signup">
  1219. <Typography variant="pnspsFormHeader">
  1220. <FormattedMessage id="userContactEmail"/>
  1221. <span style={{ color: '#f10000' }}>*</span>
  1222. </Typography>
  1223. </InputLabel>
  1224. <OutlinedInput
  1225. fullWidth
  1226. error={Boolean(formik.touched.emailConfirm && formik.errors.emailConfirm)}
  1227. id="emailConfirm-login"
  1228. type="email"
  1229. value={formik.values.emailConfirm.trim()}
  1230. name="emailConfirm"
  1231. // onBlur={formik.handleBlur}
  1232. onChange={formik.handleChange}
  1233. placeholder={intl.formatMessage({id: 'confirmEmail'})}
  1234. onBlur={formik.handleBlur}
  1235. inputProps={{
  1236. onKeyDown: (e) => {
  1237. if (e.key === 'Enter') {
  1238. e.preventDefault();
  1239. }
  1240. },
  1241. }}
  1242. />
  1243. {formik.touched.emailConfirm && formik.errors.emailConfirm && (
  1244. <FormHelperText error id="helper-text-emailConfirm-signup">
  1245. {formik.errors.emailConfirm}
  1246. </FormHelperText>
  1247. )}
  1248. </Stack>
  1249. </Grid>
  1250. </Grid>
  1251. </Grid>
  1252. <Grid item xs={12} md={12}>
  1253. <Grid container>
  1254. <Grid item xs={12} md={6}>
  1255. <Grid container>
  1256. <Grid item xs={12} md={12}>
  1257. <Stack direction="column" spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}>
  1258. <InputLabel htmlFor="phone-signup">
  1259. <Typography variant="pnspsFormHeader">
  1260. <FormattedMessage id="userContactNumber"/>
  1261. <span style={{ color: '#f10000' }}>*</span>
  1262. </Typography>
  1263. </InputLabel>
  1264. <Stack direction="row">
  1265. <OutlinedInput
  1266. id="phoneCountryCode-login"
  1267. type="phoneCountryCode"
  1268. value={formik.values.phoneCountryCode.trim()}
  1269. name="phoneCountryCode"
  1270. // onBlur={formik.handleBlur}
  1271. // onChange={formik.handleChange}
  1272. onChange={(event) => {
  1273. const value = event.target.value;
  1274. if (value.match(/[^0-9]/)) {
  1275. return event.preventDefault();
  1276. }
  1277. formik.setFieldValue("phoneCountryCode", value);
  1278. }}
  1279. placeholder={intl.formatMessage({id: 'dialingCode'})}
  1280. error={Boolean(formik.touched.phone && formik.errors.phone)}
  1281. onBlur={formik.handleBlur}
  1282. endAdornment={<InputAdornment position="end">-</InputAdornment>}
  1283. inputProps={{
  1284. maxLength: 3,
  1285. onKeyDown: (e) => {
  1286. if (e.key === 'Enter') {
  1287. e.preventDefault();
  1288. }
  1289. },
  1290. }}
  1291. sx={{ width: '33%', mr:1}}
  1292. />
  1293. <OutlinedInput
  1294. id="phone-login"
  1295. type="phone"
  1296. value={formik.values.phone.trim()}
  1297. name="phone"
  1298. // onBlur={formik.handleBlur}
  1299. // onChange={formik.handleChange}
  1300. onChange={(event) => {
  1301. const value = event.target.value;
  1302. if (value.match(/[^0-9]/)) {
  1303. return event.preventDefault();
  1304. }
  1305. formik.setFieldValue("phone", value);
  1306. }}
  1307. placeholder={intl.formatMessage({id: 'userContactNumber'})}
  1308. error={Boolean(formik.touched.phone && formik.errors.phone)}
  1309. onBlur={formik.handleBlur}
  1310. inputProps={{
  1311. maxLength: 11,
  1312. onKeyDown: (e) => {
  1313. if (e.key === 'Enter') {
  1314. e.preventDefault();
  1315. }
  1316. },
  1317. }}
  1318. sx={{ width: '66%' }}
  1319. />
  1320. </Stack>
  1321. {formik.touched.phone && formik.errors.phone && (
  1322. <FormHelperText error id="helper-text-phone-signup">
  1323. {formik.errors.phone}
  1324. </FormHelperText>
  1325. )}
  1326. </Stack>
  1327. </Grid>
  1328. </Grid>
  1329. </Grid>
  1330. <Grid item xs={12} md={6}>
  1331. <Grid container>
  1332. <Grid item xs={12} md={12}>
  1333. <Stack spacing={1} direction="column">
  1334. <InputLabel htmlFor="fax-signup">
  1335. <Typography variant="pnspsFormHeader">
  1336. <FormattedMessage id="userFaxNumber"/>
  1337. </Typography>
  1338. </InputLabel>
  1339. <Stack direction="row">
  1340. <OutlinedInput
  1341. error={Boolean(formik.touched.fax && formik.errors.fax)}
  1342. id="faxCountryCode-login"
  1343. type="faxCountryCode"
  1344. value={formik.values.faxCountryCode.trim()}
  1345. name="faxCountryCode"
  1346. // onChange={formik.handleChange}
  1347. onChange={(event) => {
  1348. const value = event.target.value;
  1349. if (value.match(/[^0-9]/)) {
  1350. return event.preventDefault();
  1351. }
  1352. formik.setFieldValue("faxCountryCode", value);
  1353. }}
  1354. placeholder={intl.formatMessage({id: 'dialingCode'})}
  1355. onBlur={formik.handleBlur}
  1356. endAdornment={<InputAdornment position="end">-</InputAdornment>}
  1357. inputProps={{
  1358. maxLength: 3,
  1359. onKeyDown: (e) => {
  1360. if (e.key === 'Enter') {
  1361. e.preventDefault();
  1362. }
  1363. },
  1364. }}
  1365. sx={{ width: '33%' , mr: 1}}
  1366. />
  1367. <OutlinedInput
  1368. id="fax-login"
  1369. type="fax"
  1370. value={formik.values.fax.trim()}
  1371. name="fax"
  1372. onBlur={formik.handleBlur}
  1373. // onChange={formik.handleChange}
  1374. onChange={(event) => {
  1375. const value = event.target.value;
  1376. if (value.match(/[^0-9]/)) {
  1377. return event.preventDefault();
  1378. }
  1379. formik.setFieldValue("fax", value);
  1380. }}
  1381. placeholder={intl.formatMessage({id: 'userFaxNumber'})}
  1382. inputProps={{
  1383. maxLength: 8,
  1384. onKeyDown: (e) => {
  1385. if (e.key === 'Enter') {
  1386. e.preventDefault();
  1387. }
  1388. },
  1389. }}
  1390. sx={{ width: '66%' }}
  1391. />
  1392. </Stack>
  1393. </Stack>
  1394. </Grid>
  1395. </Grid>
  1396. </Grid>
  1397. </Grid>
  1398. </Grid>
  1399. <Grid item xs={12} md={12} mt={1} mb={1}>
  1400. <Grid container>
  1401. <Grid item xs={12} md={12}>
  1402. <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1403. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>身份證明文件<span style={{ color: '#f10000' }}>*</span></Typography>
  1404. <Typography display="inline" variant="subtitle1" sx={{ color: 'primary.primary' }}>請上傳你的 有效身份證明文件 的數碼檔案,以驗證你的身份。</Typography>
  1405. <Typography display="inline" variant="subtitle1" sx={{ color: 'primary.primary' }}>如: 香港身份證; 護照; 中國內地身份證; 專業執業証書等</Typography>
  1406. <Stack mt={1} direction="row" justifyContent="flex-start" alignItems="center" spacing={2}>
  1407. <ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
  1408. <Button variant="contained" component="label" sx={{ height: '40px' }}>
  1409. 上傳身份證明文件
  1410. <input
  1411. accept="image/png, .jpg, .bmp, .pdf"
  1412. //className={classes.input}
  1413. id="contained-button-file"
  1414. multiple
  1415. type="file"
  1416. onChange={handleFileUpload}
  1417. style={{ display: 'none' }}
  1418. />
  1419. </Button>
  1420. </ThemeProvider>
  1421. {/*<Typography xs={12} sm={9} md={3} display="inline" variant="subtitle1" sx={{ color: 'primary.primary' }}>如: 香港身份證; 護照; 中國內地身份證等</Typography>*/}
  1422. </Stack>
  1423. {fileList != null ?
  1424. <UploadFileTable key="uploadTable" recordList={fileListData} setUpdateRows={setUpdateRows} /> : null}
  1425. {/* <Stack mt={1} direction="row" justifyContent="flex-start" alignItems="center" spacing={2}>
  1426. <Button variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button>
  1427. <Button disabled={!formik.isValid} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button>
  1428. </Stack> */}
  1429. </Stack>
  1430. </Grid>
  1431. </Grid>
  1432. </Grid>
  1433. </Grid>
  1434. <Grid item xs={12} md={12}>
  1435. <Grid container>
  1436. <Grid item xs={12} md={12}>
  1437. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  1438. <FormattedMessage id="termsAndCondition"/>
  1439. <span style={{ color: '#f10000' }}>*</span>
  1440. </Typography>
  1441. </Grid>
  1442. <Grid item xs={12} md={12}>
  1443. <Grid container>
  1444. <Grid item xs={12} md={12}>
  1445. <Typography variant="h6" height="100%" sx={{ textAlign: "left", /*overflow: "scroll",*/ borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0C489E" }}>
  1446. {termsAndCon}
  1447. </Typography>
  1448. </Grid>
  1449. </Grid>
  1450. <Grid item xs={12} s={12} md={12} lg={12}>
  1451. <Grid container>
  1452. <Grid item xs={6} s={6} md={2} lg={2}>
  1453. <Grid container>
  1454. <Grid item sx={{ display: 'flex', alignItems: 'center' }}>
  1455. <Checkbox
  1456. checked={termsAndConAccept}
  1457. onChange={handleCheckBoxChange}
  1458. name="termsAndConAccept"
  1459. color="primary"
  1460. size="small"
  1461. />
  1462. <Typography variant="pnspsFormHeader">
  1463. <FormattedMessage id="acceptTerms"/>
  1464. </Typography>
  1465. </Grid>
  1466. </Grid>
  1467. </Grid>
  1468. <Grid item xs={6} s={6} md={3} lg={3}>
  1469. <Grid container>
  1470. <Grid item sx={{ display: 'flex', alignItems: 'center' }}>
  1471. <Checkbox
  1472. checked={termsAndConNotAccept}
  1473. onChange={handleCheckBoxChange}
  1474. name="termsAndConNotAccept"
  1475. color="primary"
  1476. size="small"
  1477. />
  1478. <Typography variant="pnspsFormHeader">
  1479. <FormattedMessage id="rejectTerms"/>
  1480. </Typography>
  1481. </Grid>
  1482. </Grid>
  1483. </Grid>
  1484. </Grid>
  1485. </Grid>
  1486. </Grid>
  1487. </Grid>
  1488. </Grid>
  1489. <Grid item xs={12} lg={12}>
  1490. <Grid container>
  1491. <Stack direction="column">
  1492. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  1493. <FormattedMessage id="verify"/>
  1494. <span style={{ color: '#f10000' }}>*</span>
  1495. </Typography>
  1496. <Stack spacing={1} direction="row">
  1497. <Grid item xs={5} lg={5} style={{ "border": "1px solid black" }}>
  1498. <img src={captchaImg} alt="" />
  1499. </Grid>
  1500. <Grid item xs={1} lg={1} style={{ "border": "0px solid black" }}>
  1501. <IconButton aria-label="refrashCaptcha" size="large" onClick={() => { onCaptchaChange() }}>
  1502. <LoopIcon fontSize="inherit" />
  1503. </IconButton>
  1504. </Grid>
  1505. <Grid item xs={6} lg={6}>
  1506. <OutlinedInput
  1507. fullWidth
  1508. id="captchaField"
  1509. type="text"
  1510. value={formik.values.captchaField.trim()}
  1511. onBlur={formik.handleBlur}
  1512. error={Boolean(formik.touched.captchaField && formik.errors.captchaField)}
  1513. name="captchaField"
  1514. onChange={(event) => {
  1515. const value = event.target.value;
  1516. props.setCheckCode(event.target.value);
  1517. formik.setFieldValue("captchaField", value);
  1518. }}
  1519. sx={{ width: '75%' }}
  1520. />
  1521. </Grid>
  1522. </Stack>
  1523. {formik.touched.captchaField && formik.errors.captchaField && (
  1524. <FormHelperText error id="helper-text-captcha-signup">
  1525. {formik.errors.captchaField}
  1526. </FormHelperText>
  1527. )}
  1528. </Stack>
  1529. </Grid>
  1530. </Grid>
  1531. </Grid>
  1532. </Grid>
  1533. </FormGroup>
  1534. {/* Preview Form */}
  1535. <FormGroup id={"previewForm"} sx={{ display: props.step === 1 ? "" : "none" }}>
  1536. <Grid container spacing={3}>
  1537. <Grid item xs={12} md={12}>
  1538. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1539. <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}>
  1540. <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}>
  1541. <FormattedMessage id="becomeNewPersonalUser"/>
  1542. </Typography>
  1543. </div>
  1544. {/* <Typography mt={0.25} variant="h6" sx={{ fontSize: 12,color: '#f10000'}}>註有*的項目必須輸入資料</Typography> */}
  1545. <Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary' }}>
  1546. <FormattedMessage id="yourLoginInformation"/>
  1547. </Typography>
  1548. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  1549. Already have an account?
  1550. </Typography> */}
  1551. </Stack>
  1552. </Grid>
  1553. <Grid item xs={12} md={12}>
  1554. <Grid container spacing={2}>
  1555. <Grid item xs={12} >
  1556. <Stack spacing={2} direction="row">
  1557. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1558. <FormattedMessage id="userLoginName"/>:
  1559. </Typography>
  1560. <Typography variant="pnspsFormHeader" id="preview-username-login">
  1561. {formik.values.username}
  1562. </Typography>
  1563. </Stack>
  1564. </Grid>
  1565. <Grid item xs={12} mt={1} mb={1}>
  1566. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1567. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  1568. <FormattedMessage id="yourPersonalInformation"/>
  1569. </Typography>
  1570. {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary">
  1571. Already have an account?
  1572. </Typography> */}
  1573. </Stack>
  1574. </Grid>
  1575. <Grid item xs={12} md={12} >
  1576. <Stack spacing={1}>
  1577. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1578. 身份證明文件
  1579. </Typography>
  1580. </Stack>
  1581. </Grid>
  1582. <Grid item xs={12} md={6} >
  1583. <Stack spacing={1} direction="row">
  1584. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1585. 證件類別:
  1586. </Typography>
  1587. <Typography variant="pnspsFormHeader" name="preview-idDocType">
  1588. {selectedIdDocType.label}
  1589. </Typography>
  1590. </Stack>
  1591. </Grid>
  1592. <Grid item xs={12} md={6}>
  1593. <Stack spacing={1} direction="row">
  1594. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1595. 證件號碼:
  1596. </Typography>
  1597. <Typography variant="pnspsFormHeader" id="idNo-login">
  1598. {formik.values.idNo} {selectedIdDocType.type == "HKID" ? '(' + formik.values.checkDigit + ')' : null}
  1599. </Typography>
  1600. </Stack>
  1601. </Grid>
  1602. <Grid item xs={12} md={6}>
  1603. <Stack spacing={1} direction="row">
  1604. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1605. <FormattedMessage id="userEnglishName"/>:
  1606. </Typography>
  1607. <Typography variant="pnspsFormHeader" id="preview-enName-signup">
  1608. {formik.values.enName}
  1609. </Typography>
  1610. </Stack>
  1611. </Grid>
  1612. <Grid item xs={12} md={6}>
  1613. <Stack spacing={1} direction="row">
  1614. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1615. <FormattedMessage id="userChineseName"/>:
  1616. </Typography>
  1617. <Typography variant="pnspsFormHeader" id="preview-chName-signup">
  1618. {formik.values.chName}
  1619. </Typography>
  1620. </Stack>
  1621. </Grid>
  1622. <Grid item xs={12}>
  1623. <Stack spacing={1} direction="row">
  1624. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1625. <FormattedMessage id="formAddress"/>:
  1626. </Typography>
  1627. <Stack spacing={1} direction="column">
  1628. <Typography variant="pnspsFormHeader" id="preview-address1-signup">
  1629. {formik.values.address1}
  1630. </Typography>
  1631. {formik.values.address2 != null ?
  1632. <Typography variant="pnspsFormHeader" id="preview-address2-signup">
  1633. {formik.values.address2}
  1634. </Typography>
  1635. : null}
  1636. {formik.values.address3 != null ?
  1637. <Typography variant="pnspsFormHeader" id="preview-address3-signup">
  1638. {formik.values.address3}
  1639. </Typography>
  1640. : null}
  1641. {selectedAddress5 == ("香港") ?
  1642. <Stack direction="row">
  1643. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]} id="preview-address4-signup">
  1644. <FormattedMessage id="region"/>:
  1645. </Typography>
  1646. <Typography variant="pnspsFormHeader">{selectedAddress4}</Typography>
  1647. </Stack>
  1648. : null}
  1649. <Stack direction="row">
  1650. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]} id="preview-address5-signup">
  1651. <FormattedMessage id="regionOrCountry"/>:
  1652. </Typography>
  1653. <Typography variant="pnspsFormHeader">{selectedAddress5}</Typography>
  1654. </Stack>
  1655. </Stack>
  1656. </Stack>
  1657. </Grid>
  1658. <Grid item xs={12} mt={1} mb={1}>
  1659. <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1660. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>
  1661. <FormattedMessage id="yourContact"/>
  1662. </Typography>
  1663. </Stack>
  1664. </Grid>
  1665. <Grid item xs={12} md={12}>
  1666. <Stack spacing={1} direction="row">
  1667. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1668. <FormattedMessage id="userContactEmail"/>:
  1669. </Typography>
  1670. <Typography variant="pnspsFormHeader" id="preview-email-signup">
  1671. {formik.values.email}
  1672. </Typography>
  1673. </Stack>
  1674. </Grid>
  1675. <Grid item xs={12} md={6}>
  1676. <Stack spacing={1} direction="row">
  1677. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1678. <FormattedMessage id="userContactNumber"/>:
  1679. </Typography>
  1680. <Typography variant="pnspsFormHeader" id="preview-phone-signup">
  1681. +{formik.values.phoneCountryCode} {formik.values.phone}
  1682. </Typography>
  1683. </Stack>
  1684. </Grid>
  1685. {formik.values.faxCountryCode != "" && formik.values.fax != "" ?
  1686. <Grid item xs={12} md={6}>
  1687. <Stack spacing={1} direction="row">
  1688. <Typography variant="pnspsFormHeader" color={theme.palette.grey[600]}>
  1689. <FormattedMessage id="userFaxNumber"/>:
  1690. </Typography>
  1691. <Typography variant="pnspsFormHeader" id="preview-fax-signup">
  1692. +{formik.values.faxCountryCode} {formik.values.fax}
  1693. </Typography>
  1694. </Stack>
  1695. </Grid>
  1696. : null}
  1697. <Grid item xs={12} md={12} mt={1} mb={1}>
  1698. <Grid container>
  1699. <Grid item xs={12} md={12}>
  1700. <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
  1701. <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}>身份證明文件</Typography>
  1702. {fileList != null ?
  1703. <PreviewUploadFileTable key="previewTable" recordList={fileListData} /> : null}
  1704. </Stack>
  1705. </Grid>
  1706. </Grid>
  1707. </Grid>
  1708. </Grid>
  1709. </Grid>
  1710. </Grid>
  1711. </FormGroup>
  1712. {/* Submit page */}
  1713. <FormGroup id={"submitForm"} sx={{ display: props.step === 2 ? "" : "none" }}>
  1714. <Grid container spacing={3}>
  1715. {isLoading ?
  1716. <LoadingComponent /> :
  1717. <Grid item xs={12}>
  1718. {checkUpload ?
  1719. // SUCCESS page
  1720. <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
  1721. <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
  1722. <Typography display="inline" variant="h4">帳戶申請已成功提交。</Typography>
  1723. <Typography display="inline" variant="h4">
  1724. <FormattedMessage id="emailSent"/>
  1725. </Typography>
  1726. <Button variant="outlined" component={Link} to="/login" sx={{ fontSize: 20, height: '60px' }}><Typography variant="pnspsFormHeader">返回登入頁面</Typography></Button>
  1727. </Stack>
  1728. :
  1729. // ERROR page
  1730. <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
  1731. {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
  1732. <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
  1733. <Typography display="inline" variant="h4">申請失敗,請稍後嘗試</Typography>
  1734. <Button color="error" variant="outlined" component={Link} to="/login" sx={{ fontSize: 20, height: '60px' }}><Typography variant="pnspsFormHeader">返回登入頁面</Typography></Button>
  1735. </Stack>
  1736. }
  1737. </Grid>
  1738. }
  1739. </Grid>
  1740. </FormGroup>
  1741. </form>
  1742. </FormikProvider>
  1743. );
  1744. }
  1745. export default CustomFormWizard;