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.

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