Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

281 righe
13 KiB

  1. // material-ui
  2. import {
  3. Grid,
  4. Typography,
  5. Stack,
  6. Button,
  7. Dialog, DialogTitle, DialogContent, DialogActions
  8. } from '@mui/material';
  9. import * as UrlUtils from "utils/ApiPathConst";
  10. import * as React from "react";
  11. import * as HttpUtils from "utils/HttpUtils";
  12. import { useParams } from "react-router-dom";
  13. import { useNavigate } from "react-router-dom";
  14. import * as DateUtils from "utils/DateUtils"
  15. import * as FormatUtils from "utils/FormatUtils";
  16. import Loadable from 'components/Loadable';
  17. const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
  18. import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
  19. const BackgroundHead = {
  20. backgroundImage: `url(${titleBackgroundImg})`,
  21. width: '100%',
  22. height: '100%',
  23. backgroundSize: 'contain',
  24. backgroundRepeat: 'no-repeat',
  25. backgroundColor: '#0C489E',
  26. backgroundPosition: 'right'
  27. }
  28. import {
  29. // useEffect,
  30. useState
  31. } from "react";
  32. import { PNSPS_BUTTON_THEME, PNSPS_LONG_BUTTON_THEME } from "../../../themes/buttonConst";
  33. import { ThemeProvider } from "@emotion/react";
  34. import { FormattedMessage, useIntl } from "react-intl";
  35. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  36. const Index = () => {
  37. const params = useParams();
  38. const navigate = useNavigate()
  39. const [fee, setFee] = useState(0);
  40. const [record, setRecord] = React.useState({});
  41. const [onReady, setOnReady] = React.useState(false);
  42. const [isPopUp, setIsPopUp] = useState(false);
  43. const [paymentHoldedErrText, setPaymentHoldedErrText] = React.useState("");
  44. const [paymentHoldedErr, setPaymentHoldedErr] = React.useState(false);
  45. const intl = useIntl();
  46. React.useEffect(() => {
  47. loadForm();
  48. }, []);
  49. React.useEffect(() => {
  50. setOnReady(true);
  51. }, [record]);
  52. const loadForm = () => {
  53. if (params.id > 0) {
  54. HttpUtils.get({
  55. url: UrlUtils.GET_PROOF_PAY + "/" + params.id,
  56. onSuccess: (responseData) => {
  57. // if (!responseData.data?.id) {
  58. // navigate("/proof/search");
  59. // }
  60. setRecord(responseData.data);
  61. setFee(responseData.data.fee);
  62. },
  63. onError: () => {
  64. }
  65. });
  66. }
  67. }
  68. function doPayment() {
  69. setIsPopUp(false);
  70. let appIdList = [record?.appId]
  71. handlePaymentCheck(appIdList)
  72. }
  73. const handlePaymentCheck = (appIdList) => {
  74. HttpUtils.post({
  75. url: UrlUtils.PAYMENT_CHECK,
  76. params: {
  77. appIds: appIdList
  78. },
  79. onSuccess: (responseData) => {
  80. const latestData = {};
  81. responseData.forEach(item => {
  82. const { appId, timeDiff } = item;
  83. if (latestData[appId] === undefined || timeDiff < latestData[appId].timeDiff) {
  84. latestData[appId] = item;
  85. }
  86. });
  87. const latestDataObjects = Object.values(latestData);
  88. const filteredData = latestDataObjects.filter(item => item.timeDiff > 20 && item.status !== "APPR");
  89. const filteredAppIds = filteredData.map(item => item.appId);
  90. const appIdsNotInData = appIdList.filter(appId => !latestDataObjects.some(item => item.appId === appId));
  91. const combinedAppIdsArray = [...appIdsNotInData, ...filteredAppIds];
  92. const readyToPayment = appIdList.every(appId => combinedAppIdsArray.includes(appId));
  93. if (readyToPayment){
  94. navigate('/paymentPage', { state: { amount: fee, appIdList: appIdList } });
  95. }else{
  96. const appIdsInData = appIdList.filter(appId => !combinedAppIdsArray.some(item => item === appId));
  97. const HoldingApplication = latestDataObjects.filter(item => appIdsInData.includes(item.appId));
  98. const resultString = HoldingApplication.map(item => item.appNo).join(' , ');
  99. setPaymentHoldedErrText(resultString);
  100. // setPaymentHoldedErrText(intl.formatMessage({ id: 'MSG.paymentHolded' }, { appNo: record.appNo }));
  101. setPaymentHoldedErr(true);
  102. }
  103. }
  104. });
  105. };
  106. return (
  107. !onReady ?
  108. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
  109. <Grid item>
  110. <LoadingComponent />
  111. </Grid>
  112. </Grid>
  113. :
  114. (
  115. <Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" >
  116. <Grid item xs={12} width="100%">
  117. <div style={BackgroundHead} width="100%" >
  118. <Stack direction="row" height='70px'>
  119. <Typography ml={15} color='#FFF' variant="h4" sx={{ display: { xs: 'none', sm: 'none', md: 'block' }, pt: 2 }}>
  120. <FormattedMessage id="proofRecord" />
  121. </Typography>
  122. </Stack>
  123. </div>
  124. </Grid>
  125. {/*row 1*/}
  126. <Grid item xs={12} md={12} >
  127. <Grid container justifyContent="flex-start" alignItems="center" >
  128. <center>
  129. <Grid item xs={12} md={8} >
  130. <Typography variant="h3" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}>
  131. <FormattedMessage id="publicNoticePaymentProofDoneAndPaid" />
  132. </Typography>
  133. <Typography variant="h4" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
  134. <div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: 'MSG.payMsg1' }, { appNo: record.appNo }) }} />
  135. <br />
  136. <FormattedMessage id="MSG.payMsg2_1" />
  137. <span style={{ color: "red" }}>
  138. {DateUtils.datetimeStr(record?.proofPaymentDeadline)}
  139. </span>
  140. <FormattedMessage id="MSG.payMsg2_2" />
  141. <br />
  142. <br />
  143. <div dangerouslySetInnerHTML={{
  144. __html: intl.formatMessage({ id: 'MSG.payMsg3' },
  145. {
  146. issueYear: record?.issueYear,
  147. issueVolume: record?.issueVolume,
  148. issueNo: record?.issueNo,
  149. })
  150. }} />
  151. </Typography>
  152. <Typography variant="h4" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}>
  153. <FormattedMessage id="pleaseClickToPay" />:
  154. </Typography>
  155. <Typography variant="h4" sx={{ ml: 8, textAlign: "left" }}>
  156. <ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
  157. <Button
  158. component="span"
  159. variant="contained"
  160. sx={{ ml: { md: 4, lg: 4 }, mr: 4 }}
  161. onClick={() => { setIsPopUp(true) }}
  162. >
  163. <FormattedMessage id="payInstantly" />
  164. </Button>
  165. </ThemeProvider>
  166. <FormattedMessage id="or" />
  167. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  168. <Button
  169. component="span"
  170. variant="contained"
  171. sx={{ ml: { sm: 4, md: 4, lg: 4 }, mr: 4, mt: { xs: 2, sm: 2 }, mb: { xs: 2, sm: 2 } }}
  172. onClick={() => {
  173. navigate("/publicNotice");
  174. }}
  175. >
  176. <FormattedMessage id="payLater" />
  177. </Button>
  178. (<FormattedMessage id="backToNoticePage" />)
  179. </ThemeProvider>
  180. </Typography>
  181. </Grid>
  182. </center>
  183. </Grid>
  184. </Grid>
  185. <div>
  186. <Dialog
  187. open={isPopUp}
  188. onClose={() => setIsPopUp(false)}
  189. PaperProps={{
  190. sx: {
  191. minWidth: '40vw',
  192. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '30vw' },
  193. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '50vh' }
  194. }
  195. }}
  196. >
  197. <DialogTitle>
  198. <Typography variant="h3" >
  199. <FormattedMessage id="payConfirm" />
  200. </Typography>
  201. </DialogTitle>
  202. <DialogContent style={{ display: 'flex', }}>
  203. <Stack direction="column" justifyContent="space-between">
  204. <Typography variant="h4">
  205. <FormattedMessage id="totalAmount" /> (HK$): {FormatUtils.currencyFormat(fee)}
  206. </Typography>
  207. </Stack>
  208. </DialogContent>
  209. <DialogActions>
  210. <Button onClick={() => setIsPopUp(false)}>
  211. <Typography variant="h5">
  212. <FormattedMessage id="close" />
  213. </Typography></Button>
  214. <Button onClick={() => doPayment()}><Typography variant="h5">
  215. <FormattedMessage id="confirm" />
  216. </Typography></Button>
  217. </DialogActions>
  218. </Dialog>
  219. </div>
  220. {/*row 2*/}
  221. <div>
  222. <Dialog
  223. open={paymentHoldedErr}
  224. onClose={() => setPaymentHoldedErr(false)}
  225. PaperProps={{
  226. sx: {
  227. minWidth: '40vw',
  228. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  229. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  230. }
  231. }}
  232. >
  233. <DialogTitle></DialogTitle>
  234. <Typography variant="h4" style={{ paddingLeft: '24px' }}><FormattedMessage id="MSG.actionFail" /></Typography>
  235. <DialogContent style={{ display: 'flex', }}>
  236. <Stack direction="column" justifyContent="space-between">
  237. <div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: 'MSG.paymentHolded' }, { appNo: paymentHoldedErrText }) }} />
  238. </Stack>
  239. </DialogContent>
  240. <DialogActions>
  241. <Button onClick={() => setPaymentHoldedErr(false)} aria-label={intl.formatMessage({ id: 'close' })}>
  242. <Typography variant="h5">
  243. <FormattedMessage id="close" />
  244. </Typography></Button>
  245. </DialogActions>
  246. </Dialog>
  247. </div>
  248. </Grid >
  249. )
  250. );
  251. };
  252. export default Index;