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.
 
 

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