diff --git a/src/layout/MainLayout/Header/index.js b/src/layout/MainLayout/Header/index.js index 5d6eba1..5e4b0dc 100644 --- a/src/layout/MainLayout/Header/index.js +++ b/src/layout/MainLayout/Header/index.js @@ -169,10 +169,22 @@ function Header(props) { 校對記錄
  • - 付款記錄 + 付款記錄 + {isPrimaryLoggedIn() ? + + : + <> + }
  • - 設定 + 設定 {isPrimaryLoggedIn() ?
      diff --git a/src/pages/DemandNote/Search/DataGrid.js b/src/pages/DemandNote/Search/DataGrid.js index c7539a8..b026814 100644 --- a/src/pages/DemandNote/Search/DataGrid.js +++ b/src/pages/DemandNote/Search/DataGrid.js @@ -4,15 +4,22 @@ import { Grid, Typography, Button, - Box + Box, + Dialog, DialogTitle, DialogContent, DialogActions, } from '@mui/material'; import * as DateUtils from "utils/DateUtils"; -import * as StatusUtils from "utils/statusUtils/PublicNoteStatusUtils"; +import * as StatusUtils from "utils/statusUtils/DnStatus"; import { useNavigate } from "react-router-dom"; import { FiDataGrid } from "components/FiDataGrid"; + +import * as UrlUtils from "utils/ApiPathConst"; +import * as HttpUtils from "utils/HttpUtils"; // ==============================|| EVENT TABLE ||============================== // -export default function SeaarchDemandNote({ recordList }) { +export default function SearchDemandNote({ recordList, reloadFun }) { + + const [isConfirmPopUp, setConfirmPopUp] = React.useState(false); + const [isSendPopUp, setSendPopUp] = React.useState(false); const [rows, setRows] = React.useState(recordList); const [selectedRowItems, setSelectedRowItems] = React.useState([]); @@ -35,14 +42,24 @@ export default function SeaarchDemandNote({ recordList }) { }); }; - const onSendClick = ()=>{ - let appIdList = []; + const onSendClick = () => { + setSendPopUp(false) + let idList = []; const datas = rows?.filter((row) => selectedRowItems.includes(row.id) ); for (var i = 0; i < datas?.length; i++) { - appIdList.push(datas[i].appId); + idList.push(datas[i].id); } + HttpUtils.post({ + url: UrlUtils.DEMAND_NOTE_SEND, + params: { + dnIdList: idList + }, + onSuccess: () => { + if (reloadFun) reloadFun(); + } + }); } @@ -50,8 +67,24 @@ export default function SeaarchDemandNote({ recordList }) { } - const markPaid = ()=>{ - + const markPaid = () => { + setConfirmPopUp(false); + let idList = []; + const datas = rows?.filter((row) => + selectedRowItems.includes(row.id) + ); + for (var i = 0; i < datas?.length; i++) { + idList.push(datas[i].id); + } + HttpUtils.post({ + url: UrlUtils.DEMAND_NOTE_MARK_PAID, + params: { + dnIdList: idList + }, + onSuccess: () => { + if (reloadFun) reloadFun(); + } + }); } function handleRowDoubleClick(params) { @@ -114,7 +147,7 @@ export default function SeaarchDemandNote({ recordList }) { headerName: 'Status', width: 175, renderCell: (params) => { - return [StatusUtils.getStatusEng(params)] + return [StatusUtils.getStatus_Eng(params)] }, }, { @@ -122,7 +155,7 @@ export default function SeaarchDemandNote({ recordList }) { headerName: 'DN Sent Date', flex: 1, valueGetter: (params) => { - return params?.value?DateUtils.datetimeStr(params?.value)+" - "+params.row.sentBy:""; + return params?.value ? DateUtils.datetimeStr(params?.value) + " - " + params.row.sentBy : ""; } }, { @@ -142,7 +175,7 @@ export default function SeaarchDemandNote({ recordList }) { + + + + +
      + setSendPopUp(false)} > + Confirm + + Are you sure to send DN? + + + + + + +
      ); } diff --git a/src/pages/DemandNote/Search/index.js b/src/pages/DemandNote/Search/index.js index 80b0f2c..e23d6d3 100644 --- a/src/pages/DemandNote/Search/index.js +++ b/src/pages/DemandNote/Search/index.js @@ -5,8 +5,9 @@ import { Stack } from '@mui/material'; import MainCard from "components/MainCard"; -import * as UrlUtils from "utils/ApiPathConst"; + import * as React from "react"; +import * as UrlUtils from "utils/ApiPathConst"; import * as HttpUtils from "utils/HttpUtils"; import * as DateUtils from "utils/DateUtils"; @@ -118,6 +119,7 @@ const UserSearchPage_Individual = () => { > diff --git a/src/pages/DemandNote/Search_Public/DataGrid.js b/src/pages/DemandNote/Search_Public/DataGrid.js new file mode 100644 index 0000000..2a3f080 --- /dev/null +++ b/src/pages/DemandNote/Search_Public/DataGrid.js @@ -0,0 +1,91 @@ +// material-ui +import * as React from 'react'; +import { + Button, + Box, +} from '@mui/material'; +import * as DateUtils from "utils/DateUtils"; +import * as StatusUtils from "utils/statusUtils/DnStatus"; +import { FiDataGrid } from "components/FiDataGrid"; + +import * as HttpUtils from "utils/HttpUtils"; +// ==============================|| EVENT TABLE ||============================== // + +export default function SearchDemandNote({ recordList }) { + const [rows, setRows] = React.useState(recordList); + + React.useEffect(() => { + setRows(recordList); + }, [recordList]); + + const onDownloadClick = (params) => () => { + HttpUtils.fileDownload({ + fileId: params.row.fileId, + skey: params.row.skey, + filename: params.row.filename, + }); + }; + + const columns = [ + { + field: 'dnNo', + headerName: '繳款單號', + width: 200, + }, + { + field: 'appNo', + headerName: '申請編號', + width: 150, + }, + { + id: 'issueDate', + field: 'issueDate', + headerName: '簽發日期', + width: 175, + valueGetter: (params) => { + return DateUtils.dateStr(params?.value); + } + }, + { + field: 'status', + headerName: '狀態', + width: 175, + renderCell: (params) => { + return [StatusUtils.getStatus_Eng(params)] + }, + }, + { + field: 'sentDate', + headerName: '發送日期', + flex: 1, + valueGetter: (params) => { + return params?.value ? DateUtils.datetimeStr(params?.value) + " - " + params.row.sentBy : ""; + } + }, + { + field: 'filename', + headerName: '檔案', + flex: 1, + renderCell: (params) => { + return ; + }, + }, + ]; + + return ( +
      + + 'auto'} + /> + +
      + ); +} diff --git a/src/pages/DemandNote/Search_Public/SearchForm.js b/src/pages/DemandNote/Search_Public/SearchForm.js new file mode 100644 index 0000000..a963e8c --- /dev/null +++ b/src/pages/DemandNote/Search_Public/SearchForm.js @@ -0,0 +1,241 @@ +// material-ui +import { + Button, + CardContent, + Grid, TextField, + Autocomplete, + Typography +} from '@mui/material'; +import MainCard from "components/MainCard"; +import { useForm } from "react-hook-form"; +import * as React from "react"; +import * as ComboData from "utils/ComboData"; +import * as DateUtils from "utils/DateUtils"; +import * as FormatUtils from "utils/FormatUtils"; +// ==============================|| DASHBOARD - DEFAULT ||============================== // + + +const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData +}) => { + + const [type, setType] = React.useState([]); + const [issueSelected, setIssueSelected] = React.useState({}); + const [issueCombo, setIssueCombo] = React.useState([]); + const [selectedStatus, setSelectedStatus] = React.useState({}); + + const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); + const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo); + + const { reset, register, handleSubmit } = useForm() + const onSubmit = (data) => { + let typeArray = []; + + for (let i = 0; i < type.length; i++) { + typeArray.push(type[i].label); + } + + const temp = { + appNo: data.appNo, + issueId: issueSelected?.id, + dnNo: data.dnNo, + sentDateFrom: data.dateFrom, + sentDateTo: data.dateTo, + status: (selectedStatus?.type && selectedStatus?.type != 'all') ? selectedStatus?.type : "", + }; + applySearch(temp); + }; + + React.useEffect(() => { + if (issueComboData && issueComboData.length > 0) { + setIssueCombo(issueComboData); + } + }, [issueComboData]); + + function resetForm() { + setType([]); + // setStatus({ key: 0, label: 'All', type: 'all' }); + setOrgSelected({}); + setIssueSelected({}); + reset(); + } + + function getIssueLabel(data) { + if (data == {}) return ""; + return data.year + + " Vol. " + FormatUtils.zeroPad(data.volume, 3) + + ", No. " + FormatUtils.zeroPad(data.issueNo, 2) + + ", " + DateUtils.dateFormat(data.issueDate, "D MMM YYYY (ddd)"); + } + + return ( + + +
      + + {/*row 1*/} + + + + 搜尋 + + + + {/*row 2*/} + + + + getIssueLabel(option)} + onChange={(event, newValue) => { + if (newValue !== null) { + setIssueSelected(newValue); + } + }} + renderInput={(params) => ( + + )} + /> + + + + + + + + + + + + { + setMinDate(DateUtils.dateStr(newValue)); + }} + InputLabelProps={{ + shrink: true + }} + /> + + + + { + setMaxDate(DateUtils.dateStr(newValue)); + }} + id="dateTo" + type="date" + label={"發送日期(到)"} + defaultValue={searchCriteria.dateTo} + /> + + + + + option.labelCht} + inputValue={selectedStatus?.labelCht ? selectedStatus?.labelCht : ""} + value={selectedStatus} + onChange={(event, newValue) => { + if (newValue !== null) { + setSelectedStatus(newValue); + } + }} + renderInput={(params) => ( + + )} + InputLabelProps={{ + shrink: true + }} + /> + + + + + + + {/*last row*/} + + + + + + + + + + +
      +
      + ); +}; + +export default SearchDemandNoteForm; diff --git a/src/pages/DemandNote/Search_Public/index.js b/src/pages/DemandNote/Search_Public/index.js new file mode 100644 index 0000000..35d06c7 --- /dev/null +++ b/src/pages/DemandNote/Search_Public/index.js @@ -0,0 +1,129 @@ +// material-ui +import { + Grid, + Typography, + Stack +} from '@mui/material'; +import MainCard from "components/MainCard"; + +import * as React from "react"; +import * as UrlUtils from "utils/ApiPathConst"; +import * as HttpUtils from "utils/HttpUtils"; +import * as DateUtils from "utils/DateUtils"; + +import Loadable from 'components/Loadable'; +const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); +const SearchForm = Loadable(React.lazy(() => import('./SearchForm'))); +const EventTable = Loadable(React.lazy(() => import('./DataGrid'))); +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' + +const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: '100%', + height: '100%', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' +} + +// ==============================|| DASHBOARD - DEFAULT ||============================== // + +const UserSearchPage_Individual = () => { + + const [record, setRecord] = React.useState([]); + const [orgCombo, setOrgCombo] = React.useState([]); + const [issueCombo, setIssueCombo] = React.useState([]); + const [searchCriteria, setSearchCriteria] = React.useState({ + dateTo: DateUtils.dateStr(new Date()), + dateFrom: DateUtils.dateStr(new Date().setDate(new Date().getDate() - 14)), + }); + const [onReady, setOnReady] = React.useState(false); + + React.useEffect(() => { + getUserList(); + getOrgCombo(); + getIssueCombo(); + }, []); + + React.useEffect(() => { + setOnReady(true); + }, [record]); + + React.useEffect(() => { + getUserList(); + }, [searchCriteria]); + + function getUserList() { + HttpUtils.get({ + url: UrlUtils.DEMAND_NOTE_LIST, + params: searchCriteria, + onSuccess: function (responseData) { + setRecord(responseData); + } + }); + } + + function getOrgCombo() { + HttpUtils.get({ + url: UrlUtils.GET_ORG_COMBO, + onSuccess: function (responseData) { + let combo = responseData; + setOrgCombo(combo); + } + }); + } + + function getIssueCombo() { + HttpUtils.get({ + url: UrlUtils.GET_ISSUE_COMBO, + onSuccess: function (responseData) { + let combo = responseData; + setIssueCombo(combo); + } + }); + } + + + function applySearch(input) { + setSearchCriteria(input); + } + + return ( + !onReady ? + + : + + +
      + + 繳款通知記錄 + +
      +
      + {/*row 1*/} + + + + {/*row 2*/} + + + + + +
      + ); +} +export default UserSearchPage_Individual; diff --git a/src/routes/PublicUserRoutes.js b/src/routes/PublicUserRoutes.js index 9035b50..b0f4815 100644 --- a/src/routes/PublicUserRoutes.js +++ b/src/routes/PublicUserRoutes.js @@ -22,6 +22,7 @@ const Payment_Card = Loadable(lazy(() => import('pages/Payment/Card'))); const Payment_Callback = Loadable(lazy(() => import('pages/Payment/PaymentCallback'))); const PaymentSearch_Public = Loadable(lazy(() => import('pages/Payment/Search_Public'))); const PaymentDetails_Public = Loadable(lazy(() => import('pages/Payment/Details_Public'))); +const DemandNote_Public = Loadable(lazy(() => import('pages/DemandNote/Search_Public'))); // ==============================|| MAIN ROUTING ||============================== // @@ -100,6 +101,10 @@ const PublicDashboard = { path: 'paymentPage/details/:id', element: }, + { + path: 'paymentPage/demandNote', + element: + }, ] }, ] diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index 7c2d12f..4f9fd6e 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -98,6 +98,8 @@ export const DEMAND_NOTE_PREVIEW = apiPath+'/demandNote/preview';//GET export const DEMAND_NOTE_CREATE = apiPath+'/demandNote/create';//POST export const DEMAND_NOTE_LIST = apiPath+'/demandNote/list';//GET export const DEMAND_NOTE_LOAD = apiPath+'/demandNote/load';//GET +export const DEMAND_NOTE_SEND = apiPath+'/demandNote/send-dn';//POST +export const DEMAND_NOTE_MARK_PAID = apiPath+'/demandNote/mark-as-paid';//POST diff --git a/src/utils/statusUtils/DnStatus.js b/src/utils/statusUtils/DnStatus.js index fda63c1..5e1eda5 100644 --- a/src/utils/statusUtils/DnStatus.js +++ b/src/utils/statusUtils/DnStatus.js @@ -1,8 +1,8 @@ import {getStatusTag} from "utils/statusUtils/Base"; const pending = {color:"#f5a83d", eng:"Pending", cht:"待辦"} -const toBePaid = {color:"#f5a83d", eng:"to be paid", cht:"待支付"} -const paid = {color:"#8a8784", eng:"paid", cht:"已付費"} +const toBePaid = {color:"#f5a83d", eng:"To be paid", cht:"待支付"} +const paid = {color:"#22a13f", eng:"Paid", cht:"已付費"} export function getStatus_Cht(params) { let status = getStatus(params);