@@ -17,11 +17,11 @@ import {useNavigate} from "react-router-dom"; | |||
// ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
const OrganizationCard = ({userData, id}) => { | |||
const OrganizationCard_loadFromUser = ({userData, id}) => { | |||
const [currentUserData, setCurrentUserData] = useState(userData); | |||
const from = useForm({defaultValues: userData}); | |||
const {register,reset, handleSubmit} = from; | |||
const form = useForm({defaultValues: userData}); | |||
const {register,reset, handleSubmit} = form; | |||
const navigate = useNavigate(); | |||
@@ -57,7 +57,8 @@ const OrganizationCard = ({userData, id}) => { | |||
}, [currentUserData]); | |||
function onSubmitForm(_formData) { | |||
const onSubmitForm=(_formData)=>{ | |||
console.log(_formData); | |||
HttpUtils.post({ | |||
url: UrlUtils.POST_ORG_SAVE_PATH, | |||
params: { | |||
@@ -101,10 +102,29 @@ const OrganizationCard = ({userData, id}) => { | |||
Information | |||
</Typography> | |||
<form onSubmit={handleSubmit(onSubmitForm)}> | |||
<form id="_form" onSubmit={handleSubmit(onSubmitForm)}> | |||
<Grid container spacing={1}> | |||
{/*bottom top*/} | |||
<Grid item s={12} md={12} lg={12} sx={{mb: 3}} alignItems={"start"} justifyContent="center"> | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
type="submit" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
> | |||
Create | |||
</Button> | |||
</Grid> | |||
</Grid> | |||
{/*bottom top*/} | |||
<Grid item lg={4} > | |||
<Grid container alignItems={"center"}> | |||
<Grid item xs={4} s={4} md={4} lg={4} | |||
@@ -340,30 +360,11 @@ const OrganizationCard = ({userData, id}) => { | |||
</Grid> | |||
{/*bottom button*/} | |||
<Grid item s={12} md={12} lg={12} sx={{mb: 3}} alignItems={"end"} justifyContent="center"> | |||
<Grid container maxWidth justifyContent="flex-end"> | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
type="submit" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
> | |||
Create | |||
</Button> | |||
</Grid> | |||
</Grid> | |||
</Grid> | |||
</form> | |||
</MainCard> | |||
); | |||
}; | |||
export default OrganizationCard; | |||
export default OrganizationCard_loadFromUser; |
@@ -12,7 +12,7 @@ import * as UrlUtils from "../../utils/ApiPathConst"; | |||
// ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
const OrganizationDetailPage = () => { | |||
const OrganizationDetailPage_FromUser = () => { | |||
const params = useParams(); | |||
const [formData, setFormData] = useState({}) | |||
const [isLoading, setLoding] = useState(true); | |||
@@ -57,7 +57,6 @@ const OrganizationDetailPage = () => { | |||
<Grid item xs={12} md={12} lg={12}> | |||
<InfoCard | |||
userData={formData} | |||
loadDataFun={loadData} | |||
id={params.id} | |||
/> | |||
</Grid> | |||
@@ -70,4 +69,4 @@ const OrganizationDetailPage = () => { | |||
}; | |||
export default OrganizationDetailPage; | |||
export default OrganizationDetailPage_FromUser; |
@@ -19,7 +19,7 @@ export default function OrganizationTable({recordList}) { | |||
}, [recordList]); | |||
const handleActionClick = (id) => () => { | |||
navigate('/orgUser/'+ id); | |||
navigate('/org/'+ id); | |||
}; | |||
const columns = [ | |||
@@ -79,6 +79,8 @@ const UserInformationCard_Individual = ({userData,userFile, loadDataFun}) => { | |||
userData["faxNumber"] = userData.faxNo?.faxNumber; | |||
userData["fax_countryCode"] = userData.faxNo?.countryCode; | |||
userData["lastLoginDate"] = userData.lastLogin?DateUtils.datetimeStr(userData.lastLogin):""; | |||
setIdDocType(userData.idDocType); | |||
setDistrict(userData.district); | |||
setCountry(userData.country); | |||
@@ -92,31 +94,32 @@ const UserInformationCard_Individual = ({userData,userFile, loadDataFun}) => { | |||
}, [currentUserData]); | |||
function onSubmitForm() { | |||
function onSubmitForm(_data) { | |||
HttpUtils.post({ | |||
url: UrlUtils.POST_IND_USER+"/"+userData.id, | |||
params: { | |||
prefix: formik.values.prefix, | |||
prefix: _data.prefix, | |||
enName: formik.values.enName, | |||
chName: formik.values.chName, | |||
chName: _data.chName, | |||
idDocType: idDocType, | |||
contactTel: { | |||
countryCode: formik.values.tel_countryCode, | |||
phoneNumber: formik.values.phoneNumber | |||
countryCode: _data.tel_countryCode, | |||
phoneNumber: _data.phoneNumber | |||
}, | |||
identification: formik.values.identification, | |||
checkDigit: formik.values.checkDigit, | |||
faxNo:{ | |||
countryCode: formik.values.fax_countryCode, | |||
faxNumber: formik.values.faxNumber | |||
countryCode: _data.fax_countryCode, | |||
faxNumber: _data.faxNumber | |||
}, | |||
emailAddress:formik.values.emailAddress, | |||
emailAddress:_data.emailAddress, | |||
address:{ | |||
country:country, | |||
district:district, | |||
addressLine1: formik.values.addressLine1, | |||
addressLine2: formik.values.addressLine2, | |||
addressLine3: formik.values.addressLine3, | |||
addressLine1: _data.addressLine1, | |||
addressLine2: _data.addressLine2, | |||
addressLine3: _data.addressLine3, | |||
}, | |||
}, | |||
onSuccess: function(){ | |||
@@ -645,11 +648,8 @@ const UserInformationCard_Individual = ({userData,userFile, loadDataFun}) => { | |||
<TextField | |||
fullWidth | |||
{...register("lastLogin", | |||
{ | |||
value: currentUserData?.lastLogin, | |||
})} | |||
id='lastLogin' | |||
{...register("lastLoginDate")} | |||
id='lastLoginDate' | |||
disabled | |||
> | |||
</TextField> | |||
@@ -20,7 +20,6 @@ const UserMaintainPage_Individual = () => { | |||
useEffect(()=>{ | |||
console.log(userData); | |||
loadData(); | |||
},[]); | |||
@@ -1,6 +1,7 @@ | |||
// material-ui | |||
import { | |||
Grid, TextField, Typography, Button | |||
Grid, TextField, Typography, Button, | |||
OutlinedInput, FormHelperText, Autocomplete | |||
} from '@mui/material'; | |||
import MainCard from "../../components/MainCard"; | |||
import * as React from "react"; | |||
@@ -9,6 +10,10 @@ import {useEffect, useState} from "react"; | |||
import * as DateUtils from '../../utils/DateUtils'; | |||
import * as HttpUtils from '../../utils/HttpUtils'; | |||
import * as UrlUtils from "../../utils/ApiPathConst"; | |||
import * as ComboData from "../../utils/ComboData"; | |||
import { useFormik,FormikProvider } from 'formik'; | |||
import * as yup from 'yup'; | |||
// ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
@@ -19,28 +24,62 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
const [editMode, setEditMode] = useState(false); | |||
const [locked, setLocked] = useState(false); | |||
const [district, setDistrict] = useState(null); | |||
const [country, setCountry] = useState(ComboData.country[0]); | |||
const from = useForm({defaultValues: userData}); | |||
const {register,reset, handleSubmit} = from; | |||
const formik = useFormik({ | |||
initialValues:(currentUserData), | |||
validationSchema:yup.object().shape({ | |||
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,'請輸入商業登記證號碼'), | |||
}) | |||
}); | |||
useEffect(() => { | |||
let createDate = DateUtils.datetimeStr(userData.created); | |||
let modifiedBy = DateUtils.datetimeStr(userData.modified)+", "+userData.modifiedBy; | |||
userData["createDate"] = createDate; | |||
userData["modifieDate"] = modifiedBy; | |||
userData["verifiedStatus"] = userData.verifiedBy? "Not verify yet":DateUtils.datetimeStr(userData.verifiedDate)+", "+userData.verifiedByName; | |||
userData["verifiedStatus"] = userData.verifiedBy? DateUtils.datetimeStr(userData.verifiedDate)+", "+userData.verifiedByName: "Not verify yet"; | |||
userData["lastLoginDate"] = userData.lastLogin?DateUtils.datetimeStr(lastLoginDate):""; | |||
userData["country"] = userData.address?.country; | |||
userData["district"] = userData.address?.district; | |||
userData["addressLine1"] = userData.address?.addressLine1; | |||
userData["addressLine2"] = userData.address?.addressLine2; | |||
userData["addressLine3"] = userData.address?.addressLine3; | |||
userData["country"] = userData.addressBus?.country; | |||
userData["district"] = userData.addressBus?.district; | |||
userData["addressLine1"] = userData.addressBus?.addressLine1; | |||
userData["addressLine2"] = userData.addressBus?.addressLine2; | |||
userData["addressLine3"] = userData.addressBus?.addressLine3; | |||
userData["phoneNumber"] = userData.contactTel?.phoneNumber; | |||
userData["tel_countryCode"] = userData.contactTel?.countryCode; | |||
userData["faxNumber"] = userData.faxNo?.faxNumber; | |||
userData["fax_countryCode"] = userData.faxNo?.countryCode; | |||
userData["brExpiryDate"] = userData.brExpiryDate?DateUtils.convertToDate(brExpiryDate):""; | |||
setDistrict(userData.district); | |||
setCountry(userData.country); | |||
setCurrentUserData(userData); | |||
}, [userData]); | |||
@@ -51,29 +90,36 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
}, [currentUserData]); | |||
function onSubmitForm(_formData) { | |||
function onSubmitForm(_data) { | |||
HttpUtils.post({ | |||
url: UrlUtils.POST_IND_USER+"/"+userData.id, | |||
params: { | |||
chName: _formData.chName, | |||
enName: _formData.enName, | |||
chName: _data.chName, | |||
enName: _data.enName, | |||
contactTel: { | |||
countryCode: _formData.tel_countryCode, | |||
phoneNumber: _formData.phoneNumber | |||
countryCode: _data.tel_countryCode, | |||
phoneNumber: _data.phoneNumber | |||
}, | |||
faxNo: { | |||
countryCode: _formData.fax_countryCode, | |||
faxNumber: _formData.faxNumber | |||
countryCode: _data.fax_countryCode, | |||
faxNumber: _data.faxNumber | |||
}, | |||
addressBus: { | |||
country: _formData.country, | |||
district: _formData.district, | |||
addressLine1: _formData.addressLine1, | |||
addressLine2: _formData.addressLine2, | |||
addressLine3: _formData.addressLine3, | |||
country: country, | |||
district: district, | |||
addressLine1: _data.addressLine1, | |||
addressLine2: _data.addressLine2, | |||
addressLine3: _data.addressLine3, | |||
}, | |||
identification: _formData.identification, | |||
emailBus:_formData.emailBus, | |||
identification: _data.identification, | |||
emailBus:_data.emailBus, | |||
contactPerson: _data.contactPerson, | |||
enCompanyName: _data.enCompanyName, | |||
chCompanyName: _data.chCompanyName, | |||
brNo: _data.brNo, | |||
brExpiryDate: formik.values.brExpiryDate, | |||
}, | |||
onSuccess: function(){ | |||
loadDataFun(); | |||
@@ -89,6 +135,15 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
window.open("/org/fromUser/"+userData.id, "_blank", "noreferrer"); | |||
}; | |||
const onVerifiedClick = () => { | |||
HttpUtils.get({ | |||
url: UrlUtils.GET_IND_USER_VERIFY+"/"+userData.id, | |||
onSuccess: function(){ | |||
loadDataFun(); | |||
} | |||
}); | |||
}; | |||
const doLock = () => { | |||
HttpUtils.get({ | |||
url: UrlUtils.GET_USER_LOCK+"/"+userData.id, | |||
@@ -107,6 +162,7 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
}); | |||
}; | |||
return ( | |||
<MainCard elevation={0} | |||
border={false} | |||
@@ -116,7 +172,67 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
Information | |||
</Typography> | |||
<FormikProvider value={formik}> | |||
<form onSubmit={handleSubmit(onSubmitForm)}> | |||
{/*top button*/} | |||
<Grid item s={12} md={12} lg={12} sx={{mb: 3}} alignItems={"start"} justifyContent="center"> | |||
<Grid container maxWidth justifyContent="flex-start"> | |||
{editMode? | |||
<> | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
onClick={loadDataFun} | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
> | |||
Cancel Edit | |||
</Button> | |||
</Grid> | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
type="submit" | |||
color="success" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
> | |||
Save | |||
</Button> | |||
</Grid> | |||
</> | |||
: | |||
<> | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
onClick={onEditClick} | |||
> | |||
Edit | |||
</Button> | |||
</Grid> | |||
</> | |||
} | |||
</Grid> | |||
</Grid> | |||
{/*end top button*/} | |||
<Grid container spacing={1}> | |||
<Grid item lg={4} > | |||
@@ -243,10 +359,7 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
<Grid item xs={7} s={7} md={7} lg={6} > | |||
<TextField | |||
{...register("identification", | |||
{ | |||
value: currentUserData?.identification, | |||
})} | |||
{...register("identification")} | |||
id='identification' | |||
disabled={!editMode} | |||
/> | |||
@@ -266,8 +379,8 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
<Grid item xs={7} s={7} md={7} lg={6}> | |||
<TextField | |||
fullWidth | |||
{...register("emailAddress")} | |||
id='emailAddress' | |||
{...register("emailBus")} | |||
id='emailBus' | |||
disabled={!editMode} | |||
/> | |||
</Grid> | |||
@@ -282,8 +395,9 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
Verified: | |||
</Grid> | |||
{ | |||
currentUserData.verified || editMode? | |||
currentUserData.verifiedBy || editMode? | |||
<Grid item xs={6}> | |||
<TextField | |||
fullWidth | |||
@@ -310,17 +424,20 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
onClick={onVerifiedClick} | |||
> | |||
Verified | |||
Verify | |||
</Button> | |||
</Grid> | |||
</> | |||
} | |||
</Grid> | |||
</Grid> | |||
<Grid item lg={4}> | |||
<Grid container alignItems={"center"}> | |||
<Grid item xs={4} s={4} md={4} lg={4} | |||
@@ -332,11 +449,8 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
<TextField | |||
fullWidth | |||
{...register("lastLogin", | |||
{ | |||
value: currentUserData?.lastLogin, | |||
})} | |||
id='lastLogin' | |||
{...register("lastLoginDate")} | |||
id='lastLoginDate' | |||
disabled | |||
> | |||
</TextField> | |||
@@ -352,106 +466,69 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
Status: | |||
</Grid> | |||
{ | |||
editMode? | |||
<Grid item xs={7} s={7} md={7} lg={6}> | |||
<TextField | |||
fullWidth | |||
{...register("status")} | |||
id='status' | |||
disabled | |||
/> | |||
</Grid> | |||
: | |||
<> | |||
<Grid item lg={4}> | |||
<TextField | |||
fullWidth | |||
{...register("status")} | |||
id='status' | |||
disabled | |||
/> | |||
</Grid> | |||
{locked? | |||
<Grid lg={1}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
color="success" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
onClick={doUnlock} | |||
> | |||
Active | |||
</Button> | |||
</Grid> | |||
: | |||
<Grid item lg={1}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
color="error" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
onClick={doLock} | |||
> | |||
Lock | |||
</Button> | |||
</Grid> | |||
} | |||
</> | |||
} | |||
<Grid item xs={7} s={7} md={7} lg={6}> | |||
<TextField | |||
fullWidth | |||
{...register("status")} | |||
id='status' | |||
disabled | |||
/> | |||
</Grid> | |||
</Grid> | |||
</Grid> | |||
</Grid> | |||
{/*bottom button*/} | |||
<Grid item s={12} md={12} lg={12} sx={{mb: 3}} alignItems={"end"} justifyContent="center"> | |||
<Grid container maxWidth justifyContent="flex-end"> | |||
{editMode? | |||
<> | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
type="submit" | |||
color="success" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
> | |||
Save | |||
</Button> | |||
</Grid> | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
onClick={loadDataFun} | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
> | |||
Cancel & Back | |||
</Button> | |||
</Grid> | |||
</> | |||
: | |||
<> | |||
{locked? | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
color="primary" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
onClick={doUnlock} | |||
> | |||
Unlock | |||
</Button> | |||
</Grid> | |||
: | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
color="primary" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
onClick={doLock} | |||
> | |||
Lock | |||
</Button> | |||
</Grid> | |||
} | |||
<Grid item sx={{ml: 3, mr: 3}}> | |||
<Button | |||
size="large" | |||
variant="contained" | |||
sx={{ | |||
textTransform: 'capitalize', | |||
alignItems: 'end' | |||
}} | |||
onClick={onEditClick} | |||
> | |||
Edit | |||
</Button> | |||
</Grid> | |||
</> | |||
} | |||
</Grid> | |||
</Grid> | |||
<Grid container spacing={1}> | |||
<Grid item lg={1} > | |||
@@ -500,7 +577,7 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
fullWidth | |||
{...register("chCompanyName")} | |||
id='chCompanyName' | |||
disabled | |||
disabled={!editMode} | |||
/> | |||
</Grid> | |||
</Grid> | |||
@@ -535,7 +612,7 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
<TextField | |||
fullWidth | |||
{...register("contactPerson")} | |||
id='brExpiryDateTemp' | |||
id='contactPerson' | |||
disabled={!editMode} | |||
/> | |||
</Grid> | |||
@@ -575,12 +652,31 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
</Grid> | |||
<Grid item xs={7} s={7} md={7} lg={6}> | |||
<TextField | |||
fullWidth | |||
{...register("brExpiryDateTemp")} | |||
id='brExpiryDateTemp' | |||
disabled={!editMode} | |||
/> | |||
<OutlinedInput | |||
fullWidth | |||
disabled={!editMode} | |||
{...register("brExpiryDate")} | |||
error={Boolean(formik.touched.brExpiryDate && formik.errors.brExpiryDate)} | |||
id="brExpiryDate" | |||
type="date" | |||
value={formik.values.brExpiryDate} | |||
format="dd/MM/yyyy" | |||
name="brExpiryDate" | |||
onChange={formik.handleChange} | |||
placeholder="與與商業登記證相同如有" | |||
inputProps={{ | |||
onKeyDown: (e) => { | |||
if (e.key === 'Enter') { | |||
e.preventDefault(); | |||
} | |||
}, | |||
}} | |||
/> | |||
{formik.touched.brExpiryDate && formik.errors.brExpiryDate && ( | |||
<FormHelperText error id="brExpiryDate"> | |||
{formik.errors.brExpiryDate} | |||
</FormHelperText> | |||
)} | |||
</Grid> | |||
</Grid> | |||
</Grid> | |||
@@ -595,28 +691,19 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
<Grid item xs={7} s={7} md={12} lg={6}> | |||
<TextField | |||
fullWidth | |||
{...register("addressLine1", | |||
{ | |||
value: currentUserData?.address?.addressLine1, | |||
})} | |||
{...register("addressLine1")} | |||
id='addressLine1' | |||
disabled={!editMode} | |||
/> | |||
<TextField | |||
fullWidth | |||
{...register("addressLine2", | |||
{ | |||
value: currentUserData?.address?.addressLine2, | |||
})} | |||
{...register("addressLine2")} | |||
id='addressLine2' | |||
disabled={!editMode} | |||
/> | |||
<TextField | |||
fullWidth | |||
{...register("addressLine3", | |||
{ | |||
value: currentUserData?.address?.addressLine3, | |||
})} | |||
{...register("addressLine3")} | |||
id='addressLine3' | |||
disabled={!editMode} | |||
/> | |||
@@ -624,7 +711,7 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
</Grid> | |||
</Grid> | |||
<Grid item lg={4} > | |||
<Grid item lg={4}> | |||
<Grid container alignItems={"center"}> | |||
<Grid item xs={4} s={4} md={4} lg={4} | |||
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
@@ -632,17 +719,25 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
</Grid> | |||
<Grid item xs={7} s={7} md={7} lg={6}> | |||
<TextField | |||
fullWidth | |||
{...register("district")} | |||
id='district' | |||
disabled={!editMode} | |||
/> | |||
<Autocomplete | |||
fullWidth | |||
disablePortal | |||
id="district" | |||
{...register("district")} | |||
value={district} | |||
options={ComboData.district} | |||
onChange={(event, newValue) => { | |||
setDistrict(newValue); | |||
}} | |||
disabled={!editMode} | |||
sx={{"& .MuiInputBase-root": { height: "41px" },"#district":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | |||
renderInput={(params) => <TextField {...params} placeholder="區域 (只適用於香港)"/>} | |||
/> | |||
</Grid> | |||
</Grid> | |||
</Grid> | |||
<Grid item lg={4} > | |||
<Grid item lg={4}> | |||
<Grid container alignItems={"center"}> | |||
<Grid item xs={4} s={4} md={4} lg={4} | |||
sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
@@ -650,19 +745,31 @@ const UserInformationCard_Organization = ({userData, loadDataFun}) => { | |||
</Grid> | |||
<Grid item xs={7} s={7} md={7} lg={6}> | |||
<TextField | |||
fullWidth | |||
{...register("country")} | |||
id='country' | |||
<Autocomplete | |||
fullWidth | |||
disablePortal | |||
disabled={!editMode} | |||
id="country" | |||
value={country} | |||
options={ComboData.country} | |||
{...register("country")} | |||
onChange={(event, newValue) => { | |||
setCountry(newValue); | |||
}} | |||
sx={{"& .MuiInputBase-root": { height: "41px" },"#country":{padding: "0px 0px 0px 0px"}, "& .MuiAutocomplete-endAdornment": { top: "auto" },}} | |||
renderInput={(params) => <TextField {...params} placeholder="國家/地區"/>} | |||
/> | |||
</Grid> | |||
</Grid> | |||
</Grid> | |||
</Grid> | |||
</form> | |||
</FormikProvider> | |||
</MainCard> | |||
); | |||
}; | |||
@@ -4,7 +4,6 @@ import {useEffect, useState} from "react"; | |||
import * as React from "react"; | |||
//import axios from "axios"; | |||
import * as HttpUtils from "../../utils/HttpUtils"; | |||
import {apiPath} from "../../auth/utils"; | |||
import {useParams} from "react-router-dom"; | |||
import FileList from "../../components/FileList" | |||
import MainCard from "../../components/MainCard"; | |||
@@ -29,8 +28,11 @@ const UserMaintainPage_Organization = () => { | |||
const loadData = ()=>{ | |||
setLoding(true); | |||
HttpUtils.get({ | |||
url: `${apiPath}${UrlUtils.GET_USER_PATH}/${params.id}`, | |||
url: `${UrlUtils.GET_ORG_USER_PATH}/${params.id}`, | |||
onSuccess: function(response){ | |||
response.data["addressBus"] = JSON.parse(response.data["addressBus"]); | |||
response.data["contactTel"] = JSON.parse(response.data["contactTel"]); | |||
response.data["faxNo"] = JSON.parse(response.data["faxNo"]); | |||
setUserData(response.data) | |||
} | |||
}); | |||
@@ -1,15 +1,13 @@ | |||
// material-ui | |||
import { | |||
Button, | |||
CardContent, FormControlLabel, | |||
CardContent, | |||
Grid, TextField, | |||
Typography | |||
Autocomplete | |||
} from '@mui/material'; | |||
import MainCard from "../../components/MainCard"; | |||
import {useForm} from "react-hook-form"; | |||
import { useState} from "react"; | |||
import Checkbox from "@mui/material/Checkbox"; | |||
import * as React from "react"; | |||
// ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
@@ -17,8 +15,7 @@ import * as React from "react"; | |||
const UserSearchForm_Individual = ({applySearch}) => { | |||
const [type, setType] = useState([]); | |||
const [locked, setLocked] = useState(false); | |||
const [accountFilter, setAccountFilter] = useState("Active"); | |||
const { reset, register, handleSubmit } = useForm() | |||
const onSubmit = (data) => { | |||
@@ -34,14 +31,13 @@ const UserSearchForm_Individual = ({applySearch}) => { | |||
fullName: data.fullName, | |||
email: data.email, | |||
phone: data.phone, | |||
locked: locked, | |||
accountFilter: accountFilter, | |||
}; | |||
applySearch(temp); | |||
}; | |||
function resetForm(){ | |||
setType([]); | |||
setLocked(false); | |||
reset(); | |||
} | |||
@@ -97,18 +93,23 @@ const UserSearchForm_Individual = ({applySearch}) => { | |||
</Grid> | |||
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
<FormControlLabel | |||
control={ | |||
<Checkbox | |||
checked={locked} | |||
onChange={(event) => setLocked(event.target.checked)} | |||
name="checked" | |||
color="primary" | |||
size="small" | |||
<Autocomplete | |||
{...register("accountFilter")} | |||
disablePortal | |||
id="accountFilter" | |||
options={["Active","Locked","Not verified"]} | |||
value={accountFilter} | |||
onChange={(event, newValue) => { | |||
if (newValue !== null){ | |||
setAccountFilter(newValue); | |||
} | |||
}} | |||
renderInput={(params) => ( | |||
<TextField {...params} | |||
label="Status" | |||
/> | |||
)} | |||
/> | |||
} | |||
label={<Typography variant="h6">Locked</Typography>} | |||
/> | |||
</Grid> | |||
{/*<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>*/} | |||
{/* <TextField*/} | |||
@@ -2,19 +2,19 @@ | |||
import * as React from 'react'; | |||
import { | |||
DataGrid, | |||
GridActionsCellItem, | |||
GridActionsCellItem | |||
} from "@mui/x-data-grid"; | |||
import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
import HighlightOff from '@mui/icons-material/HighlightOff'; | |||
import CheckCircleOutline from '@mui/icons-material/CheckCircleOutline'; | |||
import {useEffect} from "react"; | |||
import {useNavigate} from "react-router-dom"; | |||
import { useTheme } from '@mui/material/styles'; | |||
import Checkbox from '@mui/material/Checkbox'; | |||
import * as DateUtils from "../../utils/DateUtils"; | |||
// ==============================|| EVENT TABLE ||============================== // | |||
export default function UserTable_Individual({recordList}) { | |||
const [rows, setRows] = React.useState(recordList); | |||
const [rowModesModel] = React.useState({}); | |||
const theme = useTheme(); | |||
const navigate = useNavigate() | |||
@@ -52,34 +52,82 @@ export default function UserTable_Individual({recordList}) { | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'name', | |||
field: 'name', | |||
headerName: 'Full Name', | |||
id: 'enName', | |||
field: 'enName', | |||
headerName: 'Name (Eng)', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'email', | |||
field: 'email', | |||
id: 'chName', | |||
field: 'chName', | |||
headerName: 'Name (Ch)', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'contactTel', | |||
field: 'contactTel', | |||
headerName: 'Tel.', | |||
flex: 1, | |||
valueGetter:(params)=>{ | |||
if(params.value){ | |||
let tel = JSON.parse(params.value); | |||
return "+"+tel.countryCode+ " "+tel.phoneNumber; | |||
} | |||
} | |||
}, | |||
{ | |||
id: 'emailAddress', | |||
field: 'emailAddress', | |||
headerName: 'Email', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'lastLogin', | |||
field: 'lastLogin', | |||
headerName: 'Last Login', | |||
flex: 1, | |||
valueGetter:(params)=>{ | |||
if(params.value){ | |||
return DateUtils.datetimeStr(params.value); | |||
} | |||
} | |||
}, | |||
{ | |||
id: 'locked', | |||
field: 'locked', | |||
type: 'bool', | |||
headerName: 'Locked', | |||
headerName: 'Status', | |||
flex: 1, | |||
renderCell: (params) => { | |||
return ( | |||
<Checkbox | |||
theme={theme} | |||
key="locked" | |||
checked={params.row.locked} | |||
color="primary" | |||
size="small" | |||
//onChange={handleChange} | |||
/> | |||
); | |||
valueGetter:(params)=>{ | |||
if(params.value){ | |||
return "Locked"; | |||
}else{ | |||
return "Active"; | |||
} | |||
} | |||
}, | |||
{ | |||
field: 'verifiedDate', | |||
type: 'actions', | |||
headerName: 'Verified', | |||
width: 100, | |||
cellClassName: 'actions', | |||
getActions: (params) => { | |||
if(params.row.verifiedDate) | |||
return [ | |||
<GridActionsCellItem | |||
key="" | |||
icon={<CheckCircleOutline/>} | |||
color="success" | |||
/>]; | |||
return [ | |||
<GridActionsCellItem | |||
key="" | |||
icon={<HighlightOff/>} | |||
color="error" | |||
/>]; | |||
}, | |||
}, | |||
]; | |||
@@ -1,15 +1,13 @@ | |||
// material-ui | |||
import { | |||
Button, | |||
CardContent, FormControlLabel, | |||
Grid, TextField, | |||
Typography | |||
CardContent, Autocomplete, | |||
Grid, TextField | |||
} from '@mui/material'; | |||
import MainCard from "../../components/MainCard"; | |||
import {useForm} from "react-hook-form"; | |||
import { useState} from "react"; | |||
import Checkbox from "@mui/material/Checkbox"; | |||
import * as React from "react"; | |||
// ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
@@ -17,7 +15,7 @@ import * as React from "react"; | |||
const UserSearchForm_Organization = ({applySearch}) => { | |||
const [type, setType] = useState([]); | |||
const [locked, setLocked] = useState(false); | |||
const [accountFilter, setAccountFilter] = useState("Active"); | |||
const { reset, register, handleSubmit } = useForm() | |||
@@ -34,14 +32,15 @@ const UserSearchForm_Organization = ({applySearch}) => { | |||
fullName: data.fullName, | |||
email: data.email, | |||
phone: data.phone, | |||
locked: locked, | |||
brNoStr: data.brNoStr, | |||
orgName: data.orgName, | |||
accountFilter: accountFilter, | |||
}; | |||
applySearch(temp); | |||
}; | |||
function resetForm(){ | |||
setType([]); | |||
setLocked(false); | |||
reset(); | |||
} | |||
@@ -60,6 +59,25 @@ const UserSearchForm_Organization = ({applySearch}) => { | |||
{/*row 2*/} | |||
<Grid container alignItems={"center"}> | |||
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
<TextField | |||
fullWidth | |||
{...register("orgName")} | |||
id="orgName" | |||
label="Org Name" | |||
/> | |||
</Grid> | |||
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
<TextField | |||
fullWidth | |||
{...register("brNoStr")} | |||
id="brNoStr" | |||
label="BR No." | |||
/> | |||
</Grid> | |||
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
<TextField | |||
fullWidth | |||
@@ -97,18 +115,23 @@ const UserSearchForm_Organization = ({applySearch}) => { | |||
</Grid> | |||
<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
<FormControlLabel | |||
control={ | |||
<Checkbox | |||
checked={locked} | |||
onChange={(event) => setLocked(event.target.checked)} | |||
name="checked" | |||
color="primary" | |||
size="small" | |||
<Autocomplete | |||
{...register("accountFilter")} | |||
disablePortal | |||
id="accountFilter" | |||
options={["Active","Locked","Not verified"]} | |||
value={accountFilter} | |||
onChange={(event, newValue) => { | |||
if (newValue !== null){ | |||
setAccountFilter(newValue); | |||
} | |||
}} | |||
renderInput={(params) => ( | |||
<TextField {...params} | |||
label="Status" | |||
/> | |||
)} | |||
/> | |||
} | |||
label={<Typography variant="h6">Locked</Typography>} | |||
/> | |||
</Grid> | |||
{/*<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>*/} | |||
{/* <TextField*/} | |||
@@ -7,14 +7,13 @@ import { | |||
import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
import {useEffect} from "react"; | |||
import {useNavigate} from "react-router-dom"; | |||
import { useTheme } from '@mui/material/styles'; | |||
import Checkbox from '@mui/material/Checkbox'; | |||
import HighlightOff from '@mui/icons-material/HighlightOff'; | |||
import CheckCircleOutline from '@mui/icons-material/CheckCircleOutline'; | |||
// ==============================|| EVENT TABLE ||============================== // | |||
export default function UserTable_Organization({recordList}) { | |||
const [rows, setRows] = React.useState(recordList); | |||
const [rowModesModel] = React.useState({}); | |||
const theme = useTheme(); | |||
const navigate = useNavigate() | |||
@@ -52,34 +51,81 @@ export default function UserTable_Organization({recordList}) { | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'name', | |||
field: 'name', | |||
headerName: 'Full Name', | |||
id: 'enName', | |||
field: 'enName', | |||
headerName: 'Name (Eng)', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'email', | |||
field: 'email', | |||
headerName: 'Email', | |||
id: 'chName', | |||
field: 'chName', | |||
headerName: 'Name (Ch)', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'enCompanyName', | |||
field: 'enCompanyName', | |||
headerName: 'Company(Eng)', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'chCompanyName', | |||
field: 'chCompanyName', | |||
headerName: 'Company(Ch)', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'brNo', | |||
field: 'brNo', | |||
headerName: 'Br No', | |||
flex: 1, | |||
}, | |||
{ | |||
id: 'lastLogin', | |||
field: 'lastLogin', | |||
headerName: 'Last Login', | |||
flex: 1, | |||
valueGetter:(params)=>{ | |||
if(params.value){ | |||
return DateUtils.datetimeStr(params.value); | |||
} | |||
} | |||
}, | |||
{ | |||
id: 'locked', | |||
field: 'locked', | |||
type: 'bool', | |||
headerName: 'Locked', | |||
headerName: 'Status', | |||
flex: 1, | |||
renderCell: (params) => { | |||
return ( | |||
<Checkbox | |||
theme={theme} | |||
key="locked" | |||
checked={params.row.locked} | |||
color="primary" | |||
size="small" | |||
//onChange={handleChange} | |||
/> | |||
); | |||
valueGetter:(params)=>{ | |||
if(params.value){ | |||
return "Locked"; | |||
}else{ | |||
return "Active"; | |||
} | |||
} | |||
}, | |||
{ | |||
field: 'verifiedDate', | |||
type: 'actions', | |||
headerName: 'Verified', | |||
width: 100, | |||
cellClassName: 'actions', | |||
getActions: (params) => { | |||
if(params.row.verifiedDate) | |||
return [ | |||
<GridActionsCellItem | |||
key="" | |||
icon={<CheckCircleOutline/>} | |||
color="success" | |||
/>]; | |||
return [ | |||
<GridActionsCellItem | |||
key="" | |||
icon={<HighlightOff/>} | |||
color="error" | |||
/>]; | |||
}, | |||
}, | |||
]; | |||
@@ -17,7 +17,7 @@ const UserGroupSearchPage = Loadable(lazy(() => import('pages/pnspsUserGroupSear | |||
const UserGroupDetailPage = Loadable(lazy(() => import('pages/pnspsUserGroupDetailPage'))); | |||
const OrganizationSearchPage = Loadable(lazy(() => import('pages/OrganizationSearchPage'))); | |||
const OrganizationDetailPage = Loadable(lazy(() => import('pages/OrganizationDetailPage'))); | |||
const OrganizationDetailPage_fromUser = Loadable(lazy(() => import('pages/OrganizationDetailPage/index_loadFormUser'))); | |||
const OrganizationDetailPage_fromUser = Loadable(lazy(() => import('pages/OrganizationDetailPage_FromUser'))); | |||
// ==============================|| AUTH ROUTING ||============================== // | |||
@@ -1,32 +1,7 @@ | |||
import * as yup from 'yup'; | |||
export const idDocType = ["passport","HKID","CNID","BR","otherCert"]; | |||
export const district = ["北區","長洲區","大埔區","大嶼山區","東區","觀塘區","黃大仙區","九龍城區","葵青區","南區","南丫島區", | |||
"坪洲區","荃灣區","沙田區","深水埗區","屯門區","灣仔區","西貢區","油尖旺區","元朗區","中西區"]; | |||
export const country = ["中國香港","中國","中國澳門"]; | |||
export const validationSchema = ()=>{ | |||
return yup.object().shape({ | |||
username: yup.string().min(8,"用戶名稱最少8位").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('請輸入電郵格式').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位數字'), | |||
}); | |||
} | |||
export const accountFilter = [{display:"Active", value:"active"},{display:"Locked", value:"locked"},{display:"Not verified", value:"notVerified"}]; |
@@ -10,9 +10,12 @@ export const dateStr = (date) =>{ | |||
return dayjs(date).format("DD-MM-YYYY") | |||
}; | |||
const convertToDate = (date)=>{ | |||
export const convertToDate = (date)=>{ | |||
if(Array.isArray(date)){ | |||
return new Date(date[0],date[1],date[2],date[3],date[4],date[5]); | |||
} | |||
if(typeof date == 'number'){ | |||
return new Date(date); | |||
} | |||
return date; | |||
} |
@@ -3,8 +3,12 @@ import DeleteIcon from '@mui/icons-material/DeleteForever'; | |||
import EditIcon from '@mui/icons-material/Edit'; | |||
import ViewIcon from '@mui/icons-material/Visibility'; | |||
import DownloadICon from '@mui/icons-material/Download'; | |||
import VaildIcon from '@mui/icons-material/CheckCircleOutline'; | |||
import InVaildIcon from '@mui/icons-material/HighlightOff'; | |||
export const Delete = DeleteIcon; | |||
export const Edit = EditIcon; | |||
export const View = ViewIcon; | |||
export const Download = DownloadICon; | |||
export const Download = DownloadICon; | |||
export const Vaild = VaildIcon; | |||
export const Invaild = InVaildIcon; |