You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

458 lines
20 KiB

  1. // material-uistatus
  2. import {
  3. Button,
  4. Grid, TextField,
  5. Autocomplete,
  6. Typography
  7. } from '@mui/material';
  8. import MainCard from "components/MainCard";
  9. import { useForm } from "react-hook-form";
  10. import * as React from "react";
  11. import * as ComboData from "utils/ComboData";
  12. import * as DateUtils from "utils/DateUtils";
  13. import {
  14. isORGLoggedIn,
  15. } from "utils/Utils";
  16. import {PNSPS_BUTTON_THEME} from "../../../themes/buttonConst";
  17. import {ThemeProvider} from "@emotion/react";
  18. import {FormattedMessage, useIntl} from "react-intl";
  19. import {DatePicker} from "@mui/x-date-pickers/DatePicker";
  20. import dayjs from "dayjs";
  21. import {DemoItem} from "@mui/x-date-pickers/internals/demo";
  22. import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
  23. import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
  24. const getDefaultDateFrom = () => DateUtils.dateValue(new Date().setDate(new Date().getDate() - 14));
  25. const getDefaultDateTo = () => DateUtils.dateValue(new Date());
  26. const isSubmitDateEmpty = (value) =>
  27. value == null || value === "" || value === "dd / mm / yyyy";
  28. const isBlank = (value) => value == null || String(value).trim() === "";
  29. const toDayjsOrNull = (value) => {
  30. if (isSubmitDateEmpty(value)) return null;
  31. const d = dayjs(value);
  32. return d.isValid() ? d : null;
  33. };
  34. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  35. const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => {
  36. const intl = useIntl();
  37. const [type, setType] = React.useState([]);
  38. const [status, setStatus] = React.useState(localStorage.getItem('userData').creditor?ComboData.publicNoticeStatic_Creditor[0]:ComboData.publicNoticeStatic[0]);
  39. const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
  40. const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
  41. const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy");
  42. const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy");
  43. const prevHasOtherRef = React.useRef(null);
  44. // const [selectedLabelsString, setSelectedLabelsString] = React.useState('');
  45. const { reset, register, handleSubmit, watch } = useForm({
  46. defaultValues: {
  47. appNo: searchCriteria.appNo || "",
  48. careOf: searchCriteria.careOf || "",
  49. contact: searchCriteria.contact || ""
  50. }
  51. });
  52. const appNo = watch("appNo");
  53. const careOf = watch("careOf");
  54. const contact = watch("contact");
  55. const marginBottom = 2.5;
  56. React.useEffect(() => {
  57. if(searchCriteria.status!=undefined){
  58. if(localStorage.getItem('userData').creditor){
  59. if(searchCriteria.status === ""){
  60. ComboData.publicNoticeStatic_Creditor[0]
  61. }else{
  62. setStatus(ComboData.publicNoticeStatic_Creditor.find(item => item.type === searchCriteria.status))
  63. }
  64. }else{
  65. if(searchCriteria.status === ""){
  66. ComboData.publicNoticeStatic[0]
  67. }else{
  68. setStatus(ComboData.publicNoticeStatic.find(item => item.type === searchCriteria.status))
  69. }
  70. }
  71. }else{
  72. if(localStorage.getItem('userData').creditor){
  73. setStatus(ComboData.publicNoticeStatic_Creditor[0])
  74. }else{
  75. setStatus(ComboData.publicNoticeStatic[0])
  76. }
  77. }
  78. }, [searchCriteria]);
  79. React.useEffect(() => {
  80. setFromDateValue(minDate);
  81. }, [minDate]);
  82. React.useEffect(() => {
  83. setToDateValue(maxDate);
  84. }, [maxDate]);
  85. const clearSubmitDates = () => {
  86. setMinDate(null);
  87. setMaxDate(null);
  88. };
  89. const restoreDefaultSubmitDates = () => {
  90. setMinDate(getDefaultDateFrom());
  91. setMaxDate(getDefaultDateTo());
  92. };
  93. const hasOtherCriteria = (textFields = {}) => {
  94. if (!isBlank(textFields.appNo)) return true;
  95. if (!isBlank(textFields.contact)) return true;
  96. if (!isBlank(textFields.careOf)) return true;
  97. if (status?.type && status.type !== "all" && status.type !== "") return true;
  98. return false;
  99. };
  100. React.useEffect(() => {
  101. const hasOther = hasOtherCriteria({ appNo, contact, careOf });
  102. if (prevHasOtherRef.current === null) {
  103. prevHasOtherRef.current = hasOther;
  104. return;
  105. }
  106. if (hasOther && !prevHasOtherRef.current) {
  107. clearSubmitDates();
  108. } else if (!hasOther && prevHasOtherRef.current) {
  109. // Only refill defaults when From or To is empty; keep user-entered dates otherwise
  110. if (isSubmitDateEmpty(minDate) || isSubmitDateEmpty(maxDate)) {
  111. restoreDefaultSubmitDates();
  112. }
  113. }
  114. prevHasOtherRef.current = hasOther;
  115. }, [appNo, contact, careOf, status]);
  116. const onSubmit = (data) => {
  117. data.status = status.type;
  118. let typeArray = [];
  119. let sentDateFrom = "";
  120. let sentDateTo = "";
  121. for (let i = 0; i < type.length; i++) {
  122. typeArray.push(type[i].label);
  123. }
  124. const hasOther = hasOtherCriteria({
  125. appNo: data.appNo,
  126. contact: data.contact,
  127. careOf: data.careOf
  128. });
  129. const datesEmpty = isSubmitDateEmpty(fromDateValue) || isSubmitDateEmpty(toDateValue)
  130. || minDate == null || maxDate == null;
  131. if (!hasOther && datesEmpty) {
  132. const dateFrom = getDefaultDateFrom();
  133. const dateTo = getDefaultDateTo();
  134. setMinDate(dateFrom);
  135. setMaxDate(dateTo);
  136. sentDateFrom = dateFrom;
  137. sentDateTo = dateTo;
  138. } else if (!datesEmpty) {
  139. sentDateFrom = DateUtils.dateValue(fromDateValue);
  140. sentDateTo = DateUtils.dateValue(toDateValue);
  141. }
  142. const temp = {
  143. appNo: data.appNo,
  144. dateFrom: sentDateFrom,
  145. dateTo: sentDateTo,
  146. contact: data.contact,
  147. careOf: data.careOf?data.careOf:"",
  148. status: (data.status === "" || data.status.includes('all')) ? "" : data.status,
  149. start:0,
  150. limit:10
  151. };
  152. if (searchCriteria?.sort && searchCriteria?.direction) {
  153. temp.sort = searchCriteria.sort;
  154. temp.direction = searchCriteria.direction;
  155. }
  156. applySearch(temp);
  157. };
  158. function resetForm() {
  159. setType([]);
  160. setStatus(localStorage.getItem('userData').creditor?ComboData.publicNoticeStatic_Creditor[0]:ComboData.publicNoticeStatic[0]);
  161. const dateFrom = getDefaultDateFrom();
  162. const dateTo = getDefaultDateTo();
  163. setMinDate(dateFrom);
  164. setMaxDate(dateTo);
  165. reset({
  166. appNo: "",
  167. careOf: "",
  168. contact: ""
  169. });
  170. prevHasOtherRef.current = false;
  171. localStorage.setItem('searchCriteria', "");
  172. // Reset form criteria and sorting first, then reload with backend default sort
  173. applySearch({
  174. appNo: "",
  175. dateFrom,
  176. dateTo,
  177. contact: "",
  178. careOf: "",
  179. status: "",
  180. start: 0,
  181. limit: 10
  182. });
  183. }
  184. return (
  185. <MainCard xs={12} md={12} lg={12}
  186. border={false}
  187. content={false}>
  188. <form onSubmit={handleSubmit(onSubmit)}>
  189. {/*row 1*/}
  190. <Grid item justifyContent="space-between" alignItems="center" sx={{mt:1,ml:3,mb:marginBottom}}>
  191. <Typography variant="pnspsFormHeader" >
  192. <FormattedMessage id="searchForm"/>
  193. </Typography>
  194. </Grid>
  195. {/*row 2*/}
  196. <Grid container alignItems={"center"}>
  197. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  198. <TextField
  199. fullWidth
  200. {...register("appNo")}
  201. id='appNo'
  202. aria-label={intl.formatMessage({id: 'applicationId'})}
  203. label={intl.formatMessage({id: 'applicationId'})}
  204. defaultValue={searchCriteria.appNo}
  205. InputLabelProps={{
  206. shrink: true
  207. }}
  208. />
  209. </Grid>
  210. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  211. <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}>
  212. <DemoItem components={['DatePicker']}>
  213. <DatePicker
  214. id="dateFrom"
  215. onError={() => {}}
  216. slotProps={{
  217. field: { readOnly: true, clearable: true },
  218. textField: {
  219. InputLabelProps: { shrink: true },
  220. error: false,
  221. helperText: null
  222. },
  223. }}
  224. format="DD/MM/YYYY"
  225. aria-label={intl.formatMessage({id: 'submitDateFrom'})}
  226. label={intl.formatMessage({id: 'submitDateFrom'})}
  227. value={toDayjsOrNull(minDate)}
  228. maxDate={toDayjsOrNull(maxDate)}
  229. onChange={(newValue) => {
  230. setMinDate(newValue && newValue.isValid?.() ? newValue : null);
  231. }}
  232. />
  233. </DemoItem >
  234. </LocalizationProvider>
  235. </Grid>
  236. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  237. <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}>
  238. <DemoItem components={['DatePicker']}>
  239. <DatePicker
  240. id="dateTo"
  241. onError={() => {}}
  242. slotProps={{
  243. field: { readOnly: true, clearable: true },
  244. textField: {
  245. InputLabelProps: { shrink: true },
  246. error: false,
  247. helperText: null
  248. },
  249. }}
  250. format="DD/MM/YYYY"
  251. label={intl.formatMessage({id: 'submitDateTo'})}
  252. value={toDayjsOrNull(maxDate)}
  253. minDate={toDayjsOrNull(minDate)}
  254. onChange={(newValue) => {
  255. setMaxDate(newValue && newValue.isValid?.() ? newValue : null);
  256. }}
  257. />
  258. </DemoItem >
  259. </LocalizationProvider>
  260. </Grid>
  261. {isORGLoggedIn()?
  262. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  263. <TextField
  264. fullWidth
  265. {...register("careOf")}
  266. id="careOf"
  267. label={intl.formatMessage({id: 'careOf'})}
  268. aria-label={intl.formatMessage({id: 'careOf'})}
  269. defaultValue={searchCriteria.careOf}
  270. InputLabelProps={{
  271. shrink: true
  272. }}
  273. />
  274. </Grid>:null
  275. }
  276. {/* <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  277. <TextField
  278. fullWidth
  279. {...register("contact")}
  280. id="contact"
  281. label={intl.formatMessage({id: 'contactPerson'})}
  282. aria-label={intl.formatMessage({id: 'contactPerson'})}
  283. defaultValue={searchCriteria.contact}
  284. InputLabelProps={{
  285. shrink: true
  286. }}
  287. />
  288. </Grid> */}
  289. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  290. <Autocomplete
  291. {...register("status")}
  292. id="status"
  293. size="small"
  294. disableClearable
  295. // filterOptions={(options)=>options}
  296. options={
  297. localStorage.getItem('userData').creditor ?
  298. ComboData.publicNoticeStatic_Creditor :
  299. ComboData.publicNoticeStatic
  300. }
  301. value={status}
  302. // inputValue={status?.labelCht}
  303. getOptionLabel={(option) => {
  304. if (option == null || option.label == null) return "";
  305. const s = intl.formatMessage({ id: option.label });
  306. return typeof s === "string" ? s : String(s ?? "");
  307. }}
  308. onChange={(event, newValue) => {
  309. if(newValue ==null){
  310. setStatus(localStorage.getItem('userData').creditor?ComboData.publicNoticeStatic_Creditor[0]:ComboData.publicNoticeStatic[0]);
  311. }else{
  312. setStatus(newValue);
  313. }
  314. }}
  315. sx={{
  316. '& .MuiInputBase-root': { alignItems: 'center' },
  317. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  318. '& .MuiOutlinedInput-root': { height: 40 }
  319. }}
  320. renderInput={(params) => (
  321. <TextField {...params}
  322. label={intl.formatMessage({id: 'status'})}
  323. aria-label={intl.formatMessage({id: 'status'})}
  324. InputLabelProps={{
  325. shrink: true
  326. }}
  327. />
  328. )}
  329. clearText={intl.formatMessage({ id: "muiClear" })}
  330. closeText={intl.formatMessage({ id: "muiClose" })}
  331. openText={intl.formatMessage({ id: "muiOpen" })}
  332. noOptionsText={intl.formatMessage({ id: "muiNoOptions" })}
  333. // InputLabelProps={{
  334. // shrink: true
  335. // }}
  336. />
  337. </Grid>
  338. {/* <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  339. <Autocomplete
  340. multiple
  341. {...register("status")}
  342. id="status"
  343. size="small"
  344. // filterOptions={(options)=>options}
  345. options={
  346. localStorage.getItem('userData').creditor ?
  347. ComboData.publicNoticeStatic_Creditor :
  348. ComboData.publicNoticeStatic
  349. }
  350. value={status}
  351. // inputValue={status?.labelCht}
  352. getOptionLabel={(option) => {
  353. if (option == null || option.label == null) return "";
  354. const s = intl.formatMessage({ id: option.label });
  355. return typeof s === "string" ? s : String(s ?? "");
  356. }}
  357. onChange={(event, newValue) => {
  358. console.log(newValue)
  359. const findAllIndex = newValue.findIndex((ele) => {
  360. return ele.type === "all"
  361. })
  362. if (findAllIndex > -1) {
  363. setStatus([newValue[findAllIndex]]);
  364. setSelectedLabelsString('all')
  365. } else {
  366. const selectedLabels = newValue.map(option => option.type);
  367. const selectedLabelsString = `${selectedLabels.join(',')}`;
  368. setStatus(newValue);
  369. console.log(newValue)
  370. setSelectedLabelsString(selectedLabelsString);
  371. }
  372. console.log(selectedLabelsString)
  373. console.log(status)
  374. }}
  375. renderInput={(params) => (
  376. <TextField {...params}
  377. label={intl.formatMessage({id: 'status'})}
  378. aria-label={intl.formatMessage({id: 'status'})}
  379. InputLabelProps={{
  380. shrink: true
  381. }}
  382. />
  383. )}
  384. // InputLabelProps={{
  385. // shrink: true
  386. // }}
  387. />
  388. </Grid> */}
  389. </Grid>
  390. {/*last row*/}
  391. <Grid container maxWidth justifyContent="flex-end">
  392. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  393. <Grid item sx={{ ml: 3, mr: 3 }}>
  394. <Button
  395. variant="contained"
  396. color="cancel"
  397. onClick={resetForm}
  398. aria-label={intl.formatMessage({id: 'reset'})}
  399. >
  400. <Typography variant="pnspsButtonText">
  401. <FormattedMessage id="reset"/>
  402. </Typography>
  403. </Button>
  404. </Grid>
  405. <Grid item>
  406. <Button
  407. variant="contained"
  408. type="submit"
  409. disabled={onGridReady}
  410. aria-label={intl.formatMessage({id: 'search'})}
  411. >
  412. <Typography variant="pnspsButtonText">
  413. <FormattedMessage id="search"/>
  414. </Typography>
  415. </Button>
  416. </Grid>
  417. </ThemeProvider>
  418. </Grid>
  419. </form>
  420. </MainCard>
  421. );
  422. };
  423. export default SearchPublicNoticeForm;