選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

OrganizationCard.js 28 KiB

2年前
2年前
1年前
2年前
2年前
2年前
1年前
1年前
2年前
2年前
1年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
1年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
2年前
2年前
1年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
1年前
2年前
2年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. // material-ui
  2. import {
  3. Grid, Button, Checkbox, FormControlLabel, Typography,
  4. Dialog, DialogTitle, DialogContent, DialogActions,
  5. FormHelperText, TextField,
  6. } from '@mui/material';
  7. // import { FormControlLabel } from '@material-ui/core';
  8. import MainCard from "components/MainCard";
  9. import * as React from "react";
  10. import { useFormik } from 'formik';
  11. import { useForm } from "react-hook-form";
  12. import * as yup from 'yup';
  13. import { useEffect, useState } from "react";
  14. import * as DateUtils from 'utils/DateUtils';
  15. import * as HttpUtils from 'utils/HttpUtils';
  16. import * as UrlUtils from "utils/ApiPathConst";
  17. import * as FieldUtils from "utils/FieldUtils";
  18. import * as ComboData from "utils/ComboData";
  19. const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent')));
  20. import Loadable from 'components/Loadable';
  21. import { lazy } from 'react';
  22. import { notifySaveSuccess } from 'utils/CommonFunction';
  23. import { useIntl } from "react-intl";
  24. import { PNSPS_BUTTON_THEME } from "themes/buttonConst";
  25. import { ThemeProvider } from "@emotion/react";
  26. import { makeStyles } from '@mui/styles';
  27. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  28. const useStyles = makeStyles(() => ({
  29. root: {
  30. position: "relative"
  31. },
  32. display: {
  33. position: "absolute",
  34. top: 2,
  35. left: 12,
  36. bottom: 2,
  37. background: "white",
  38. pointerEvents: "none",
  39. right: 50,
  40. display: "flex",
  41. alignItems: "center",
  42. width:"70%"
  43. },
  44. }));
  45. const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => {
  46. const intl = useIntl();
  47. const [creditorConfirmPopUp, setCreditorConfirmPopUp] = React.useState(false);
  48. const [nonCreditorConfirmPopUp, setNonCreditorConfirmPopUp] = React.useState(false);
  49. const [currentUserData, setCurrentUserData] = useState({});
  50. const [editMode, setEditMode] = useState(false);
  51. const [createMode, setCreateMode] = useState(false);
  52. const [onReady, setOnReady] = useState(false);
  53. const [errorMsg, setErrorMsg] = useState("");
  54. const [minDate] = React.useState(new Date());
  55. const [fromDate, setFromDate] = React.useState("dd / mm / yyyy");
  56. const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy");
  57. const {register, handleSubmit, reset} = useForm()
  58. React.useEffect(() => {
  59. setFromDateValue(fromDate);
  60. }, [fromDate]);
  61. useEffect(() => {
  62. //if state data are ready and assign to different field
  63. // console.log(currentApplicationDetailData)
  64. if (Object.keys(currentUserData).length > 0) {
  65. setFromDate(currentUserData.brExpiryDate)
  66. setOnReady(true);
  67. }
  68. }, [currentUserData]);
  69. function FormDateInputComponent({ inputRef, ...props }) {
  70. const classes = useStyles();
  71. return (
  72. <>
  73. <div className={classes.display}>
  74. {DateUtils.dateStr(fromDateValue) == "Invalid Date" ?
  75. fromDateValue
  76. :
  77. DateUtils.dateStr(fromDateValue)}
  78. </div>
  79. <input
  80. // className={classes.input}
  81. ref={inputRef}
  82. {...props}
  83. // onChange={handleChange}
  84. value={fromDateValue}
  85. min={minDate}
  86. />
  87. </>
  88. );
  89. }
  90. function displayErrorMsg(errorMsg) {
  91. return <Typography variant="errorMessage1">{errorMsg}</Typography>
  92. }
  93. function getMaxErrStr(num, fieldname) {
  94. return displayErrorMsg(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: num, fieldname: fieldname ? intl.formatMessage({ id: fieldname }) + ": " : "" }));
  95. }
  96. function getRequiredErrStr(fieldname) {
  97. return displayErrorMsg(intl.formatMessage({ id: 'require' }, { fieldname: fieldname ? intl.formatMessage({ id: fieldname }) : "" }));
  98. }
  99. const formik = useFormik({
  100. enableReinitialize: true,
  101. initialValues: currentUserData,
  102. validationSchema: yup.object().shape({
  103. enCompanyName: yup.string().max(255, getMaxErrStr(255)).required(displayErrorMsg(intl.formatMessage({ id: 'userRequireEnglishName' }))),
  104. chCompanyName: yup.string().max(255, displayErrorMsg(intl.formatMessage({ id: 'userRequireChineseName' }))).nullable(),
  105. orgShortName: yup.string().max(24, getMaxErrStr(24)).required(getRequiredErrStr("Org. Short Name")),
  106. addressLine1: yup.string().max(40, getMaxErrStr(40)).required(displayErrorMsg(intl.formatMessage({ id: 'validateAddressLine1' }))),
  107. addressLine2: yup.string().max(40, getMaxErrStr(40)),
  108. addressLine3: yup.string().max(40, getMaxErrStr(40)),
  109. contactPerson: yup.string().max(60, getMaxErrStr(60)).required(getRequiredErrStr("contactPerson")),
  110. fax_countryCode: yup.string().min(3, displayErrorMsg(intl.formatMessage({ id: 'requireDialingCode' }))).nullable(),
  111. tel_countryCode: yup.string().min(3, displayErrorMsg(intl.formatMessage({ id: 'requireDialingCode' }))),
  112. phoneNumber: yup.string().min(8, displayErrorMsg(intl.formatMessage({ id: 'requiredValidNumber' }))).required(displayErrorMsg(intl.formatMessage({ id: 'requireContactNumber' }))),
  113. faxNumber: yup.string().min(8, displayErrorMsg(intl.formatMessage({ id: 'require8Number' }))).nullable(),
  114. brExpiryDate: yup.string().min(8).required(displayErrorMsg(intl.formatMessage({ id: 'pleaseFillInBusinessRegCertValidityDate' }))),
  115. brNo: yup.string().required(displayErrorMsg(intl.formatMessage({ id: 'pleaseFillInBusinessRegCertNumber' }))).test('checkBrNoFormat', displayErrorMsg(displayErrorMsg(intl.formatMessage({ id: 'pleaseFillInValidBusinessRegCertNumber' }))), function (value) {
  116. var brNo_pattern = /[0-9]{8}/
  117. if (value !== undefined) {
  118. if (value.match(brNo_pattern)) {
  119. return true
  120. } else {
  121. return false
  122. }
  123. }
  124. }),
  125. }),
  126. onSubmit: values => {
  127. if (values.country == null) {
  128. setErrorMsg(intl.formatMessage({ id: 'pleaseFillInCountry' }))
  129. } else {
  130. if (values.country.type == "hongKong" && values.district == null) {
  131. setErrorMsg(intl.formatMessage({ id: 'pleaseFillInDistrict' }))
  132. } else {
  133. let sentDateFrom = "";
  134. if (fromDateValue != "dd / mm / yyyy") {
  135. sentDateFrom = DateUtils.dateValue(fromDateValue)
  136. }
  137. HttpUtils.post({
  138. url: UrlUtils.POST_ORG_SAVE_PATH,
  139. params: {
  140. id: id > 0 ? id : null,
  141. enCompanyName: values.enCompanyName,
  142. chCompanyName: values.chCompanyName,
  143. orgShortName: values.creditor?values.orgShortName:"",
  144. brNo: values.brNo,
  145. // brExpiryDate: values.brExpiryDate,
  146. brExpiryDate: sentDateFrom,
  147. enCompanyNameTemp: values.enCompanyNameTemp,
  148. chCompanyNameTemp: values.chCompanyNameTemp,
  149. brExpiryDateTemp: values.brExpiryDateTemp,
  150. contactPerson: values.contactPerson,
  151. contactTel: {
  152. countryCode: values.tel_countryCode,
  153. phoneNumber: values.phoneNumber
  154. },
  155. faxNo: {
  156. countryCode: values.fax_countryCode,
  157. faxNumber: values.faxNumber
  158. },
  159. addressTemp: {
  160. country: values.country.type,
  161. district: values.district?.type,
  162. addressLine1: values.addressLine1,
  163. addressLine2: values.addressLine2,
  164. addressLine3: values.addressLine3,
  165. },
  166. creditor: values.creditor,
  167. },
  168. onSuccess: function () {
  169. notifySaveSuccess()
  170. loadDataFun();
  171. setEditMode(false);
  172. }
  173. });
  174. }
  175. }
  176. }
  177. });
  178. useEffect(() => {
  179. setEditModeFun(editMode);
  180. }, [editMode]);
  181. useEffect(() => {
  182. if (Object.keys(userData).length > 0) {
  183. setCreateMode(id <= 0);
  184. setEditMode(id <= 0);
  185. setCurrentUserData(userData);
  186. }
  187. }, [userData]);
  188. // useEffect(() => {
  189. // if (Object.keys(userData).length > 0) {
  190. // if(userData.creditor === undefined||userData.creditor === null){
  191. // userData.creditor = false
  192. // }
  193. // setCurrentUserData(userData);
  194. // }
  195. // }, []);
  196. const onEditClick = () => {
  197. setEditMode(true);
  198. };
  199. const onSubmit = (data) => {
  200. let sentOrgShortName = "";
  201. if(data.orgShortName!=null && data.orgShortName!=""){
  202. sentOrgShortName = data.orgShortName
  203. if (sentOrgShortName.length <=24){
  204. const temp = {
  205. orgShortName: sentOrgShortName,
  206. };
  207. markAsCreditor(temp);
  208. }else{
  209. alert("Organisation Short Name must not exceed 24 characters.")
  210. }
  211. }else{
  212. alert("Please enter Organisation Short Name for Demand Note.")
  213. }
  214. };
  215. function resetForm() {
  216. reset();
  217. }
  218. const markAsCreditor = (temp) => {
  219. setCreditorConfirmPopUp(false);
  220. HttpUtils.post({
  221. url: UrlUtils.GET_ORG_MARK_AS_CREDITOR + "/" + id,
  222. params: temp,
  223. onSuccess: () => {
  224. resetForm();
  225. loadDataFun();
  226. }
  227. });
  228. }
  229. const markAsNonCreditor = () => {
  230. setNonCreditorConfirmPopUp(false);
  231. HttpUtils.get({
  232. url: UrlUtils.GET_ORG_MARK_AS_NON_CREDITOR + "/" + id,
  233. onSuccess: () => {
  234. loadDataFun();
  235. }
  236. });
  237. }
  238. return (
  239. <MainCard elevation={0}
  240. border={false}
  241. content={false}
  242. >
  243. <form onSubmit={formik.handleSubmit} style={{ padding: 24 }}>
  244. {/*top*/}
  245. <Grid item s={12} md={12} lg={12} sx={{ mb: 3 }} alignItems={"start"} justifyContent="center">
  246. <Grid container maxWidth justifyContent="flex-start">
  247. {editMode ?
  248. <>
  249. {createMode ?
  250. <>
  251. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  252. <Grid item sx={{ ml: 0, mr: 3 }}>
  253. <Button
  254. variant="contained"
  255. type="submit"
  256. color="success"
  257. >
  258. Create
  259. </Button>
  260. </Grid>
  261. </ThemeProvider>
  262. </> :
  263. <>
  264. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  265. <Grid item sx={{ ml: 0, mr: 3 }}>
  266. <Button
  267. variant="contained"
  268. onClick={loadDataFun}
  269. color="cancel"
  270. >
  271. Reset & Back
  272. </Button>
  273. </Grid>
  274. <Grid item sx={{ ml: 3, mr: 3 }}>
  275. <Button
  276. variant="contained"
  277. type="submit"
  278. color="success"
  279. >
  280. Save
  281. </Button>
  282. </Grid>
  283. </ThemeProvider>
  284. </>
  285. }
  286. </>
  287. :
  288. <>
  289. <Grid item sx={{ ml: 0, mr: 3 }}>
  290. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  291. <Button
  292. variant="contained"
  293. onClick={onEditClick}
  294. color="success"
  295. >
  296. Edit
  297. </Button>
  298. </ThemeProvider>
  299. </Grid>
  300. {
  301. currentUserData.creditor ?
  302. <Grid item sx={{ ml: 3, mr: 3 }}>
  303. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  304. <Button
  305. variant="contained"
  306. color="error"
  307. onClick={() => setNonCreditorConfirmPopUp(true)}
  308. >
  309. Mark as Non-Credit Client
  310. </Button>
  311. </ThemeProvider>
  312. </Grid>
  313. :
  314. <Grid item sx={{ ml: 3, mr: 3 }}>
  315. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  316. <Button
  317. variant="contained"
  318. color="orange"
  319. onClick={() => setCreditorConfirmPopUp(true)}
  320. >
  321. Mark as Credit Client
  322. </Button>
  323. </ThemeProvider>
  324. </Grid>
  325. }
  326. </>
  327. }
  328. </Grid>
  329. </Grid>
  330. {/*top*/}
  331. {!onReady ?
  332. <LoadingComponent />
  333. :
  334. <Grid container spacing={1}>
  335. <Grid item xs={12}>
  336. <Typography variant="h4" sx={{ mb: 2, mr: 3, borderBottom: "1px solid black" }}>
  337. Organisation Details
  338. </Typography>
  339. </Grid>
  340. <Grid item xs={12}>
  341. <FormHelperText error id="helper-text-address1-signup">
  342. <Typography variant="errorMessage1">
  343. {errorMsg}
  344. </Typography>
  345. </FormHelperText>
  346. </Grid>
  347. <Grid item xs={12} lg={4} >
  348. {FieldUtils.getTextField({
  349. label: FieldUtils.notNullFieldLabel("BR No.:"),
  350. valueName: "brNo",
  351. disabled: (!editMode && !createMode),
  352. form: formik
  353. })}
  354. </Grid>
  355. <Grid item xs={12} lg={4} >
  356. <FormControlLabel
  357. control={<Checkbox checked={formik.values.creditor} />}
  358. label="is Credit Client"
  359. name="creditor"
  360. onChange={() => {
  361. formik.setFieldValue("creditor", !formik.values.creditor);
  362. }}
  363. disabled={true}
  364. //disabled={!editMode && !createMode}
  365. />
  366. </Grid>
  367. <Grid item xs={12} lg={4} ></Grid>
  368. <Grid item xs={12} lg={4} >
  369. {FieldUtils.getTextField({
  370. label: FieldUtils.notNullFieldLabel("Name (Eng):"),
  371. valueName: "enCompanyName",
  372. disabled: (!editMode && !createMode),
  373. form: formik
  374. })}
  375. </Grid>
  376. <Grid item xs={12} lg={4} >
  377. {FieldUtils.getTextField({
  378. label: "Name (Ch):",
  379. valueName: "chCompanyName",
  380. disabled: (!editMode && !createMode),
  381. form: formik
  382. })}
  383. </Grid>
  384. <Grid item xs={12} lg={4} >
  385. <Grid container alignItems={"center"}>
  386. <Grid item xs={12} md={3} lg={3} sx={{ display: 'flex', alignItems: 'center' }}>
  387. <Typography variant="pnspsFormParagraphBold">{FieldUtils.notNullFieldLabel("Expiry Date:")}</Typography>
  388. </Grid>
  389. <Grid item xs={12} md={6} lg={6}>
  390. <TextField
  391. fullWidth
  392. id="brExpiryDate"
  393. type="date"
  394. name="brExpiryDate"
  395. error={Boolean(formik.errors["brExpiryDate"])}
  396. helperText={formik.errors["brExpiryDate"] ? formik.errors["brExpiryDate"] : ''}
  397. defaultValue={fromDate}
  398. InputProps={{
  399. inputComponent: FormDateInputComponent,
  400. }}
  401. onChange={(newValue) => {
  402. if (newValue.target.value>DateUtils.dateValue(minDate)){
  403. setFromDate(newValue.target.value);
  404. }else{
  405. alert("Please select a date after today.")
  406. }
  407. }}
  408. InputLabelProps={{
  409. shrink: true
  410. }}
  411. disabled={(!editMode && !createMode)}
  412. sx={{ "& .MuiInputBase-input": {display:"block", textIndent: "-9999px"} }}
  413. />
  414. </Grid>
  415. </Grid>
  416. </Grid>
  417. <Grid item xs={12} lg={4} >
  418. {FieldUtils.getTextField({
  419. label: FieldUtils.notNullFieldLabel("Contact Person:"),
  420. valueName: "contactPerson",
  421. disabled: (!editMode && !createMode),
  422. form: formik
  423. })}
  424. </Grid>
  425. <Grid item xs={12} lg={4} >
  426. {FieldUtils.getPhoneField({
  427. label: FieldUtils.notNullFieldLabel("Contact Tel:"),
  428. valueName: {
  429. code: "tel_countryCode",
  430. num: "phoneNumber"
  431. },
  432. disabled: (!editMode && !createMode),
  433. form: formik
  434. })}
  435. </Grid>
  436. <Grid item xs={12} lg={4} >
  437. {FieldUtils.getPhoneField({
  438. label: "Fax No:",
  439. valueName: {
  440. code: "fax_countryCode",
  441. num: "faxNumber"
  442. },
  443. disabled: (!editMode && !createMode),
  444. form: formik
  445. })}
  446. </Grid>
  447. <Grid item xs={12} lg={4} >
  448. {FieldUtils.getComboField({
  449. label: FieldUtils.notNullFieldLabel("Country:"),
  450. valueName: "country",
  451. disabled: (!editMode && !createMode),
  452. dataList: ComboData.country,
  453. getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
  454. form: formik
  455. })}
  456. </Grid>
  457. <Grid item xs={12} lg={4} >
  458. {FieldUtils.getComboField({
  459. label: FieldUtils.notNullFieldLabel("District:"),
  460. valueName: "district",
  461. disabled: (!editMode && !createMode),
  462. dataList: ComboData.district,
  463. getOptionLabel: (option) => option.type ? intl.formatMessage({ id: option.type }) : "",
  464. form: formik
  465. })}
  466. </Grid>
  467. {
  468. currentUserData.creditor ?
  469. <Grid item xs={12} lg={4} >
  470. {FieldUtils.getTextField({
  471. label: FieldUtils.notNullFieldLabel("Org. Short Name:"),
  472. valueName: "orgShortName",
  473. disabled: (!editMode && !createMode),
  474. form: formik
  475. })}
  476. </Grid>
  477. :
  478. null
  479. }
  480. <Grid item xs={12} lg={12} >
  481. {FieldUtils.getAddressField({
  482. label: FieldUtils.notNullFieldLabel("Address:"),
  483. valueName: ["addressLine1", "addressLine2", "addressLine3"],
  484. disabled: (!editMode && !createMode),
  485. form: formik
  486. })}
  487. </Grid>
  488. <Grid item lg={12} ></Grid>
  489. </Grid>
  490. }
  491. </form>
  492. <div>
  493. <Dialog
  494. open={creditorConfirmPopUp}
  495. onClose={() => setCreditorConfirmPopUp(false)}
  496. PaperProps={{
  497. sx: {
  498. minWidth: '40vw',
  499. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  500. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  501. }
  502. }}
  503. >
  504. <form onSubmit={handleSubmit(onSubmit)}>
  505. <DialogTitle><Typography variant="h3">Confirm</Typography></DialogTitle>
  506. <DialogContent style={{ display: 'flex', }}>
  507. <Grid container direction="column">
  508. <Grid item>
  509. <Typography variant="h4" style={{ padding: '16px' }}>Are you sure mark as Credit Client?</Typography>
  510. </Grid>
  511. <Grid item>
  512. <Typography variant="h6" style={{ padding: '16px' }}>Please Enter Organisation Short Name for Credit Client (Used for Demand Note)</Typography>
  513. </Grid>
  514. <Grid item sx={{padding: '16px'}}>
  515. <TextField
  516. fullWidth
  517. {...register("orgShortName")}
  518. id='orgShortName'
  519. label="Organisation Short Name"
  520. defaultValue={currentUserData.orgShortName}
  521. InputLabelProps={{
  522. shrink: true
  523. }}
  524. />
  525. </Grid>
  526. </Grid>
  527. </DialogContent>
  528. <DialogActions>
  529. <Button onClick={() => setCreditorConfirmPopUp(false)}><Typography variant="h5">Cancel</Typography></Button>
  530. <Button type="submit"><Typography variant="h5">Confirm</Typography></Button>
  531. {/* <Button onClick={() => markAsCreditor()}><Typography variant="h5">Confirm</Typography></Button> */}
  532. </DialogActions>
  533. </form>
  534. </Dialog>
  535. </div>
  536. <div>
  537. <Dialog
  538. open={nonCreditorConfirmPopUp}
  539. onClose={() => setNonCreditorConfirmPopUp(false)}
  540. PaperProps={{
  541. sx: {
  542. minWidth: '40vw',
  543. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  544. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  545. }
  546. }}
  547. >
  548. <DialogTitle><Typography variant="h3">Confirm</Typography></DialogTitle>
  549. <DialogContent style={{ display: 'flex', }}>
  550. <Typography variant="h4" style={{ padding: '16px' }}>Are you sure mark as Non-Credit Client?</Typography>
  551. </DialogContent>
  552. <DialogActions>
  553. <Button onClick={() => setNonCreditorConfirmPopUp(false)}><Typography variant="h5">Cancel</Typography></Button>
  554. <Button onClick={() => markAsNonCreditor()}><Typography variant="h5">Confirm</Typography></Button>
  555. </DialogActions>
  556. </Dialog>
  557. </div>
  558. </MainCard>
  559. );
  560. };
  561. export default OrganizationCard;