Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

546 rader
25 KiB

  1. import {
  2. Dialog, DialogTitle, DialogContent, DialogActions,
  3. Typography,
  4. Autocomplete,
  5. CardContent,
  6. Grid,
  7. Stack,
  8. TextField,
  9. FormLabel,
  10. Button
  11. } from '@mui/material';
  12. import * as UrlUtils from "utils/ApiPathConst";
  13. import * as HttpUtils from "utils/HttpUtils";
  14. import * as DateUtils from "utils/DateUtils"
  15. import MainCard from "components/MainCard";
  16. import * as ComboData from "utils/ComboData";
  17. import * as React from "react";
  18. import { useFormik } from 'formik';
  19. import { useNavigate } from "react-router-dom";
  20. import { useIntl } from 'react-intl';
  21. import Loadable from 'components/Loadable';
  22. import { notifySaveSuccess } from 'utils/CommonFunction';
  23. const UploadFileTable = Loadable(React.lazy(() => import('./UploadFileTable')));
  24. const FormPanel = ({ formData }) => {
  25. const intl = useIntl();
  26. const [data, setData] = React.useState({});
  27. const [columnPrice, setColumnPrice] = React.useState(ComboData.proofPrice[0]);
  28. const [attachments, setAttachments] = React.useState([]);
  29. const [checkCode, setCheckCode] = React.useState("");
  30. const [expectedCode, setExpectedCode] = React.useState("");
  31. const [wait, setWait] = React.useState(false);
  32. const [isWarningPopUp, setIsWarningPopUp] = React.useState(false);
  33. const [warningText, setWarningText] = React.useState("");
  34. const [saving, setSaving] = React.useState(false);
  35. const [proofPaymentDeadlineMin, setProofPaymentDeadlineMin] = React.useState({});
  36. const [reviseDeadlineMin, setReviseDeadlineMin] = React.useState({});
  37. const fileInputRef = React.useRef(null);
  38. const navigate = useNavigate()
  39. React.useEffect(() => {
  40. if (formData) {
  41. setData(formData);
  42. if (formData.groupType == "Private Bill") {
  43. setColumnPrice(ComboData.proofPrice[1])
  44. formData['length'] = 18;
  45. }
  46. setProofPaymentDeadlineMin(formData.proofPaymentDeadline);
  47. setReviseDeadlineMin(formData.reviseDeadline);
  48. setExpectedCode(formData.groupNo.substr(1,formData.groupNo.length)+"-"+formData.issueNo+"-"+formData.issueYear.toString().substr(2, formData.issueYear.toString().length));
  49. }
  50. }, [formData]);
  51. React.useEffect(() => {
  52. if (!attachments || attachments.length <= 0) {
  53. formik.setFieldValue("length", 0);
  54. formik.setFieldValue("noOfPages", 0);
  55. formik.setFieldValue("fee", 0);
  56. return;
  57. }
  58. doCalculate();
  59. }, [attachments]);
  60. const doCalculate = () => {
  61. setWait(true);
  62. if (!attachments || attachments.length <= 0) {
  63. setWarningText("Unable to calculate, please upload a valid document.");
  64. setIsWarningPopUp(true);
  65. setWait(false);
  66. return;
  67. }
  68. HttpUtils.postWithFiles({
  69. url: UrlUtils.PROOF_CHECK_PRICE,
  70. params: {
  71. appId: data.id,
  72. },
  73. files: attachments,
  74. onSuccess: function (responseData) {
  75. if (responseData.data.detail) {
  76. setWarningText("Unable to calculate, please upload a valid document or input manually.");
  77. setIsWarningPopUp(true);
  78. setWait(false);
  79. return;
  80. }
  81. formik.setFieldValue("length", responseData.data.length);
  82. let colValue = 0;
  83. setColumnPrice(ComboData.proofPrice.find(obj => {
  84. colValue = obj.value;
  85. return obj.colCount === responseData.data.column
  86. }));
  87. formik.setFieldValue("noOfPages", responseData.data.total_no_of_page);
  88. formik.setFieldValue("fee", (data.groupType == "Private Bill" ? 6552 * responseData.data.total_no_of_page : responseData.data.length * colValue));
  89. if (data.groupType == "Private Bill" && responseData.data.file.length > 0) {
  90. let attachmentList = attachments;
  91. for (let i = 0; i < responseData.data.file.length; i++) {
  92. let file = responseData.data.file[i];
  93. attachmentList.find(item => item.name == file.filename)["no_of_page"] = file.no_of_page;
  94. }
  95. setAttachments(attachmentList);
  96. }
  97. setCheckCode(responseData.data.check_code);
  98. setWait(false);
  99. },
  100. onError: function () {
  101. // console.log(error)
  102. setWarningText("Unable to calculate, please input manually.");
  103. setIsWarningPopUp(true);
  104. setWait(false);
  105. }
  106. });
  107. }
  108. const formik = useFormik({
  109. enableReinitialize: true,
  110. initialValues: data,
  111. onSubmit: values => {
  112. setSaving(true);
  113. if (!attachments || attachments.length <= 0) {
  114. setWarningText("Please upload file.");
  115. setIsWarningPopUp(true);
  116. setSaving(false);
  117. return;
  118. }
  119. if (!values.length|| values.length <= 0) {
  120. setWarningText("Column should > 0");
  121. setIsWarningPopUp(true);
  122. setSaving(false);
  123. return;
  124. }
  125. if(formik.values.groupType == "Private Bill" ){
  126. if (!values.noOfPages || values.noOfPages <= 0) {
  127. setWarningText("Page should > 0");
  128. setIsWarningPopUp(true);
  129. setSaving(false);
  130. return;
  131. }
  132. }
  133. // console.log(values);
  134. HttpUtils.postWithFiles({
  135. url: UrlUtils.CREATE_PROOF,
  136. params: {
  137. appId: values.id,
  138. fee: values.fee,
  139. length: values.length,
  140. colCount: columnPrice.colCount,
  141. noOfPages: values.noOfPages,
  142. reviseDeadline: DateUtils.convertToDate(values.reviseDeadline).getTime(),
  143. proofPaymentDeadline: DateUtils.convertToDate(values.proofPaymentDeadline).getTime()
  144. },
  145. files: attachments,
  146. onSuccess: function (responeData) {
  147. if (responeData.success == true) {
  148. notifySaveSuccess()
  149. navigate("/proof/search");
  150. } else {
  151. let msg = responeData.msg;
  152. if (msg === "haveActiveProof") {
  153. msg = "Action Failed: There is already a pending payment and proofreading record for client review."
  154. } else if (msg === "haveProofed") {
  155. msg = "Action Failed: An active proof is already created for this application."
  156. } else if (msg === "applicationNotFound") {
  157. msg = "Application not found."
  158. }
  159. setWarningText(msg);
  160. setIsWarningPopUp(true);
  161. }
  162. }
  163. });
  164. }
  165. });
  166. const readFile = (event) => {
  167. let file = event.target.files && event.target.files[0];
  168. if (file) {
  169. if (!file.name.toLowerCase().substr(file.name.length - 4).includes(".pdf")) {
  170. setWarningText("Please upload a valid file (File format: .pdf).");
  171. setIsWarningPopUp(true);
  172. event.target.value = "";
  173. return;
  174. }
  175. if (file.size >= (10 * 1024 * 1034)) {
  176. setWarningText("The file size for uploading should be less than 10MB");
  177. setIsWarningPopUp(true);
  178. event.target.value = "";
  179. return;
  180. }
  181. file['id'] = attachments.length;
  182. setAttachments([
  183. ...attachments,
  184. file
  185. ]);
  186. event.target.value = "";
  187. }
  188. }
  189. return (
  190. <MainCard xs={12} md={12} lg={12}
  191. border={false}
  192. content={false}>
  193. <form onSubmit={formik.handleSubmit}>
  194. {/*row 1*/}
  195. <CardContent sx={{ px: 2.5, pt: 3 }}>
  196. <Grid item justifyContent="space-between" alignItems="center">
  197. <Typography variant="h4" sx={{ mb: 2, borderBottom: "1px solid black" }}>
  198. Proof
  199. </Typography>
  200. </Grid>
  201. </CardContent>
  202. {/*row 2*/}
  203. <Grid container direction="column" sx={{ paddingLeft: 4, paddingRight: 4 }} spacing={1}>
  204. <Grid item xs={12} md={12}>
  205. <Stack direction="row" sx={{ display: 'flex', alignItems: 'center' }}>
  206. <FormLabel sx={{ paddingRight: 2, textAlign: "center" }}>
  207. <Typography variant="h5">Deadline for online manuscript revision:</Typography>
  208. </FormLabel>
  209. <TextField
  210. fullWidth
  211. size="small"
  212. type="datetime-local"
  213. onChange={formik.handleChange}
  214. name="reviseDeadline"
  215. value={formik.values["reviseDeadline"]}
  216. InputProps={{ inputProps: { min: DateUtils.datetimeStr(reviseDeadlineMin) } }}
  217. variant="outlined"
  218. sx={
  219. {
  220. "& .MuiInputBase-input.Mui-disabled": {
  221. WebkitTextFillColor: "#000000",
  222. background: "#f8f8f8",
  223. },
  224. width: '30%'
  225. }
  226. }
  227. />
  228. </Stack>
  229. </Grid>
  230. <Grid item xs={12} md={12}>
  231. <Stack direction="row" sx={{ display: 'flex', alignItems: 'center' }}>
  232. <FormLabel sx={{ paddingRight: 2, textAlign: "center" }}>
  233. <Typography variant="h5">Deadline for online confirm proof:</Typography>
  234. </FormLabel>
  235. <TextField
  236. fullWidth
  237. size="small"
  238. type="datetime-local"
  239. onChange={formik.handleChange}
  240. name="proofPaymentDeadline"
  241. value={formik.values["proofPaymentDeadline"]}
  242. InputProps={{ inputProps: { min: DateUtils.datetimeStr(proofPaymentDeadlineMin) } }}
  243. variant="outlined"
  244. sx={
  245. {
  246. "& .MuiInputBase-input.Mui-disabled": {
  247. WebkitTextFillColor: "#000000",
  248. background: "#f8f8f8",
  249. },
  250. width: '30%'
  251. }
  252. }
  253. />
  254. </Stack>
  255. </Grid>
  256. <Grid item xs={12} md={12}>
  257. <Button
  258. variant="contained"
  259. size="large"
  260. disabled={attachments.length >= (formik.values.groupType == "Private Bill" ? 2 : 1)}
  261. type="button"
  262. onClick={() => {
  263. if (fileInputRef.current) {
  264. fileInputRef.current.click();
  265. }
  266. }}
  267. onKeyDown={(event) => {
  268. if (event.key === 'Enter' || event.key === ' ') {
  269. event.preventDefault();
  270. if (fileInputRef.current) {
  271. fileInputRef.current.click();
  272. }
  273. }
  274. }}
  275. >
  276. <Typography variant="h5">Upload Files</Typography>
  277. </Button>
  278. <input
  279. id="uploadFileBtn"
  280. name="file"
  281. type="file"
  282. accept=".pdf"
  283. hidden
  284. disabled={attachments.length >= (formik.values.groupType == "Private Bill" ? 2 : 1)}
  285. onChange={readFile}
  286. aria-label={intl.formatMessage({ id: 'ariaUploadPdfFile' })}
  287. ref={fileInputRef}
  288. />
  289. </Grid>
  290. <Grid item xs={12} md={12}>
  291. <UploadFileTable
  292. key="uploadTable"
  293. recordList={attachments}
  294. setRecordList={setAttachments}
  295. showPageColumn={formik.values.groupType == "Private Bill"}
  296. _checkCode={checkCode}
  297. _expectedCode={expectedCode}
  298. />
  299. </Grid>
  300. {
  301. wait ?
  302. <Grid item xs={12} md={12} sx={{ mt: 1.5, mb: 1.5 }}>
  303. <Typography variant="h3" style={{ color: "blue" }}>Calculating, please wait ...</Typography>
  304. </Grid>
  305. :
  306. <Grid item xs={12} md={12}>
  307. <Button
  308. size="large"
  309. variant="contained"
  310. onClick={doCalculate}
  311. sx={{
  312. textTransform: 'capitalize',
  313. alignItems: 'end'
  314. }}>
  315. <Typography variant="h5">Calculate</Typography>
  316. </Button>
  317. </Grid>
  318. }
  319. {
  320. formik.values.groupType == "Private Bill" ?
  321. <Grid item xs={12} md={12}>
  322. <Stack direction="row" sx={{ display: 'flex', alignItems: 'center' }}>
  323. <TextField
  324. fullWidth
  325. size="small"
  326. type="number"
  327. value={formik.values["noOfPages"]}
  328. onChange={(event) => {
  329. const value = parseInt(event.target.value);
  330. formik.setFieldValue("noOfPages", value);
  331. formik.setFieldValue("fee", 6552 * value);
  332. }}
  333. variant="outlined"
  334. sx={
  335. {
  336. "& .MuiInputBase-input.Mui-disabled": {
  337. WebkitTextFillColor: "#000000",
  338. background: "#f8f8f8",
  339. },
  340. width: '15%'
  341. }
  342. }
  343. />
  344. <FormLabel sx={{ paddingLeft: 2, paddingRight: 2, textAlign: "center" }}>
  345. <Typography variant="h5">pages</Typography>
  346. </FormLabel>
  347. <FormLabel sx={{ paddingLeft: 2, paddingRight: 2, textAlign: "center" }}>
  348. <Typography variant="h5">x</Typography>
  349. </FormLabel>
  350. <FormLabel sx={{ paddingLeft: 2, paddingRight: 2, textAlign: "center" }}>
  351. <Typography variant="h5">${formik.values.price ? formik.values.price : "6,552"}</Typography>
  352. </FormLabel>
  353. </Stack>
  354. </Grid>
  355. :
  356. <Grid item xs={12} md={12}>
  357. <Stack direction="row" sx={{ display: 'flex', alignItems: 'center' }}>
  358. <TextField
  359. fullWidth
  360. size="small"
  361. type="number"
  362. onChange={(event) => {
  363. let value = parseInt(event.target.value);
  364. formik.setFieldValue("length", value);
  365. formik.setFieldValue("fee", columnPrice.value * value);
  366. }}
  367. name="length"
  368. value={formik.values["length"]}
  369. variant="outlined"
  370. sx={
  371. {
  372. "& .MuiInputBase-input.Mui-disabled": {
  373. WebkitTextFillColor: "#000000",
  374. background: "#f8f8f8",
  375. },
  376. width: '15%'
  377. }
  378. }
  379. />
  380. <FormLabel sx={{ paddingLeft: 2, paddingRight: 2, textAlign: "center" }}>
  381. <Typography variant="h5">cm</Typography>
  382. </FormLabel>
  383. <FormLabel sx={{ paddingLeft: 2, paddingRight: 4, textAlign: "center" }}>
  384. <Typography variant="h5">x</Typography>
  385. </FormLabel>
  386. <Autocomplete
  387. sx={{
  388. width: "15%",
  389. '& .MuiInputBase-root': { alignItems: 'center' },
  390. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  391. '& .MuiOutlinedInput-root': { height: 40 }
  392. }}
  393. disablePortal
  394. id="price"
  395. options={ComboData.proofPrice}
  396. value={columnPrice}
  397. inputValue={(columnPrice?.label) ? columnPrice?.label : ""}
  398. getOptionLabel={(option) => option.label ? option.label : ""}
  399. onChange={(event, newValue) => {
  400. setColumnPrice(newValue)
  401. formik.values["fee"] = newValue.value * formik.values.length;
  402. }}
  403. renderInput={(params) => (
  404. <TextField {...params}
  405. InputLabelProps={{
  406. shrink: true
  407. }}
  408. sx={{
  409. width: "100%"
  410. }}
  411. />
  412. )}
  413. />
  414. </Stack>
  415. </Grid>
  416. }
  417. <Grid item xs={12} md={12}>
  418. <Stack direction="row" sx={{ display: 'flex', alignItems: 'center' }}>
  419. <FormLabel sx={{ paddingRight: 2, textAlign: "center" }}>
  420. <Typography variant="h5">Necessary fee:</Typography>
  421. </FormLabel>
  422. <FormLabel sx={{ paddingLeft: 2, paddingRight: 2, textAlign: "center" }}>
  423. <Typography variant="h5">$</Typography>
  424. </FormLabel>
  425. <TextField
  426. fullWidth
  427. size="small"
  428. type="text"
  429. onChange={formik.handleChange}
  430. name="fee"
  431. value={formik.values["fee"]}
  432. variant="outlined"
  433. sx={
  434. {
  435. "& .MuiInputBase-input.Mui-disabled": {
  436. WebkitTextFillColor: "#000000",
  437. background: "#f8f8f8",
  438. },
  439. width: '15%'
  440. }
  441. }
  442. />
  443. </Stack>
  444. </Grid>
  445. <Grid item xs={12} md={12}>
  446. <Button
  447. size="large"
  448. variant="contained"
  449. color="success"
  450. type="submit"
  451. disabled={saving}
  452. sx={{
  453. textTransform: 'capitalize',
  454. alignItems: 'end'
  455. }}>
  456. <Typography variant="h5">Save</Typography>
  457. </Button>
  458. </Grid>
  459. </Grid>
  460. </form>
  461. <div>
  462. <Dialog
  463. open={isWarningPopUp}
  464. onClose={() => setIsWarningPopUp(false)}
  465. PaperProps={{
  466. sx: {
  467. minWidth: '40vw',
  468. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  469. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  470. }
  471. }}
  472. >
  473. <DialogTitle><Typography variant="h3">Warning</Typography></DialogTitle>
  474. <DialogContent style={{ display: 'flex', }}>
  475. <Typography variant="h4" style={{ padding: '16px' }}>{warningText}</Typography>
  476. </DialogContent>
  477. <DialogActions>
  478. <Button onClick={() => setIsWarningPopUp(false)}><Typography variant="h5">OK</Typography></Button>
  479. </DialogActions>
  480. </Dialog>
  481. </div>
  482. <div>
  483. <Dialog
  484. open={wait}
  485. onClose={() => setWait(false)}
  486. PaperProps={{
  487. sx: {
  488. minWidth: '40vw',
  489. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  490. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  491. }
  492. }}
  493. >
  494. <DialogContent style={{ display: 'flex', }}>
  495. <Typography variant="h4" style={{ padding: '16px' }}>Calculating, please wait ...</Typography>
  496. </DialogContent>
  497. </Dialog>
  498. </div>
  499. </MainCard>
  500. );
  501. };
  502. export default FormPanel;