選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Pay_Online.js 16 KiB

2年前
7ヶ月前
2年前
2年前
2年前
2年前
7ヶ月前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
7ヶ月前
7ヶ月前
2年前
7ヶ月前
7ヶ月前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  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 { checkPaymentSuspension } from "utils/Utils";
  17. import {
  18. checkIsOnlyOnlinePayment,
  19. } from "utils/Utils";
  20. import Loadable from 'components/Loadable';
  21. const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
  22. import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
  23. const BackgroundHead = {
  24. backgroundImage: `url(${titleBackgroundImg})`,
  25. width: '100%',
  26. height: '100%',
  27. backgroundSize: 'contain',
  28. backgroundRepeat: 'no-repeat',
  29. backgroundColor: '#0C489E',
  30. backgroundPosition: 'right'
  31. }
  32. const contentBoxSx = {
  33. px: { xs: 2, sm: 3, md: 5, lg: 6 },
  34. maxWidth: 1500,
  35. width: '100%',
  36. };
  37. const headerSx = {
  38. textAlign: 'left',
  39. mt: 4,
  40. fontSize: { xs: '1.15rem', sm: '1.35rem', md: '1.5rem' },
  41. textDecoration: 'underline',
  42. textDecorationThickness: '2px',
  43. textUnderlineOffset: '4px',
  44. };
  45. const bodySx = {
  46. mt: 4,
  47. textAlign: 'left',
  48. fontSize: { xs: '1rem', sm: '1.1rem', md: '1.25rem' },
  49. lineHeight: 1.6,
  50. };
  51. const payButtonSx = {
  52. minWidth: 'unset',
  53. px: { xs: 2, sm: 3 },
  54. py: 1.25,
  55. whiteSpace: 'nowrap',
  56. width: { xs: '100%', sm: 'auto' },
  57. fontSize: { xs: '1rem', sm: '1.2rem' },
  58. };
  59. import {
  60. // useEffect,
  61. useState
  62. } from "react";
  63. import { PNSPS_BUTTON_THEME,
  64. // PNSPS_LONG_BUTTON_THEME
  65. } from "../../../themes/buttonConst";
  66. import { ThemeProvider } from "@emotion/react";
  67. import { FormattedMessage, useIntl } from "react-intl";
  68. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  69. const Index = () => {
  70. const params = useParams();
  71. const navigate = useNavigate()
  72. const [fee, setFee] = useState(0);
  73. const [record, setRecord] = React.useState({});
  74. const [onReady, setOnReady] = React.useState(false);
  75. const [isPopUp, setIsPopUp] = useState(false);
  76. const [paymentHoldedErrText, setPaymentHoldedErrText] = React.useState("");
  77. const [paymentHoldedErr, setPaymentHoldedErr] = React.useState(false);
  78. const intl = useIntl();
  79. const { locale } = intl;
  80. React.useEffect(() => {
  81. loadForm();
  82. }, []);
  83. React.useEffect(() => {
  84. setOnReady(true);
  85. }, [record]);
  86. const isAfter = checkIsOnlyOnlinePayment();
  87. const loadForm = () => {
  88. if (params.id > 0) {
  89. HttpUtils.get({
  90. url: UrlUtils.GET_PROOF_PAY + "/" + params.id,
  91. onSuccess: (responseData) => {
  92. // if (!responseData.data?.id) {
  93. // navigate("/proof/search");
  94. // }
  95. setRecord(responseData.data);
  96. setFee(responseData.data.fee);
  97. },
  98. onError: () => {
  99. }
  100. });
  101. }
  102. }
  103. function doPayment() {
  104. setIsPopUp(false);
  105. let appIdList = [record?.appId]
  106. handlePaymentCheck(appIdList)
  107. }
  108. const handlePaymentCheck = (appIdList) => {
  109. HttpUtils.post({
  110. url: UrlUtils.PAYMENT_CHECK,
  111. params: {
  112. appIds: appIdList
  113. },
  114. onSuccess: (responseData) => {
  115. const latestData = {};
  116. responseData.forEach(item => {
  117. const { appId, timeDiff } = item;
  118. if (latestData[appId] === undefined || timeDiff < latestData[appId].timeDiff) {
  119. latestData[appId] = item;
  120. }
  121. });
  122. const latestDataObjects = Object.values(latestData);
  123. const filteredData = latestDataObjects.filter(item => item.timeDiff > 30 || item.status !== "APPR");
  124. const filteredAppIds = filteredData.map(item => item.appId);
  125. const appIdsNotInData = appIdList.filter(appId => !latestDataObjects.some(item => item.appId === appId));
  126. const combinedAppIdsArray = [...appIdsNotInData, ...filteredAppIds];
  127. const readyToPayment = appIdList.every(appId => combinedAppIdsArray.includes(appId));
  128. if (readyToPayment) {
  129. navigate('/paymentPage', { state: { amount: fee, appIdList: appIdList } });
  130. } else {
  131. const appIdsInData = appIdList.filter(appId => !combinedAppIdsArray.some(item => item === appId));
  132. const HoldingApplication = latestDataObjects.filter(item => appIdsInData.includes(item.appId));
  133. const resultString = HoldingApplication.map(item => item.appNo).join(' , ');
  134. setPaymentHoldedErrText(resultString);
  135. // setPaymentHoldedErrText(intl.formatMessage({ id: 'MSG.paymentHolded' }, { appNo: record.appNo }));
  136. setPaymentHoldedErr(true);
  137. }
  138. }
  139. });
  140. };
  141. return (
  142. !onReady ?
  143. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
  144. <Grid item>
  145. <LoadingComponent />
  146. </Grid>
  147. </Grid>
  148. :
  149. (
  150. <Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" >
  151. <Grid item xs={12} width="100%">
  152. <div style={BackgroundHead} width="100%" >
  153. <Stack direction="row" height='70px'>
  154. <Typography ml={15} color='#FFF' variant="h4" sx={{ display: { xs: 'none', sm: 'none', md: 'block' }, pt: 2 }}>
  155. <FormattedMessage id="proofRecord" />
  156. </Typography>
  157. </Stack>
  158. </div>
  159. </Grid>
  160. {/*row 1*/}
  161. <Grid item xs={12} md={12} >
  162. <Grid container justifyContent="center" alignItems="center" >
  163. <Grid item xs={12} md={11} lg={10} sx={contentBoxSx}>
  164. {isAfter ? (
  165. <Typography variant="h4" sx={headerSx}>
  166. <FormattedMessage id="proofPaymentHeader_online2" />
  167. </Typography>
  168. ) : (
  169. <Typography variant="h4" sx={headerSx}>
  170. <FormattedMessage id="proofPaymentHeader_online" />
  171. </Typography>
  172. )}
  173. <Typography variant="h5" sx={bodySx}>
  174. <div dangerouslySetInnerHTML={{
  175. __html: intl.formatMessage(
  176. {
  177. id: 'proofPaymentBody_online'
  178. },
  179. {
  180. appNo: record?.appNo,
  181. }
  182. )
  183. }} />
  184. <br />
  185. <div dangerouslySetInnerHTML={{
  186. __html: intl.formatMessage(
  187. {
  188. id: 'proofPaymentBody_online2'
  189. },
  190. {
  191. paymentDeadline: DateUtils.formatDateForLocale(record?.expiryDate, intl, locale),
  192. }
  193. )
  194. }} />
  195. <br />
  196. {checkPaymentSuspension()?
  197. <div>
  198. <Typography style={{ textAlign: "flex-start", color: "red" }}>
  199. <div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "suspensionMessageText" }) }} />
  200. </Typography>
  201. <br />
  202. </div>:null
  203. }
  204. </Typography>
  205. {!checkPaymentSuspension()?
  206. <Stack
  207. direction={{ xs: 'column', sm: 'row' }}
  208. alignItems={{ xs: 'stretch', sm: 'center' }}
  209. sx={{ mt: 4, gap: { xs: 1.5, sm: 2 } }}
  210. >
  211. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  212. <Button
  213. component="span"
  214. variant="contained"
  215. sx={payButtonSx}
  216. onClick={() => { setIsPopUp(true) }}
  217. >
  218. <FormattedMessage id="payInstantly" />
  219. </Button>
  220. </ThemeProvider>
  221. <Typography
  222. component="span"
  223. variant="h4"
  224. sx={{
  225. textAlign: { xs: 'center', sm: 'left' },
  226. fontSize: { xs: '1rem', sm: '1.25rem' },
  227. my: { xs: 0.5, sm: 0 },
  228. }}
  229. >
  230. <FormattedMessage id="or" />
  231. </Typography>
  232. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  233. <Button
  234. component="span"
  235. variant="contained"
  236. sx={payButtonSx}
  237. onClick={() => {
  238. navigate("/publicNotice");
  239. }}
  240. >
  241. <FormattedMessage id="payLater" />
  242. </Button>
  243. </ThemeProvider>
  244. </Stack>:null
  245. }
  246. <Typography variant="h4" sx={bodySx}>
  247. <div dangerouslySetInnerHTML={{
  248. __html: intl.formatMessage(
  249. {
  250. id: 'proofPaymentBody_online3'
  251. }
  252. )
  253. }} />
  254. <br />
  255. </Typography>
  256. </Grid>
  257. </Grid>
  258. </Grid>
  259. <div>
  260. <Dialog
  261. open={isPopUp}
  262. onClose={() => setIsPopUp(false)}
  263. PaperProps={{
  264. sx: {
  265. minWidth: '40vw',
  266. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '30vw' },
  267. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '50vh' }
  268. }
  269. }}
  270. >
  271. <DialogTitle>
  272. <Typography variant="h3" >
  273. <FormattedMessage id="payConfirm" />
  274. </Typography>
  275. </DialogTitle>
  276. <DialogContent style={{ display: 'flex', }}>
  277. <Stack direction="column" justifyContent="space-between">
  278. <Typography variant="h4">
  279. <FormattedMessage id="totalAmount" /> ($): {FormatUtils.currencyFormat(fee)}
  280. </Typography>
  281. </Stack>
  282. </DialogContent>
  283. <DialogActions>
  284. <Button onClick={() => setIsPopUp(false)}>
  285. <Typography variant="h5">
  286. <FormattedMessage id="close" />
  287. </Typography></Button>
  288. <Button onClick={() => doPayment()}><Typography variant="h5">
  289. <FormattedMessage id="confirm" />
  290. </Typography></Button>
  291. </DialogActions>
  292. </Dialog>
  293. </div>
  294. {/*row 2*/}
  295. <div>
  296. <Dialog
  297. open={paymentHoldedErr}
  298. onClose={() => setPaymentHoldedErr(false)}
  299. PaperProps={{
  300. sx: {
  301. minWidth: '40vw',
  302. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  303. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  304. }
  305. }}
  306. >
  307. <DialogTitle></DialogTitle>
  308. <Typography variant="h4" style={{ paddingLeft: '24px' }}><FormattedMessage id="MSG.actionFail" /></Typography>
  309. <DialogContent style={{ display: 'flex', }}>
  310. <Stack direction="column" justifyContent="space-between">
  311. <div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: 'MSG.paymentHolded' }, { appNo: paymentHoldedErrText }) }} />
  312. </Stack>
  313. </DialogContent>
  314. <DialogActions>
  315. <Button onClick={() => setPaymentHoldedErr(false)} aria-label={intl.formatMessage({ id: 'close' })}>
  316. <Typography variant="h5">
  317. <FormattedMessage id="close" />
  318. </Typography></Button>
  319. </DialogActions>
  320. </Dialog>
  321. </div>
  322. </Grid >
  323. )
  324. );
  325. };
  326. export default Index;