您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 

530 行
24 KiB

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