You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

612 regels
37 KiB

  1. // material-ui
  2. import {
  3. Dialog, DialogTitle, DialogContent, DialogActions,
  4. Typography,
  5. Grid,
  6. Stack,
  7. TextField,
  8. FormLabel,
  9. Button,
  10. Checkbox,
  11. RadioGroup, Radio,
  12. FormControlLabel
  13. } from '@mui/material';
  14. import * as UrlUtils from "utils/ApiPathConst";
  15. import * as HttpUtils from "utils/HttpUtils";
  16. import FileList from "components/FileList"
  17. import MainCard from "components/MainCard";
  18. import * as React from "react";
  19. import * as yup from 'yup';
  20. import { useParams } from "react-router-dom";
  21. import { useFormik } from 'formik';
  22. import { useNavigate } from "react-router-dom";
  23. import * as DateUtils from "utils/DateUtils"
  24. import Loadable from 'components/Loadable';
  25. import { notifyActionSuccess } from 'utils/CommonFunction';
  26. import { PNSPS_BUTTON_THEME } from "themes/buttonConst";
  27. import { ThemeProvider } from "@emotion/react";
  28. import { FormattedMessage, useIntl } from "react-intl";
  29. import { isDummyLoggedIn } from "utils/Utils"
  30. const UploadFileTable = Loadable(React.lazy(() => import('./UploadFileTable')));
  31. //import * as ProofStatus from "utils/statusUtils/ProofStatus";
  32. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  33. const FormPanel = ({ formData }) => {
  34. const intl = useIntl();
  35. const { locale } = intl;
  36. const [data, setData] = React.useState({});
  37. const [paymentMethod, set_paymentMethod] = React.useState("");
  38. const [attachments, setAttachments] = React.useState([]);
  39. const [actionValue, setActionValue] = React.useState(true);
  40. const [isWarningPopUp, setIsWarningPopUp] = React.useState(false);
  41. const [warningText, setWarningText] = React.useState("");
  42. const navigate = useNavigate()
  43. const params = useParams();
  44. const tabelStyle = {
  45. border: "2px solid gray",
  46. borderCollapse: "collapse",
  47. padding: "right"
  48. }
  49. React.useEffect(() => {
  50. if (formData) {
  51. setData(formData);
  52. if (isDummyLoggedIn()) {
  53. set_paymentMethod("demandNote")
  54. }
  55. }
  56. }, [formData]);
  57. const formik = useFormik({
  58. enableReinitialize: true,
  59. initialValues: data,
  60. validationSchema: yup.object().shape({
  61. vaild: yup.string().max(255, intl.formatMessage({ id: 'requireLoginPassword' })).required(intl.formatMessage({ id: 'requireLoginPassword' })),
  62. }),
  63. onSubmit: values => {
  64. if (!isDummyLoggedIn()){
  65. if (isOverTime()) {
  66. setWarningText(intl.formatMessage({ id: 'MSG.proofOutOfTime' }));
  67. setIsWarningPopUp(true);
  68. return;
  69. }
  70. }
  71. let pm = paymentMethod;
  72. if (pm == "demandNote") {
  73. pm = isOverDnReviseDeadline() ? "" : pm;
  74. } else if (pm == "office") {
  75. pm = isOverNpgoReviseDeadline() ? "" : pm;
  76. }
  77. if (actionValue == false && isOverReviseDeadline()) {
  78. setWarningText(intl.formatMessage({ id: 'MSG.overReviseDeadline' }));
  79. setIsWarningPopUp(true);
  80. return;
  81. }
  82. else if (formData.creditor == false && pm == "") {
  83. setWarningText(intl.formatMessage({ id: 'MSG.plzSelectPaymentMethod' }));
  84. setIsWarningPopUp(true);
  85. return;
  86. }
  87. if (!actionValue) {
  88. if (!attachments || attachments.length <= 0) {
  89. setWarningText(intl.formatMessage({ id: 'requireFile' }));
  90. setIsWarningPopUp(true);
  91. return;
  92. }
  93. }
  94. // console.log(values);
  95. HttpUtils.postWithFiles({
  96. url: UrlUtils.REPLY_PROOF,
  97. params: {
  98. id: data.id,
  99. action: actionValue,
  100. vaild: values.vaild,
  101. paymentMethod: pm
  102. },
  103. files: attachments ? attachments : [],
  104. onSuccess: function (responseData) {
  105. if (responseData.msg) {
  106. setWarningText(intl.formatMessage({ id: responseData.msg }));
  107. setIsWarningPopUp(true);
  108. return;
  109. }
  110. if (responseData.id == params.id) {
  111. notifyActionSuccess(intl.formatMessage({ id: "submitted" }))
  112. navigate("/proof/pay/" + params.id);
  113. } else {
  114. navigate("/proof/search");
  115. }
  116. },
  117. onFail: function (response) {
  118. setWarningText(intl.formatMessage({ id: 'actionFail' }));
  119. setIsWarningPopUp(true);
  120. console.log(response);
  121. },
  122. onError: function (error) {
  123. setWarningText(intl.formatMessage({ id: 'actionFail' }));
  124. setIsWarningPopUp(true);
  125. console.log(error);
  126. }
  127. });
  128. }
  129. });
  130. const readFile = (event) => {
  131. let file = event.target.files[0];
  132. if (file) {
  133. if (!file.name.toLowerCase().substr(file.name.length - 4).includes(".pdf")) {
  134. setWarningText(intl.formatMessage({ id: 'requireValidFileWithPdfFormat' }));
  135. setIsWarningPopUp(true);
  136. document.getElementById("uploadFileBtn").value = "";
  137. return;
  138. }
  139. if (file.size >= (10 * 1024 * 1034)) {
  140. setWarningText(intl.formatMessage({ id: 'fileSizeWarning' }));
  141. setIsWarningPopUp(true);
  142. return;
  143. }
  144. file['id'] = attachments.length;
  145. setAttachments([
  146. ...attachments,
  147. file
  148. ]);
  149. document.getElementById("uploadFileBtn").value = "";
  150. }
  151. }
  152. const isOverTime = () => {
  153. let proofPaymentDeadline = DateUtils.convertToDate(formData?.proofPaymentDeadline);
  154. if (!proofPaymentDeadline) return true;
  155. let current = new Date();
  156. return current.getTime() > proofPaymentDeadline;
  157. }
  158. const isOverReviseDeadline = () => {
  159. // if (paymentMethod == "demandNote") return isOverDnReviseDeadline();
  160. // if (paymentMethod == "office") return isOverNpgoReviseDeadline();
  161. //online payment
  162. let reviseDeadline = DateUtils.convertToDate(formData?.reviseDeadline);
  163. // reviseDeadline?.setTime(reviseDeadline?.getTime() + (14 * 60 * 60 * 1000));// 14:00
  164. if (!reviseDeadline) return true;
  165. let current = new Date();
  166. return current.getTime() > reviseDeadline;
  167. }
  168. const isOverDnReviseDeadline = () => {
  169. let reviseDeadline = DateUtils.convertToDate(formData?.closingDateOff);
  170. reviseDeadline?.setTime(reviseDeadline?.getTime() + (17 * 60 * 60 * 1000));// 17:00
  171. if (!reviseDeadline) return true;
  172. let current = new Date();
  173. return current.getTime() > reviseDeadline;
  174. }
  175. const isOverNpgoReviseDeadline = () => {
  176. let reviseDeadline = DateUtils.convertToDate(formData?.closingDate);
  177. reviseDeadline?.setTime(reviseDeadline?.getTime() + (12 * 60 * 60 * 1000));// 12:00
  178. if (!reviseDeadline) return true;
  179. let current = new Date();
  180. return current.getTime() > reviseDeadline;
  181. }
  182. return (
  183. <MainCard xs={12} sm={12} md={12} lg={12}
  184. border={false}
  185. content={false}>
  186. <Typography variant="h4" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}>
  187. <FormattedMessage id="publicNoticePaymentProofComment" />
  188. </Typography>
  189. <form onSubmit={formik.handleSubmit}>
  190. {
  191. formik.values.replyDate ?
  192. <Grid container direction="column" sx={{ paddingLeft: 0, paddingRight: 0 }}>
  193. <Grid item xs={12} sm={12} md={12} lg={8} textAlign="left">
  194. <Typography variant="h5">
  195. <FormattedMessage id="proofReplyDate" /> :&nbsp;
  196. {
  197. locale === 'en' ?
  198. DateUtils.dateValue(formik.values.replyDate)
  199. :
  200. DateUtils.datetimeStr_Cht(formik.values.replyDate)
  201. }
  202. </Typography>
  203. </Grid>
  204. <Grid item xs={12} md={12} textAlign="left">
  205. <Typography variant="h5">
  206. <FormattedMessage id="proofReply" /> : {formik.values.action ?
  207. (<span style={{ color: 'green' }}>
  208. <FormattedMessage id="proofErrorFree" />
  209. </span>)
  210. :
  211. (<span style={{ color: 'red' }}>
  212. <FormattedMessage id="proofWithError" />
  213. </span>)}
  214. </Typography>
  215. </Grid>
  216. {/* <Grid item xs={12} md={12} textAlign="left">
  217. <Typography variant="h5">
  218. <FormattedMessage id="proofReply" /> :&nbsp;
  219. <span style={{ color: 'green' }}>
  220. {
  221. locale === 'en' ?
  222. ProofStatus.getStatusText_Eng(formik.values).text
  223. :
  224. ProofStatus.getStatusText_Cht(formik.values).text
  225. }
  226. </span>
  227. </Typography>
  228. </Grid> */}
  229. {
  230. formik.values.action ?
  231. null
  232. :
  233. <Grid item xs={12} md={12} textAlign="left" sx={{ width: '95%', maxWidth: { xs: '70vw', sm: '72vw', md: '75vw', lg: '80vw' } }}>
  234. <FileList
  235. lang="ch"
  236. refId={params.id}
  237. refType={"proofReply"}
  238. dateHideable={true}
  239. disablePagination
  240. disableSelectionOnClick
  241. disableColumnMenu
  242. disableColumnSelector
  243. hideFooter
  244. />
  245. </Grid>
  246. }
  247. </Grid>
  248. :
  249. (
  250. isOverTime() ?
  251. <Grid container direction="column" sx={{ paddingLeft: 0, paddingRight: 0 }} spacing={1}>
  252. <Grid item xs={12} md={12} textAlign="left">
  253. <Typography variant="h5"><FormattedMessage id="MSG.proofOutOfTime" /></Typography>
  254. </Grid>
  255. </Grid>
  256. :
  257. <Grid container direction="column" sx={{ paddingLeft: 0, paddingRight: 0 }} spacing={1}>
  258. <Grid item xs={12} md={12}>
  259. <RadioGroup
  260. aria-labelledby="demo-radio-buttons-group-label"
  261. id="action"
  262. name="action"
  263. defaultValue={true}
  264. onChange={(event) => {
  265. setActionValue(event.target.value === "true" ? true : false);
  266. }}
  267. >
  268. <FormControlLabel value={true} control={<Radio />} label={intl.formatMessage({ id: 'proofErrorFree' })} />
  269. <FormControlLabel value={false} control={<Radio />} label={intl.formatMessage({ id: 'proofWithError' })} />
  270. </RadioGroup>
  271. </Grid>
  272. {
  273. actionValue && formData.creditor == false ?
  274. isDummyLoggedIn() ?
  275. <Grid item xs={12} sx={{ mb: 1, }}>
  276. <table style={tabelStyle}>
  277. <tr style={tabelStyle}>
  278. <th style={tabelStyle} width="50" align="left"></th>
  279. <th style={tabelStyle} width="400" align="left"><FormattedMessage id="paymentMeans" /></th>
  280. <th style={tabelStyle} width="400" align="left"><FormattedMessage id="paymentMethodMeans" /></th>
  281. <th style={tabelStyle} width="300" align="left"><FormattedMessage id="confirmingDealine" /></th>
  282. <th style={tabelStyle} width="300" align="left"><FormattedMessage id="PaymentCoonpletDealine" /></th>
  283. </tr>
  284. <tr>
  285. <td style={tabelStyle}>
  286. <Checkbox
  287. checked={paymentMethod == "demandNote"}
  288. onChange={() => {
  289. set_paymentMethod("demandNote")
  290. }}
  291. />
  292. </td>
  293. <td style={tabelStyle}><FormattedMessage id="payDn" /></td>
  294. <td style={tabelStyle}>
  295. <ul>
  296. <li><FormattedMessage id="atm" /></li>
  297. <li><FormattedMessage id="pps" /></li>
  298. <li><FormattedMessage id="eBank" /></li>
  299. <li><FormattedMessage id="phoneBank" /></li>
  300. <li><FormattedMessage id="eCheque" /></li>
  301. <li><FormattedMessage id="fps" /></li>
  302. <li><FormattedMessage id="hkpo" /></li>
  303. <li><FormattedMessage id="store" /></li>
  304. <li><FormattedMessage id="post" /></li>
  305. </ul>
  306. </td>
  307. <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} 5:00 p.m.</td>
  308. <td style={tabelStyle}>
  309. <FormattedMessage id="payDnRemark" values={{
  310. date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:30 p.m."
  311. }} />
  312. </td>
  313. </tr>
  314. <tr>
  315. <td style={tabelStyle}>
  316. <Checkbox
  317. checked={paymentMethod == "office"}
  318. onChange={() => {
  319. set_paymentMethod("office")
  320. }}
  321. />
  322. </td>
  323. <td style={tabelStyle}><FormattedMessage id="payNPGO" /></td>
  324. <td style={tabelStyle}>
  325. <ul>
  326. <li><FormattedMessage id="cheque" /></li>
  327. <li><FormattedMessage id="cash" /></li>
  328. </ul>
  329. </td>
  330. <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 12:00 p.m.</td>
  331. <td style={tabelStyle}>
  332. <FormattedMessage id="payNPGORemark" values={{
  333. date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:30 p.m."
  334. }} />
  335. </td>
  336. </tr>
  337. </table>
  338. </Grid> :
  339. <Grid item xs={12} sx={{ mb: 1, }}>
  340. <table style={tabelStyle}>
  341. <tr style={tabelStyle}>
  342. <th style={tabelStyle} width="50" align="left"></th>
  343. <th style={tabelStyle} width="400" align="left"><FormattedMessage id="paymentMeans" /></th>
  344. <th style={tabelStyle} width="400" align="left"><FormattedMessage id="paymentMethodMeans" /></th>
  345. <th style={tabelStyle} width="300" align="left"><FormattedMessage id="confirmingDealine" /></th>
  346. <th style={tabelStyle} width="300" align="left"><FormattedMessage id="PaymentCoonpletDealine" /></th>
  347. </tr>
  348. <tr>
  349. <td style={tabelStyle}>
  350. <Checkbox
  351. checked={paymentMethod == "online"}
  352. onChange={() => {
  353. set_paymentMethod("online")
  354. }}
  355. />
  356. </td>
  357. <td style={tabelStyle}><FormattedMessage id="payOnline" /></td>
  358. <td style={tabelStyle}>
  359. <ul>
  360. <li><FormattedMessage id="fps" /></li>
  361. <li><FormattedMessage id="card" /></li>
  362. <li><FormattedMessage id="pps" /></li>
  363. </ul>
  364. </td>
  365. <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 2:00 p.m.</td>
  366. <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 2:30 p.m.</td>
  367. </tr>
  368. <tr>
  369. <td style={tabelStyle}>
  370. {isOverDnReviseDeadline() ?
  371. <></> :
  372. <Checkbox
  373. checked={paymentMethod == "demandNote"}
  374. onChange={() => {
  375. set_paymentMethod("demandNote")
  376. }}
  377. />
  378. }
  379. </td>
  380. <td style={tabelStyle}><FormattedMessage id="payDn" /></td>
  381. <td style={tabelStyle}>
  382. <ul>
  383. <li><FormattedMessage id="atm" /></li>
  384. <li><FormattedMessage id="pps" /></li>
  385. <li><FormattedMessage id="eBank" /></li>
  386. <li><FormattedMessage id="phoneBank" /></li>
  387. <li><FormattedMessage id="eCheque" /></li>
  388. <li><FormattedMessage id="fps" /></li>
  389. <li><FormattedMessage id="hkpo" /></li>
  390. <li><FormattedMessage id="store" /></li>
  391. <li><FormattedMessage id="post" /></li>
  392. </ul>
  393. </td>
  394. <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDateOff, intl.formatMessage({ id: "dateStrFormat" }))} 5:00 p.m.</td>
  395. <td style={tabelStyle}>
  396. <FormattedMessage id="payDnRemark" values={{
  397. date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:30 p.m."
  398. }} />
  399. </td>
  400. </tr>
  401. <tr>
  402. <td style={tabelStyle}>
  403. {
  404. isOverNpgoReviseDeadline() ?
  405. <></> :
  406. <Checkbox
  407. checked={paymentMethod == "office"}
  408. onChange={() => {
  409. set_paymentMethod("office")
  410. }}
  411. />
  412. }
  413. </td>
  414. <td style={tabelStyle}><FormattedMessage id="payNPGO" /></td>
  415. <td style={tabelStyle}>
  416. <ul>
  417. <li><FormattedMessage id="cheque" /></li>
  418. <li><FormattedMessage id="cash" /></li>
  419. </ul>
  420. </td>
  421. <td style={tabelStyle}>{DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" }))} 12:00 p.m.</td>
  422. <td style={tabelStyle}>
  423. <FormattedMessage id="payNPGORemark" values={{
  424. date: DateUtils.dateFormat(formData.closingDate, intl.formatMessage({ id: "dateStrFormat" })) + " 12:30 p.m."
  425. }} />
  426. </td>
  427. </tr>
  428. </table>
  429. </Grid>
  430. :
  431. actionValue ?
  432. <></>
  433. :
  434. <>
  435. {
  436. isOverReviseDeadline() ?
  437. <Grid item xs={12} md={12} textAlign="left">
  438. <Typography variant="h5" style={{ color: "red" }}>
  439. <FormattedMessage id="MSG.overReviseDeadline" />
  440. </Typography>
  441. </Grid>
  442. :
  443. <>
  444. <Grid item xs={12} md={12} textAlign="left">
  445. <Typography variant="h5">
  446. <FormattedMessage id="requiredUploadFix" />:
  447. </Typography>
  448. </Grid>
  449. <Grid item xs={12} md={12} textAlign="left">
  450. <input
  451. id="uploadFileBtn"
  452. name="file"
  453. type="file"
  454. accept=".pdf"
  455. style={{ display: 'none' }}
  456. disabled={attachments.length >= (formik.values.groupType === "Private Bill" ? 2 : 1)}
  457. onChange={(event) => {
  458. readFile(event)
  459. }}
  460. />
  461. <label htmlFor="uploadFileBtn">
  462. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  463. <Button
  464. color="save"
  465. component="span"
  466. variant="contained"
  467. aria-label={intl.formatMessage({ id: 'upload' })}
  468. disabled={attachments.length >= (formik.values.groupType === "Private Bill" ? 2 : 1)}
  469. >
  470. <FormattedMessage id="upload" />
  471. </Button>
  472. </ThemeProvider>
  473. </label>
  474. </Grid>
  475. <Grid item xs={12} sm={12} md={12} lg={12} textAlign="left" sx={{ width: '95%', maxWidth: { xs: '70vw', sm: '72vw', md: '75vw', lg: '80vw' } }} >
  476. <UploadFileTable key="uploadTable" recordList={attachments} setRecordList={setAttachments} />
  477. </Grid>
  478. </>
  479. }
  480. </>
  481. }
  482. {
  483. actionValue == false && isOverReviseDeadline() ?
  484. <></>
  485. :
  486. <Grid item xs={12} sm={12} md={12} lg={12}>
  487. <Stack direction="row" alignItems="center">
  488. <FormLabel sx={{ paddingRight: 2, paddingBottom: 3, textAlign: "center" }}>
  489. <Typography variant="h5">
  490. <FormattedMessage id="sign" />:
  491. </Typography>
  492. </FormLabel>
  493. <TextField
  494. fullWidth
  495. type="password"
  496. onChange={formik.handleChange}
  497. name="vaild"
  498. variant="outlined"
  499. error={Boolean(formik.errors["vaild"])}
  500. helperText={formik.errors["vaild"] ? formik.errors["vaild"] : ' '}
  501. placeholder={intl.formatMessage({ id: 'requireLoginPassword' })}
  502. sx={
  503. {
  504. "& .MuiInputBase-input.Mui-disabled": {
  505. WebkitTextFillColor: "#000000",
  506. background: "#f8f8f8",
  507. },
  508. width: '70%'
  509. }
  510. }
  511. />
  512. </Stack>
  513. </Grid>
  514. }
  515. <Grid item xs={12} md={12} textAlign="left">
  516. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  517. <Button
  518. variant="contained"
  519. color="success"
  520. type="submit"
  521. disabled={actionValue == false && isOverReviseDeadline()}
  522. aria-label={intl.formatMessage({ id: 'submitReply' })}
  523. >
  524. <FormattedMessage id="submitReply" />
  525. </Button>
  526. </ThemeProvider>
  527. </Grid>
  528. </Grid>
  529. )
  530. }
  531. </form>
  532. <div>
  533. <Dialog
  534. open={isWarningPopUp}
  535. onClose={() => setIsWarningPopUp(false)}
  536. PaperProps={{
  537. sx: {
  538. minWidth: '40vw',
  539. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  540. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  541. }
  542. }}
  543. >
  544. <DialogTitle>
  545. <FormattedMessage id="attention" />
  546. </DialogTitle>
  547. <DialogContent style={{ display: 'flex', }}>
  548. <Typography variant="h3" style={{ padding: '16px' }}>{warningText}</Typography>
  549. </DialogContent>
  550. <DialogActions>
  551. <Button
  552. aria-label={intl.formatMessage({ id: 'ok' })}
  553. onClick={() => setIsWarningPopUp(false)}
  554. >
  555. OK
  556. </Button>
  557. </DialogActions>
  558. </Dialog>
  559. </div>
  560. </MainCard>
  561. );
  562. };
  563. export default FormPanel;