Anna Ho 2 лет назад
Родитель
Сommit
fd1be6220b
8 измененных файлов: 353 добавлений и 181 удалений
  1. +11
    -0
      package-lock.json
  2. +1
    -0
      package.json
  3. +3
    -8
      src/pages/authentication/BusRegister.js
  4. +8
    -10
      src/pages/authentication/Register.js
  5. +147
    -63
      src/pages/authentication/auth-forms/BusCustomFormWizard.js
  6. +177
    -99
      src/pages/authentication/auth-forms/CustomFormWizard.js
  7. +1
    -1
      src/pages/authentication/auth-forms/UploadFileTable.js
  8. +5
    -0
      yarn.lock

+ 11
- 0
package-lock.json Просмотреть файл

@@ -19,6 +19,7 @@
"@mui/lab": "^5.0.0-alpha.139",
"@mui/material": "^5.10.6",
"@mui/x-data-grid": "^6.11.1",
"@mui/x-date-pickers": "^6.12.0",
"@reduxjs/toolkit": "^1.8.5",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
@@ -48,6 +49,7 @@
"react-router-dom": "^6.4.1",
"react-scripts": "^5.0.1",
"react-syntax-highlighter": "^15.5.0",
"react-to-print": "^2.14.13",
"react-window": "^1.8.7",
"redux": "^4.2.0",
"simplebar": "^5.3.8",
@@ -18407,6 +18409,15 @@
"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": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",


+ 1
- 0
package.json Просмотреть файл

@@ -45,6 +45,7 @@
"react-router-dom": "^6.4.1",
"react-scripts": "^5.0.1",
"react-syntax-highlighter": "^15.5.0",
"react-to-print": "^2.14.13",
"react-window": "^1.8.7",
"redux": "^4.2.0",
"simplebar": "^5.3.8",


+ 3
- 8
src/pages/authentication/BusRegister.js Просмотреть файл

@@ -48,11 +48,7 @@
const BusRegister = () => {
const [activeStep, setActiveStep] = useState(0);
const [completed, setCompleted] = useState([false]);

const uploadStep = (value) => {
setActiveStep(value);
console.log(value)
};
const [updateValid, setUpdateValid] = useState(false);

const totalSteps = () => {
return steps.length;
@@ -71,7 +67,6 @@
};

const handleNext = () => {
console.log("test 1")
const newActiveStep =
isLastStep() && !allStepsCompleted()
? // It's the last step, but not all steps have been completed,
@@ -140,7 +135,7 @@
) : (
<React.Fragment>
<AuthWrapper>
<CustomFormWizard uploadStep={uploadStep} step={activeStep} />
<CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} />
{/* <CustomFormWizard step={activeStep} /> */}
</AuthWrapper>
<Stack direction="row" sx={{ pt: 2 }}>
@@ -178,7 +173,7 @@
</Button>
):
(
<Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}>
<Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}>
繼續
</Button>
)


+ 8
- 10
src/pages/authentication/Register.js Просмотреть файл

@@ -1,5 +1,7 @@
// import { Link } from 'react-router-dom';
import React,{useState} from 'react';
import React,{useState
// ,useEffect
} from 'react';

// material-ui
import {
@@ -48,11 +50,7 @@
const Register = () => {
const [activeStep, setActiveStep] = useState(0);
const [completed, setCompleted] = useState([false]);

const uploadStep = (value) => {
setActiveStep(value);
console.log(value)
};
const [updateValid, setUpdateValid] = useState(false);

const totalSteps = () => {
return steps.length;
@@ -71,7 +69,6 @@
};

const handleNext = () => {
console.log("test 1")
const newActiveStep =
isLastStep() && !allStepsCompleted()
? // It's the last step, but not all steps have been completed,
@@ -80,6 +77,7 @@
: activeStep + 1;
setActiveStep(newActiveStep);
console.log(newActiveStep)
};

const handleBack = () => {
@@ -140,11 +138,11 @@
) : (
<React.Fragment>
<AuthWrapper>
<CustomFormWizard uploadStep={uploadStep} step={activeStep} />
<CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} />
{/* <CustomFormWizard step={activeStep} /> */}
</AuthWrapper>
<Stack direction="row" sx={{ pt: 2 }}>
{ activeStep === totalSteps() - 1 ? (
{ activeStep === 2|| activeStep === 0? (
<Button
color="inherit"
disabled={true}
@@ -178,7 +176,7 @@
</Button>
):
(
<Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}>
<Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}>
繼續
</Button>
)


+ 147
- 63
src/pages/authentication/auth-forms/BusCustomFormWizard.js Просмотреть файл

@@ -21,7 +21,7 @@ import Autocomplete from "@mui/material/Autocomplete";

// third party
import { useFormik,FormikProvider } from 'formik';
import * as Yup from 'yup';
import * as yup from 'yup';
// import axios from "axios";

// project import
@@ -49,7 +49,6 @@ const BusCustomFormWizard = (props) => {
const [showConfirmPassword, setshowConfirmPassword] = useState(false);
const [fileList, setFileList] = useState([]);
const [fileListData, setFileListData] = useState([]);
const [uploadStep, setUploadStep] = useState(0);
const [checkUpload, setCheckUpload] = useState(false);

const handleClickShowPassword = () => {
@@ -72,33 +71,49 @@ const BusCustomFormWizard = (props) => {
const [selectedAddress5, setSelectedAddress5] = useState("香港");
const [termsAndConAccept, setTermsAndConAccept] = useState(false);
const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false);
const [isValid, setisValid] = useState(false);
const address4ComboList =
["北區","長洲區","大埔區","大嶼山區","東區","觀塘區","黃大仙區","九龍城區","葵青區","南區","南丫島區",
"坪洲區","荃灣區","沙田區","深水埗區","屯門區","灣仔區","西貢區","油尖旺區","元朗區","中西區"];
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(() => {
changePassword('');
}, []);

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);
};

useEffect(() => {
props.setUpdateValid(isValid)
}, [isValid])

useEffect(() => {
checkDataField(values)
}, [selectedAddress4,selectedAddress5,
termsAndConAccept,termsAndConNotAccept,fileList])

useEffect(() => {
props.step ==2?_onSubmit():null;
setUploadStep(props.step)
}, [props.step])

const {handleSubmit} = useForm({})
@@ -147,20 +170,14 @@ const BusCustomFormWizard = (props) => {
"addressLine1":"",
"addressLine2":"",
"addressLine3":"",
"district":"",
"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 = {
"countryCode":values.faxCountryCode,
@@ -178,7 +195,7 @@ const BusCustomFormWizard = (props) => {
tncFlag = false
}

if (checkDataField(values)){
if (isValid){
axios.post(`${apiPath}${POST_PUBLIC_USER_REGISTER}`, {
username: values.username,
password: values.password,
@@ -188,7 +205,7 @@ const BusCustomFormWizard = (props) => {
emailBus: values.email,
brNo:values.brNo,
brExpiryDate:values.brExpiryDate,
faxNo:userFaxNo,
userFaxNo:userFaxNo,
busUserContactTel:busUserContactTel,
busUserAddress:busUserAddress,
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({
initialValues:({
username:'',
@@ -235,34 +289,51 @@ const BusCustomFormWizard = (props) => {
brExpiryDate:'',
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
useEffect(() => {
checkDataField(values)
}, [values])

return (
<FormikProvider value={formik}>
<form onSubmit={handleSubmit(_onSubmit)}>
{/* Input Form */}
<FormGroup id={"inputForm"} sx={{ display: uploadStep === 0 ? "" : "none" }}>
<FormGroup id={"inputForm"} sx={{ display: props.step === 0 ? "" : "none" }}>
<Grid container spacing={3}>
<Grid item xs={12} md={12}>
<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"}}>
<Typography display="inline" variant="h3" sx={{ color: '#1A4399'}}>成為新的機構/公司用戶</Typography>
</div>
@@ -289,6 +360,7 @@ const BusCustomFormWizard = (props) => {
placeholder="用戶登入名稱"
fullWidth
error={Boolean(formik.touched.username && formik.errors.username)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -377,9 +449,10 @@ const BusCustomFormWizard = (props) => {
type={showConfirmPassword ? 'text' : 'password'}
value={formik.values.confirmPassword}
name="confirmPassword"
onBlur={formik.handleBlur}
onChange={(e) => {
formik.handleChange(e);
changePassword(e.target.value);
// changePassword(e.target.value);
}}
inputProps={{
onKeyDown: (e) => {
@@ -437,6 +510,7 @@ const BusCustomFormWizard = (props) => {
placeholder="與與商業登記證相同如有"
fullWidth
error={Boolean(formik.touched.enCompanyName && formik.errors.enCompanyName)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -546,6 +620,7 @@ const BusCustomFormWizard = (props) => {
name="address1"
onChange={formik.handleChange}
placeholder="第一行"
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -650,6 +725,7 @@ const BusCustomFormWizard = (props) => {
placeholder="與你的身份證明文件相同"
fullWidth
error={Boolean(formik.touched.enName && formik.errors.enName)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -681,6 +757,7 @@ const BusCustomFormWizard = (props) => {
name="email"
onChange={formik.handleChange}
placeholder="電郵"
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -711,6 +788,7 @@ const BusCustomFormWizard = (props) => {
// onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="確認電郵"
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -747,6 +825,7 @@ const BusCustomFormWizard = (props) => {
onChange={formik.handleChange}
placeholder="eg:852"
error={Boolean(formik.touched.phone && formik.errors.phone)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 3,
onKeyDown: (e) => {
@@ -762,7 +841,7 @@ const BusCustomFormWizard = (props) => {
type="phone"
value={formik.values.phone}
name="phone"
// onBlur={formik.handleBlur}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="聯絡電話"
error={Boolean(formik.touched.phone && formik.errors.phone)}
@@ -776,12 +855,12 @@ const BusCustomFormWizard = (props) => {
}}
sx={{width:'75%'}}
/>
{formik.touched.phone && formik.errors.phone && (
<FormHelperText error id="helper-text-phone-signup">
{formik.errors.phone}
</FormHelperText>
)}
</Stack>
{formik.touched.phone && formik.errors.phone && (
<FormHelperText error id="helper-text-phone-signup">
{formik.errors.phone}
</FormHelperText>
)}
</Stack>
</Grid>
</Grid>
@@ -925,7 +1004,7 @@ const BusCustomFormWizard = (props) => {
</Grid>
</FormGroup>
{/* Preview Form */}
<FormGroup id={"previewForm"} sx={{ display: uploadStep === 1 ? "" : "none"}}>
<FormGroup id={"previewForm"} sx={{ display: props.step === 1 ? "" : "none"}}>
<Grid container spacing={2}>
<Grid item xs={12}>
<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} >
<Stack spacing={1}>
<Typography>
商業登記證:
商業登記證
</Typography>
</Stack>
</Grid>
@@ -1019,17 +1098,23 @@ const BusCustomFormWizard = (props) => {
<Typography id="preview-address1-signup">
{formik.values.address1}
</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">
{formik.values.address3}
</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">
{formik.values.address5}
國家/地區: {selectedAddress5}
</Typography>
</Stack>
</Stack>
@@ -1085,13 +1170,12 @@ const BusCustomFormWizard = (props) => {
</Grid>
</FormGroup>
{/* Submit page */}
<FormGroup id={"submitForm"} sx={{ display: uploadStep === 2 ? "" : "none"}}>
<FormGroup id={"submitForm"} sx={{ display: props.step === 2 ? "" : "none"}}>
<Grid container spacing={3}>
<Grid item xs={12}>
{checkUpload?
// SUCCESS page
<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"}}/>
<Typography display="inline" variant="h4">完成申請,請登入帳戶</Typography>
<Button variant="outlined" component={Link} to="/login" sx={{ fontSize: 20,height:'60px'}}>返回登入頁面</Button>


+ 177
- 99
src/pages/authentication/auth-forms/CustomFormWizard.js Просмотреть файл

@@ -48,7 +48,6 @@ const CustomFormWizard = (props) => {
const [showConfirmPassword, setshowConfirmPassword] = useState(false);
const [fileList, setFileList] = useState([]);
const [fileListData, setFileListData] = useState([]);
const [uploadStep, setUploadStep] = useState(0);
const [checkUpload, setCheckUpload] = useState(false);

const handleClickShowPassword = () => {
@@ -72,39 +71,56 @@ const CustomFormWizard = (props) => {
const [selectedAddress5, setSelectedAddress5] = useState("香港");
const [termsAndConAccept, setTermsAndConAccept] = useState(false);
const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false);
const [isValid, setisValid] = useState(false);
const idDocTypeComboList = ["passport","HKID","CNID","BR","otherCert"];
const address4ComboList =
["北區","長洲區","大埔區","大嶼山區","東區","觀塘區","黃大仙區","九龍城區","葵青區","南區","南丫島區",
"坪洲區","荃灣區","沙田區","深水埗區","屯門區","灣仔區","西貢區","油尖旺區","元朗區","中西區"];
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(() => {
changePassword('');
}, []);

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) => {
console.log (event.target)
if(event.target.name == 'termsAndConAccept'){
setTermsAndConAccept(event.target.checked)
setTermsAndConNotAccept(!event.target.checked)
@@ -134,9 +150,17 @@ const CustomFormWizard = (props) => {
setFileList(uploadFileList);
};

useEffect(() => {
props.setUpdateValid(isValid)
}, [isValid])

useEffect(() => {
checkDataField(values)
}, [selectedIdDocType,selectedAddress4,selectedAddress5,
termsAndConAccept,termsAndConNotAccept,fileList])

useEffect(() => {
props.step ==2?_onSubmit():null;
setUploadStep(props.step)
}, [props.step])

const {handleSubmit} = useForm({})
@@ -144,26 +168,19 @@ const CustomFormWizard = (props) => {
values.idDocType = selectedIdDocType
values.address4 = selectedAddress4
values.address5 = selectedAddress5
console.log(values)
const userAddress = {
"addressLine1":"",
"addressLine2":"",
"addressLine3":"",
"district":"",
"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 = {
"countryCode":values.faxCountryCode,
"faxNumber":values.fax,
@@ -179,8 +196,8 @@ const CustomFormWizard = (props) => {
if (termsAndConNotAccept){
tncFlag = false
}
if (checkDataField(values)){
if (isValid){
axios.post(`${apiPath}${POST_PUBLIC_USER_REGISTER}`, {
username: values.username,
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({
initialValues:({
username:'',
enName: '',
chName: '',
email: '',
emailConfirm: '',
address1: '',
address2: '',
address3: '',
@@ -235,56 +302,58 @@ const CustomFormWizard = (props) => {
submit: null,
fax:'',
faxCountryCode:'852',
idDocType:selectedIdDocType
}),
validationSchema:yup.object().shape({
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('請輸入英文姓名'),
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('請輸入第三行地址')}),
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
useEffect(() => {
checkDataField(values)
}, [values])

return (
<FormikProvider value={formik}>
<form onSubmit={handleSubmit(_onSubmit)}>
{/* Input Form */}
<FormGroup id={"inputForm"} sx={{ display: uploadStep === 0 ? "" : "none" }}>
<FormGroup id={"inputForm"} sx={{ display: props.step === 0 ? "" : "none" }}>
<Grid container spacing={3}>
<Grid item xs={12} md={12}>
<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"}}>
<Typography display="inline" variant="h3" sx={{ color: '#1A4399'}}>成為新的個人用戶</Typography>
<Typography display="inline" variant="h3" sx={{ color: '#1A4399'}}>成為新的個人用戶</Typography>
</div>
<Typography mt={0.25} variant="h6" sx={{ fontSize: 12,color: '#f10000'}}>註有*的項目必須輸入資料</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>
</Grid>
<Grid item xs={12} md={12}>
@@ -370,16 +439,16 @@ const CustomFormWizard = (props) => {
)}
</Stack>
<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>
</FormControl>
</Grid>
<Grid item xs={12} md={6} >
@@ -395,7 +464,7 @@ const CustomFormWizard = (props) => {
onBlur={formik.handleBlur}
onChange={(e) => {
formik.handleChange(e);
changePassword(e.target.value);
// changePassword(e.target.value);
}}
inputProps={{
onKeyDown: (e) => {
@@ -457,17 +526,22 @@ const CustomFormWizard = (props) => {
<Stack spacing={1} sx={{mr:{md:1},mb:{xs:0.5}}}>
<Autocomplete
disablePortal
id="idDocType-combo"
value={selectedIdDocType === null ? null : selectedIdDocType}
id="idDocType"
value={selectedIdDocType}
options={idDocTypeComboList}
onBlur={formik.handleBlur}
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="證件類別"/>}
/>
{formik.touched.idDocType && (
selectedIdDocType===null?
<FormHelperText error id="helper-text-idDocType-signup">
請輸入證件類別
</FormHelperText>:''
)}
</Stack>
</Grid>
{selectedIdDocType =="HKID"?
@@ -495,10 +569,15 @@ const CustomFormWizard = (props) => {
}}
/>
{formik.touched.idNo && formik.errors.idNo && (
<FormHelperText error id="helper-text-enName-signup">
<FormHelperText error id="helper-text-idNo-signup">
{formik.errors.idNo}
</FormHelperText>
)}
{formik.touched.checkDigit && formik.errors.checkDigit && (
<FormHelperText error id="helper-text-checkDigit-signup">
{formik.errors.checkDigit}
</FormHelperText>
)}
</Stack>
</Grid>
<Grid item xs={2} md={1}>
@@ -521,12 +600,8 @@ const CustomFormWizard = (props) => {
}}
fullWidth
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>
</Grid>
</>:
@@ -542,6 +617,7 @@ const CustomFormWizard = (props) => {
fullWidth
sx={{mr:1}}
error={Boolean(formik.touched.idNo && formik.errors.idNo)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -551,7 +627,7 @@ const CustomFormWizard = (props) => {
}}
/>
{formik.touched.idNo && formik.errors.idNo && (
<FormHelperText error id="helper-text-enName-signup">
<FormHelperText error id="helper-text-idNo-signup">
{formik.errors.idNo}
</FormHelperText>
)}
@@ -574,6 +650,7 @@ const CustomFormWizard = (props) => {
placeholder="與你的身份證明文件相同"
fullWidth
error={Boolean(formik.touched.enName && formik.errors.enName)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -629,6 +706,7 @@ const CustomFormWizard = (props) => {
name="address1"
onChange={formik.handleChange}
placeholder="第一行"
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -672,12 +750,10 @@ const CustomFormWizard = (props) => {
<Autocomplete
disablePortal
id="address4-combo"
value={selectedAddress4 === null ? null : selectedAddress4}
value={selectedAddress4}
options={address4ComboList}
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" },}}
@@ -689,9 +765,7 @@ const CustomFormWizard = (props) => {
value={selectedAddress5}
options={address5ComboList}
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" },}}
@@ -735,6 +809,7 @@ const CustomFormWizard = (props) => {
name="email"
onChange={formik.handleChange}
placeholder="電郵"
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -765,6 +840,7 @@ const CustomFormWizard = (props) => {
// onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="確認電郵"
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
@@ -801,6 +877,7 @@ const CustomFormWizard = (props) => {
onChange={formik.handleChange}
placeholder="eg:852"
error={Boolean(formik.touched.phone && formik.errors.phone)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 3,
onKeyDown: (e) => {
@@ -820,6 +897,7 @@ const CustomFormWizard = (props) => {
onChange={formik.handleChange}
placeholder="聯絡電話"
error={Boolean(formik.touched.phone && formik.errors.phone)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 8,
onKeyDown: (e) => {
@@ -830,12 +908,12 @@ const CustomFormWizard = (props) => {
}}
sx={{width:'75%'}}
/>
{formik.touched.phone && formik.errors.phone && (
<FormHelperText error id="helper-text-phone-signup">
{formik.errors.phone}
</FormHelperText>
)}
</Stack>
{formik.touched.phone && formik.errors.phone && (
<FormHelperText error id="helper-text-phone-signup">
{formik.errors.phone}
</FormHelperText>
)}
</Stack>
</Grid>
</Grid>
@@ -852,9 +930,9 @@ const CustomFormWizard = (props) => {
type="faxCountryCode"
value={formik.values.faxCountryCode}
name="faxCountryCode"
// onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="eg:852"
onBlur={formik.handleBlur}
inputProps={{
maxLength: 3,
onKeyDown: (e) => {
@@ -870,7 +948,7 @@ const CustomFormWizard = (props) => {
type="fax"
value={formik.values.fax}
name="fax"
// onBlur={formik.handleBlur}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
placeholder="傳真號碼"
inputProps={{
@@ -977,7 +1055,7 @@ const CustomFormWizard = (props) => {
</Grid>
</FormGroup>
{/* Preview Form */}
<FormGroup id={"previewForm"} sx={{ display: uploadStep === 1 ? "" : "none"}}>
<FormGroup id={"previewForm"} sx={{ display: props.step === 1 ? "" : "none"}}>
<Grid container spacing={2}>
<Grid item xs={12}>
<Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
@@ -1127,7 +1205,7 @@ const CustomFormWizard = (props) => {
</Stack>
</Grid>
: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 } }}>
<Typography display="inline" variant="h4" sx={{ 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>
</Stack>
</Stack>
</Grid>
</Grid> */}
</Grid>
</Grid>
</Grid>
</FormGroup>
{/* Submit page */}
<FormGroup id={"submitForm"} sx={{ display: uploadStep === 2 ? "" : "none"}}>
<FormGroup id={"submitForm"} sx={{ display: props.step === 2 ? "" : "none"}}>
<Grid container spacing={3}>
<Grid item xs={12}>
{checkUpload?


+ 1
- 1
src/pages/authentication/auth-forms/UploadFileTable.js Просмотреть файл

@@ -78,7 +78,7 @@ export default function UploadFileTable({recordList}) {
paginationModel: {page: 0, pageSize: 5},
},
}}
// pageSizeOptions={[5, 10]}
pageSizeOptions={[5, 10]}
autoHeight
/>
</Box>


+ 5
- 0
yarn.lock Просмотреть файл

@@ -8866,6 +8866,11 @@ react-syntax-highlighter@^15.5.0:
prismjs "^1.27.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:
version "4.4.5"
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz"


Загрузка…
Отмена
Сохранить