Alex Cheung 2 år sedan
förälder
incheckning
0adb790e55
15 ändrade filer med 530 tillägg och 322 borttagningar
  1. +28
    -27
      src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js
  2. +2
    -3
      src/pages/OrganizationDetailPage_FromUser/index.js
  3. +1
    -1
      src/pages/OrganizationSearchPage/OrganizationTable.js
  4. +16
    -16
      src/pages/pnspsUserDetailPage_Individual/UserInformationCard_Individual.js
  5. +0
    -1
      src/pages/pnspsUserDetailPage_Individual/index.js
  6. +269
    -162
      src/pages/pnspsUserDetailPage_Organization/UserInformationCard_Organization.js
  7. +4
    -2
      src/pages/pnspsUserDetailPage_Organization/index.js
  8. +20
    -19
      src/pages/pnspsUserSearchPage_Individual/UserSearchForm_Individual.js
  9. +70
    -22
      src/pages/pnspsUserSearchPage_Individual/UserTable_Individual.js
  10. +41
    -18
      src/pages/pnspsUserSearchPage_Organization/UserSearchForm_Organization.js
  11. +68
    -22
      src/pages/pnspsUserSearchPage_Organization/UserTable_Organization.js
  12. +1
    -1
      src/routes/SettingRoutes.js
  13. +1
    -26
      src/utils/ComboData.js
  14. +4
    -1
      src/utils/DateUtils.js
  15. +5
    -1
      src/utils/IconUtils.js

src/pages/OrganizationDetailPage/OrganizationCard_loadFromUser.js → src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js Visa fil

@@ -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;

src/pages/OrganizationDetailPage/index_loadFormUser.js → src/pages/OrganizationDetailPage_FromUser/index.js Visa fil

@@ -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;

+ 1
- 1
src/pages/OrganizationSearchPage/OrganizationTable.js Visa fil

@@ -19,7 +19,7 @@ export default function OrganizationTable({recordList}) {
}, [recordList]);

const handleActionClick = (id) => () => {
navigate('/orgUser/'+ id);
navigate('/org/'+ id);
};

const columns = [


+ 16
- 16
src/pages/pnspsUserDetailPage_Individual/UserInformationCard_Individual.js Visa fil

@@ -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>


+ 0
- 1
src/pages/pnspsUserDetailPage_Individual/index.js Visa fil

@@ -20,7 +20,6 @@ const UserMaintainPage_Individual = () => {


useEffect(()=>{
console.log(userData);
loadData();
},[]);



+ 269
- 162
src/pages/pnspsUserDetailPage_Organization/UserInformationCard_Organization.js Visa fil

@@ -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
- 2
src/pages/pnspsUserDetailPage_Organization/index.js Visa fil

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


+ 20
- 19
src/pages/pnspsUserSearchPage_Individual/UserSearchForm_Individual.js Visa fil

@@ -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*/}


+ 70
- 22
src/pages/pnspsUserSearchPage_Individual/UserTable_Individual.js Visa fil

@@ -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"
/>];
},
},
];


+ 41
- 18
src/pages/pnspsUserSearchPage_Organization/UserSearchForm_Organization.js Visa fil

@@ -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*/}


+ 68
- 22
src/pages/pnspsUserSearchPage_Organization/UserTable_Organization.js Visa fil

@@ -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"
/>];
},
},
];


+ 1
- 1
src/routes/SettingRoutes.js Visa fil

@@ -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
- 26
src/utils/ComboData.js Visa fil

@@ -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"}];

+ 4
- 1
src/utils/DateUtils.js Visa fil

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

+ 5
- 1
src/utils/IconUtils.js Visa fil

@@ -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;

Laddar…
Avbryt
Spara