@@ -19,6 +19,7 @@ | |||||
"@mui/lab": "^5.0.0-alpha.139", | "@mui/lab": "^5.0.0-alpha.139", | ||||
"@mui/material": "^5.10.6", | "@mui/material": "^5.10.6", | ||||
"@mui/x-data-grid": "^6.11.1", | "@mui/x-data-grid": "^6.11.1", | ||||
"@mui/x-date-pickers": "^6.12.0", | |||||
"@reduxjs/toolkit": "^1.8.5", | "@reduxjs/toolkit": "^1.8.5", | ||||
"@testing-library/jest-dom": "^5.16.5", | "@testing-library/jest-dom": "^5.16.5", | ||||
"@testing-library/react": "^13.4.0", | "@testing-library/react": "^13.4.0", | ||||
@@ -48,6 +49,7 @@ | |||||
"react-router-dom": "^6.4.1", | "react-router-dom": "^6.4.1", | ||||
"react-scripts": "^5.0.1", | "react-scripts": "^5.0.1", | ||||
"react-syntax-highlighter": "^15.5.0", | "react-syntax-highlighter": "^15.5.0", | ||||
"react-to-print": "^2.14.13", | |||||
"react-window": "^1.8.7", | "react-window": "^1.8.7", | ||||
"redux": "^4.2.0", | "redux": "^4.2.0", | ||||
"simplebar": "^5.3.8", | "simplebar": "^5.3.8", | ||||
@@ -18407,6 +18409,15 @@ | |||||
"react": ">= 0.14.0" | "react": ">= 0.14.0" | ||||
} | } | ||||
}, | }, | ||||
"node_modules/react-to-print": { | |||||
"version": "2.14.13", | |||||
"resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-2.14.13.tgz", | |||||
"integrity": "sha512-PqUGgTRZvkyBzWgaZHVBECWPX2nGEc3HOUy6WNXof6HT4yTFI92wtIkqQtr4jfvHbadqjwTgzgh6vgN8KXlWWw==", | |||||
"peerDependencies": { | |||||
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", | |||||
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" | |||||
} | |||||
}, | |||||
"node_modules/react-transition-group": { | "node_modules/react-transition-group": { | ||||
"version": "4.4.5", | "version": "4.4.5", | ||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", | "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", | ||||
@@ -45,6 +45,7 @@ | |||||
"react-router-dom": "^6.4.1", | "react-router-dom": "^6.4.1", | ||||
"react-scripts": "^5.0.1", | "react-scripts": "^5.0.1", | ||||
"react-syntax-highlighter": "^15.5.0", | "react-syntax-highlighter": "^15.5.0", | ||||
"react-to-print": "^2.14.13", | |||||
"react-window": "^1.8.7", | "react-window": "^1.8.7", | ||||
"redux": "^4.2.0", | "redux": "^4.2.0", | ||||
"simplebar": "^5.3.8", | "simplebar": "^5.3.8", | ||||
@@ -48,11 +48,7 @@ | |||||
const BusRegister = () => { | const BusRegister = () => { | ||||
const [activeStep, setActiveStep] = useState(0); | const [activeStep, setActiveStep] = useState(0); | ||||
const [completed, setCompleted] = useState([false]); | const [completed, setCompleted] = useState([false]); | ||||
const uploadStep = (value) => { | |||||
setActiveStep(value); | |||||
console.log(value) | |||||
}; | |||||
const [updateValid, setUpdateValid] = useState(false); | |||||
const totalSteps = () => { | const totalSteps = () => { | ||||
return steps.length; | return steps.length; | ||||
@@ -71,7 +67,6 @@ | |||||
}; | }; | ||||
const handleNext = () => { | const handleNext = () => { | ||||
console.log("test 1") | |||||
const newActiveStep = | const newActiveStep = | ||||
isLastStep() && !allStepsCompleted() | isLastStep() && !allStepsCompleted() | ||||
? // It's the last step, but not all steps have been completed, | ? // It's the last step, but not all steps have been completed, | ||||
@@ -140,7 +135,7 @@ | |||||
) : ( | ) : ( | ||||
<React.Fragment> | <React.Fragment> | ||||
<AuthWrapper> | <AuthWrapper> | ||||
<CustomFormWizard uploadStep={uploadStep} step={activeStep} /> | |||||
<CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} /> | |||||
{/* <CustomFormWizard step={activeStep} /> */} | {/* <CustomFormWizard step={activeStep} /> */} | ||||
</AuthWrapper> | </AuthWrapper> | ||||
<Stack direction="row" sx={{ pt: 2 }}> | <Stack direction="row" sx={{ pt: 2 }}> | ||||
@@ -178,7 +173,7 @@ | |||||
</Button> | </Button> | ||||
): | ): | ||||
( | ( | ||||
<Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||||
<Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||||
繼續 | 繼續 | ||||
</Button> | </Button> | ||||
) | ) | ||||
@@ -1,5 +1,7 @@ | |||||
// import { Link } from 'react-router-dom'; | // import { Link } from 'react-router-dom'; | ||||
import React,{useState} from 'react'; | |||||
import React,{useState | |||||
// ,useEffect | |||||
} from 'react'; | |||||
// material-ui | // material-ui | ||||
import { | import { | ||||
@@ -48,11 +50,7 @@ | |||||
const Register = () => { | const Register = () => { | ||||
const [activeStep, setActiveStep] = useState(0); | const [activeStep, setActiveStep] = useState(0); | ||||
const [completed, setCompleted] = useState([false]); | const [completed, setCompleted] = useState([false]); | ||||
const uploadStep = (value) => { | |||||
setActiveStep(value); | |||||
console.log(value) | |||||
}; | |||||
const [updateValid, setUpdateValid] = useState(false); | |||||
const totalSteps = () => { | const totalSteps = () => { | ||||
return steps.length; | return steps.length; | ||||
@@ -71,7 +69,6 @@ | |||||
}; | }; | ||||
const handleNext = () => { | const handleNext = () => { | ||||
console.log("test 1") | |||||
const newActiveStep = | const newActiveStep = | ||||
isLastStep() && !allStepsCompleted() | isLastStep() && !allStepsCompleted() | ||||
? // It's the last step, but not all steps have been completed, | ? // It's the last step, but not all steps have been completed, | ||||
@@ -80,6 +77,7 @@ | |||||
: activeStep + 1; | : activeStep + 1; | ||||
setActiveStep(newActiveStep); | setActiveStep(newActiveStep); | ||||
console.log(newActiveStep) | console.log(newActiveStep) | ||||
}; | }; | ||||
const handleBack = () => { | const handleBack = () => { | ||||
@@ -140,11 +138,11 @@ | |||||
) : ( | ) : ( | ||||
<React.Fragment> | <React.Fragment> | ||||
<AuthWrapper> | <AuthWrapper> | ||||
<CustomFormWizard uploadStep={uploadStep} step={activeStep} /> | |||||
<CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} /> | |||||
{/* <CustomFormWizard step={activeStep} /> */} | {/* <CustomFormWizard step={activeStep} /> */} | ||||
</AuthWrapper> | </AuthWrapper> | ||||
<Stack direction="row" sx={{ pt: 2 }}> | <Stack direction="row" sx={{ pt: 2 }}> | ||||
{ activeStep === totalSteps() - 1 ? ( | |||||
{ activeStep === 2|| activeStep === 0? ( | |||||
<Button | <Button | ||||
color="inherit" | color="inherit" | ||||
disabled={true} | disabled={true} | ||||
@@ -178,7 +176,7 @@ | |||||
</Button> | </Button> | ||||
): | ): | ||||
( | ( | ||||
<Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||||
<Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||||
繼續 | 繼續 | ||||
</Button> | </Button> | ||||
) | ) | ||||
@@ -21,7 +21,7 @@ import Autocomplete from "@mui/material/Autocomplete"; | |||||
// third party | // third party | ||||
import { useFormik,FormikProvider } from 'formik'; | import { useFormik,FormikProvider } from 'formik'; | ||||
import * as Yup from 'yup'; | |||||
import * as yup from 'yup'; | |||||
// import axios from "axios"; | // import axios from "axios"; | ||||
// project import | // project import | ||||
@@ -49,7 +49,6 @@ const BusCustomFormWizard = (props) => { | |||||
const [showConfirmPassword, setshowConfirmPassword] = useState(false); | const [showConfirmPassword, setshowConfirmPassword] = useState(false); | ||||
const [fileList, setFileList] = useState([]); | const [fileList, setFileList] = useState([]); | ||||
const [fileListData, setFileListData] = useState([]); | const [fileListData, setFileListData] = useState([]); | ||||
const [uploadStep, setUploadStep] = useState(0); | |||||
const [checkUpload, setCheckUpload] = useState(false); | const [checkUpload, setCheckUpload] = useState(false); | ||||
const handleClickShowPassword = () => { | const handleClickShowPassword = () => { | ||||
@@ -72,33 +71,49 @@ const BusCustomFormWizard = (props) => { | |||||
const [selectedAddress5, setSelectedAddress5] = useState("香港"); | const [selectedAddress5, setSelectedAddress5] = useState("香港"); | ||||
const [termsAndConAccept, setTermsAndConAccept] = useState(false); | const [termsAndConAccept, setTermsAndConAccept] = useState(false); | ||||
const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false); | const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false); | ||||
const [isValid, setisValid] = useState(false); | |||||
const address4ComboList = | const address4ComboList = | ||||
["北區","長洲區","大埔區","大嶼山區","東區","觀塘區","黃大仙區","九龍城區","葵青區","南區","南丫島區", | ["北區","長洲區","大埔區","大嶼山區","東區","觀塘區","黃大仙區","九龍城區","葵青區","南區","南丫島區", | ||||
"坪洲區","荃灣區","沙田區","深水埗區","屯門區","灣仔區","西貢區","油尖旺區","元朗區","中西區"]; | "坪洲區","荃灣區","沙田區","深水埗區","屯門區","灣仔區","西貢區","油尖旺區","元朗區","中西區"]; | ||||
const address5ComboList = ["香港","內地","澳門"]; | const address5ComboList = ["香港","內地","澳門"]; | ||||
const termsAndCon = "Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n"+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
const termsAndCon = "此網址由香港特別行政區政府物流服務署製作及管理。本署會盡力確保網址上的資料無誤,\n" | |||||
+ "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址" | |||||
+ "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評" | |||||
+ "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港" | |||||
+ "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限" | |||||
+ "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" | |||||
+ "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" | |||||
+ "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" | |||||
useEffect(() => { | useEffect(() => { | ||||
changePassword(''); | changePassword(''); | ||||
}, []); | }, []); | ||||
const checkDataField = (data)=> { | const checkDataField = (data)=> { | ||||
if (data.username !=="", | |||||
data.password !=="", | |||||
data.enName !=="", | |||||
data.email !=="", | |||||
data.password !=="", | |||||
data.password !=="" | |||||
if (data.username !==""&& | |||||
data.password !==""&& | |||||
data.confirmPassword !==""&& | |||||
data.password == data.confirmPassword&& | |||||
data.enCompanyName !==""&& | |||||
data.enName !==""&& | |||||
data.address1 !==""&& | |||||
data.email !==""&& | |||||
data.emailConfirm !==""&& | |||||
data.phone !==""&& | |||||
data.phoneCountryCode !==""&& | |||||
termsAndConAccept == true&& | |||||
fileList.length!==0&& | |||||
handlePassword(data.password)&& | |||||
handleEmail(data.email)&& | |||||
handlePhone(data.phone) | |||||
) | ) | ||||
{ | { | ||||
return true | |||||
setisValid(true) | |||||
return isValid | |||||
}else{ | |||||
setisValid(false) | |||||
return isValid | |||||
} | } | ||||
}; | }; | ||||
@@ -133,9 +148,17 @@ const BusCustomFormWizard = (props) => { | |||||
setFileList(uploadFileList); | setFileList(uploadFileList); | ||||
}; | }; | ||||
useEffect(() => { | |||||
props.setUpdateValid(isValid) | |||||
}, [isValid]) | |||||
useEffect(() => { | |||||
checkDataField(values) | |||||
}, [selectedAddress4,selectedAddress5, | |||||
termsAndConAccept,termsAndConNotAccept,fileList]) | |||||
useEffect(() => { | useEffect(() => { | ||||
props.step ==2?_onSubmit():null; | props.step ==2?_onSubmit():null; | ||||
setUploadStep(props.step) | |||||
}, [props.step]) | }, [props.step]) | ||||
const {handleSubmit} = useForm({}) | const {handleSubmit} = useForm({}) | ||||
@@ -147,20 +170,14 @@ const BusCustomFormWizard = (props) => { | |||||
"addressLine1":"", | "addressLine1":"", | ||||
"addressLine2":"", | "addressLine2":"", | ||||
"addressLine3":"", | "addressLine3":"", | ||||
"district":"", | |||||
"country":"" | "country":"" | ||||
}; | }; | ||||
if (values.address5=='香港'){ | |||||
busUserAddress.addressLine1 = values.address1 | |||||
busUserAddress.addressLine2 = values.address2 | |||||
busUserAddress.addressLine3 = values.address3 | |||||
busUserAddress.country = values.address5 | |||||
}else{ | |||||
busUserAddress.addressLine1 = values.address1 | |||||
busUserAddress.addressLine2 = values.address2 | |||||
busUserAddress.addressLine3 = values.address4 | |||||
busUserAddress.country = values.address5 | |||||
} | |||||
busUserAddress.addressLine1 = values.address1 | |||||
busUserAddress.addressLine2 = values.address2 | |||||
busUserAddress.addressLine3 = values.address3 | |||||
busUserAddress.district = values.address4 | |||||
busUserAddress.country = values.address5 | |||||
const userFaxNo = { | const userFaxNo = { | ||||
"countryCode":values.faxCountryCode, | "countryCode":values.faxCountryCode, | ||||
@@ -178,7 +195,7 @@ const BusCustomFormWizard = (props) => { | |||||
tncFlag = false | tncFlag = false | ||||
} | } | ||||
if (checkDataField(values)){ | |||||
if (isValid){ | |||||
axios.post(`${apiPath}${POST_PUBLIC_USER_REGISTER}`, { | axios.post(`${apiPath}${POST_PUBLIC_USER_REGISTER}`, { | ||||
username: values.username, | username: values.username, | ||||
password: values.password, | password: values.password, | ||||
@@ -188,7 +205,7 @@ const BusCustomFormWizard = (props) => { | |||||
emailBus: values.email, | emailBus: values.email, | ||||
brNo:values.brNo, | brNo:values.brNo, | ||||
brExpiryDate:values.brExpiryDate, | brExpiryDate:values.brExpiryDate, | ||||
faxNo:userFaxNo, | |||||
userFaxNo:userFaxNo, | |||||
busUserContactTel:busUserContactTel, | busUserContactTel:busUserContactTel, | ||||
busUserAddress:busUserAddress, | busUserAddress:busUserAddress, | ||||
contactPerson: values.enName, | contactPerson: values.enName, | ||||
@@ -215,6 +232,43 @@ const BusCustomFormWizard = (props) => { | |||||
} | } | ||||
} | } | ||||
function handlePhone(phone) { | |||||
if (phone.length < 8) { | |||||
return false; | |||||
} else { | |||||
return true; | |||||
} | |||||
} | |||||
function handlePassword(password) { | |||||
let new_pass = password; | |||||
// regular expressions to validate password | |||||
var lowerCase = /[a-z]/g; | |||||
var upperCase = /[A-Z]/g; | |||||
var numbers = /[0-9]/g; | |||||
if (!new_pass.match(lowerCase)) { | |||||
return false; | |||||
} else if (!new_pass.match(upperCase)) { | |||||
return false; | |||||
} else if (!new_pass.match(numbers)) { | |||||
return false; | |||||
} else if (new_pass.length < 8) { | |||||
return false; | |||||
} else { | |||||
return true; | |||||
} | |||||
} | |||||
function handleEmail(email) { | |||||
var reg = /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/; | |||||
var result = reg.test(email); | |||||
if (result == false) { | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
const formik = useFormik({ | const formik = useFormik({ | ||||
initialValues:({ | initialValues:({ | ||||
username:'', | username:'', | ||||
@@ -235,34 +289,51 @@ const BusCustomFormWizard = (props) => { | |||||
brExpiryDate:'', | brExpiryDate:'', | ||||
brNo:'', | brNo:'', | ||||
}), | }), | ||||
validationSchema:Yup.object().shape({ | |||||
username: Yup.string().max(255).required('請輸入用戶名稱'), | |||||
password: Yup.string().max(255).required('請輸入密碼'), | |||||
confirmPassword: Yup.string().max(255).required('請確認密碼'), | |||||
enName: Yup.string().max(255).required('請輸入英文姓名'), | |||||
chName: Yup.string().max(255).required('請輸入中文姓名'), | |||||
address1: Yup.string().max(255).required('請輸入第一行地址'), | |||||
address2: Yup.string().max(255).required('請輸入第二行地址'), | |||||
address3: Yup.string().max(255).required('請輸入第三行地址'), | |||||
email: Yup.string().email('Must be a valid email').max(255).required('Email is required'), | |||||
idNo: Yup.string().max(255).required('請輸入證件號碼'), | |||||
checkDigit:Yup.string().max(1).required('請輸入證件號碼'), | |||||
idType: Yup.string().max(255).required('請輸入第三行地址')}) | |||||
validationSchema:yup.object().shape({ | |||||
username: yup.string().max(255).required('請輸入用戶名稱'), | |||||
password: yup.string().min(8,'請輸入最少8位密碼').required('請輸入密碼') | |||||
.matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') | |||||
.matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') | |||||
.matches(/^(?=.*[0-9])/, '請包括最少1個數字') | |||||
.matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), | |||||
confirmPassword: yup.string().min(8,'請最少輸入8位密碼').required('請確認密碼').oneOf([yup.ref('password'), null], '請輸入相同密碼'), | |||||
enName: yup.string().max(255).required('請輸入英文姓名'), | |||||
enCompanyName: yup.string().max(255).required('請輸入英文名稱'), | |||||
chName: yup.string().max(255).required('請輸入中文姓名'), | |||||
address1: yup.string().max(255).required('請輸入第一行地址'), | |||||
address2: yup.string().max(255).required('請輸入第二行地址'), | |||||
address3: yup.string().max(255).required('請輸入第三行地址'), | |||||
email: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵'), | |||||
emailConfirm: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵').oneOf([yup.ref('email'), null], '請輸入相同電郵'), | |||||
phoneCountryCode: yup.string().min(3,'請輸入3位數字').required('請輸入國際區號'), | |||||
faxCountryCode: yup.string().min(3,'請輸入3位數字'), | |||||
phone: yup.string().min(8,'請輸入8位數字').required('請輸入聯絡電話'), | |||||
fax: yup.string().min(8,'請輸入8位數字'), | |||||
brExpiryDate: yup.string().min(8,'請輸入商業登記證有效日期'), | |||||
brNo: yup.string().min(8,'請輸入商業登記證號碼'), | |||||
}) | |||||
}); | }); | ||||
const handleReset = (resetForm) => { | |||||
resetForm(); | |||||
setSelectedAddress4("") | |||||
}; | |||||
const { values } = formik | const { values } = formik | ||||
useEffect(() => { | useEffect(() => { | ||||
checkDataField(values) | |||||
}, [values]) | }, [values]) | ||||
return ( | return ( | ||||
<FormikProvider value={formik}> | <FormikProvider value={formik}> | ||||
<form onSubmit={handleSubmit(_onSubmit)}> | <form onSubmit={handleSubmit(_onSubmit)}> | ||||
{/* Input Form */} | {/* Input Form */} | ||||
<FormGroup id={"inputForm"} sx={{ display: uploadStep === 0 ? "" : "none" }}> | |||||
<FormGroup id={"inputForm"} sx={{ display: props.step === 0 ? "" : "none" }}> | |||||
<Grid container spacing={3}> | <Grid container spacing={3}> | ||||
<Grid item xs={12} md={12}> | <Grid item xs={12} md={12}> | ||||
<Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | ||||
<Button variant="outlined" type="reset" onClick={handleReset.bind(null, formik.resetForm)} sx={{ fontSize: 16,height:'30px'}}>重置</Button> | |||||
<div style={{borderBottom: "3px solid #1A4399", width:"100%", margin_right: "15px"}}> | <div style={{borderBottom: "3px solid #1A4399", width:"100%", margin_right: "15px"}}> | ||||
<Typography display="inline" variant="h3" sx={{ color: '#1A4399'}}>成為新的機構/公司用戶</Typography> | <Typography display="inline" variant="h3" sx={{ color: '#1A4399'}}>成為新的機構/公司用戶</Typography> | ||||
</div> | </div> | ||||
@@ -289,6 +360,7 @@ const BusCustomFormWizard = (props) => { | |||||
placeholder="用戶登入名稱" | placeholder="用戶登入名稱" | ||||
fullWidth | fullWidth | ||||
error={Boolean(formik.touched.username && formik.errors.username)} | error={Boolean(formik.touched.username && formik.errors.username)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -377,9 +449,10 @@ const BusCustomFormWizard = (props) => { | |||||
type={showConfirmPassword ? 'text' : 'password'} | type={showConfirmPassword ? 'text' : 'password'} | ||||
value={formik.values.confirmPassword} | value={formik.values.confirmPassword} | ||||
name="confirmPassword" | name="confirmPassword" | ||||
onBlur={formik.handleBlur} | |||||
onChange={(e) => { | onChange={(e) => { | ||||
formik.handleChange(e); | formik.handleChange(e); | ||||
changePassword(e.target.value); | |||||
// changePassword(e.target.value); | |||||
}} | }} | ||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
@@ -437,6 +510,7 @@ const BusCustomFormWizard = (props) => { | |||||
placeholder="與與商業登記證相同如有" | placeholder="與與商業登記證相同如有" | ||||
fullWidth | fullWidth | ||||
error={Boolean(formik.touched.enCompanyName && formik.errors.enCompanyName)} | error={Boolean(formik.touched.enCompanyName && formik.errors.enCompanyName)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -546,6 +620,7 @@ const BusCustomFormWizard = (props) => { | |||||
name="address1" | name="address1" | ||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="第一行" | placeholder="第一行" | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -650,6 +725,7 @@ const BusCustomFormWizard = (props) => { | |||||
placeholder="與你的身份證明文件相同" | placeholder="與你的身份證明文件相同" | ||||
fullWidth | fullWidth | ||||
error={Boolean(formik.touched.enName && formik.errors.enName)} | error={Boolean(formik.touched.enName && formik.errors.enName)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -681,6 +757,7 @@ const BusCustomFormWizard = (props) => { | |||||
name="email" | name="email" | ||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="電郵" | placeholder="電郵" | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -711,6 +788,7 @@ const BusCustomFormWizard = (props) => { | |||||
// onBlur={formik.handleBlur} | // onBlur={formik.handleBlur} | ||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="確認電郵" | placeholder="確認電郵" | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -747,6 +825,7 @@ const BusCustomFormWizard = (props) => { | |||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="eg:852" | placeholder="eg:852" | ||||
error={Boolean(formik.touched.phone && formik.errors.phone)} | error={Boolean(formik.touched.phone && formik.errors.phone)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
maxLength: 3, | maxLength: 3, | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
@@ -762,7 +841,7 @@ const BusCustomFormWizard = (props) => { | |||||
type="phone" | type="phone" | ||||
value={formik.values.phone} | value={formik.values.phone} | ||||
name="phone" | name="phone" | ||||
// onBlur={formik.handleBlur} | |||||
onBlur={formik.handleBlur} | |||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="聯絡電話" | placeholder="聯絡電話" | ||||
error={Boolean(formik.touched.phone && formik.errors.phone)} | error={Boolean(formik.touched.phone && formik.errors.phone)} | ||||
@@ -776,12 +855,12 @@ const BusCustomFormWizard = (props) => { | |||||
}} | }} | ||||
sx={{width:'75%'}} | sx={{width:'75%'}} | ||||
/> | /> | ||||
{formik.touched.phone && formik.errors.phone && ( | |||||
<FormHelperText error id="helper-text-phone-signup"> | |||||
{formik.errors.phone} | |||||
</FormHelperText> | |||||
)} | |||||
</Stack> | </Stack> | ||||
{formik.touched.phone && formik.errors.phone && ( | |||||
<FormHelperText error id="helper-text-phone-signup"> | |||||
{formik.errors.phone} | |||||
</FormHelperText> | |||||
)} | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
@@ -925,7 +1004,7 @@ const BusCustomFormWizard = (props) => { | |||||
</Grid> | </Grid> | ||||
</FormGroup> | </FormGroup> | ||||
{/* Preview Form */} | {/* Preview Form */} | ||||
<FormGroup id={"previewForm"} sx={{ display: uploadStep === 1 ? "" : "none"}}> | |||||
<FormGroup id={"previewForm"} sx={{ display: props.step === 1 ? "" : "none"}}> | |||||
<Grid container spacing={2}> | <Grid container spacing={2}> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||
<Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | ||||
@@ -984,7 +1063,7 @@ const BusCustomFormWizard = (props) => { | |||||
<Grid item xs={12} md={12} > | <Grid item xs={12} md={12} > | ||||
<Stack spacing={1}> | <Stack spacing={1}> | ||||
<Typography> | <Typography> | ||||
商業登記證: | |||||
商業登記證 | |||||
</Typography> | </Typography> | ||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
@@ -1019,17 +1098,23 @@ const BusCustomFormWizard = (props) => { | |||||
<Typography id="preview-address1-signup"> | <Typography id="preview-address1-signup"> | ||||
{formik.values.address1} | {formik.values.address1} | ||||
</Typography> | </Typography> | ||||
<Typography id="preview-address2-signup"> | |||||
{formik.values.address2} | |||||
</Typography> | |||||
{formik.values.address2!=null? | |||||
<Typography id="preview-address2-signup"> | |||||
{formik.values.address2} | |||||
</Typography> | |||||
:null} | |||||
{formik.values.address3!=null? | |||||
<Typography id="preview-address3-signup"> | <Typography id="preview-address3-signup"> | ||||
{formik.values.address3} | {formik.values.address3} | ||||
</Typography> | </Typography> | ||||
<Typography id="preview-address4-signup"> | |||||
{formik.values.address4} | |||||
</Typography> | |||||
:null} | |||||
{selectedAddress5==("香港")? | |||||
<Typography id="preview-address4-signup"> | |||||
區域 (只適用於香港): {selectedAddress4} | |||||
</Typography> | |||||
:null} | |||||
<Typography id="preview-address5-signup"> | <Typography id="preview-address5-signup"> | ||||
{formik.values.address5} | |||||
國家/地區: {selectedAddress5} | |||||
</Typography> | </Typography> | ||||
</Stack> | </Stack> | ||||
</Stack> | </Stack> | ||||
@@ -1085,13 +1170,12 @@ const BusCustomFormWizard = (props) => { | |||||
</Grid> | </Grid> | ||||
</FormGroup> | </FormGroup> | ||||
{/* Submit page */} | {/* Submit page */} | ||||
<FormGroup id={"submitForm"} sx={{ display: uploadStep === 2 ? "" : "none"}}> | |||||
<FormGroup id={"submitForm"} sx={{ display: props.step === 2 ? "" : "none"}}> | |||||
<Grid container spacing={3}> | <Grid container spacing={3}> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||
{checkUpload? | {checkUpload? | ||||
// SUCCESS page | // SUCCESS page | ||||
<Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | ||||
{/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */} | |||||
<CheckCircleOutlineIcon color="success" sx={{width:"200px",height:"200px"}}/> | <CheckCircleOutlineIcon color="success" sx={{width:"200px",height:"200px"}}/> | ||||
<Typography display="inline" variant="h4">完成申請,請登入帳戶</Typography> | <Typography display="inline" variant="h4">完成申請,請登入帳戶</Typography> | ||||
<Button variant="outlined" component={Link} to="/login" sx={{ fontSize: 20,height:'60px'}}>返回登入頁面</Button> | <Button variant="outlined" component={Link} to="/login" sx={{ fontSize: 20,height:'60px'}}>返回登入頁面</Button> | ||||
@@ -48,7 +48,6 @@ const CustomFormWizard = (props) => { | |||||
const [showConfirmPassword, setshowConfirmPassword] = useState(false); | const [showConfirmPassword, setshowConfirmPassword] = useState(false); | ||||
const [fileList, setFileList] = useState([]); | const [fileList, setFileList] = useState([]); | ||||
const [fileListData, setFileListData] = useState([]); | const [fileListData, setFileListData] = useState([]); | ||||
const [uploadStep, setUploadStep] = useState(0); | |||||
const [checkUpload, setCheckUpload] = useState(false); | const [checkUpload, setCheckUpload] = useState(false); | ||||
const handleClickShowPassword = () => { | const handleClickShowPassword = () => { | ||||
@@ -72,39 +71,56 @@ const CustomFormWizard = (props) => { | |||||
const [selectedAddress5, setSelectedAddress5] = useState("香港"); | const [selectedAddress5, setSelectedAddress5] = useState("香港"); | ||||
const [termsAndConAccept, setTermsAndConAccept] = useState(false); | const [termsAndConAccept, setTermsAndConAccept] = useState(false); | ||||
const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false); | const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false); | ||||
const [isValid, setisValid] = useState(false); | |||||
const idDocTypeComboList = ["passport","HKID","CNID","BR","otherCert"]; | const idDocTypeComboList = ["passport","HKID","CNID","BR","otherCert"]; | ||||
const address4ComboList = | const address4ComboList = | ||||
["北區","長洲區","大埔區","大嶼山區","東區","觀塘區","黃大仙區","九龍城區","葵青區","南區","南丫島區", | ["北區","長洲區","大埔區","大嶼山區","東區","觀塘區","黃大仙區","九龍城區","葵青區","南區","南丫島區", | ||||
"坪洲區","荃灣區","沙田區","深水埗區","屯門區","灣仔區","西貢區","油尖旺區","元朗區","中西區"]; | "坪洲區","荃灣區","沙田區","深水埗區","屯門區","灣仔區","西貢區","油尖旺區","元朗區","中西區"]; | ||||
const address5ComboList = ["香港","內地","澳門"]; | const address5ComboList = ["香港","內地","澳門"]; | ||||
const termsAndCon = "Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n"+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
+"Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy \n" | |||||
const termsAndCon = "此網址由香港特別行政區政府物流服務署製作及管理。本署會盡力確保網址上的資料無誤,\n" | |||||
+ "但有絕對酌情權隨時刪除、暫停登載或編輯各項資料而無須給予任何理由。\n由於任何與網址" | |||||
+ "內資料有關的理由或原因,而導致出現申索、損失或損害,本署概不負責。\n使用者須自行評" | |||||
+ "估本網址所載或與本網址有關連的各項資料,並應在根據該等資料行事前,參照印行的香港" | |||||
+ "特別行政區憲報以核實該等資料,以及徵詢獨立意見。\n版權公告本網頁的內容,包括但不限" | |||||
+ "於所有文本、平面圖像、圖畫、圖片、照片以及數據或其他資料的匯編,均受版權保障。\n香" | |||||
+ "港特別行政區政府是本網頁內所有版權作品的擁有人,除非預先得到政府物流服務署的書面" | |||||
+ "授權,否則嚴禁複製、改編、分發、發布或向公眾提供該等版權作品。" | |||||
useEffect(() => { | useEffect(() => { | ||||
changePassword(''); | changePassword(''); | ||||
}, []); | }, []); | ||||
const checkDataField = (data)=> { | const checkDataField = (data)=> { | ||||
if (data.username !=="", | |||||
data.password !=="", | |||||
data.enName !=="", | |||||
data.email !=="", | |||||
data.password !=="", | |||||
data.password !=="" | |||||
if (data.username !==""&& | |||||
data.password !==""&& | |||||
data.confirmPassword !==""&& | |||||
data.password == data.confirmPassword&& | |||||
selectedIdDocType !==""&& | |||||
data.idNo !==""&& | |||||
data.enName !==""&& | |||||
data.address1 !==""&& | |||||
data.email !==""&& | |||||
data.emailConfirm !==""&& | |||||
data.phone !==""&& | |||||
data.phoneCountryCode !==""&& | |||||
termsAndConAccept == true&& | |||||
fileList.length!==0&& | |||||
handlePassword(data.password)&& | |||||
handleEmail(data.email)&& | |||||
handleIdNo(data.idNo,selectedIdDocType)&& | |||||
handlePhone(data.phone) | |||||
) | ) | ||||
{ | { | ||||
return true | |||||
setisValid(true) | |||||
return isValid | |||||
}else{ | |||||
setisValid(false) | |||||
return isValid | |||||
} | } | ||||
}; | }; | ||||
const handleCheckBoxChange = (event) => { | const handleCheckBoxChange = (event) => { | ||||
console.log (event.target) | |||||
if(event.target.name == 'termsAndConAccept'){ | if(event.target.name == 'termsAndConAccept'){ | ||||
setTermsAndConAccept(event.target.checked) | setTermsAndConAccept(event.target.checked) | ||||
setTermsAndConNotAccept(!event.target.checked) | setTermsAndConNotAccept(!event.target.checked) | ||||
@@ -134,9 +150,17 @@ const CustomFormWizard = (props) => { | |||||
setFileList(uploadFileList); | setFileList(uploadFileList); | ||||
}; | }; | ||||
useEffect(() => { | |||||
props.setUpdateValid(isValid) | |||||
}, [isValid]) | |||||
useEffect(() => { | |||||
checkDataField(values) | |||||
}, [selectedIdDocType,selectedAddress4,selectedAddress5, | |||||
termsAndConAccept,termsAndConNotAccept,fileList]) | |||||
useEffect(() => { | useEffect(() => { | ||||
props.step ==2?_onSubmit():null; | props.step ==2?_onSubmit():null; | ||||
setUploadStep(props.step) | |||||
}, [props.step]) | }, [props.step]) | ||||
const {handleSubmit} = useForm({}) | const {handleSubmit} = useForm({}) | ||||
@@ -144,26 +168,19 @@ const CustomFormWizard = (props) => { | |||||
values.idDocType = selectedIdDocType | values.idDocType = selectedIdDocType | ||||
values.address4 = selectedAddress4 | values.address4 = selectedAddress4 | ||||
values.address5 = selectedAddress5 | values.address5 = selectedAddress5 | ||||
console.log(values) | |||||
const userAddress = { | const userAddress = { | ||||
"addressLine1":"", | "addressLine1":"", | ||||
"addressLine2":"", | "addressLine2":"", | ||||
"addressLine3":"", | "addressLine3":"", | ||||
"district":"", | |||||
"country":"" | "country":"" | ||||
}; | }; | ||||
if (values.address5=='香港'){ | |||||
userAddress.addressLine1 = values.address1 | |||||
userAddress.addressLine2 = values.address2 | |||||
userAddress.addressLine3 = values.address3 | |||||
userAddress.country = values.address5 | |||||
}else{ | |||||
userAddress.addressLine1 = values.address1 | |||||
userAddress.addressLine2 = values.address2 | |||||
userAddress.addressLine3 = values.address4 | |||||
userAddress.country = values.address5 | |||||
} | |||||
userAddress.addressLine1 = values.address1 | |||||
userAddress.addressLine2 = values.address2 | |||||
userAddress.addressLine3 = values.address3 | |||||
userAddress.district = values.address4 | |||||
userAddress.country = values.address5 | |||||
const userFaxNo = { | const userFaxNo = { | ||||
"countryCode":values.faxCountryCode, | "countryCode":values.faxCountryCode, | ||||
"faxNumber":values.fax, | "faxNumber":values.fax, | ||||
@@ -179,8 +196,8 @@ const CustomFormWizard = (props) => { | |||||
if (termsAndConNotAccept){ | if (termsAndConNotAccept){ | ||||
tncFlag = false | tncFlag = false | ||||
} | } | ||||
if (checkDataField(values)){ | |||||
if (isValid){ | |||||
axios.post(`${apiPath}${POST_PUBLIC_USER_REGISTER}`, { | axios.post(`${apiPath}${POST_PUBLIC_USER_REGISTER}`, { | ||||
username: values.username, | username: values.username, | ||||
password: values.password, | password: values.password, | ||||
@@ -217,12 +234,62 @@ const CustomFormWizard = (props) => { | |||||
} | } | ||||
} | } | ||||
function handlePhone(phone) { | |||||
if (phone.length < 8) { | |||||
return false; | |||||
} else { | |||||
return true; | |||||
} | |||||
} | |||||
function handleIdNo(idNo,selectedIdDocType) { | |||||
var upperCase = /[A-Z]/g; | |||||
if (!idNo.match(upperCase)&&selectedIdDocType=="HKID") { | |||||
return false; | |||||
} | |||||
else if (idNo.length < 7) { | |||||
return false; | |||||
} else { | |||||
return true; | |||||
} | |||||
} | |||||
function handlePassword(password) { | |||||
let new_pass = password; | |||||
// regular expressions to validate password | |||||
var lowerCase = /[a-z]/g; | |||||
var upperCase = /[A-Z]/g; | |||||
var numbers = /[0-9]/g; | |||||
if (!new_pass.match(lowerCase)) { | |||||
return false; | |||||
} else if (!new_pass.match(upperCase)) { | |||||
return false; | |||||
} else if (!new_pass.match(numbers)) { | |||||
return false; | |||||
} else if (new_pass.length < 8) { | |||||
return false; | |||||
} else { | |||||
return true; | |||||
} | |||||
} | |||||
function handleEmail(email) { | |||||
var reg = /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/; | |||||
var result = reg.test(email); | |||||
if (result == false) { | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
const formik = useFormik({ | const formik = useFormik({ | ||||
initialValues:({ | initialValues:({ | ||||
username:'', | username:'', | ||||
enName: '', | enName: '', | ||||
chName: '', | chName: '', | ||||
email: '', | email: '', | ||||
emailConfirm: '', | |||||
address1: '', | address1: '', | ||||
address2: '', | address2: '', | ||||
address3: '', | address3: '', | ||||
@@ -235,56 +302,58 @@ const CustomFormWizard = (props) => { | |||||
submit: null, | submit: null, | ||||
fax:'', | fax:'', | ||||
faxCountryCode:'852', | faxCountryCode:'852', | ||||
idDocType:selectedIdDocType | |||||
}), | }), | ||||
validationSchema:yup.object().shape({ | validationSchema:yup.object().shape({ | ||||
username: yup.string().max(255).required('請輸入用戶名稱'), | username: yup.string().max(255).required('請輸入用戶名稱'), | ||||
password: yup.string().max(255).required('請輸入密碼'), | |||||
confirmPassword: yup.string().max(255).required('請確認密碼'), | |||||
password: yup.string().min(8,'請輸入最少8位密碼').required('請輸入密碼') | |||||
.matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') | |||||
.matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') | |||||
.matches(/^(?=.*[0-9])/, '請包括最少1個數字') | |||||
.matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), | |||||
confirmPassword: yup.string().min(8,'請最少輸入8位密碼').required('請確認密碼').oneOf([yup.ref('password'), null], '請輸入相同密碼'), | |||||
enName: yup.string().max(255).required('請輸入英文姓名'), | enName: yup.string().max(255).required('請輸入英文姓名'), | ||||
chName: yup.string().max(255).required('請輸入中文姓名'), | chName: yup.string().max(255).required('請輸入中文姓名'), | ||||
address1: yup.string().max(255).required('請輸入第一行地址'), | address1: yup.string().max(255).required('請輸入第一行地址'), | ||||
address2: yup.string().max(255).required('請輸入第二行地址'), | address2: yup.string().max(255).required('請輸入第二行地址'), | ||||
address3: yup.string().max(255).required('請輸入第三行地址'), | address3: yup.string().max(255).required('請輸入第三行地址'), | ||||
email: yup.string().email('Must be a valid email').max(255).required('Email is required'), | |||||
idNo: yup.string().max(255).required('請輸入證件號碼'), | |||||
checkDigit:yup.string().max(1).required('請輸入證件號碼'), | |||||
idType: yup.string().max(255).required('請輸入第三行地址')}), | |||||
email: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵'), | |||||
emailConfirm: yup.string().email('請輸入電郵格式').max(255).required('請輸入電郵').oneOf([yup.ref('email'), null], '請輸入相同電郵'), | |||||
idNo: yup.string().min(7,"請輸入證件號碼").required('請輸入證件號碼'), | |||||
checkDigit:yup.string().max(1).required('請輸入括號內的數字或字母'), | |||||
idDocType: yup.string().max(255).required('請輸入證件類別'), | |||||
phoneCountryCode: yup.string().min(3,'請輸入3位數字').required('請輸入國際區號'), | |||||
faxCountryCode: yup.string().min(3,'請輸入3位數字'), | |||||
phone: yup.string().min(8,'請輸入8位數字').required('請輸入聯絡電話'), | |||||
fax: yup.string().min(8,'請輸入8位數字'), | |||||
}), | |||||
}); | }); | ||||
// const validationSchema =yup.object().shape({ | |||||
// username: yup.string().max(255).required('請輸入用戶名稱'), | |||||
// password: yup.string().max(255).required('請輸入密碼'), | |||||
// confirmPassword: yup.string().max(255).required('請確認密碼'), | |||||
// enName: yup.string().max(255).required('請輸入英文姓名'), | |||||
// chName: yup.string().max(255).required('請輸入中文姓名'), | |||||
// address1: yup.string().max(255).required('請輸入第一行地址'), | |||||
// address2: yup.string().max(255).required('請輸入第二行地址'), | |||||
// address3: yup.string().max(255).required('請輸入第三行地址'), | |||||
// email: yup.string().email('Must be a valid email').max(255).required('Email is required'), | |||||
// idNo: yup.string().max(255).required('請輸入證件號碼'), | |||||
// checkDigit:yup.string().max(1).required('請輸入證件號碼'), | |||||
// idType: yup.string().max(255).required('請輸入第三行地址')}); | |||||
const handleReset = (resetForm) => { | |||||
resetForm(); | |||||
setSelectedAddress4("") | |||||
setSelectedIdDocType("") | |||||
}; | |||||
const { values } = formik | const { values } = formik | ||||
useEffect(() => { | useEffect(() => { | ||||
checkDataField(values) | |||||
}, [values]) | }, [values]) | ||||
return ( | return ( | ||||
<FormikProvider value={formik}> | <FormikProvider value={formik}> | ||||
<form onSubmit={handleSubmit(_onSubmit)}> | <form onSubmit={handleSubmit(_onSubmit)}> | ||||
{/* Input Form */} | {/* Input Form */} | ||||
<FormGroup id={"inputForm"} sx={{ display: uploadStep === 0 ? "" : "none" }}> | |||||
<FormGroup id={"inputForm"} sx={{ display: props.step === 0 ? "" : "none" }}> | |||||
<Grid container spacing={3}> | <Grid container spacing={3}> | ||||
<Grid item xs={12} md={12}> | <Grid item xs={12} md={12}> | ||||
<Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | ||||
<Button variant="outlined" type="reset" onClick={handleReset.bind(null, formik.resetForm)} sx={{ fontSize: 16,height:'30px'}}>重置</Button> | |||||
<div style={{borderBottom: "3px solid #1A4399", width:"100%", margin_right: "15px"}}> | <div style={{borderBottom: "3px solid #1A4399", width:"100%", margin_right: "15px"}}> | ||||
<Typography display="inline" variant="h3" sx={{ color: '#1A4399'}}>成為新的個人用戶</Typography> | |||||
<Typography display="inline" variant="h3" sx={{ color: '#1A4399'}}>成為新的個人用戶</Typography> | |||||
</div> | </div> | ||||
<Typography mt={0.25} variant="h6" sx={{ fontSize: 12,color: '#f10000'}}>註有*的項目必須輸入資料</Typography> | <Typography mt={0.25} variant="h6" sx={{ fontSize: 12,color: '#f10000'}}>註有*的項目必須輸入資料</Typography> | ||||
<Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary'}}>你的登入資料</Typography> | <Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary'}}>你的登入資料</Typography> | ||||
{/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||||
Already have an account? | |||||
</Typography> */} | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={12} md={12}> | <Grid item xs={12} md={12}> | ||||
@@ -370,16 +439,16 @@ const CustomFormWizard = (props) => { | |||||
)} | )} | ||||
</Stack> | </Stack> | ||||
<FormControl fullWidth sx={{ mt: 2 }}> | <FormControl fullWidth sx={{ mt: 2 }}> | ||||
<Grid container spacing={2} alignItems="center"> | |||||
<Grid item> | |||||
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} /> | |||||
</Grid> | |||||
<Grid item> | |||||
<Typography variant="subtitle1" fontSize="0.75rem"> | |||||
{level?.label} | |||||
</Typography> | |||||
<Grid container spacing={2} alignItems="center"> | |||||
<Grid item> | |||||
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} /> | |||||
</Grid> | |||||
<Grid item> | |||||
<Typography variant="subtitle1" fontSize="0.75rem"> | |||||
{level?.label} | |||||
</Typography> | |||||
</Grid> | |||||
</Grid> | </Grid> | ||||
</Grid> | |||||
</FormControl> | </FormControl> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={12} md={6} > | <Grid item xs={12} md={6} > | ||||
@@ -395,7 +464,7 @@ const CustomFormWizard = (props) => { | |||||
onBlur={formik.handleBlur} | onBlur={formik.handleBlur} | ||||
onChange={(e) => { | onChange={(e) => { | ||||
formik.handleChange(e); | formik.handleChange(e); | ||||
changePassword(e.target.value); | |||||
// changePassword(e.target.value); | |||||
}} | }} | ||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
@@ -457,17 +526,22 @@ const CustomFormWizard = (props) => { | |||||
<Stack spacing={1} sx={{mr:{md:1},mb:{xs:0.5}}}> | <Stack spacing={1} sx={{mr:{md:1},mb:{xs:0.5}}}> | ||||
<Autocomplete | <Autocomplete | ||||
disablePortal | disablePortal | ||||
id="idDocType-combo" | |||||
value={selectedIdDocType === null ? null : selectedIdDocType} | |||||
id="idDocType" | |||||
value={selectedIdDocType} | |||||
options={idDocTypeComboList} | options={idDocTypeComboList} | ||||
onBlur={formik.handleBlur} | |||||
onChange={(event, newValue) => { | onChange={(event, newValue) => { | ||||
if (newValue !== null){ | |||||
setSelectedIdDocType(newValue); | |||||
} | |||||
setSelectedIdDocType(newValue); | |||||
}} | }} | ||||
sx={{"& .MuiInputBase-root": { height: "41px" },"#idDocType-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | |||||
sx={{"& .MuiInputBase-root": { height: "41px" },"#idDocType":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | |||||
renderInput={(params) => <TextField {...params} placeholder="證件類別"/>} | renderInput={(params) => <TextField {...params} placeholder="證件類別"/>} | ||||
/> | /> | ||||
{formik.touched.idDocType && ( | |||||
selectedIdDocType===null? | |||||
<FormHelperText error id="helper-text-idDocType-signup"> | |||||
請輸入證件類別 | |||||
</FormHelperText>:'' | |||||
)} | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
{selectedIdDocType =="HKID"? | {selectedIdDocType =="HKID"? | ||||
@@ -495,10 +569,15 @@ const CustomFormWizard = (props) => { | |||||
}} | }} | ||||
/> | /> | ||||
{formik.touched.idNo && formik.errors.idNo && ( | {formik.touched.idNo && formik.errors.idNo && ( | ||||
<FormHelperText error id="helper-text-enName-signup"> | |||||
<FormHelperText error id="helper-text-idNo-signup"> | |||||
{formik.errors.idNo} | {formik.errors.idNo} | ||||
</FormHelperText> | </FormHelperText> | ||||
)} | )} | ||||
{formik.touched.checkDigit && formik.errors.checkDigit && ( | |||||
<FormHelperText error id="helper-text-checkDigit-signup"> | |||||
{formik.errors.checkDigit} | |||||
</FormHelperText> | |||||
)} | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={2} md={1}> | <Grid item xs={2} md={1}> | ||||
@@ -521,12 +600,8 @@ const CustomFormWizard = (props) => { | |||||
}} | }} | ||||
fullWidth | fullWidth | ||||
error={Boolean(formik.touched.checkDigit && formik.errors.checkDigit)} | error={Boolean(formik.touched.checkDigit && formik.errors.checkDigit)} | ||||
onBlur={formik.handleBlur} | |||||
/> | /> | ||||
{formik.touched.checkDigit && formik.errors.checkDigit && ( | |||||
<FormHelperText error id="helper-text-enName-signup"> | |||||
{formik.errors.checkDigit} | |||||
</FormHelperText> | |||||
)} | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
</>: | </>: | ||||
@@ -542,6 +617,7 @@ const CustomFormWizard = (props) => { | |||||
fullWidth | fullWidth | ||||
sx={{mr:1}} | sx={{mr:1}} | ||||
error={Boolean(formik.touched.idNo && formik.errors.idNo)} | error={Boolean(formik.touched.idNo && formik.errors.idNo)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -551,7 +627,7 @@ const CustomFormWizard = (props) => { | |||||
}} | }} | ||||
/> | /> | ||||
{formik.touched.idNo && formik.errors.idNo && ( | {formik.touched.idNo && formik.errors.idNo && ( | ||||
<FormHelperText error id="helper-text-enName-signup"> | |||||
<FormHelperText error id="helper-text-idNo-signup"> | |||||
{formik.errors.idNo} | {formik.errors.idNo} | ||||
</FormHelperText> | </FormHelperText> | ||||
)} | )} | ||||
@@ -574,6 +650,7 @@ const CustomFormWizard = (props) => { | |||||
placeholder="與你的身份證明文件相同" | placeholder="與你的身份證明文件相同" | ||||
fullWidth | fullWidth | ||||
error={Boolean(formik.touched.enName && formik.errors.enName)} | error={Boolean(formik.touched.enName && formik.errors.enName)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -629,6 +706,7 @@ const CustomFormWizard = (props) => { | |||||
name="address1" | name="address1" | ||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="第一行" | placeholder="第一行" | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -672,12 +750,10 @@ const CustomFormWizard = (props) => { | |||||
<Autocomplete | <Autocomplete | ||||
disablePortal | disablePortal | ||||
id="address4-combo" | id="address4-combo" | ||||
value={selectedAddress4 === null ? null : selectedAddress4} | |||||
value={selectedAddress4} | |||||
options={address4ComboList} | options={address4ComboList} | ||||
onChange={(event, newValue) => { | onChange={(event, newValue) => { | ||||
if (newValue !== null){ | |||||
setSelectedAddress4(newValue); | |||||
} | |||||
setSelectedAddress4(newValue); | |||||
}} | }} | ||||
sx={{"& .MuiInputBase-root": { height: "41px" },"#address4-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | sx={{"& .MuiInputBase-root": { height: "41px" },"#address4-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | ||||
@@ -689,9 +765,7 @@ const CustomFormWizard = (props) => { | |||||
value={selectedAddress5} | value={selectedAddress5} | ||||
options={address5ComboList} | options={address5ComboList} | ||||
onChange={(event, newValue) => { | onChange={(event, newValue) => { | ||||
if (newValue !== null){ | |||||
setSelectedAddress5(newValue); | |||||
} | |||||
setSelectedAddress5(newValue); | |||||
}} | }} | ||||
sx={{"& .MuiInputBase-root": { height: "41px" },"#address5-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | sx={{"& .MuiInputBase-root": { height: "41px" },"#address5-combo":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | ||||
@@ -735,6 +809,7 @@ const CustomFormWizard = (props) => { | |||||
name="email" | name="email" | ||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="電郵" | placeholder="電郵" | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -765,6 +840,7 @@ const CustomFormWizard = (props) => { | |||||
// onBlur={formik.handleBlur} | // onBlur={formik.handleBlur} | ||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="確認電郵" | placeholder="確認電郵" | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
if (e.key === 'Enter') { | if (e.key === 'Enter') { | ||||
@@ -801,6 +877,7 @@ const CustomFormWizard = (props) => { | |||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="eg:852" | placeholder="eg:852" | ||||
error={Boolean(formik.touched.phone && formik.errors.phone)} | error={Boolean(formik.touched.phone && formik.errors.phone)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
maxLength: 3, | maxLength: 3, | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
@@ -820,6 +897,7 @@ const CustomFormWizard = (props) => { | |||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="聯絡電話" | placeholder="聯絡電話" | ||||
error={Boolean(formik.touched.phone && formik.errors.phone)} | error={Boolean(formik.touched.phone && formik.errors.phone)} | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
maxLength: 8, | maxLength: 8, | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
@@ -830,12 +908,12 @@ const CustomFormWizard = (props) => { | |||||
}} | }} | ||||
sx={{width:'75%'}} | sx={{width:'75%'}} | ||||
/> | /> | ||||
{formik.touched.phone && formik.errors.phone && ( | |||||
<FormHelperText error id="helper-text-phone-signup"> | |||||
{formik.errors.phone} | |||||
</FormHelperText> | |||||
)} | |||||
</Stack> | </Stack> | ||||
{formik.touched.phone && formik.errors.phone && ( | |||||
<FormHelperText error id="helper-text-phone-signup"> | |||||
{formik.errors.phone} | |||||
</FormHelperText> | |||||
)} | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
@@ -852,9 +930,9 @@ const CustomFormWizard = (props) => { | |||||
type="faxCountryCode" | type="faxCountryCode" | ||||
value={formik.values.faxCountryCode} | value={formik.values.faxCountryCode} | ||||
name="faxCountryCode" | name="faxCountryCode" | ||||
// onBlur={formik.handleBlur} | |||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="eg:852" | placeholder="eg:852" | ||||
onBlur={formik.handleBlur} | |||||
inputProps={{ | inputProps={{ | ||||
maxLength: 3, | maxLength: 3, | ||||
onKeyDown: (e) => { | onKeyDown: (e) => { | ||||
@@ -870,7 +948,7 @@ const CustomFormWizard = (props) => { | |||||
type="fax" | type="fax" | ||||
value={formik.values.fax} | value={formik.values.fax} | ||||
name="fax" | name="fax" | ||||
// onBlur={formik.handleBlur} | |||||
onBlur={formik.handleBlur} | |||||
onChange={formik.handleChange} | onChange={formik.handleChange} | ||||
placeholder="傳真號碼" | placeholder="傳真號碼" | ||||
inputProps={{ | inputProps={{ | ||||
@@ -977,7 +1055,7 @@ const CustomFormWizard = (props) => { | |||||
</Grid> | </Grid> | ||||
</FormGroup> | </FormGroup> | ||||
{/* Preview Form */} | {/* Preview Form */} | ||||
<FormGroup id={"previewForm"} sx={{ display: uploadStep === 1 ? "" : "none"}}> | |||||
<FormGroup id={"previewForm"} sx={{ display: props.step === 1 ? "" : "none"}}> | |||||
<Grid container spacing={2}> | <Grid container spacing={2}> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||
<Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | ||||
@@ -1127,7 +1205,7 @@ const CustomFormWizard = (props) => { | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
:null} | :null} | ||||
<Grid item xs={12} mt={1} mb={1}> | |||||
{/* <Grid item xs={12} mt={1} mb={1}> | |||||
<Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | ||||
<Typography display="inline" variant="h4" sx={{ color: 'primary.primary'}}>身份證明文件</Typography> | <Typography display="inline" variant="h4" sx={{ color: 'primary.primary'}}>身份證明文件</Typography> | ||||
<Typography display="inline" variant="h6" sx={{ fontSize: 12,color: 'primary.primary'}}>請上傳你的 有效身份證明文件 的數碼檔案,以驗證你的身份。</Typography> | <Typography display="inline" variant="h6" sx={{ fontSize: 12,color: 'primary.primary'}}>請上傳你的 有效身份證明文件 的數碼檔案,以驗證你的身份。</Typography> | ||||
@@ -1139,13 +1217,13 @@ const CustomFormWizard = (props) => { | |||||
<Typography display="inline" variant="h6" sx={{ fontSize: 12, color: 'primary.primary'}}>如: 香港身份證; 護照; 中國內地身份證等</Typography> | <Typography display="inline" variant="h6" sx={{ fontSize: 12, color: 'primary.primary'}}>如: 香港身份證; 護照; 中國內地身份證等</Typography> | ||||
</Stack> | </Stack> | ||||
</Stack> | </Stack> | ||||
</Grid> | |||||
</Grid> */} | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</FormGroup> | </FormGroup> | ||||
{/* Submit page */} | {/* Submit page */} | ||||
<FormGroup id={"submitForm"} sx={{ display: uploadStep === 2 ? "" : "none"}}> | |||||
<FormGroup id={"submitForm"} sx={{ display: props.step === 2 ? "" : "none"}}> | |||||
<Grid container spacing={3}> | <Grid container spacing={3}> | ||||
<Grid item xs={12}> | <Grid item xs={12}> | ||||
{checkUpload? | {checkUpload? | ||||
@@ -78,7 +78,7 @@ export default function UploadFileTable({recordList}) { | |||||
paginationModel: {page: 0, pageSize: 5}, | paginationModel: {page: 0, pageSize: 5}, | ||||
}, | }, | ||||
}} | }} | ||||
// pageSizeOptions={[5, 10]} | |||||
pageSizeOptions={[5, 10]} | |||||
autoHeight | autoHeight | ||||
/> | /> | ||||
</Box> | </Box> | ||||
@@ -8866,6 +8866,11 @@ react-syntax-highlighter@^15.5.0: | |||||
prismjs "^1.27.0" | prismjs "^1.27.0" | ||||
refractor "^3.6.0" | refractor "^3.6.0" | ||||
react-to-print@^2.14.13: | |||||
version "2.14.13" | |||||
resolved "https://registry.npmjs.org/react-to-print/-/react-to-print-2.14.13.tgz" | |||||
integrity sha512-PqUGgTRZvkyBzWgaZHVBECWPX2nGEc3HOUy6WNXof6HT4yTFI92wtIkqQtr4jfvHbadqjwTgzgh6vgN8KXlWWw== | |||||
react-transition-group@^4.0.0, react-transition-group@^4.4.0, react-transition-group@^4.4.5: | react-transition-group@^4.0.0, react-transition-group@^4.4.0, react-transition-group@^4.4.5: | ||||
version "4.4.5" | version "4.4.5" | ||||
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz" | resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz" | ||||