您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 

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