jason.lam 1 年之前
父節點
當前提交
8b350e3878
共有 6 個檔案被更改,包括 202 行新增184 行删除
  1. +5
    -2
      src/pages/DemandNote/Create/SearchForm.js
  2. +79
    -2
      src/pages/DemandNote/Search/DataGrid.js
  3. +2
    -31
      src/pages/DemandNote/Search/index.js
  4. +67
    -106
      src/pages/Payment/MultiPaymentWindow.js
  5. +5
    -20
      src/pages/Payment/index.js
  6. +44
    -23
      src/utils/HttpUtils.js

+ 5
- 2
src/pages/DemandNote/Create/SearchForm.js 查看文件

@@ -27,6 +27,7 @@ const SearchPublicNoticeForm = ({ applySearch, issueComboData, _paymentCount, _p

const [isSuccessPopUp, setIsSuccessPopUp] = React.useState(false);
const [resultCount, setResultCount] = React.useState(0);
const [dnIdList, setDnIdList] = React.useState([]);

const [issueSelected, setIssueSelected] = React.useState({});
const [paymentCount, setPaymentCount] = React.useState(0);
@@ -86,6 +87,7 @@ const SearchPublicNoticeForm = ({ applySearch, issueComboData, _paymentCount, _p
url: UrlUtils.DEMAND_NOTE_CREATE + "/" + issueSelected.id,
onSuccess: function (responseData) {
setResultCount(responseData.count);
setDnIdList(responseData.idList);
setIsSuccessPopUp(true);
}
});
@@ -95,9 +97,10 @@ const SearchPublicNoticeForm = ({ applySearch, issueComboData, _paymentCount, _p

const fileDownload = () => {
HttpUtils.fileDownload({
method:'post',
url: UrlUtils.DEMAND_NOTE_EXPORT,
params: {
"issueId": issueSelected.id
"dnIdList": dnIdList
},
onSuccess: function () {
notifyDownloadSuccess();
@@ -219,7 +222,7 @@ const SearchPublicNoticeForm = ({ applySearch, issueComboData, _paymentCount, _p
<Grid item md={12}>
<Button
size="large"
onClick={fileDownload}
onClick={()=>fileDownload()}
sx={{
textTransform: 'capitalize',
alignItems: 'end'


+ 79
- 2
src/pages/DemandNote/Search/DataGrid.js 查看文件

@@ -11,15 +11,19 @@ import * as DateUtils from "utils/DateUtils";
import * as StatusUtils from "utils/statusUtils/DnStatus";
import { useNavigate } from "react-router-dom";
import { FiDataGrid } from "components/FiDataGrid";
import { notifyDownloadSuccess } from 'utils/CommonFunction';

import * as UrlUtils from "utils/ApiPathConst";
import * as HttpUtils from "utils/HttpUtils";
// ==============================|| EVENT TABLE ||============================== //

export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }) {
export default function SearchDemandNote({ recordList, reloadFun }) {

const [isConfirmPopUp, setConfirmPopUp] = React.useState(false);
const [isSendPopUp, setSendPopUp] = React.useState(false);
const [isErrorPopUp, setIsErrorPopUp] = React.useState(false);
const [selectonWarning, setSelectonWarning] = React.useState(false);
const [wait, setWait] = React.useState(false);

const [rows, setRows] = React.useState(recordList);
const [selectedRowItems, setSelectedRowItems] = React.useState([]);
@@ -33,6 +37,32 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
navigate('/paymentPage/demandNote/details/' + params.id);
};

const exportXml = () => {
let idList = [];
const datas = rows?.filter((row) =>
selectedRowItems.includes(row.id)
);
if(datas?.length<1){
setSelectonWarning(true);
return;
}else if (datas?.length >= 100) {
setIsErrorPopUp(true);
return;
}
for (var i = 0; i < datas?.length; i++) {
idList.push(datas[i].id);
}
HttpUtils.fileDownload({
method:'post',
url: UrlUtils.DEMAND_NOTE_EXPORT,
params: {
dnIdList:idList
},
onSuccess: function () {
notifyDownloadSuccess();
}
});
}

const onDownloadClick = (params) => () => {
HttpUtils.fileDownload({
@@ -48,6 +78,10 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
const datas = rows?.filter((row) =>
selectedRowItems.includes(row.id)
);
if(datas?.length<1){
setSelectonWarning(true);
return;
}
for (var i = 0; i < datas?.length; i++) {
idList.push(datas[i].id);
}
@@ -64,6 +98,7 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
}

const doUploadFile = (event) => {
setWait(true);
let dnMap = {};
const datas = rows?.filter((row) =>
selectedRowItems.includes(row.id)
@@ -80,6 +115,7 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
},
files:[file],
onSuccess() {
setWait(false);
if (reloadFun) reloadFun();
},
});
@@ -92,6 +128,10 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
const datas = rows?.filter((row) =>
selectedRowItems.includes(row.id)
);
if(datas?.length<1){
setSelectonWarning(true);
return;
}
for (var i = 0; i < datas?.length; i++) {
idList.push(datas[i].id);
}
@@ -198,6 +238,14 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
accept=".pdf"
style={{ display: 'none' }}
onChange={(event) => {
const datas = rows?.filter((row) =>
selectedRowItems.includes(row.id)
);
if(datas.length==0){
setSelectonWarning(true);
document.getElementById("uploadFileBtn").value = "";
return;
}
doUploadFile(event)
}}
/>
@@ -228,7 +276,7 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
<Button
size="large"
variant="contained"
onClick={exportXmlFun}
onClick={()=>exportXml()}
sx={{
textTransform: 'capitalize',
alignItems: 'end'
@@ -268,6 +316,28 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
onRowDoubleClick={handleRowDoubleClick}
/>
</Box>
<div>
<Dialog open={isErrorPopUp} onClose={() => setIsErrorPopUp(false)} >
<DialogTitle><Typography variant="h3">Action Fail</Typography></DialogTitle>
<DialogContent style={{ display: 'flex', }}>
<Typography variant="h4" style={{ padding: '16px' }}>Number of DN record must less than 100.<br/>Please edit search form.</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setIsErrorPopUp(false)}><Typography variant="h5">OK</Typography></Button>
</DialogActions>
</Dialog>
</div>
<div>
<Dialog open={selectonWarning} onClose={() => setSelectonWarning(false)} >
<DialogTitle><Typography variant="h3">Warning</Typography></DialogTitle>
<DialogContent style={{ display: 'flex', }}>
<Typography variant="h4" style={{ padding: '16px' }}>Please Select DN.</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setSelectonWarning(false)}><Typography variant="h5">OK</Typography></Button>
</DialogActions>
</Dialog>
</div>
<div>
<Dialog open={isConfirmPopUp} onClose={() => setConfirmPopUp(false)} >
<DialogTitle><Typography variant="h3">Confirm</Typography></DialogTitle>
@@ -292,6 +362,13 @@ export default function SearchDemandNote({ recordList, reloadFun, exportXmlFun }
</DialogActions>
</Dialog>
</div>
<div>
<Dialog open={wait} onClose={() => setWait(false)} >
<DialogContent style={{ display: 'flex', }}>
<Typography variant="h4" style={{ padding: '16px' }}>Calculating, please wait ...</Typography>
</DialogContent>
</Dialog>
</div>
</div>
);
}

+ 2
- 31
src/pages/DemandNote/Search/index.js 查看文件

@@ -3,8 +3,6 @@ import {
Grid,
Typography,
Stack,
Button,
Dialog, DialogTitle, DialogContent, DialogActions,
} from '@mui/material';
import MainCard from "components/MainCard";

@@ -18,7 +16,7 @@ const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/Loa
const SearchForm = Loadable(React.lazy(() => import('./SearchForm')));
const EventTable = Loadable(React.lazy(() => import('./DataGrid')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import { notifyDownloadSuccess } from 'utils/CommonFunction';

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
@@ -34,8 +32,6 @@ const BackgroundHead = {

const UserSearchPage_Individual = () => {

const [isErrorPopUp, setIsErrorPopUp] = React.useState(false);

const [record, setRecord] = React.useState([]);
const [orgCombo, setOrgCombo] = React.useState([]);
const [issueCombo, setIssueCombo] = React.useState([]);
@@ -69,20 +65,6 @@ const UserSearchPage_Individual = () => {
});
}

function exportXml() {
if (record.length >= 100) {
setIsErrorPopUp(true);
return;
}
HttpUtils.fileDownload({
url: UrlUtils.DEMAND_NOTE_EXPORT,
params: searchCriteria,
onSuccess: function () {
notifyDownloadSuccess();
}
});
}

function getOrgCombo() {
HttpUtils.get({
url: UrlUtils.GET_ORG_COMBO,
@@ -140,21 +122,10 @@ const UserSearchPage_Individual = () => {
<EventTable
recordList={record}
reloadFun={getUserList}
exportXmlFun={exportXml}
/>
</MainCard>
</Grid>
<div>
<Dialog open={isErrorPopUp} onClose={() => setIsErrorPopUp(false)} >
<DialogTitle><Typography variant="h3">Action Fail</Typography></DialogTitle>
<DialogContent style={{ display: 'flex', }}>
<Typography variant="h4" style={{ padding: '16px' }}>Number of DN record must less than 100.<br/>Please edit search form.</Typography>
</DialogContent>
<DialogActions>
<Button onClick={() => setIsErrorPopUp(false)}><Typography variant="h5">OK</Typography></Button>
</DialogActions>
</Dialog>
</div>
</Grid>
);
}


+ 67
- 106
src/pages/Payment/MultiPaymentWindow.js 查看文件

@@ -34,7 +34,7 @@ import FpsIcon from "assets/images/icons/fps.svg";
const MultiPaymentWindow = (props) => {

const windowTitle = "請選擇付款方式";
const [content, setContent] = useState();
// const [content, setContent] = useState();
const [loadtTransactionData, setLoadtTransactionData] = useState({});
const [loadAvailableMethodData, setLoadAvailableMethodData] = useState([]);
const [paymentMethod, setPaymentMethod] = useState("");
@@ -106,110 +106,10 @@ const MultiPaymentWindow = (props) => {
props.setConfirmPayment(true);
};

// const getMethodImgClass = (method) => () =>{
// setPaymentMethodClass()
// return paymentMethod == method || paymentMethod == "" ? "" : "grayscale";
// }

useEffect(() => {
if(props.selectedPaymentMethod === ""){
setPaymentMethod("")
}
if (availableMethodData.length>0){
setContent(
<Grid container spacing={2} direction="column" justifyContent="space-between" alignItems="flex-start">
{/* <Grid item xs={12} md={12}>
<Grid container >
<Grid item>
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}>
交易參考編號:
</FormLabel>
</Grid>
<Grid item>
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}>
{props.transactionData.transactionid}
</FormLabel>
</Grid>
</Grid>
</Grid>
<Grid item xs={12} md={12}>
<Grid container >
<Grid item>
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}>
付款金額:
</FormLabel>
</Grid>
<Grid item>
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}>
{"HK$ "+FormatUtils.currencyFormat(props.totalAmount)}
</FormLabel>
</Grid>
</Grid>
</Grid> */}
<Grid item xs={12} md={12}>
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="center">
<Grid item>
<Typography variant="h5" sx={{ textAlign: "left" }}>
請選擇付款方法:
</Typography>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("FPS")} disabled={props.fpsStatus.active === "N"}>
<img className={fpsClass} src={FpsIcon} width="80" height="80" alt="FPS"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("Visa")} disabled={props.creditCardStatus.active === "N"}>
<img className={visaClass} src={VisaIcon} width="80" height="80" alt="Visa"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("Mastercard")} disabled={props.creditCardStatus.active === "N"}>
<img className={mastercardClass} src={MasterIcon} width="80" height="80" alt="Mastercard"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("UnionPay")} disabled={props.unionPayStatus.active === "N"}>
<img className={unionPayClass} src={UnionPayIcon} width="80" height="80" alt="UnionPay"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("JCB")} disabled={props.unionPayStatus.active === "N"}>
<img className={jCBClass} src={JcbIcon} width="80" height="80" alt="JCB"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("PPS")} disabled={props.ppsStatus.active === "N"}>
<img className={pPSClass} src={PpsIcon} width="80" height="80" alt="PPS"></img>
</Button>
</Grid>
</Grid>
</Grid>
{paymentMethod !=""?
<Grid item xs={12} md={12}>
<Grid container direction="row" justifyContent="flex-start" alignItems="center">
<Grid item>
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}>
已選擇付款方法:
</FormLabel>
</Grid>
<Grid item>
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}>
{paymentMethod}
</FormLabel>
</Grid>
</Grid>
</Grid>
: null}
</Grid>
)
}else{
<Grid container direction="row" justifyContent="center" alignItems="center">
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "center" }}>
付款功能現在不可用。
</FormLabel>
</Grid>
}
}, [availableMethodData]);

const formik = useFormik({
@@ -256,19 +156,80 @@ const MultiPaymentWindow = (props) => {
</Typography> */}
{!props.onReady ?
<LoadingComponent />
:content
:availableMethodData.length>0?
<Grid container spacing={2} direction="column" justifyContent="space-between" alignItems="flex-start">
<Grid item xs={12} md={12}>
<Grid container spacing={1} direction="row" justifyContent="flex-start" alignItems="center">
<Grid item>
<Typography variant="h5" sx={{ textAlign: "left" }}>
請選擇付款方法:
</Typography>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("FPS")} disabled={props.fpsStatus.active === "N"}>
<img className={fpsClass} src={FpsIcon} width="80" height="80" alt="FPS"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("Visa")} disabled={props.creditCardStatus.active === "N"}>
<img className={visaClass} src={VisaIcon} width="80" height="80" alt="Visa"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("Mastercard")} disabled={props.creditCardStatus.active === "N"}>
<img className={mastercardClass} src={MasterIcon} width="80" height="80" alt="Mastercard"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("UnionPay")} disabled={props.unionPayStatus.active === "N"}>
<img className={unionPayClass} src={UnionPayIcon} width="80" height="80" alt="UnionPay"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("JCB")} disabled={props.unionPayStatus.active === "N"}>
<img className={jCBClass} src={JcbIcon} width="80" height="80" alt="JCB"></img>
</Button>
</Grid>
<Grid item>
<Button variant="contained" color="white" onClick={selectedPaymentMethodHandle("PPS")} disabled={props.ppsStatus.active === "N"}>
<img className={pPSClass} src={PpsIcon} width="80" height="80" alt="PPS"></img>
</Button>
</Grid>
</Grid>
</Grid>
{paymentMethod !=""?
<Grid item xs={12} md={12}>
<Grid container direction="row" justifyContent="flex-start" alignItems="center">
<Grid item>
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "center" }}>
已選擇付款方法:&nbsp;
</FormLabel>
</Grid>
<Grid item>
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "center" }}>
{paymentMethod}
</FormLabel>
</Grid>
</Grid>
</Grid>
: null}
</Grid>:
<Grid container direction="row" justifyContent="center" alignItems="center">
<FormLabel sx={{ fontSize: "20px", color: "#000000", textAlign: "center"}}>
付款功能現在不可用。
</FormLabel>
</Grid>
}
</Grid>
<Grid item xs={12} md={12}>
<Grid container >
<Grid item>
<Typography variant="h5" sx={{ textAlign: "left" }}>
付款總額(HK$):
<Typography sx={{fontSize: "20px", color: "#000000", textAlign: "left" }}>
付款總額(HK$):&nbsp;
</Typography>
</Grid>
<Grid item>
<Typography variant="h5" sx={{ textAlign: "left" }}>
<Typography sx={{fontSize: "20px", color: "#000000", textAlign: "left" }}>
{" HK$ " + FormatUtils.currencyFormat(props.totalAmount)}
</Typography>
</Grid>


+ 5
- 20
src/pages/Payment/index.js 查看文件

@@ -47,7 +47,7 @@ const Index = () => {
const navigate = useNavigate()
const location = useLocation();

// const local = {en:"en_us", zh:"zh_hk", cn:"zh_cn"};
// const local = {en:"en-us", zh:"zh-hk", cn:"zh-cn"};
const preferpaymentmethods = ['visa', 'mastercard', 'pps', 'creditcard', 'fps'];
const [totalAmount, setTotalAmount] = useState(0);
const [appIds, setAppIds] = useState([]);
@@ -169,8 +169,12 @@ const Index = () => {
let availableMethods = responseData.availablepaymentmethods;
setAvailableMethods(availableMethods);

},
onError: () =>{
setOnReady(true)
}
});
// const responseData = {
// "availablepaymentmethods": [
// {
@@ -298,25 +302,6 @@ const Index = () => {
// };
// let availableMethods = responseData.availablepaymentmethods;
// setAvailableMethods(availableMethods);
// if (availableMethods.length>0){
// availableMethods.forEach((method)=>{
// if(method.subtype === "FPS" ){
// setFPSStatus(method)
// }else if (method.subtype === "CreditCard"){
// method.supportedcard.forEach((supportedcard)=>{
// if (supportedcard === "JCB" || supportedcard === "MasterCard" || supportedcard === "Visa"){
// setCreditCardStatus(method)
// } else {
// if (supportedcard === "UnionPay"){
// setUnionPayStatus(method)
// }
// }
// })
// }else if (method.subtype === "PPS" ){
// setPPSStatus(method)
// }
// });
// }
}

useEffect(() => {


+ 44
- 23
src/utils/HttpUtils.js 查看文件

@@ -58,35 +58,56 @@ export const postWithFiles = ({url, params, files, onSuccess, onFail, onError})
});
};

export const fileDownload = ({url, fileId, skey, filename, onResponse, onError}) =>{
export const fileDownload = ({url, fileId, skey, filename, params, method, onResponse, onError}) =>{
if(!url){
url = FILE_DOWN_GET+"/"+fileId+"/"+skey+"/"+filename
}
axios.get( url,
{
responseType: 'blob',
}
).then(
(response)=>{
const fn = response.headers.get("content-disposition")?.split("filename=")[1]?.split('"')[1]?.trim()??filename;
const url = URL.createObjectURL(response.data);
const a = document.createElement('a');
a.href = url;
a.setAttribute("download", fn);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
if(onResponse){
onResponse();
if(method == 'post'){
axios.post( url, params,
{
responseType: 'blob',
headers:{
"Content-Type":"application/json"
}
}
}
).catch(error => {
return handleError(error,onError);
});
};
).then(
(response)=>{
fileDownloadResponse(response, onResponse)
}
).catch(error => {
return handleError(error,onError);
});

}else{
axios.get( url,
{
responseType: 'blob',
params:params
}
).then(
(response)=>{
fileDownloadResponse(response, onResponse)
}
).catch(error => {
return handleError(error,onError);
});
}
};

const fileDownloadResponse=(response, onResponse)=>{
const fn = response.headers.get("content-disposition")?.split("filename=")[1]?.split('"')[1]?.trim()??filename;
const url = URL.createObjectURL(response.data);
const a = document.createElement('a');
a.href = url;
a.setAttribute("download", fn);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
if(onResponse){
onResponse();
}
}

export const fileUpload = ({refType, refId, files, refCode, onSuccess, onFail, onError}) =>{
postWithFiles({


Loading…
取消
儲存