Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 

362 wiersze
16 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 { 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;