Browse Source

Merge branch 'master' into iAmSmart

master
Anna Ho 1 year ago
parent
commit
3a1bf7c5ef
40 changed files with 1289 additions and 377 deletions
  1. +1
    -1
      src/components/FiDataGrid.js
  2. +1
    -1
      src/components/MainCard.js
  3. +19
    -17
      src/layout/MainLayout/Header/HeaderContent/Profile/index.js
  4. +26
    -22
      src/layout/MainLayout/Header/index.js
  5. +311
    -0
      src/pages/EmailTemplate/Detail_GLD/EmailTemplateDetails.js
  6. +155
    -0
      src/pages/EmailTemplate/Detail_GLD/index.js
  7. +100
    -0
      src/pages/EmailTemplate/Search_GLD/DataGrid.js
  8. +100
    -0
      src/pages/EmailTemplate/Search_GLD/index.js
  9. +24
    -12
      src/pages/OrganizationDetailPage/OrganizationCard.js
  10. +1
    -1
      src/pages/OrganizationDetailPage/index.js
  11. +22
    -9
      src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js
  12. +1
    -1
      src/pages/OrganizationDetailPage_FromUser/index.js
  13. +1
    -1
      src/pages/OrganizationSearchPage/index.js
  14. +3
    -3
      src/pages/Proof/Payment/Pay.js
  15. +2
    -2
      src/pages/Proof/Payment/Pay_Creditor.js
  16. +1
    -1
      src/pages/Proof/Reply_Public/ApplicationDetails.js
  17. +1
    -1
      src/pages/Proof/Search_GLD/SearchForm.js
  18. +1
    -1
      src/pages/Proof/Search_Public/DataGrid.js
  19. +12
    -7
      src/pages/PublicNotice/ApplyForm/PublicNoticeApplyForm.js
  20. +15
    -15
      src/pages/PublicNotice/ApplyForm/index.js
  21. +39
    -28
      src/pages/PublicNotice/Details_Public/ApplicationDetailCard.js
  22. +25
    -25
      src/pages/PublicNotice/ListPanel/BaseGrid.js
  23. +26
    -26
      src/pages/PublicNotice/ListPanel/PendingPaymentTab.js
  24. +1
    -1
      src/pages/PublicNotice/ListPanel/SearchPublicNoticeForm.js
  25. +28
    -28
      src/pages/PublicNotice/ListPanel/SearchPublicNoticeTable.js
  26. +1
    -1
      src/pages/PublicNotice/Search_GLD/SearchForm.js
  27. +1
    -1
      src/pages/User/DetailPage/index.js
  28. +29
    -16
      src/pages/User/DetailsPage_Organization/UserInformationCard_Organization.js
  29. +1
    -1
      src/pages/User/DetailsPage_Organization/index.js
  30. +9
    -0
      src/pages/User/SearchPage/UserSearchForm.js
  31. +1
    -1
      src/pages/User/SearchPage_Organization/index.js
  32. +104
    -40
      src/pages/authentication/auth-forms/BusCustomFormWizard.js
  33. +62
    -8
      src/pages/authentication/auth-forms/CustomFormWizard.js
  34. +1
    -0
      src/pages/authentication/auth-forms/PreviewUploadFileTable.js
  35. +1
    -0
      src/pages/authentication/auth-forms/UploadFileTable.js
  36. +10
    -3
      src/pages/pnspsNotifyTest/index.js
  37. +10
    -0
      src/routes/SettingRoutes.js
  38. +9
    -2
      src/utils/ApiPathConst.js
  39. +111
    -88
      src/utils/CommonFunction.js
  40. +23
    -13
      src/utils/FieldUtils.js

+ 1
- 1
src/components/FiDataGrid.js View File

@@ -14,7 +14,7 @@ export function FiDataGrid({ rows, columns, sx, autoHeight,
const [_columns, set_columns] = React.useState([]);
const [_rowModesModel, set_rowModesModel] = React.useState({});
const [_editMode, set_editMode] = React.useState("row");
const [_pageSizeOptions, set_pageSizeOptions] = React.useState([5, 10, 25]);
const [_pageSizeOptions, set_pageSizeOptions] = React.useState([10, 25, 50]);

const [_autoHeight, set_autoHeight] = React.useState(true);
const [myHideFooterSelectedRowCount, setMyHideFooterSelectedRowCount] = React.useState(true);


+ 1
- 1
src/components/MainCard.js View File

@@ -62,7 +62,7 @@ const MainCard = forwardRef(
fontFamily: theme.typography.fontFamily,
fontSize: '0.75rem'
},
maxWidth: { xs: 700, sm: 900, md: 1000, lg: 1300, xl: 1850 },
// maxWidth: { xs: 700, sm: 900, md: 1000, lg: 1300, xl: 1850 },
// minWidth: { xs: 600, sm: 800, md: 900, lg: 1000, xl: 1000 },
margin: { xs: 2.5, md: 3 },
// '& > *': {


+ 19
- 17
src/layout/MainLayout/Header/HeaderContent/Profile/index.js View File

@@ -14,20 +14,22 @@ import {
Paper,
Popper,
Stack,
Tab,
Tabs,
// Tab,
// Tabs,
Typography
} from '@mui/material';

// project import
import MainCard from 'components/MainCard';
import Transitions from 'components/@extended/Transitions';
import ProfileTab from './ProfileTab';
import SettingTab from './SettingTab';
// import ProfileTab from './ProfileTab';
// import SettingTab from './SettingTab';

// assets
import avatar1 from 'assets/images/users/avatar-1.png';
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
import { LogoutOutlined,
// SettingOutlined, UserOutlined
} from '@ant-design/icons';
import { handleLogoutFunction } from 'auth/index';
import {useNavigate} from "react-router-dom";
import {useDispatch} from "react-redux";
@@ -48,12 +50,12 @@ TabPanel.propTypes = {
value: PropTypes.any.isRequired
};

function a11yProps(index) {
return {
id: `profile-tab-${index}`,
'aria-controls': `profile-tabpanel-${index}`
};
}
// function a11yProps(index) {
// return {
// id: `profile-tab-${index}`,
// 'aria-controls': `profile-tabpanel-${index}`
// };
// }

// ==============================|| HEADER CONTENT - PROFILE ||============================== //

@@ -82,11 +84,11 @@ const Profile = () => {
setOpen(false);
};

const [value, setValue] = useState(0);
// const [value, setValue] = useState(0);

const handleChange = (event, newValue) => {
setValue(newValue);
};
// const handleChange = (event, newValue) => {
// setValue(newValue);
// };

const iconBackColorOpen = 'grey.300';

@@ -165,7 +167,7 @@ const Profile = () => {
</Grid>
</Grid>
</CardContent>
{open && (
{/* {open && (
<>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs variant="fullWidth" value={value} onChange={handleChange} aria-label="profile tabs">
@@ -202,7 +204,7 @@ const Profile = () => {
<SettingTab />
</TabPanel>
</>
)}
)} */}
</MainCard>
</ClickAwayListener>
</Paper>


+ 26
- 22
src/layout/MainLayout/Header/index.js View File

@@ -74,81 +74,85 @@ function Header(props) {
isGLDLoggedIn() ?
<div id="adminContent">
<li>
<Link className="dashboard" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:1}} >Dashboard</Typography></Link>
<Link className="dashboard" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ ml: 1 }} >Dashboard</Typography></Link>
</li>
<li>
<Link className="application" to='/application/search'><Typography variant={"headerTitle1"} sx={{ml:1}}>Application</Typography></Link>
<Link className="application" to='/application/search'><Typography variant={"headerTitle1"} sx={{ ml: 1 }}>Application</Typography></Link>
</li>
<li>
<Link className="proof" to='/proof/search'><Typography variant={"headerTitle1"} sx={{ml:2}}>Proof</Typography></Link>
<Link className="proof" to='/proof/search'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Proof</Typography></Link>
</li>
<li>
<Link className="payment" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>Payment</Typography></Link>
<Link className="payment" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Payment</Typography></Link>
</li>
<li>
<Link className="client" ><Typography variant={"headerTitle1"} sx={{ml:2}}>Client</Typography><KeyboardArrowDownIcon /></Link>
<Link className="client" ><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Client</Typography><KeyboardArrowDownIcon /></Link>
<ul className='dropdown'>
<li>
<Link className="userSearchview" to='/userSearchview'><Typography variant={"headerTitle1"} sx={{ml:2}}>Users (GLD)</Typography></Link>
<Link className="userSearchview" to='/userSearchview'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Users (GLD)</Typography></Link>
</li>
<li>
<Link className="indUser" to='/indUser'><Typography variant={"headerTitle1"} sx={{ml:2}}>Users (Individual)</Typography></Link>
<Link className="indUser" to='/indUser'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Users (Individual)</Typography></Link>
</li>
<li>
<Link className="orgUser" to='/orgUser'><Typography variant={"headerTitle1"} sx={{ml:2}}>Users (Organization)</Typography></Link>
<Link className="orgUser" to='/orgUser'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Users (Organisation)</Typography></Link>
</li>
<li>
<Link className="org" to='/org'><Typography variant={"headerTitle1"} sx={{ml:2}}>Organization</Typography></Link>
<Link className="org" to='/org'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Organisation</Typography></Link>
</li>
<li>
<Link className="usergroupSearchview" to='/usergroupSearchview'><Typography variant={"headerTitle1"} sx={{ml:2}}>User Group</Typography></Link>
<Link className="usergroupSearchview" to='/usergroupSearchview'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>User Group</Typography></Link>
</li>

</ul>
</li>
<li>
<Link className="logout" onClick={handleLogout}><Typography variant={"headerTitle1"} sx={{ml:2}}>Logout</Typography></Link>
<Link className="emailTemplate" to='/emailTemplate'><Typography variant={"headerTitle1"} sx={{ ml: 0 }}>Email Template</Typography></Link>
</li>
{/* <li>
<Link className="logout" onClick={handleLogout}><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>Logout</Typography></Link>
</li> */}
</div>
:
<div id="individualUserContent">
<li>
<Link className="dashboard" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>主頁</Typography></Link>
<Link className="dashboard" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>主頁</Typography></Link>
</li>
<li>
<Link className="myDocumet" to='/publicNotice'><Typography variant={"headerTitle1"} sx={{ml:0.5}}>我的公共啟事</Typography></Link>
<Link className="myDocumet" to='/publicNotice'><Typography variant={"headerTitle1"} sx={{ ml: 0.5 }}>我的公共啟事</Typography></Link>
</li>
<li>
<Link className="documentRecord" to='/proof/search'><Typography variant={"headerTitle1"} sx={{ml:1.5}}>校對記錄</Typography></Link>
<Link className="documentRecord" to='/proof/search'><Typography variant={"headerTitle1"} sx={{ ml: 1.5 }}>校對記錄</Typography></Link>
</li>
<li>
<Link className="paymentRecord" to='/paymentPage/search'><Typography variant={"headerTitle1"} sx={{ml:1.5}}>付款記錄</Typography></Link>
<Link className="paymentRecord" to='/paymentPage/search'><Typography variant={"headerTitle1"} sx={{ ml: 1.5 }}>付款記錄</Typography></Link>
</li>
<li>
<Link className="userSetting" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>設定</Typography><KeyboardArrowDownIcon /></Link>
<Link className="userSetting" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>設定</Typography><KeyboardArrowDownIcon /></Link>
{isPrimaryLoggedIn() ?
<ul className='dropdown'>

<li>
<Link className="manageOrgUser" to='setting/manageUser'><Typography variant={"headerTitle1"} sx={{ml:2}}>公司/機構用戶記錄</Typography></Link>
<Link className="manageOrgUser" to='setting/manageUser'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>公司/機構用戶記錄</Typography></Link>
</li>
</ul>
:
<></>
}
</li>
<li>
<Link className="logout" onClick={handleLogout}><Typography variant={"headerTitle1"} sx={{ml:2}}>登出</Typography></Link>
</li>
{/* <li>
<Link className="logout" onClick={handleLogout}><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>登出</Typography></Link>
</li> */}
</div>
);

const logoutContent = (
<div>
<li>
<Link className="login" to='/login'><Typography variant={"headerTitle1"} sx={{ml:2}}>登入</Typography></Link>
<Link className="login" to='/login'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>登入</Typography></Link>
</li>
<li>
<Link className="register" to='/register'><Typography variant={"headerTitle1"} sx={{ml:2}}>申請</Typography></Link>
<Link className="register" to='/register'><Typography variant={"headerTitle1"} sx={{ ml: 2 }}>申請</Typography></Link>
</li>
</div>
);


+ 311
- 0
src/pages/EmailTemplate/Detail_GLD/EmailTemplateDetails.js View File

@@ -0,0 +1,311 @@
// material-ui
import {
FormControl,
Grid,
Typography,
FormLabel,
OutlinedInput,
Button,
// TextField,
// Autocomplete,
} from '@mui/material';

// import { useFormik } from 'formik';
import * as React from "react";
import Loadable from 'components/Loadable';
const MainCard = Loadable(React.lazy(() => import('components/MainCard')));
import { useForm } from 'react-hook-form';
// ==============================|| DASHBOARD - DEFAULT ||============================== //
const ApplicationDetailCard = ({
formData,
_onSubmit,
handleDelete
}) => {

// const [data, setData] = React.useState({});

// React.useEffect(() => {
// if (formData) {
// setData(formData);
// }
// }, [formData]);

// const formik = useFormik({
// enableReinitialize: true,
// initialValues: data,
// });

const DisplayField = ({ name, width, value, rows = 1, disabled = false }) => {
return <OutlinedInput
fullWidth
multiline
disabled={disabled}
size="small"
// onChange={formik.handleChange}
{...register(name,
{
value: value,
})}
id={name}
name={name}
variant="outlined"
maxRows={6}
rows={rows}
sx={
{
"& .Mui-disabled": {
WebkitTextFillColor: "#000000",
background: "#f8f8f8",
},
// "& .MuiInputBase-input.Mui-disabled": {
// WebkitTextFillColor: "#000000",
// background: "#f8f8f8",
// },
width: width ? width : '100%'
}
}
/>;
}

const { register, handleSubmit } = useForm()


// const DisplaySelection = ({ name = "test", value = "", onChange }) => {
// return <Autocomplete
// {...register(name)}
// disablePortal
// id={name}
// options={formData}
// vale={value}
// onChange={onChange}
// renderInput={(params) => (
// <TextField {...params}
// InputLabelProps={{
// shrink: true
// }}
// />
// )}
// />
// }
return (
<MainCard
id={"emailTemplateMainCard"}
border={false}
content={false}
>
<Typography variant="h4" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}>
Maintain Email Template
</Typography>
<form onSubmit={handleSubmit(_onSubmit)}>
<Grid container direction="column">
<Grid item xs={12} md={12} lg={12}>
<Grid container direction="row" justifyContent="space-between"
alignItems="center">
{/* <Grid item xs={12} md={6} lg={6} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Email Key:</FormLabel>
</Grid>
<Grid item xs={12} md={9} lg={9}>
<DisplaySelection

/>
</Grid>
</Grid>
</Grid> */}
<Grid item xs={12} md={6} lg={6} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel required>Key:</FormLabel>
</Grid>
<Grid item xs={12} md={9} lg={9}>
<DisplayField
name={"tempKey"}
value={formData?.tempKey}
/>
</Grid>
</Grid>
</Grid>
<Grid item xs={12} md={5} lg={5} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Description:</FormLabel>
</Grid>

<Grid item xs={12} md={9} lg={9}>
<FormControl variant="outlined" fullWidth disabled >
<DisplayField
name="description"
value={formData?.description}
/>
</FormControl>
</Grid>
</Grid>
</Grid>
</Grid>

<Grid container direction="row" justifyContent="space-between"
alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}>
<Grid item xs={12} md={1.5} lg={1.5}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Params:</FormLabel>
</Grid>
<Grid item xs={12} md={10.5} lg={10.5}>
<DisplayField
name="params"
value={formData?.params}
/>
</Grid>
</Grid>
</Grid>
</Grid>

<Grid container direction="row" justifyContent="space-between"
alignItems="center">
<Grid item xs={12} md={6} lg={6} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Subject (Cht):</FormLabel>
</Grid>

<Grid item xs={12} md={9} lg={9}>
<DisplayField
name="subjectCht"
value={formData?.subjectCht}
rows={2}
/>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container direction="row" justifyContent="space-between"
alignItems="center" sx={{ mb: 1 }}>
<Grid item xs={12} md={1.5} lg={1.5}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Content (Cht):</FormLabel>
</Grid>

<Grid item xs={12} md={10.5} lg={10.5}>
<DisplayField
name="contentCht"
value={formData?.contentCht}
rows={4}
/>
</Grid>
</Grid>
<Grid container direction="row" justifyContent="space-between"
alignItems="center">
<Grid item xs={12} md={6} lg={6} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Subject (Chs):</FormLabel>
</Grid>

<Grid item xs={12} md={9} lg={9}>
<DisplayField
name="subjectChs"
value={formData?.subjectChs}
rows={2}
/>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container direction="row" justifyContent="space-between"
alignItems="center" sx={{ mb: 1 }}>
<Grid item xs={12} md={1.5} lg={1.5}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Content (Chs):</FormLabel>
</Grid>

<Grid item xs={12} md={10.5} lg={10.5}>
<DisplayField
name="contentChs"
value={formData?.contentChs}
rows={4}
/>
</Grid>
</Grid>
<Grid container direction="row" justifyContent="space-between"
alignItems="center">
<Grid item xs={12} md={6} lg={6} sx={{ mb: 1 }}>
<Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Subject (Eng):</FormLabel>
</Grid>

<Grid item xs={12} md={9} lg={9}>
<DisplayField
name="subjectEng"
value={formData?.subjectEng}
rows={2}
/>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container direction="row" justifyContent="space-between"
alignItems="center" sx={{ mb: 1 }}>
<Grid item xs={12} md={1.5} lg={1.5}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel>Content (Eng):</FormLabel>
</Grid>

<Grid item xs={12} md={10.5} lg={10.5}>
<DisplayField
name="contentEng"
value={formData?.contentEng}
rows={4}
/>
</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">
<Grid item sx={{ ml: 3, mr: 3 }}>
<Button
size="large"
color="error"
variant="contained"
onClick={handleDelete}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}
>
<Typography variant="h5">Delete</Typography>
</Button>
</Grid>
<Grid item sx={{ ml: 3, mr: 3 }}>
<Button
size="large"
variant="contained"
type="submit"
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}
>
<Typography variant="h5">Save</Typography>
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</form>
</MainCard>
);
};

export default ApplicationDetailCard;

+ 155
- 0
src/pages/EmailTemplate/Detail_GLD/index.js View File

@@ -0,0 +1,155 @@
// material-ui
import {
Grid,
Typography,
Stack,
Box,
Button
} from '@mui/material';
import * as UrlUtils from "utils/ApiPathConst";
import * as React from "react";
import ForwardIcon from '@mui/icons-material/Forward';

import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
const EmailTemplate = Loadable(React.lazy(() => import('pages/EmailTemplate/Detail_GLD/EmailTemplateDetails')))
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import { useParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
import { notifyDeleteSuccess, notifySaveSuccess } from 'utils/CommonFunction';
const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: '100%',
height: '100%',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const Index = () => {

const [record, setRecord] = React.useState(null);
const [onReady, setOnReady] = React.useState(false);
const params = useParams()
const navigate = useNavigate()

React.useLayoutEffect(() => {
loadForm();
}, []);

React.useLayoutEffect(() => {
if(record !== null || params.id <= 0) setOnReady(true);
}, [record]);

const loadForm = () => {
if (params.id > 0) {
axios.get(`${UrlUtils.GET_EMAIL}/${params.id}`)
.then((response) => {
if (response.status === 200) {
console.log(response)
setRecord(response.data.data)
}
})
.catch(error => {
console.log(error);
return false;
});
}
// HttpUtils.get({
// url: UrlUtils.GET_EMAIL,
// params: {
// id: params.id
// },
// onSuccess: (responseData) => {
// setRecord(responseData);
// }
// });
}

const onSubmit = (data) => {
axios.post(`${UrlUtils.POST_EMAIL_SAVE}`,
{
id: params.id > 0 ? params.id : null,
contentChs: data?.contentChs,
contentCht: data?.contentCht,
contentEng: data?.contentEng,
description: data?.description,
tempKey: data?.tempKey,
params: data?.params,
subjectChs: data?.subjectChs,
subjectCht: data?.subjectCht,
subjectEng: data?.subjectEng
}
).then((response) => {
if (response.status === 200) {
// location.reload();
navigate('/emailTemplate')
notifySaveSuccess()
}
})
.catch(error => {
console.log(error);
return false;
});
console.log(data)
}

const handleDelete = () => {
axios.delete(`${UrlUtils.DELETE_EMAIL}/${params.id}`,
)
.then((response) => {
console.log(response)
if (response.status === 204) {
// location.reload();
navigate('/emailTemplate');
notifyDeleteSuccess()
}
})
.catch(error => {
console.log(error);
return false;
});
}

return (
!onReady ?
<LoadingComponent />
:
(
<Grid container sx={{ minHeight: '110vh', backgroundColor: 'backgroundColor.default' }} direction="column" justifyContent="flex-start" alignItems="center" >
<Grid item xs={12} width="100%">
<div style={BackgroundHead} width="100%">
<Stack direction="row" height='70px'>
<Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>Email Template</Typography>
</Stack>
</div>
</Grid>
<Grid item xs={12} width="100%">
<Button title="Back" sx={{ ml: 6, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate("/emailTemplate") }}>
<ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
</Button>
</Grid>
{/*row 1*/}

<Grid item xs={12} md={12} width="100%">
<Grid item xs={12} md={12} sx={{ pt: 2, ml: 6, mr: 6, mb: 6}}>
<Box xs={12} md={12} sx={{ p: 4, borderRadius: '10px', backgroundColor: '#ffffff' }}>
<EmailTemplate
formData={record}
_onSubmit={onSubmit}
handleDelete={handleDelete}
/>
</Box>
</Grid>
</Grid>
{/*row 2*/}
</Grid >
)
);
};

export default Index;

+ 100
- 0
src/pages/EmailTemplate/Search_GLD/DataGrid.js View File

@@ -0,0 +1,100 @@
// material-ui
import * as React from 'react';
import { GridActionsCellItem, } from "@mui/x-data-grid";
import { FiDataGrid } from "components/FiDataGrid";
import EditIcon from '@mui/icons-material/Edit';
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";

// ==============================|| EVENT TABLE ||============================== //

export default function EmailTemplateTable({ recordList }) {
const [rows, setRows] = React.useState(recordList);

const navigate = useNavigate()

useEffect(() => {
setRows(recordList);
}, [recordList]);

const handleEditClick = (id) => () => {
navigate('/emailTemplate/' + id);
};

const columns = [
{
field: 'actions',
type: 'actions',
headerName: 'Actions',
width: 100,
cellClassName: 'actions',
getActions: ({ id }) => {
return [
<GridActionsCellItem
key="OutSave"
icon={<EditIcon />}
label="Edit"
className="textPrimary"
onClick={handleEditClick(id)}
color="primary"
/>]
},
},
{
id: 'tempKey',
field: 'tempKey',
headerName: 'Key',
flex: 1,
},
{
id: 'description',
field: 'description',
headerName: 'Description',
flex: 1,
},
{
id: 'params',
field: 'params',
headerName: 'Params',
flex: 1,
},
{
id: 'subjectCht',
field: 'subjectCht',
headerName: 'SubjectCht',
flex: 1,
},
{
id: 'subjectChs',
field: 'subjectChs',
headerName: 'SubjectChs',
flex: 1,
},
{
id: 'subjectEng',
field: 'subjectEng',
headerName: 'SubjectEng',
flex: 1,
},
];

function handleRowDoubleClick(params) {
navigate('/emailTemplate/' + params.id);
}

return (
<div style={{ height: "fit-content", width: '100%' }}>
<FiDataGrid
rows={rows}
columns={columns}
initialState={{
pagination: {
paginationModel: { page: 0, pageSize: 5 },
},
}}
onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'}
/>
</div>
);
}

+ 100
- 0
src/pages/EmailTemplate/Search_GLD/index.js View File

@@ -0,0 +1,100 @@
// material-ui
import {
Grid,
Typography,
Stack,
Button,
} from '@mui/material';
import * as UrlUtils from "utils/ApiPathConst";
import * as React from "react";
import * as HttpUtils from "utils/HttpUtils";

import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
const EmailTemplateTable = Loadable(React.lazy(() => import('pages/EmailTemplate/Search_GLD/DataGrid')))
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
import MainCard from 'components/MainCard';
const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: '100%',
height: '100%',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}
import { useNavigate } from "react-router";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const Index = () => {

const [record, setRecord] = React.useState([]);
const [onReady, setOnReady] = React.useState(false);
const navigate = useNavigate()

React.useLayoutEffect(() => {
loadForm();
}, []);

React.useLayoutEffect(() => {
setOnReady(true);
}, [record]);

const loadForm = () => {
HttpUtils.get({
url: UrlUtils.GET_EMAIL_LIST,
onSuccess: (responseData) => {
setRecord(responseData);
}
});
}

return (
!onReady ?
<LoadingComponent />
:
(
<Grid container sx={{ minHeight: '110vh', backgroundColor: 'backgroundColor.default' }} direction="column" justifyContent="flex-start" alignItems="center" >
<Grid item xs={12} width="100%">
<div style={BackgroundHead} width="100%">
<Stack direction="row" height='70px'>
<Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>Email Template</Typography>
</Stack>
</div>
</Grid>
{/*row 1*/}
<Grid item xs={12} md={12} lg={12} width="100%">
<MainCard elevation={0}
border={false}
content={false}
>
<EmailTemplateTable
recordList={record}
/>
</MainCard>
</Grid>
<Grid container direction="row"
justifyContent="space-between"
alignItems="center">
<Grid item xs={3} md={3} sx={{ ml: 3, mr: 1, mb: 3, mt: 3 }}>
<Button
size="large"
variant="contained"
onClick={()=>{navigate('/emailTemplate/-1')}}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
}}>
<AddCircleOutlineIcon sx={{ mb: 0.5 }} />
<Typography sx={{ ml: 1 }} variant="h5">New Email Template</Typography>
</Button>
</Grid>
</Grid>
</Grid >
)
);
};

export default Index;

+ 24
- 12
src/pages/OrganizationDetailPage/OrganizationCard.js View File

@@ -35,22 +35,34 @@ const OrganizationCard = ({ userData, loadDataFun, id }) => {
}
}, [currentUserData]);

function displayErrorMsg(errorMsg) {
return <Typography variant="errorMessage1">{errorMsg}</Typography>
}

const formik = useFormik({
enableReinitialize: true,
initialValues: currentUserData,
validationSchema: yup.object().shape({
enCompanyName: yup.string().max(255).required('請輸入英文名稱'),
chCompanyName: yup.string().max(255, '請輸入中文名稱').nullable(),
addressLine1: yup.string().max(255).required('請輸入第一行地址'),
addressLine2: yup.string().max(255, "length must <= 255"),
addressLine3: yup.string().max(255, "length must <= 255"),
fax_countryCode: yup.string().min(3, '請輸入國際區號').nullable(),
tel_countryCode: yup.string().min(3, '請輸入國際區號'),
phoneNumber: yup.string().min(8, '請輸入有效聯絡電話').required('請輸入聯絡電話'),
faxNumber: yup.string().min(8, '請輸入8位數字').nullable(),
brExpiryDate: yup.string().min(8).required('請輸入商業登記證有效日期'),
brNo: yup.string().min(8, '請輸入有效商業登記證號碼').max(8, '請輸入有效商業登記證號碼').required('請輸入商業登記證號碼'),
enCompanyName: yup.string().max(255).required(displayErrorMsg('請輸入英文名稱')),
chCompanyName: yup.string().max(255, displayErrorMsg('請輸入中文名稱')).nullable(),
addressLine1: yup.string().max(255).required(displayErrorMsg('請輸入第一行地址')),
addressLine2: yup.string().max(255, displayErrorMsg("length must <= 255")),
addressLine3: yup.string().max(255, displayErrorMsg("length must <= 255")),
fax_countryCode: yup.string().min(3, displayErrorMsg('請輸入國際區號')).nullable(),
tel_countryCode: yup.string().min(3, displayErrorMsg('請輸入國際區號')),
phoneNumber: yup.string().min(8, displayErrorMsg('請輸入有效聯絡電話')).required(displayErrorMsg('請輸入聯絡電話')),
faxNumber: yup.string().min(8, displayErrorMsg('請輸入8位數字')).nullable(),
brExpiryDate: yup.string().min(8).required(displayErrorMsg('請輸入商業登記證有效日期')),
brNo: yup.string().required(displayErrorMsg('請輸入商業登記證號碼')).test('checkBrNoFormat', displayErrorMsg(displayErrorMsg(`請輸入有效商業登記證號碼`)), function (value) {
var brNo_pattern = /[0-9]{8}-[0-9]{3}-(0[1-9]|1[012])-[0-9]{2}-[0-9A-Z]{1}/
if (value !== undefined) {
if (value.match(brNo_pattern)) {
return true
} else {
return false
}
}
}),
}),
onSubmit: vaule => {
console.log(vaule)
@@ -201,7 +213,7 @@ const OrganizationCard = ({ userData, loadDataFun, id }) => {
<Grid container spacing={1}>
<Grid item xs={12}>
<Typography variant="h4" sx={{mb: 2, mr: 3, borderBottom: "1px solid black" }}>
Organization Details
Organisation Details
</Typography>
</Grid>
<Grid item lg={4} >


+ 1
- 1
src/pages/OrganizationDetailPage/index.js View File

@@ -77,7 +77,7 @@ const OrganizationDetailPage = () => {
<Grid item xs={12}>
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4">Maintain Organization</Typography>
<Typography ml={15} color='#FFF' variant="h4">Maintain Organisation</Typography>
</Stack>
</div>
</Grid>


+ 22
- 9
src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js View File

@@ -1,6 +1,6 @@
// material-ui
import {
Grid, Button
Grid, Button, Typography
} from '@mui/material';
import MainCard from "../../components/MainCard";
import * as React from "react";
@@ -34,21 +34,34 @@ const OrganizationCard_loadFromUser = ({ userData, userId }) => {
}
}, [currentUserData]);

function displayErrorMsg(errorMsg) {
return <Typography variant="errorMessage1">{errorMsg}</Typography>
}

const formik = useFormik({
enableReinitialize: true,
initialValues: currentUserData,
validationSchema: yup.object().shape({
enCompanyName: yup.string().max(255, "請輸入英文名稱").required('請輸入英文名稱'),
chCompanyName: yup.string().max(255, '請輸入中文名稱').nullable(),
addressLine1: yup.string().max(255).required('請輸入第一行地址'),
enCompanyName: yup.string().max(255, displayErrorMsg("請輸入英文名稱")).required(displayErrorMsg('請輸入英文名稱')),
chCompanyName: yup.string().max(255, displayErrorMsg('請輸入中文名稱')).nullable(),
addressLine1: yup.string().max(255).required(displayErrorMsg('請輸入第一行地址')),
addressLine2: yup.string().max(255).nullable(),
addressLine3: yup.string().max(255).nullable(),
fax_countryCode: yup.string().min(3, "請輸入國際區號").nullable(),
tel_countryCode: yup.string().min(3, "請輸入國際區號"),
phoneNumber: yup.string().min(8, '請輸入有效聯絡電話').required('請輸入聯絡電話'),
fax_countryCode: yup.string().min(3, displayErrorMsg("請輸入國際區號")).nullable(),
tel_countryCode: yup.string().min(3, displayErrorMsg("請輸入國際區號")),
phoneNumber: yup.string().min(8, displayErrorMsg('請輸入有效聯絡電話')).required(displayErrorMsg('請輸入聯絡電話')),
faxNumber: yup.string().min(8).nullable(),
brExpiryDate: yup.string().min(8).required('請輸入商業登記證有效日期'),
brNo: yup.string().min(8, '請輸入有效商業登記證號碼').max(8, '請輸入有效商業登記證號碼').required('請輸入商業登記證號碼'),
brExpiryDate: yup.string().min(8).required(displayErrorMsg('請輸入商業登記證有效日期')),
brNo: yup.string().required(displayErrorMsg('請輸入商業登記證號碼')).test('checkBrNoFormat', displayErrorMsg(displayErrorMsg(`請輸入有效商業登記證號碼`)), function (value) {
var brNo_pattern = /[0-9]{8}-[0-9]{3}-(0[1-9]|1[012])-[0-9]{2}-[0-9A-Z]{1}/
if (value !== undefined) {
if (value.match(brNo_pattern)) {
return true
} else {
return false
}
}
}),
}),
onSubmit: values => {
HttpUtils.post({


+ 1
- 1
src/pages/OrganizationDetailPage_FromUser/index.js View File

@@ -66,7 +66,7 @@ const OrganizationDetailPage_FromUser = () => {
:
<Grid container rowSpacing={4.5} columnSpacing={2.75}>
<Grid item xs={12} sx={{mb: -2.25}}>
<Typography variant="h5">Organization (Create From User)</Typography>
<Typography variant="h5">Organisation (Create From User)</Typography>
</Grid>
{/*col 1*/}
<Grid item xs={12} >


+ 1
- 1
src/pages/OrganizationSearchPage/index.js View File

@@ -70,7 +70,7 @@ const OrganizationSearchPage = () => {
<Grid item xs={12}>
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4">View Organization</Typography>
<Typography ml={15} color='#FFF' variant="h4">View Organisation</Typography>
</Stack>
</div>
</Grid>


+ 3
- 3
src/pages/Proof/Payment/Pay.js View File

@@ -77,15 +77,15 @@ const Index = () => {
<center>
<Grid item xs={12} md={8} >
<Typography variant="h2" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
公共啟事:對完成及付款
公共啟事:對完成及付款
</Typography>

<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
我們已收到申請編號: {record?.appNo} 的稿件對確定及可付印的指示。
我們已收到申請編號: {record?.appNo} 的稿件對確定及可付印的指示。
<br /><br />
請於 <span style={{ color: "red" }}>{DateUtils.dateStr_Cht(record?.returnBeforeDate)} 下午 2:00 前</span> 完成繳費,我們將於收到繳費確認後處理刊出事宜。
<br /><br />
如你在憲報期數 {record?.issueYear} 年 {record?.issueVolume} 卷, 第 {record?.issueNo} 期內有多於一個公共啟事的申請,你可選擇完成所有此期所有稿件對確定後,於繳費期限前在「我的公共啟事」內合併付款。
如你在憲報期數 {record?.issueYear} 年 {record?.issueVolume} 卷, 第 {record?.issueNo} 期內有多於一個公共啟事的申請,你可選擇完成所有此期所有稿件對確定後,於繳費期限前在「我的公共啟事」內合併付款。
</Typography>

<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>


+ 2
- 2
src/pages/Proof/Payment/Pay_Creditor.js View File

@@ -76,12 +76,12 @@ const Index = () => {
<center>
<Grid item xs={12} md={8} >
<Typography variant="h2" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
公共啟事:對完成
公共啟事:對完成
</Typography>


<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
我們已收到你已確定申請編號: {record?.appNo} 的稿件對確定及可付印的指示,並將安排刊登於憲報
我們已收到你已確定申請編號: {record?.appNo} 的稿件對確定及可付印的指示,並將安排刊登於憲報
期數 {record?.appNo} 年 {record?.issueVolume} 卷 第 {record?.issueNo} 期內。
<br/><br/>
此公共啟事申請的費用將於下期發出的繳費發票時收取,請依時繳費。


+ 1
- 1
src/pages/Proof/Reply_Public/ApplicationDetails.js View File

@@ -166,7 +166,7 @@ const ApplicationDetailCard = ({ formData, }) => {
<Grid container alignItems="left">
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
<FormLabel><Typography variant="h5">我的備:</Typography></FormLabel>
<FormLabel><Typography variant="h5">我的備:</Typography></FormLabel>
</Grid>

<Grid item xs={12} md={9} lg={9}>


+ 1
- 1
src/pages/Proof/Search_GLD/SearchForm.js View File

@@ -264,7 +264,7 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
}}
renderInput={(params) => (
<TextField {...params}
label="Organization"
label="Organisation"
InputLabelProps={{
shrink: true
}}


+ 1
- 1
src/pages/Proof/Search_Public/DataGrid.js View File

@@ -144,7 +144,7 @@ export default function SearchPublicNoticeTable({ recordList }) {
columns={columns}
initialState={{
pagination: {
paginationModel: { page: 0, pageSize: 5 },
paginationModel: { page: 0, pageSize: 10 },
},
}}
getRowHeight={()=>"auto"}


+ 12
- 7
src/pages/PublicNotice/ApplyForm/PublicNoticeApplyForm.js View File

@@ -14,7 +14,7 @@ import * as HttpUtils from "utils/HttpUtils";
import * as UrlUtils from "utils/ApiPathConst";
import * as FieldUtils from "utils/FieldUtils";
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import ForwardIcon from '@mui/icons-material/Forward';

import { useNavigate } from "react-router-dom";
import { notifyActionSuccess } from 'utils/CommonFunction';
@@ -72,7 +72,6 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {
setIsWarningPopUp(true);
return;
}
// console.log(values);
HttpUtils.postWithFiles({
url: UrlUtils.POST_PUBLIC_NOTICE_APPLY,
params: {
@@ -120,7 +119,7 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {


return (
<Grid container sx={{ minHeight: '95vh', backgroundColor: '#ffffff' }} direction="column" alignItems="center">
<Grid container sx={{ minHeight: '95vh', backgroundColor: '#ffffff', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
@@ -128,6 +127,11 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {
</Stack>
</div>
</Grid>
<Grid item xs={12} width="60%">
<Button title="返回" sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate("/publicNotice") }}>
<ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
</Button>
</Grid>
{/* <Grid item xs={12}>
<Typography variant="h5">申請公共啟事</Typography>
</Grid> */}
@@ -169,7 +173,7 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {
<Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
目標期數:
<Typography variant="h5">目標期數:</Typography>
</Grid>
<Grid item xs={12} md={6} lg={6}>
<RadioGroup
@@ -177,7 +181,7 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {
id="issueId"
name="issueId"
defaultValue={issueId}
onChange={(event)=>{
onChange={(event) => {
setIssueId(event.target.value);
}}
>
@@ -188,11 +192,12 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {
</Grid>
</Grid>
</Grid>

<Grid item xs={12} md={12} lg={12}>
<Grid container direction="row" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
稿件檔案 ({"檔案大小應<10MB"}):
<Typography variant="h5">稿件檔案 ({"檔案大小應<10MB"}):</Typography>
</Grid>
<Grid item xs={12} md={3} lg={3}>
<input
@@ -215,10 +220,10 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {
size="large"
>{attachment ? "上傳檔案" : "重新上傳"}</Button>
</label>

</Grid>
</Grid>
</Grid>

<Grid item xs={12} md={12} lg={12}>
{FieldUtils.getTextArea({
label: "備註:",


+ 15
- 15
src/pages/PublicNotice/ApplyForm/index.js View File

@@ -7,7 +7,7 @@ import * as FormatUtils from "utils/FormatUtils";

import {
Radio,
FormControlLabel
FormControlLabel
} from '@mui/material';

import Loadable from 'components/Loadable';
@@ -19,24 +19,25 @@ const PublicNoticeApplyForm = Loadable(lazy(() => import('./PublicNoticeApplyFor
// ==============================|| DASHBOARD - DEFAULT ||============================== //

const ApplyForm = () => {
const [userData, setUserData] = React.useState([]);
const [selections, setSelection] = React.useState([]);
const [userData, setUserData] = React.useState(null);
const [selections, setSelection] = React.useState([]);
const [isLoading, setLoding] = React.useState(true);

React.useEffect(()=>{
React.useEffect(() => {
loadUserData();
},[]);
}, []);

const loadUserData = ()=>{
const loadUserData = () => {
setLoding(true);
HttpUtils.get({
url: `${UrlUtils.GET_PUBLIC_NOTICE_getApplyUser}`,
onSuccess: function(response){
onSuccess: function (response) {
response["tel_countryCode"] = response?.contactTelNo?.countryCode;
response["phoneNumber"] = response?.contactTelNo?.phoneNumber;
response["fax_countryCode"] = response?.contactFaxNo?.countryCode;
response["faxNumber"] = response?.contactFaxNo?.faxNumber;
response["issueId"] = response?.gazetteIssueList[0].id;
response["remarks"] = "";

var selection = [];
for (var i = 0; i < response?.gazetteIssueList?.length; i++) {
@@ -45,26 +46,25 @@ const ApplyForm = () => {
selection.push(<FormControlLabel value={data.id} control={<Radio />} label={label} />);
}
setSelection(selection);
setUserData(response);
}
});
};

function getIssueLabel(data){
return data.year
+" Vol. "+FormatUtils.zeroPad(data.volume,3)
+", No. "+FormatUtils.zeroPad(data.issueNo,2)
+", "+DateUtils.dateFormat(data.issueDate, "D MMM YYYY (ddd)");
function getIssueLabel(data) {
return data.year
+ " Vol. " + FormatUtils.zeroPad(data.volume, 3)
+ ", No. " + FormatUtils.zeroPad(data.issueNo, 2)
+ ", " + DateUtils.dateFormat(data.issueDate, "D MMM YYYY (ddd)");
}

React.useEffect(() => {
setLoding(false);
if (userData !== null) setLoding(false);
}, [userData]);

return (
isLoading ?
<LoadingComponent/>
<LoadingComponent />
:
<PublicNoticeApplyForm
loadedData={userData}


+ 39
- 28
src/pages/PublicNotice/Details_Public/ApplicationDetailCard.js View File

@@ -96,7 +96,7 @@ const ApplicationDetailCard = (

function doPayment() {
setIsPopUp(false);
navigate('/paymentPage', { state: { amount: fee, appIdList: [currentApplicationDetailData.id]} });
navigate('/paymentPage', { state: { amount: fee, appIdList: [currentApplicationDetailData.id] } });
}

return (
@@ -121,7 +121,7 @@ const ApplicationDetailCard = (
<Button
// size="large"
variant="contained"
onClick={()=>{setIsPopUp(true)}}
onClick={() => { setIsPopUp(true) }}
disabled={currentApplicationDetailData.status == "rejected" || currentApplicationDetailData.status == "cancelled" || currentApplicationDetailData.status == "paid"}
sx={{
textTransform: 'capitalize',
@@ -191,20 +191,31 @@ const ApplicationDetailCard = (
<FormLabel><Typography variant="h5">申請狀態:</Typography></FormLabel>
</Grid>

<Grid item xs={12} md={2} lg={2}>
<Grid item xs={12} md={4} lg={4}>
<FormControl variant="outlined">
{StatusUtils.getStatusByText(currentApplicationDetailData.status)}
</FormControl>
</Grid>
<Grid item xs={12} md={7} lg={7}>
<Stack direction="row" justifyContent="flex-start" alignItems="center">
<FormControl variant="outlined" fullWidth disabled>
<Typography id='reason' variant="h5">
{currentApplicationDetailData.reason}
</Typography>
</FormControl>
</Stack>
</Grid>
{
currentApplicationDetailData.reason ?
<Grid item xs={12} md={5} lg={5}>
<Grid container alignItems={"center"}>
<Stack direction="row" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={7} lg={7}>
<FormLabel><Typography variant="h5">原因:</Typography></FormLabel>
</Grid>
<Grid item xs={12} md={5} lg={5}>
<FormControl variant="outlined" fullWidth disabled>
<Typography id='reason' variant="h5">
{currentApplicationDetailData.reason}
</Typography>
</FormControl>
</Grid>
</Stack>
</Grid>
</Grid>
: ""
}
</Grid>
</Grid>
</Grid>
@@ -506,29 +517,29 @@ const ApplicationDetailCard = (
<FormLabel><Typography variant="h5">備註:</Typography></FormLabel>
</Grid>
<Grid item xs={12} md={9} lg={9}>
<FormLabel><Typography variant="h5">{currentApplicationDetailData.remarks}</Typography></FormLabel>
<Typography variant="h5">{currentApplicationDetailData.remarks}</Typography>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
<div>
<Dialog open={isPopUp} onClose={() => setIsPopUp(false)} >
<DialogTitle></DialogTitle>
<Typography variant="h3" style={{ padding: '16px' }}>確認付款</Typography>
<DialogContent style={{ display: 'flex', }}>
<Stack direction="column" justifyContent="space-between">
<Typography variant="h4">總計金額: {FormatUtils.currencyFormat(fee)}</Typography>
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={() => setIsPopUp(false)}><Typography variant="h5">Close</Typography></Button>
<Button onClick={() => doPayment()}><Typography variant="h5">確認</Typography></Button>
</DialogActions>
</Dialog>
</div>
<Dialog open={isPopUp} onClose={() => setIsPopUp(false)} >
<DialogTitle></DialogTitle>
<Typography variant="h3" style={{ padding: '16px' }}>確認付款</Typography>
<DialogContent style={{ display: 'flex', }}>
<Stack direction="column" justifyContent="space-between">
<Typography variant="h4">總計金額: {FormatUtils.currencyFormat(fee)}</Typography>
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={() => setIsPopUp(false)}><Typography variant="h5">Close</Typography></Button>
<Button onClick={() => doPayment()}><Typography variant="h5">確認</Typography></Button>
</DialogActions>
</Dialog>
</div>
</form>
</MainCard>
</MainCard >
);
};



+ 25
- 25
src/pages/PublicNotice/ListPanel/BaseGrid.js View File

@@ -33,32 +33,32 @@ export default function BaseGrid({rows}) {
return DateUtils.datetimeStr(params?.value);
}
},
{
id: 'contactPerson',
field: 'contactPerson',
headerName: '聯絡人',
flex: 2,
renderCell: (params) => {
let phone = JSON.parse(params.row.contactTelNo);
let faxNo = JSON.parse(params.row.contactFaxNo);
// {
// id: 'contactPerson',
// field: 'contactPerson',
// headerName: '聯絡人',
// flex: 2,
// renderCell: (params) => {
// let phone = JSON.parse(params.row.contactTelNo);
// let faxNo = JSON.parse(params.row.contactFaxNo);

let contact = "";
if (phone) {
contact = "電話: " + phone?.countryCode + " " + phone?.phoneNumber
}
// let contact = "";
// if (phone) {
// contact = "電話: " + phone?.countryCode + " " + phone?.phoneNumber
// }

if (faxNo && faxNo?.faxNumber) {
if (contact != "")
contact = contact + ", "
contact = contact + "傳真:" + faxNo?.countryCode + " " + faxNo?.faxNumber
}
// if (faxNo && faxNo?.faxNumber) {
// if (contact != "")
// contact = contact + ", "
// contact = contact + "傳真:" + faxNo?.countryCode + " " + faxNo?.faxNumber
// }

return (<>
{params?.value}<br />
{contact}
</>);
}
},
// return (<>
// {params?.value}<br />
// {contact}
// </>);
// }
// },
{
id: 'remarks',
field: 'remarks',
@@ -90,13 +90,13 @@ export default function BaseGrid({rows}) {
}

return (
<div style={{height: 400, width: '100%', padding: 4}}>
<div style={{minHeight: 400, width: '100%', padding: 4}}>
<FiDataGrid
rows={rows}
columns={columns}
initialState={{
pagination: {
paginationModel: {page: 0, pageSize: 5},
paginationModel: {page: 0, pageSize: 10},
},
}}
onRowDoubleClick={handleRowDoubleClick}


+ 26
- 26
src/pages/PublicNotice/ListPanel/PendingPaymentTab.js View File

@@ -39,32 +39,32 @@ export default function SubmittedTab({ rows }) {
return DateUtils.datetimeStr(params.value);
}
},
{
id: 'contactPerson',
field: 'contactPerson',
headerName: '聯絡人',
flex: 2,
renderCell: (params) => {
let phone = JSON.parse(params.row.contactTelNo);
let faxNo = JSON.parse(params.row.contactFaxNo);
let contact = "";
if (phone) {
contact = "電話: " + phone?.countryCode + " " + phone?.phoneNumber
}
if (faxNo && faxNo?.faxNumber) {
if (contact != "")
contact = contact + ", "
contact = contact + "傳真:" + faxNo?.countryCode + " " + faxNo?.faxNumber
}
return (<>
{params?.value}<br />
{contact}
</>);
}
},
// {
// id: 'contactPerson',
// field: 'contactPerson',
// headerName: '聯絡人',
// flex: 2,
// renderCell: (params) => {
// let phone = JSON.parse(params.row.contactTelNo);
// let faxNo = JSON.parse(params.row.contactFaxNo);
// let contact = "";
// if (phone) {
// contact = "電話: " + phone?.countryCode + " " + phone?.phoneNumber
// }
// if (faxNo && faxNo?.faxNumber) {
// if (contact != "")
// contact = contact + ", "
// contact = contact + "傳真:" + faxNo?.countryCode + " " + faxNo?.faxNumber
// }
// return (<>
// {params?.value}<br />
// {contact}
// </>);
// }
// },
{
id: 'remarks',
field: 'remarks',


+ 1
- 1
src/pages/PublicNotice/ListPanel/SearchPublicNoticeForm.js View File

@@ -44,7 +44,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria }) => {

function resetForm() {
setType([]);
setStatus({ key: 0, label: 'All', labelCht: "全部", type: 'all' });
setStatus([{ key: 0, label: 'All', labelCht: "全部", type: 'all' }]);
reset();
}



+ 28
- 28
src/pages/PublicNotice/ListPanel/SearchPublicNoticeTable.js View File

@@ -37,32 +37,32 @@ export default function SearchPublicNoticeTable({ recordList }) {
return DateUtils.datetimeStr(params?.value);
}
},
{
id: 'contactPerson',
field: 'contactPerson',
headerName: '聯絡人',
flex: 2,
renderCell: (params) => {
let phone = JSON.parse(params.row.contactTelNo);
let faxNo = JSON.parse(params.row.contactFaxNo);
// {
// id: 'contactPerson',
// field: 'contactPerson',
// headerName: '聯絡人',
// flex: 2,
// renderCell: (params) => {
// let phone = JSON.parse(params.row.contactTelNo);
// let faxNo = JSON.parse(params.row.contactFaxNo);

let contact = "";
if (phone) {
contact = "電話: " + phone?.countryCode + " " + phone?.phoneNumber
}
// let contact = "";
// if (phone) {
// contact = "電話: " + phone?.countryCode + " " + phone?.phoneNumber
// }

if (faxNo && faxNo?.faxNumber) {
if (contact != "")
contact = contact + ", "
contact = contact + "傳真:" + faxNo?.countryCode + " " + faxNo?.faxNumber
}
// if (faxNo && faxNo?.faxNumber) {
// if (contact != "")
// contact = contact + ", "
// contact = contact + "傳真:" + faxNo?.countryCode + " " + faxNo?.faxNumber
// }

return (<>
{params?.value}<br />
{contact}
</>);
}
},
// return (<>
// {params?.value}<br />
// {contact}
// </>);
// }
// },
{
id: 'remarks',
field: 'remarks',
@@ -73,7 +73,7 @@ export default function SearchPublicNoticeTable({ recordList }) {
id: 'status',
field: 'status',
headerName: '狀態',
width: 100,
width: 160,
renderCell: (params) => {
return [StatusUtils.getStatus(params)]
},
@@ -82,7 +82,7 @@ export default function SearchPublicNoticeTable({ recordList }) {
field: 'actions',
type: 'actions',
headerName: '',
width: 100,
width: 150,
cellClassName: 'actions',
renderCell: (params) => {
return <Button onClick={handleDetailClick(params)}>查看詳細</Button>;
@@ -95,17 +95,17 @@ export default function SearchPublicNoticeTable({ recordList }) {
}

return (
<div style={{ height: 400, width: '100%' }}>

<div style={{ minHeight: 400, width: '100%' }}>
<FiDataGrid
rows={rows}
columns={columns}
initialState={{
pagination: {
paginationModel: { page: 0, pageSize: 5 },
paginationModel: { page: 0, pageSize: 10 },
},
}}
onRowDoubleClick={handleRowDoubleClick}
getRowHeight={() => 'auto'}
/>
</div>
);


+ 1
- 1
src/pages/PublicNotice/Search_GLD/SearchForm.js View File

@@ -236,7 +236,7 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss
}}
renderInput={(params) => (
<TextField {...params}
label="Organization"
label="Organisation"
InputLabelProps={{
shrink: true
}}


+ 1
- 1
src/pages/User/DetailPage/index.js View File

@@ -146,7 +146,7 @@ const UserMaintainPage = () => {
const deletedUserGroup = getDeletedRecordWithRefList(refUserData.groupIds, userGroupData);
// console.log(userGroupData)
// console.log(userAuthData)
if (parseInt(params.id) >= -1) {
if (parseInt(params.id) > -1) {
axios.post(`${GLD_USER_PATH}/${params.id}`,
{
"enName": editedCustomerData.enName,


+ 29
- 16
src/pages/User/DetailsPage_Organization/UserInformationCard_Organization.js View File

@@ -1,7 +1,7 @@
// material-ui
import {
Grid, Typography, Button,
Dialog, DialogTitle, DialogContent, DialogActions
Dialog, DialogTitle, DialogContent, DialogActions,
} from '@mui/material';
import MainCard from "../../../components/MainCard";
import * as React from "react";
@@ -39,23 +39,36 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) =>
}
}, [currentUserData]);

function displayErrorMsg(errorMsg) {
return <Typography variant="errorMessage1">{errorMsg}</Typography>
}

const formik = useFormik({
enableReinitialize: true,
initialValues: currentUserData,
validationSchema: yup.object().shape({
contactPerson: yup.string().max(255).required('請輸入姓名'),
enCompanyName: yup.string().max(255).required('請輸入英文名稱'),
contactPerson: yup.string().max(255).required(displayErrorMsg('請輸入姓名')),
enCompanyName: yup.string().max(255).required(displayErrorMsg('請輸入英文名稱')),
chCompanyName: yup.string().max(255).nullable(),
addressLine1: yup.string().max(255).required('請輸入第一行地址'),
addressLine1: yup.string().max(255).required(displayErrorMsg('請輸入第一行地址')),
addressLine2: yup.string().max(255).nullable(),
addressLine3: yup.string().max(255).nullable(),
emailBus: yup.string().max(255).required('請輸入電郵'),
tel_countryCode: yup.string().min(3, '請輸入3位數字').required('請輸入國際區號'),
fax_countryCode: yup.string().min(3, '請輸入3位數字').nullable(),
phoneNumber: yup.string().min(8, '請輸入8位數字').required('請輸入聯絡電話'),
faxNumber: yup.string().min(8, '請輸入8位數字').nullable(),
brExpiryDate: yup.string().min(8, '請輸入商業登記證有效日期'),
brNo: yup.string().min(8, '請輸入有效商業登記證號碼').max(8, '請輸入有效商業登記證號碼').required('請輸入商業登記證號碼'),
emailBus: yup.string().max(255).required(displayErrorMsg('請輸入電郵')),
tel_countryCode: yup.string().min(3, displayErrorMsg('請輸入3位數字')).required(displayErrorMsg('請輸入國際區號')),
fax_countryCode: yup.string().min(3, displayErrorMsg('請輸入3位數字')).nullable(),
phoneNumber: yup.string().min(8, displayErrorMsg('請輸入8位數字')).required(displayErrorMsg('請輸入聯絡電話')),
faxNumber: yup.string().min(8, displayErrorMsg('請輸入8位數字')).nullable(),
brExpiryDate: yup.string().min(8, displayErrorMsg('請輸入商業登記證有效日期')),
brNo: yup.string().required(displayErrorMsg('請輸入商業登記證號碼')).test('checkBrNoFormat', displayErrorMsg(`請輸入有效商業登記證號碼`), function (value) {
var brNo_pattern = /[0-9]{8}-[0-9]{3}-(0[1-9]|1[012])-[0-9]{2}-[0-9A-Z]{1}/
if (value !== undefined) {
if (value.match(brNo_pattern)) {
return true
} else {
return false
}
}
}),
}),
onSubmit: (values) => {
HttpUtils.post({
@@ -126,7 +139,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) =>
}
});
} else {
setWarningText("Please select Organization before active this account.")
setWarningText("Please select Organisation before active this account.")
setIsWarningPopUp(true);
}

@@ -235,7 +248,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) =>
{/*end top button*/}
<div style={{ paddingLeft: 24, paddingRight: 24 }}>
<Typography variant="h4" sx={{ mt: 3, mb: 2, mr: 3, borderBottom: "1px solid black" }}>
Organization User Details
Organisation User Details
</Typography>
<Grid container spacing={1}>
<Grid item lg={4}>
@@ -297,7 +310,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) =>

<Grid item lg={4}>
{FieldUtils.getComboField({
label: "Organization:",
label: "Organisation:",
valueName: "orgId",
disabled: (!editMode),
dataList: orgData,
@@ -466,7 +479,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) =>
<Button variant="contained"
onClick={createOrgClick}
>
<Typography variant="h5">Create Organization</Typography>
<Typography variant="h5">Create Organisation</Typography>
</Button>
</Grid>
: null
@@ -475,7 +488,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) =>
</Grid>
<Grid item lg={12} >
<Typography variant="h4" sx={{ mt: 3, mb: 2, mr: 3, borderBottom: "1px solid black" }}>
Organization
Organisation
</Typography>
</Grid>
<Grid item lg={4}>


+ 1
- 1
src/pages/User/DetailsPage_Organization/index.js View File

@@ -133,7 +133,7 @@ const UserMaintainPage_Organization = () => {
<Grid item xs={12}>
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4">Maintain Organization User</Typography>
<Typography ml={15} color='#FFF' variant="h4">Maintain Organisation User</Typography>
</Stack>
</div>
</Grid>


+ 9
- 0
src/pages/User/SearchPage/UserSearchForm.js View File

@@ -17,6 +17,8 @@ import Checkbox from "@mui/material/Checkbox";
import * as React from "react";
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
import { useNavigate } from "react-router";
import axios from "axios";
import { GET_EMAIL_LIST } from 'utils/ApiPathConst';

// ==============================|| DASHBOARD - DEFAULT ||============================== //

@@ -53,6 +55,13 @@ const UserSearchForm = ({ applySearch }) => {
setType([]);
setLocked(false);
reset();
axios.get(`${GET_EMAIL_LIST}`)
.then(r => {
console.log(r)
})
.catch(err => {
console.log(err)
})
}

const handleNewUserClick = () => {


+ 1
- 1
src/pages/User/SearchPage_Organization/index.js View File

@@ -72,7 +72,7 @@ const UserSearchPage_Organization = () => {
<Grid item xs={12}>
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4">View Organization User</Typography>
<Typography ml={15} color='#FFF' variant="h4">View Organisation User</Typography>
</Stack>
</div>
</Grid>


+ 104
- 40
src/pages/authentication/auth-forms/BusCustomFormWizard.js View File

@@ -30,7 +30,7 @@ import * as yup from 'yup';
import { strengthColorChi, strengthIndicator } from 'utils/password-strength';
// import {apiPath} from "auth/utils";
import axios from "axios";
import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, GET_USERNAME } from "utils/ApiPathConst";
import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, GET_USERNAME, GET_USER_EMAIL } from "utils/ApiPathConst";
// import * as HttpUtils from 'utils/HttpUtils';
import * as ComboData from "utils/ComboData";

@@ -65,7 +65,7 @@ const BusCustomFormWizard = (props) => {
const [checkUpload, setCheckUpload] = useState(false);
const [isLoading, setLoding] = useState(true);
const [updateRows, setUpdateRows] = useState([]);
const [userNameList, setUserNameList] = useState([]);
// const [userNameList, setUserNameList] = useState([]);

const [captcha, setCaptcha] = useState([]);
const [captchaImg, setCaptchaImage] = useState([]);
@@ -92,7 +92,12 @@ const BusCustomFormWizard = (props) => {
const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false);
const [isValid, setisValid] = useState(false);
const [checkCountry, setCheckCountry] = useState(false);
const username = document.getElementById("username-login")
const [checkUsername, setCheckUsername] = useState(false);
const [checkUsernameBlur, setCheckUsernameBlur] = useState(false)
const email = document.getElementById("email-login")
const [checkEmail, setCheckEmail] = useState(false)
const [checkEmailBlur, setCheckEmailBlur] = useState(false)

const address4ComboList = ComboData.district;
const address5ComboList = ComboData.country;
@@ -115,19 +120,19 @@ const BusCustomFormWizard = (props) => {
// localStorage.setItem("checkCode",null);
// localStorage.setItem("base64Url",null);
// }else{
onCaptchaChange();
// }
axios.get(`${GET_USERNAME}`)
.then((response) => {
if (response.status === 200) {
setUserNameList(response.data);
}
// onCaptchaChange();
// // }
// axios.get(`${GET_USERNAME}`)
// .then((response) => {
// if (response.status === 200) {
// setUserNameList(response.data);
// }

})
.catch(error => {
console.log(error);
return false;
});
// })
// .catch(error => {
// console.log(error);
// return false;
// });
}, []);

const handleCheckUsername = async () => {
@@ -142,6 +147,48 @@ const BusCustomFormWizard = (props) => {
}
}

const handleCheckEmail = async () => {
if (values?.email) {
const response = await axios.get(`${GET_USER_EMAIL}`, {
params: {
email: values.email,
}
})
setCheckEmail((Number(response.data[0]) === 1))
return Number(response.data[0]) === 1
}
}

useEffect(() => {
if (username) {
username.addEventListener("blur", function () {
setCheckUsernameBlur(true)
})
}
}, [username])

useEffect(() => {
if (checkUsernameBlur) {
handleCheckUsername()
setCheckUsernameBlur(false)
}
}, [checkUsernameBlur])

useEffect(() => {
if (email) {
email.addEventListener("blur", function () {
setCheckEmailBlur(true)
})
}
}, [email])

useEffect(() => {
if (checkEmailBlur) {
handleCheckEmail()
setCheckEmailBlur(false)
}
}, [checkEmailBlur])

const onCaptchaChange = () => {
HttpUtils.post({
url: POST_CAPTCHA,
@@ -181,6 +228,7 @@ const BusCustomFormWizard = (props) => {
handlePhone(data.phone) &&
handleUserName(data.username) &&
handleCaptcha(data.captchaField) &&
handleBrNo(data.brNo) &&
!checkUsername
) {
setisValid(true)
@@ -223,6 +271,17 @@ const BusCustomFormWizard = (props) => {

}, [updateRows]);

const handleBrNo = (brNo) => {
var brNo_pattern = /[0-9]{8}-[0-9]{3}-(0[1-9]|1[012])-[0-9]{2}-[0-9A-Z]{1}/
if (brNo !== undefined) {
if (brNo.match(brNo_pattern)) {
return true
} else {
return false
}
}
}

const handleFileUpload = (event) => {
let updateList = new DataTransfer();
let currentFileList = fileListData;
@@ -343,6 +402,7 @@ const BusCustomFormWizard = (props) => {
formData.append("userFaxNo", JSON.stringify(userFaxNo));
formData.append("busUserContactTel", JSON.stringify(busUserContactTel));
formData.append("busUserAddress", JSON.stringify(busUserAddress));
// formData.append("preferLocale", "en");

if (isValid) {
axios.post(POST_PUBLIC_USER_REGISTER, formData, {
@@ -454,32 +514,22 @@ const BusCustomFormWizard = (props) => {
}),

validationSchema: yup.object().shape({
username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg('請輸入用戶名稱')).test(
"checkUserNameUsed",
displayErrorMsg("此用戶登入名稱已被注冊,請使用其他用戶登入名稱"),
function (value) {
if (userNameList.some(item => item.username === value)) {
return false
} else {
return true
}
}
)
.matches(/^[aA-zZ0-9\s]+$/, {message: displayErrorMsg("用戶名稱不包含特殊字符")})
.matches(/^\S*$/, {message: displayErrorMsg('用戶名稱不包含空格')}),
username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg('請輸入用戶名稱'))
.matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg("用戶名稱不包含特殊字符") })
.matches(/^\S*$/, { message: displayErrorMsg('用戶名稱不包含空格') }),
password: yup.string().min(8, displayErrorMsg('請輸入最少8位密碼')).required(displayErrorMsg('請輸入密碼'))
.matches(/^\S*$/, {message: displayErrorMsg('密碼不包含空格')})
.matches(/^(?=.*[a-z])/, {message: displayErrorMsg('請包括最少1個小寫字母')})
.matches(/^(?=.*[A-Z])/, {message: displayErrorMsg('請包括最少1個大寫字母')})
.matches(/^(?=.*[0-9])/, {message: displayErrorMsg('請包括最少1個數字')})
.matches(/^(?=.*[!@#%&])/, {message: displayErrorMsg('請包括最少1個特殊字符')}),
.matches(/^\S*$/, { message: displayErrorMsg('密碼不包含空格') })
.matches(/^(?=.*[a-z])/, { message: displayErrorMsg('請包括最少1個小寫字母') })
.matches(/^(?=.*[A-Z])/, { message: displayErrorMsg('請包括最少1個大寫字母') })
.matches(/^(?=.*[0-9])/, { message: displayErrorMsg('請包括最少1個數字') })
.matches(/^(?=.*[!@#%&])/, { message: displayErrorMsg('請包括最少1個特殊字符') }),
confirmPassword: yup.string().min(8, displayErrorMsg('請最少輸入8位密碼')).required(displayErrorMsg('請確認密碼')).oneOf([yup.ref('password'), null], displayErrorMsg('請輸入相同密碼')),
enName: yup.string().max(255).required(displayErrorMsg('請輸入英文姓名')),
enCompanyName: yup.string().matches(/^[^$^*()]+$/, {message: displayErrorMsg('No special characters $/^/*/(/)')}).when('chCompanyName', {
enCompanyName: yup.string().matches(/^[^$^*()]+$/, { message: displayErrorMsg('No special characters $/^/*/(/)') }).when('chCompanyName', {
is: (chCompanyName) => !chCompanyName || chCompanyName.length === 0,
then: yup.string().required(displayErrorMsg('Please enter either English or Chinese name')),
}),
chCompanyName: yup.string().matches(/^[^$^*()]+$/, {message: displayErrorMsg('不包含特殊字符 $/^/*/(/)')}).when('enCompanyName', {
chCompanyName: yup.string().matches(/^[^$^*()]+$/, { message: displayErrorMsg('不包含特殊字符 $/^/*/(/)') }).when('enCompanyName', {
is: (enCompanyName) => !enCompanyName || enCompanyName.length === 0,
then: yup.string().required(displayErrorMsg('請輸入英文或中文名稱')),
}),
@@ -494,7 +544,16 @@ const BusCustomFormWizard = (props) => {
phone: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')).required(displayErrorMsg('請輸入聯絡電話')),
fax: yup.string().min(8, displayErrorMsg('請輸入最少8位數字')),
brExpiryDate: yup.date().min(new Date().toISOString().split("T")[0], displayErrorMsg('請輸入商業登記證有效日期')).max("2099-12-31", displayErrorMsg('請輸入商業登記證有效日期')).required(displayErrorMsg('請輸入商業登記證有效日期')),
brNo: yup.string().min(8, displayErrorMsg('請輸入商業登記證號碼')).required(displayErrorMsg('請輸入商業登記證號碼')),
brNo: yup.string().required(displayErrorMsg('請輸入商業登記證號碼')).test('checkBrNoFormat', displayErrorMsg(`請輸入有效商業登記證號碼`), function (value) {
var brNo_pattern = /[0-9]{8}-[0-9]{3}-(0[1-9]|1[012])-[0-9]{2}-[0-9A-Z]{1}/
if (value !== undefined) {
if (value.match(brNo_pattern)) {
return true
} else {
return false
}
}
}),
captchaField: yup.string().required(displayErrorMsg('請輸入驗證')).oneOf([captcha], displayErrorMsg('請輸入有效驗證')),
}, ['enCompanyName', 'chCompanyName']),

@@ -542,12 +601,12 @@ const BusCustomFormWizard = (props) => {
<Typography variant="h5">
用戶登入名稱
<span style={{ color: '#f10000' }}>*</span>
<Button
{/* <Button
variant="contained"
onClick={handleCheckUsername}
sx={{ ml: 2, height: "40px" }}>
<Typography variant="h6">檢查是否重覆</Typography>
</Button>
</Button> */}
</Typography>
</InputLabel>
<OutlinedInput
@@ -562,7 +621,7 @@ const BusCustomFormWizard = (props) => {
}}
placeholder="用戶登入名稱"
fullWidth
error={Boolean(formik.touched.username && formik.errors.username)}
error={Boolean((formik.touched.username && formik.errors.username) || checkUsername)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
@@ -1018,7 +1077,7 @@ const BusCustomFormWizard = (props) => {
</InputLabel>
<OutlinedInput
fullWidth
error={Boolean(formik.touched.email && formik.errors.email)}
error={Boolean((formik.touched.email && formik.errors.email) || checkEmail)}
id="email-login"
type="email"
value={formik.values.email.trim()}
@@ -1039,6 +1098,11 @@ const BusCustomFormWizard = (props) => {
{formik.errors.email}
</FormHelperText>
)}
{checkEmail && (
<FormHelperText error id="helper-text-email-signup">
此電郵已被注冊,請使用其他電郵
</FormHelperText>
)}
</Stack>
</Grid>
<Grid item xs={12} md={6}>
@@ -1547,7 +1611,7 @@ const BusCustomFormWizard = (props) => {
<Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
<CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
<Typography display="inline" variant="h4">帳戶申請已成功提交。</Typography>
<Typography display="inline" variant="h4">驗證電郵將發送到你的電郵地址,請指示完成驗證及登入系統。</Typography>
<Typography display="inline" variant="h4">驗證電郵將發送到你的電郵地址,請指示完成驗證及登入系統。</Typography>
<Button variant="outlined" component={Link} to="/login" sx={{ fontSize: 20, height: '60px' }}><Typography variant="h5">返回登入頁面</Typography></Button>
</Stack>
:


+ 62
- 8
src/pages/authentication/auth-forms/CustomFormWizard.js View File

@@ -29,7 +29,7 @@ import * as yup from 'yup';
import { strengthColorChi, strengthIndicator } from 'utils/password-strength';
// import {apiPath} from "auth/utils";
import axios from "axios";
import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, GET_USERNAME } from "utils/ApiPathConst";
import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, GET_USERNAME, GET_USER_EMAIL } from "utils/ApiPathConst";
// import * as HttpUtils from 'utils/HttpUtils';
import * as ComboData from "utils/ComboData";

@@ -93,7 +93,12 @@ const CustomFormWizard = (props) => {
const [termsAndConNotAccept, setTermsAndConNotAccept] = useState(false);
const [isValid, setisValid] = useState(false);
const [checkCountry, setCheckCountry] = useState(false);
const username = document.getElementById("username-login")
const [checkUsername, setCheckUsername] = useState(false);
const [checkUsernameBlur, setCheckUsernameBlur] = useState(false)
const email = document.getElementById("email-login")
const [checkEmail, setCheckEmail] = useState(false)
const [checkEmailBlur, setCheckEmailBlur] = useState(false)

const idDocTypeComboList = ComboData.idDocType;
const address4ComboList = ComboData.district;
@@ -125,6 +130,48 @@ const CustomFormWizard = (props) => {
}
}

const handleCheckEmail = async () => {
if (values?.email) {
const response = await axios.get(`${GET_USER_EMAIL}`, {
params: {
email: values.email,
}
})
setCheckEmail((Number(response.data[0]) === 1))
return Number(response.data[0]) === 1
}
}

useEffect(() => {
if (username) {
username.addEventListener("blur", function () {
setCheckUsernameBlur(true)
})
}
}, [username])

useEffect(() => {
if (checkUsernameBlur) {
handleCheckUsername()
setCheckUsernameBlur(false)
}
}, [checkUsernameBlur])

useEffect(() => {
if (email) {
email.addEventListener("blur", function () {
setCheckEmailBlur(true)
})
}
}, [email])

useEffect(() => {
if (checkEmailBlur) {
handleCheckEmail()
setCheckEmailBlur(false)
}
}, [checkEmailBlur])

const onCaptchaChange = () => {
HttpUtils.post({
url: POST_CAPTCHA,
@@ -162,7 +209,8 @@ const CustomFormWizard = (props) => {
handlePhone(data.phone) &&
handleUsername(data.username) &&
handleCaptcha(data.captchaField) &&
!checkUsername
!checkUsername &&
!checkEmail
) {
setisValid(true)
return isValid
@@ -324,6 +372,7 @@ const CustomFormWizard = (props) => {
formData.append("userFaxNo", JSON.stringify(userFaxNo));
formData.append("userMobileNumber", JSON.stringify(userMobileNumber));
formData.append("userAddress", JSON.stringify(userAddress));
// formData.append("preferLocale", "en");

// if(refCode){
// formData.append("refCode", refCode);
@@ -503,7 +552,7 @@ const CustomFormWizard = (props) => {
captchaField: ''
}),
validationSchema: yup.object().shape({
username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg("請輸入用戶登入名稱"))
username: yup.string().min(6, displayErrorMsg('用戶名稱最少6位')).required(displayErrorMsg("請輸入用戶名稱"))
.matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg("用戶名稱不包含特殊字符") })
.matches(/^\S*$/, { message: displayErrorMsg("用戶名稱不包含空格") }),
password: yup.string().min(8, displayErrorMsg('請輸入最少8位密碼')).required(displayErrorMsg('請輸入密碼'))
@@ -626,13 +675,13 @@ const CustomFormWizard = (props) => {
<InputLabel htmlFor="username-signup">
<Typography variant="h5">
用戶登入名稱
<span style={{ color: '#f10000' }}>*</span>
{/* <span style={{ color: '#f10000' }}>*</span>
<Button
variant="contained"
onClick={handleCheckUsername}
sx={{ ml: 2, height: "40px" }}>
<Typography variant="h6">檢查是否重覆</Typography>
</Button>
</Button> */}
</Typography>
</InputLabel>
<OutlinedInput
@@ -647,7 +696,7 @@ const CustomFormWizard = (props) => {
}}
placeholder="用戶登入名稱"
fullWidth
error={Boolean(formik.touched.username && formik.errors.username)}
error={Boolean((formik.touched.username && formik.errors.username) || checkUsername)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
@@ -1168,7 +1217,7 @@ const CustomFormWizard = (props) => {
</InputLabel>
<OutlinedInput
fullWidth
error={Boolean(formik.touched.email && formik.errors.email)}
error={Boolean((formik.touched.email && formik.errors.email) || checkEmail)}
id="email-login"
type="email"
value={formik.values.email.trim()}
@@ -1189,6 +1238,11 @@ const CustomFormWizard = (props) => {
{formik.errors.email}
</FormHelperText>
)}
{checkEmail && (
<FormHelperText error id="helper-text-email-signup">
此電郵已被注冊,請使用其他電郵
</FormHelperText>
)}
</Stack>
</Grid>
<Grid item xs={12} md={6}>
@@ -1685,7 +1739,7 @@ const CustomFormWizard = (props) => {
<Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}>
<CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
<Typography display="inline" variant="h4">帳戶申請已成功提交。</Typography>
<Typography display="inline" variant="h4">驗證電郵將發送到你的電郵地址,請指示完成驗證及登入系統。</Typography>
<Typography display="inline" variant="h4">驗證電郵將發送到你的電郵地址,請指示完成驗證及登入系統。</Typography>
<Button variant="outlined" component={Link} to="/login" sx={{ fontSize: 20, height: '60px' }}><Typography variant="h5">返回登入頁面</Typography></Button>
</Stack>
:


+ 1
- 0
src/pages/authentication/auth-forms/PreviewUploadFileTable.js View File

@@ -104,6 +104,7 @@ export default function PreviewUploadFileTable({ recordList, }) {
disableColumnMenu
disableColumnSelector
hideFooter
getRowHeight={()=>"auto"}
/>
</Box>
);


+ 1
- 0
src/pages/authentication/auth-forms/UploadFileTable.js View File

@@ -106,6 +106,7 @@ export default function UploadFileTable({ recordList, setUpdateRows, }) {
disableColumnMenu
disableColumnSelector
hideFooter
getRowHeight={()=>"auto"}
/>
</Box>
);


+ 10
- 3
src/pages/pnspsNotifyTest/index.js View File

@@ -6,6 +6,7 @@ import { apiPath } from 'auth/utils';
const TestMailPage = () => {
const [host, setHost] = useState(apiPath+'/test');
const [mail, setMail] = useState('');
const [tempKey, setTempKey] = useState('');

const hostChange = (event) => {
setHost(event.target.value);
@@ -15,9 +16,14 @@ const TestMailPage = () => {
setMail(event.target.value);
};

const tempKeyChange = (event) => {
setTempKey(event.target.value);
};

const doMailTest = () => {
axios.post(host, {
email: mail
email: mail,
tempKey: tempKey,
})
.then((response) => {
console.log(response.data);
@@ -41,8 +47,9 @@ const TestMailPage = () => {
}
}}
spacing={3}>
<Grid item xs={12}><TextField id='hostField' label='Outlined' variant='filled' onChange={hostChange} value={host} fullWidth /></Grid>
<Grid item xs={12}><TextField id='mailField' label='Outlined' variant='filled' onChange={mailChange} value={mail} fullWidth /></Grid>
<Grid item xs={12}><TextField id='hostField' label='Email Api' variant='filled' onChange={hostChange} value={host} fullWidth /></Grid>
<Grid item xs={12}><TextField id='mailField' label='Target Email' variant='filled' onChange={mailChange} value={mail} fullWidth /></Grid>
<Grid item xs={12}><TextField id='mailField' label='Email Template Key' variant='filled' onChange={tempKeyChange} value={tempKey} fullWidth /></Grid>
<Grid item xs={12}><Button variant='contained' onClick={doMailTest}>Test</Button></Grid>
</Grid>
);


+ 10
- 0
src/routes/SettingRoutes.js View File

@@ -20,6 +20,8 @@ const UserGroupDetailPage = Loadable(lazy(() => import('pages/pnspsUserGroupDeta
const OrganizationSearchPage = Loadable(lazy(() => import('pages/OrganizationSearchPage')));
const OrganizationDetailPage = Loadable(lazy(() => import('pages/OrganizationDetailPage')));
const OrganizationDetailPage_fromUser = Loadable(lazy(() => import('pages/OrganizationDetailPage_FromUser')));
const EmailTemplatePage = Loadable(lazy(() => import('pages/EmailTemplate/Search_GLD')));
const EmailTemplateDetailPage = Loadable(lazy(() => import('pages/EmailTemplate/Detail_GLD')));


// ==============================|| AUTH ROUTING ||============================== //
@@ -80,6 +82,14 @@ const SettingRoutes = {
path: 'passwordpolicy',
element: <PasswordPolicyPage />
},
{
path: 'emailTemplate',
element: <EmailTemplatePage/>
},
{
path: '/emailTemplate/:id',
element: <EmailTemplateDetailPage/>
},
]
};



+ 9
- 2
src/utils/ApiPathConst.js View File

@@ -44,7 +44,7 @@ export const POST_CAPTCHA = apiPath+'/captcha';
//register
export const POST_PUBLIC_USER_REGISTER = apiPath+'/user/register';
export const GET_USERNAME = apiPath+'/user/username';
export const GET_USER_EMAIL = apiPath+'/user/email';

//Public
export const GET_PUBLIC_ORG_USER_LIST = apiPath+'/user/listOrg';
@@ -91,4 +91,11 @@ export const PAYMENT_APP_LIST = apiPath+'/payment/applist';//POST


//User Group
export const POST_AND_UPDATE_USER_GROUP = apiPath+'/group/save';
export const POST_AND_UPDATE_USER_GROUP = apiPath+'/group/save';

// Email
export const GET_EMAIL_LIST = apiPath+'/email/list';
export const GET_EMAIL_COMBO = apiPath+'/email/combo';
export const GET_EMAIL = apiPath+'/email/load';
export const POST_EMAIL_SAVE = apiPath+'/email/save';
export const DELETE_EMAIL = apiPath+'/email/delete';

+ 111
- 88
src/utils/CommonFunction.js View File

@@ -3,27 +3,27 @@ import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import DialogContentText from "@mui/material/DialogContentText";
import DialogActions from "@mui/material/DialogActions";
import {Button} from "@mui/material";
import { Button } from "@mui/material";
import Dialog from "@mui/material/Dialog";
import * as React from "react";
import { toast } from "react-toastify";

export function getDeletedRecordWithRefList(referenceList, updatedList){
return referenceList.filter(x => !updatedList.includes(x)) ;
export function getDeletedRecordWithRefList(referenceList, updatedList) {
return referenceList.filter(x => !updatedList.includes(x));
}

export function getIdList(input){
export function getIdList(input) {
const output = input.map(function (obj) {
return obj.id;
});
return output;
}

export function getObjectById(list, id){
export function getObjectById(list, id) {
const obj = list.find((element) => {
return element.id === id;
});
return obj === undefined || Object.keys(obj).length <= 0? null : obj
return obj === undefined || Object.keys(obj).length <= 0 ? null : obj
}

export function removeObjectWithId(arr, id) {
@@ -34,7 +34,7 @@ export function removeObjectWithId(arr, id) {
}

export function getDateString(queryDateArray) {
return(
return (
queryDateArray[0]
+ "-" +
queryDateArray[1]
@@ -60,7 +60,8 @@ export const notifySaveSuccess = () => {
draggable: true,
progress: undefined,
theme: "light",
})};
})
};

export const notifyCreateSuccess = () => {
const userType = JSON.parse(localStorage.getItem("userData")).type
@@ -73,108 +74,130 @@ export const notifyCreateSuccess = () => {
draggable: true,
progress: undefined,
theme: "light",
})};
})
};

export const notifyVerifySuccess = () => {
const userType = JSON.parse(localStorage.getItem("userData")).type
toast.success(userType === "GLD" ? 'Verify success!' : "驗證成功!", {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyDeleteSuccess = () => {
const userType = JSON.parse(localStorage.getItem("userData")).type
toast.success(userType === "GLD" ? 'Delete success!' : "刪除成功!", {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyLockSuccess = () => {
toast.success('Lock success!', {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyUnlockSuccess = () => {
toast.success('Unlock success!', {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyActiveSuccess = () => {
toast.success('Active success!', {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyDownloadSuccess = () => {
const userType = JSON.parse(localStorage.getItem("userData")).type
toast.success(userType === "GLD" ? 'Download success!' : "下載成功!", {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyActionSuccess = (actionMsg) => {
toast.success(`${actionMsg}`, {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyActionError = (actionMsg) => {
toast.error(`${actionMsg}`, {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})};

export function prettyJson(json){
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
};

export const notifyActionWarning = (actionMsg) => {
toast.warn(`${actionMsg}`, {
position: "bottom-right",
autoClose: 5000,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
})
}

export function prettyJson(json) {
console.log(json);
console.log(JSON.stringify(json, null, 2));
return (
@@ -183,11 +206,11 @@ export function prettyJson(json){
}

export function GeneralConfirmWindow({
isWindowOpen,
title,
content,
onNormalClose,
onConfirmClose}){
isWindowOpen,
title,
content,
onNormalClose,
onConfirmClose }) {
return (
<Dialog
open={isWindowOpen}


+ 23
- 13
src/utils/FieldUtils.js View File

@@ -67,15 +67,7 @@ export const getTextArea = ({ label, valueName, form, disabled, inputProps, ...p
}

export const getPhoneField = ({ label, valueName, form, disabled }) => {
form.handleChange = (event) => {
const value = event.target.value;
const name = event.target.name;
if (value.match(/[^0-9]/)) {
return event.preventDefault();
}
if (valueName.code === name) form.setFieldValue(valueName.code, value)
if (valueName.num === name) form.setFieldValue(valueName.num, value)
}

return <Grid container alignItems={"center"}>
<Grid item xs={12} md={3} lg={3}
sx={{ display: 'flex', alignItems: 'center' }}>
@@ -88,13 +80,31 @@ export const getPhoneField = ({ label, valueName, form, disabled }) => {
valueName: valueName.code,
form: form,
disabled: disabled,
width: '35%'
width: '35%',
handleChange: (event) => {
const value = event.target.value;
const name = event.target.name;
if (value.match(/[^0-9]/)) {
return event.preventDefault();
}
if (valueName.code === name) form.setFieldValue(valueName.code, value)
if (valueName.num === name) form.setFieldValue(valueName.num, value)
}
})}
{initField({
type: "tel",
valueName: valueName.num,
form: form,
disabled: disabled
disabled: disabled,
handleChange: (event) => {
const value = event.target.value;
const name = event.target.name;
if (value.match(/[^0-9]/)) {
return event.preventDefault();
}
if (valueName.code === name) form.setFieldValue(valueName.code, value)
if (valueName.num === name) form.setFieldValue(valueName.num, value)
}
})}
</Stack>
</Grid>
@@ -160,7 +170,7 @@ export const getComboField = ({ label, dataList, valueName, form, disabled, getO
</Grid>;
}

export const initField = ({ type, valueName, form, disabled, multiline, placeholder, inputProps, width, ...props }) => {
export const initField = ({ type, valueName, form, disabled, multiline, handleChange, placeholder, inputProps, width, ...props }) => {
let err = Boolean(form.errors[valueName]);

return <TextField
@@ -173,7 +183,7 @@ export const initField = ({ type, valueName, form, disabled, multiline, placehol
inputProps={inputProps}
error={err}
helperText={form.errors[valueName] ? form.errors[valueName] : ''}
onChange={form.handleChange}
onChange={handleChange ? handleChange : form.handleChange}
value={form.values[valueName]}
disabled={disabled}
sx={{


Loading…
Cancel
Save