diff --git a/src/components/FiDataGrid.js b/src/components/FiDataGrid.js index cbfe52e..92db46a 100644 --- a/src/components/FiDataGrid.js +++ b/src/components/FiDataGrid.js @@ -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); diff --git a/src/components/MainCard.js b/src/components/MainCard.js index bc1a196..8b3124c 100644 --- a/src/components/MainCard.js +++ b/src/components/MainCard.js @@ -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 }, // '& > *': { diff --git a/src/layout/MainLayout/Header/HeaderContent/Profile/index.js b/src/layout/MainLayout/Header/HeaderContent/Profile/index.js index cec4aad..239eda5 100644 --- a/src/layout/MainLayout/Header/HeaderContent/Profile/index.js +++ b/src/layout/MainLayout/Header/HeaderContent/Profile/index.js @@ -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 = () => { - {open && ( + {/* {open && ( <> @@ -202,7 +204,7 @@ const Profile = () => { - )} + )} */} diff --git a/src/layout/MainLayout/Header/index.js b/src/layout/MainLayout/Header/index.js index f3b96be..1c93bed 100644 --- a/src/layout/MainLayout/Header/index.js +++ b/src/layout/MainLayout/Header/index.js @@ -74,81 +74,85 @@ function Header(props) { isGLDLoggedIn() ?
  • - Dashboard + Dashboard
  • - Application + Application
  • - Proof + Proof
  • - Payment + Payment
  • - Client + Client
    • - Users (GLD) + Users (GLD)
    • - Users (Individual) + Users (Individual)
    • - Users (Organization) + Users (Organisation)
    • - Organization + Organisation
    • - User Group + User Group
    • +
  • - Logout + Email Template
  • + {/*
  • + Logout +
  • */}
    :
  • - 主頁 + 主頁
  • - 我的公共啟事 + 我的公共啟事
  • - 校對記錄 + 校對記錄
  • - 付款記錄 + 付款記錄
  • - 設定 + 設定 {isPrimaryLoggedIn() ?
    • - 公司/機構用戶記錄 + 公司/機構用戶記錄
    : <> }
  • -
  • - 登出 -
  • + {/*
  • + 登出 +
  • */}
    ); const logoutContent = (
  • - 登入 + 登入
  • - 申請 + 申請
  • ); diff --git a/src/pages/EmailTemplate/Detail_GLD/EmailTemplateDetails.js b/src/pages/EmailTemplate/Detail_GLD/EmailTemplateDetails.js new file mode 100644 index 0000000..ff10def --- /dev/null +++ b/src/pages/EmailTemplate/Detail_GLD/EmailTemplateDetails.js @@ -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 ; + } + + const { register, handleSubmit } = useForm() + + + + // const DisplaySelection = ({ name = "test", value = "", onChange }) => { + // return ( + // + // )} + // /> + // } + return ( + + + Maintain Email Template + +
    + + + + {/* + + + Email Key: + + + + + + */} + + + + Key: + + + + + + + + + + Description: + + + + + + + + + + + + + + + + Params: + + + + + + + + + + + + + Subject (Cht): + + + + + + + + + + + Content (Cht): + + + + + + + + + + + Subject (Chs): + + + + + + + + + + + Content (Chs): + + + + + + + + + + + Subject (Eng): + + + + + + + + + + + Content (Eng): + + + + + + + + + {/*bottom button*/} + + + + + + + + + + + +
    +
    + ); +}; + +export default ApplicationDetailCard; diff --git a/src/pages/EmailTemplate/Detail_GLD/index.js b/src/pages/EmailTemplate/Detail_GLD/index.js new file mode 100644 index 0000000..78cf80f --- /dev/null +++ b/src/pages/EmailTemplate/Detail_GLD/index.js @@ -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 ? + + : + ( + + +
    + + Email Template + +
    +
    + + + + {/*row 1*/} + + + + + + + + + {/*row 2*/} +
    + ) + ); +}; + +export default Index; \ No newline at end of file diff --git a/src/pages/EmailTemplate/Search_GLD/DataGrid.js b/src/pages/EmailTemplate/Search_GLD/DataGrid.js new file mode 100644 index 0000000..542ce2e --- /dev/null +++ b/src/pages/EmailTemplate/Search_GLD/DataGrid.js @@ -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 [ + } + 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 ( +
    + 'auto'} + /> +
    + ); +} \ No newline at end of file diff --git a/src/pages/EmailTemplate/Search_GLD/index.js b/src/pages/EmailTemplate/Search_GLD/index.js new file mode 100644 index 0000000..2556ba1 --- /dev/null +++ b/src/pages/EmailTemplate/Search_GLD/index.js @@ -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 ? + + : + ( + + +
    + + Email Template + +
    +
    + {/*row 1*/} + + + + + + + + + + +
    + ) + ); +}; + +export default Index; \ No newline at end of file diff --git a/src/pages/OrganizationDetailPage/OrganizationCard.js b/src/pages/OrganizationDetailPage/OrganizationCard.js index 2d4af82..6911dd7 100644 --- a/src/pages/OrganizationDetailPage/OrganizationCard.js +++ b/src/pages/OrganizationDetailPage/OrganizationCard.js @@ -35,22 +35,34 @@ const OrganizationCard = ({ userData, loadDataFun, id }) => { } }, [currentUserData]); + function displayErrorMsg(errorMsg) { + return {errorMsg} + } 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 }) => { - Organization Details + Organisation Details diff --git a/src/pages/OrganizationDetailPage/index.js b/src/pages/OrganizationDetailPage/index.js index a617e79..8be47cf 100644 --- a/src/pages/OrganizationDetailPage/index.js +++ b/src/pages/OrganizationDetailPage/index.js @@ -77,7 +77,7 @@ const OrganizationDetailPage = () => {
    - Maintain Organization + Maintain Organisation
    diff --git a/src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js b/src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js index e910d9c..84581bf 100644 --- a/src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js +++ b/src/pages/OrganizationDetailPage_FromUser/OrganizationCard_loadFromUser.js @@ -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 {errorMsg} + } + 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({ diff --git a/src/pages/OrganizationDetailPage_FromUser/index.js b/src/pages/OrganizationDetailPage_FromUser/index.js index a7784f3..57f3bd5 100644 --- a/src/pages/OrganizationDetailPage_FromUser/index.js +++ b/src/pages/OrganizationDetailPage_FromUser/index.js @@ -66,7 +66,7 @@ const OrganizationDetailPage_FromUser = () => { : - Organization (Create From User) + Organisation (Create From User) {/*col 1*/} diff --git a/src/pages/OrganizationSearchPage/index.js b/src/pages/OrganizationSearchPage/index.js index eb1a25b..3995a76 100644 --- a/src/pages/OrganizationSearchPage/index.js +++ b/src/pages/OrganizationSearchPage/index.js @@ -70,7 +70,7 @@ const OrganizationSearchPage = () => {
    - View Organization + View Organisation
    diff --git a/src/pages/Proof/Payment/Pay.js b/src/pages/Proof/Payment/Pay.js index defd2f2..03da615 100644 --- a/src/pages/Proof/Payment/Pay.js +++ b/src/pages/Proof/Payment/Pay.js @@ -77,15 +77,15 @@ const Index = () => {
    - 公共啟事:交對完成及付款 + 公共啟事:校對完成及付款 - 我們已收到申請編號: {record?.appNo} 的稿件交對確定及可付印的指示。 + 我們已收到申請編號: {record?.appNo} 的稿件校對確定及可付印的指示。

    請於 {DateUtils.dateStr_Cht(record?.returnBeforeDate)} 下午 2:00 前 完成繳費,我們將於收到繳費確認後處理刊出事宜。

    - 如你在憲報期數 {record?.issueYear} 年 {record?.issueVolume} 卷, 第 {record?.issueNo} 期內有多於一個公共啟事的申請,你可選擇完成所有此期所有稿件交對確定後,於繳費期限前在「我的公共啟事」內合併付款。 + 如你在憲報期數 {record?.issueYear} 年 {record?.issueVolume} 卷, 第 {record?.issueNo} 期內有多於一個公共啟事的申請,你可選擇完成所有此期所有稿件校對確定後,於繳費期限前在「我的公共啟事」內合併付款。
    diff --git a/src/pages/Proof/Payment/Pay_Creditor.js b/src/pages/Proof/Payment/Pay_Creditor.js index b41a49b..c2b2b37 100644 --- a/src/pages/Proof/Payment/Pay_Creditor.js +++ b/src/pages/Proof/Payment/Pay_Creditor.js @@ -76,12 +76,12 @@ const Index = () => {
    - 公共啟事:交對完成 + 公共啟事:校對完成 - 我們已收到你已確定申請編號: {record?.appNo} 的稿件交對確定及可付印的指示,並將安排刊登於憲報 + 我們已收到你已確定申請編號: {record?.appNo} 的稿件校對確定及可付印的指示,並將安排刊登於憲報 期數 {record?.appNo} 年 {record?.issueVolume} 卷 第 {record?.issueNo} 期內。

    此公共啟事申請的費用將於下期發出的繳費發票時收取,請依時繳費。 diff --git a/src/pages/Proof/Reply_Public/ApplicationDetails.js b/src/pages/Proof/Reply_Public/ApplicationDetails.js index ed7a89d..7ffa56c 100644 --- a/src/pages/Proof/Reply_Public/ApplicationDetails.js +++ b/src/pages/Proof/Reply_Public/ApplicationDetails.js @@ -166,7 +166,7 @@ const ApplicationDetailCard = ({ formData, }) => { - 我的備注: + 我的備註: diff --git a/src/pages/Proof/Search_GLD/SearchForm.js b/src/pages/Proof/Search_GLD/SearchForm.js index b953ae1..4bbb7b6 100644 --- a/src/pages/Proof/Search_GLD/SearchForm.js +++ b/src/pages/Proof/Search_GLD/SearchForm.js @@ -264,7 +264,7 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss }} renderInput={(params) => ( "auto"} diff --git a/src/pages/PublicNotice/ApplyForm/PublicNoticeApplyForm.js b/src/pages/PublicNotice/ApplyForm/PublicNoticeApplyForm.js index cbe3bd2..e7ab1b8 100644 --- a/src/pages/PublicNotice/ApplyForm/PublicNoticeApplyForm.js +++ b/src/pages/PublicNotice/ApplyForm/PublicNoticeApplyForm.js @@ -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 ( - +
    @@ -128,6 +127,11 @@ const PublicNoticeApplyForm = ({ loadedData, selections }) => {
    + + + {/* 申請公共啟事 */} @@ -169,7 +173,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 }) => {
    + - 稿件檔案 ({"檔案大小應<10MB"}): + 稿件檔案 ({"檔案大小應<10MB"}): { size="large" >{attachment ? "上傳檔案" : "重新上傳"} - + {FieldUtils.getTextArea({ label: "備註:", diff --git a/src/pages/PublicNotice/ApplyForm/index.js b/src/pages/PublicNotice/ApplyForm/index.js index f43a626..af41ca4 100644 --- a/src/pages/PublicNotice/ApplyForm/index.js +++ b/src/pages/PublicNotice/ApplyForm/index.js @@ -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(} 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 ? - + : {setIsPopUp(true)}} + onClick={() => { setIsPopUp(true) }} disabled={currentApplicationDetailData.status == "rejected" || currentApplicationDetailData.status == "cancelled" || currentApplicationDetailData.status == "paid"} sx={{ textTransform: 'capitalize', @@ -191,20 +191,31 @@ const ApplicationDetailCard = ( 申請狀態: - + {StatusUtils.getStatusByText(currentApplicationDetailData.status)} - - - - - {currentApplicationDetailData.reason} - - - - + { + currentApplicationDetailData.reason ? + + + + + 原因: + + + + + {currentApplicationDetailData.reason} + + + + + + + : "" + }
    @@ -506,29 +517,29 @@ const ApplicationDetailCard = ( 備註:
    - {currentApplicationDetailData.remarks} + {currentApplicationDetailData.remarks}
    - setIsPopUp(false)} > - - 確認付款 - - - 總計金額: {FormatUtils.currencyFormat(fee)} - - - - - - - -
    + setIsPopUp(false)} > + + 確認付款 + + + 總計金額: {FormatUtils.currencyFormat(fee)} + + + + + + + + - + ); }; diff --git a/src/pages/PublicNotice/ListPanel/BaseGrid.js b/src/pages/PublicNotice/ListPanel/BaseGrid.js index bb8fbc7..0e565cf 100644 --- a/src/pages/PublicNotice/ListPanel/BaseGrid.js +++ b/src/pages/PublicNotice/ListPanel/BaseGrid.js @@ -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}
    - {contact} - ); - } - }, + // return (<> + // {params?.value}
    + // {contact} + // ); + // } + // }, { id: 'remarks', field: 'remarks', @@ -90,13 +90,13 @@ export default function BaseGrid({rows}) { } return ( -
    +
    { - 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}
    - {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}
    + // {contact} + // ); + // } + // }, { id: 'remarks', field: 'remarks', diff --git a/src/pages/PublicNotice/ListPanel/SearchPublicNoticeForm.js b/src/pages/PublicNotice/ListPanel/SearchPublicNoticeForm.js index d51819e..fe500a1 100644 --- a/src/pages/PublicNotice/ListPanel/SearchPublicNoticeForm.js +++ b/src/pages/PublicNotice/ListPanel/SearchPublicNoticeForm.js @@ -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(); } diff --git a/src/pages/PublicNotice/ListPanel/SearchPublicNoticeTable.js b/src/pages/PublicNotice/ListPanel/SearchPublicNoticeTable.js index 4235186..87bedfd 100644 --- a/src/pages/PublicNotice/ListPanel/SearchPublicNoticeTable.js +++ b/src/pages/PublicNotice/ListPanel/SearchPublicNoticeTable.js @@ -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}
    - {contact} - ); - } - }, + // return (<> + // {params?.value}
    + // {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 ; @@ -95,17 +95,17 @@ export default function SearchPublicNoticeTable({ recordList }) { } return ( -
    - +
    'auto'} />
    ); diff --git a/src/pages/PublicNotice/Search_GLD/SearchForm.js b/src/pages/PublicNotice/Search_GLD/SearchForm.js index 27cc414..2d4292b 100644 --- a/src/pages/PublicNotice/Search_GLD/SearchForm.js +++ b/src/pages/PublicNotice/Search_GLD/SearchForm.js @@ -236,7 +236,7 @@ const SearchPublicNoticeForm = ({ applySearch, orgComboData, searchCriteria, iss }} renderInput={(params) => ( { 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, diff --git a/src/pages/User/DetailsPage_Organization/UserInformationCard_Organization.js b/src/pages/User/DetailsPage_Organization/UserInformationCard_Organization.js index 4c957ab..ae961d3 100644 --- a/src/pages/User/DetailsPage_Organization/UserInformationCard_Organization.js +++ b/src/pages/User/DetailsPage_Organization/UserInformationCard_Organization.js @@ -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 {errorMsg} + } + 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*/}
    - Organization User Details + Organisation User Details @@ -297,7 +310,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) => {FieldUtils.getComboField({ - label: "Organization:", + label: "Organisation:", valueName: "orgId", disabled: (!editMode), dataList: orgData, @@ -466,7 +479,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) => : null @@ -475,7 +488,7 @@ const UserInformationCard_Organization = ({ userData, loadDataFun, orgData }) => - Organization + Organisation diff --git a/src/pages/User/DetailsPage_Organization/index.js b/src/pages/User/DetailsPage_Organization/index.js index df96f6a..0b124a8 100644 --- a/src/pages/User/DetailsPage_Organization/index.js +++ b/src/pages/User/DetailsPage_Organization/index.js @@ -133,7 +133,7 @@ const UserMaintainPage_Organization = () => {
    - Maintain Organization User + Maintain Organisation User
    diff --git a/src/pages/User/SearchPage/UserSearchForm.js b/src/pages/User/SearchPage/UserSearchForm.js index f172c32..c393d05 100644 --- a/src/pages/User/SearchPage/UserSearchForm.js +++ b/src/pages/User/SearchPage/UserSearchForm.js @@ -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 = () => { diff --git a/src/pages/User/SearchPage_Organization/index.js b/src/pages/User/SearchPage_Organization/index.js index 7200ad8..98f9553 100644 --- a/src/pages/User/SearchPage_Organization/index.js +++ b/src/pages/User/SearchPage_Organization/index.js @@ -72,7 +72,7 @@ const UserSearchPage_Organization = () => {
    - View Organization User + View Organisation User
    diff --git a/src/pages/authentication/auth-forms/BusCustomFormWizard.js b/src/pages/authentication/auth-forms/BusCustomFormWizard.js index b96fbc6..ac6c10b 100644 --- a/src/pages/authentication/auth-forms/BusCustomFormWizard.js +++ b/src/pages/authentication/auth-forms/BusCustomFormWizard.js @@ -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) => { 用戶登入名稱 * - + */} { }} 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) => { { {formik.errors.email} )} + {checkEmail && ( + + 此電郵已被注冊,請使用其他電郵 + + )}
    @@ -1547,7 +1611,7 @@ const BusCustomFormWizard = (props) => { 帳戶申請已成功提交。 - 驗證電郵將發送到你的電郵地址,請要指示完成驗證及登入系統。 + 驗證電郵將發送到你的電郵地址,請依指示完成驗證及登入系統。 : diff --git a/src/pages/authentication/auth-forms/CustomFormWizard.js b/src/pages/authentication/auth-forms/CustomFormWizard.js index 143e700..4a63af8 100644 --- a/src/pages/authentication/auth-forms/CustomFormWizard.js +++ b/src/pages/authentication/auth-forms/CustomFormWizard.js @@ -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) => { 用戶登入名稱 - * + {/* * + */} { }} 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) => { { {formik.errors.email} )} + {checkEmail && ( + + 此電郵已被注冊,請使用其他電郵 + + )} @@ -1685,7 +1739,7 @@ const CustomFormWizard = (props) => { 帳戶申請已成功提交。 - 驗證電郵將發送到你的電郵地址,請要指示完成驗證及登入系統。 + 驗證電郵將發送到你的電郵地址,請依指示完成驗證及登入系統。 : diff --git a/src/pages/authentication/auth-forms/PreviewUploadFileTable.js b/src/pages/authentication/auth-forms/PreviewUploadFileTable.js index 779a7b6..4a48bb9 100644 --- a/src/pages/authentication/auth-forms/PreviewUploadFileTable.js +++ b/src/pages/authentication/auth-forms/PreviewUploadFileTable.js @@ -104,6 +104,7 @@ export default function PreviewUploadFileTable({ recordList, }) { disableColumnMenu disableColumnSelector hideFooter + getRowHeight={()=>"auto"} /> ); diff --git a/src/pages/authentication/auth-forms/UploadFileTable.js b/src/pages/authentication/auth-forms/UploadFileTable.js index 2b295e2..cecc645 100644 --- a/src/pages/authentication/auth-forms/UploadFileTable.js +++ b/src/pages/authentication/auth-forms/UploadFileTable.js @@ -106,6 +106,7 @@ export default function UploadFileTable({ recordList, setUpdateRows, }) { disableColumnMenu disableColumnSelector hideFooter + getRowHeight={()=>"auto"} /> ); diff --git a/src/pages/pnspsNotifyTest/index.js b/src/pages/pnspsNotifyTest/index.js index dcd6c23..e9e2e13 100644 --- a/src/pages/pnspsNotifyTest/index.js +++ b/src/pages/pnspsNotifyTest/index.js @@ -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}> - - + + + ); diff --git a/src/routes/SettingRoutes.js b/src/routes/SettingRoutes.js index 048040e..1e712c4 100644 --- a/src/routes/SettingRoutes.js +++ b/src/routes/SettingRoutes.js @@ -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: }, + { + path: 'emailTemplate', + element: + }, + { + path: '/emailTemplate/:id', + element: + }, ] }; diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index cf6fb6d..b6523a6 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -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'; \ No newline at end of file +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'; \ No newline at end of file diff --git a/src/utils/CommonFunction.js b/src/utils/CommonFunction.js index aef31ea..4ac4443 100644 --- a/src/utils/CommonFunction.js +++ b/src/utils/CommonFunction.js @@ -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 ( { - 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 @@ -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) + } })} @@ -160,7 +170,7 @@ export const getComboField = ({ label, dataList, valueName, form, disabled, getO ; } -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