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.
 
 

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