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

SearchForm.js 24 KiB

7 个月前
2 年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // material-ui
  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 * as FormatUtils from "utils/FormatUtils";
  14. import {PNSPS_BUTTON_THEME} from "../../../themes/buttonConst";
  15. import {ThemeProvider} from "@emotion/react";
  16. import { useIntl } from "react-intl";
  17. import {DatePicker} from "@mui/x-date-pickers/DatePicker";
  18. import dayjs from "dayjs";
  19. import {DemoItem} from "@mui/x-date-pickers/internals/demo";
  20. import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider";
  21. import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs";
  22. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  23. const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issueComboData, onGridReady
  24. }) => {
  25. const [type, setType] = React.useState([]);
  26. const [orgSelected, setOrgSelected] = React.useState({});
  27. const [orgCombo, setOrgCombo] = React.useState();
  28. const [issueSelected, setIssueSelected] = React.useState({});
  29. const [issueCombo, setIssueCombo] = React.useState([]);
  30. const [selectedStatus, setSelectedStatus] = React.useState(ComboData.denmandNoteStatus[0]);
  31. const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom);
  32. const [maxDate, setMaxDate] = React.useState(searchCriteria.dateTo);
  33. const [fromDateValue, setFromDateValue] = React.useState(searchCriteria.dateFrom);
  34. const [toDateValue, setToDateValue] = React.useState(searchCriteria.dateTo);
  35. const [minDueDate, setMinDueDate] = React.useState(null);
  36. const [maxDueDate, setMaxDueDate] = React.useState(null);
  37. const [fromDueDateValue, setFromDueDateValue] = React.useState(null);
  38. const [toDueDateValue, setToDueDateValue] = React.useState(null);
  39. const intl = useIntl();
  40. const { locale } = intl;
  41. React.useEffect(() => {
  42. if(searchCriteria.status!=undefined){
  43. if(searchCriteria.status === ""){
  44. ComboData.denmandNoteStatus[0]
  45. }else{
  46. setSelectedStatus(ComboData.denmandNoteStatus.find(item => item.type === searchCriteria.status))
  47. }
  48. if(searchCriteria.dueDateFrom != ""){
  49. setMinDueDate(DateUtils.dateValue(searchCriteria.dueDateFrom))
  50. }else{
  51. setMinDueDate(null)
  52. }
  53. if(searchCriteria.dueDateTo != ""){
  54. setMaxDueDate(DateUtils.dateValue(searchCriteria.dueDateTo))
  55. }else{
  56. setMaxDueDate(null);
  57. }
  58. }else{
  59. setSelectedStatus(ComboData.denmandNoteStatus[0])
  60. }
  61. }, [searchCriteria]);
  62. React.useEffect(() => {
  63. setFromDateValue(minDate);
  64. }, [minDate]);
  65. React.useEffect(() => {
  66. setToDateValue(maxDate);
  67. }, [maxDate]);
  68. React.useEffect(() => {
  69. setFromDueDateValue(minDueDate);
  70. }, [minDueDate]);
  71. React.useEffect(() => {
  72. setToDueDateValue(maxDueDate);
  73. }, [maxDueDate]);
  74. const { reset, register, handleSubmit } = useForm()
  75. const onSubmit = (data) => {
  76. data.status = selectedStatus?.type;
  77. let typeArray = [];
  78. let sentDateFrom = "";
  79. let sentDateTo = "";
  80. let sentDueDateFrom = "";
  81. let sentDueDateTo = "";
  82. for (let i = 0; i < type.length; i++) {
  83. typeArray.push(type[i].label);
  84. }
  85. if (fromDateValue != "dd / mm / yyyy" && toDateValue != "dd / mm / yyyy") {
  86. sentDateFrom = DateUtils.dateValue(fromDateValue)
  87. sentDateTo = DateUtils.dateValue(toDateValue)
  88. }
  89. if (fromDueDateValue != "dd / mm / yyyy" && toDueDateValue != "dd / mm / yyyy") {
  90. sentDueDateFrom = DateUtils.dateValue(fromDueDateValue)
  91. sentDueDateTo = DateUtils.dateValue(toDueDateValue)
  92. }
  93. const temp = {
  94. appNo: data.appNo,
  95. issueId: issueSelected?.id,
  96. orgId: (orgSelected?.key && orgSelected?.key > 0) ? orgSelected?.key : "",
  97. dnNo: data.dnNo,
  98. dateFrom: sentDateFrom,
  99. dateTo: sentDateTo,
  100. dueDateFrom: sentDueDateFrom,
  101. dueDateTo: sentDueDateTo,
  102. status: (data?.status === '' || data?.status?.includes("all")) ? "" : data.status,
  103. start:0,
  104. limit:10
  105. };
  106. applySearch(temp);
  107. };
  108. React.useEffect(() => {
  109. if (orgComboData && orgComboData.length > 0) {
  110. setOrgCombo(orgComboData);
  111. if(searchCriteria.orgId!=undefined){
  112. setOrgSelected(orgComboData.find(item => item.key === searchCriteria.orgId))
  113. }
  114. }
  115. }, [orgComboData]);
  116. React.useEffect(() => {
  117. if (issueComboData && issueComboData.length > 0) {
  118. setIssueCombo(issueComboData);
  119. if(searchCriteria.issueId!=undefined){
  120. setIssueSelected(issueComboData.find(item => item.id === searchCriteria.issueId))
  121. }
  122. }
  123. }, [issueComboData]);
  124. function resetForm() {
  125. setType([]);
  126. setOrgSelected({});
  127. setIssueSelected({});
  128. setSelectedStatus(ComboData.denmandNoteStatus[0]);
  129. setMinDueDate(null);
  130. setMaxDueDate(null);
  131. setMinDate(DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)))
  132. setMaxDate(DateUtils.dateValue(new Date()))
  133. reset({
  134. appNo:"",
  135. dnNo:"",
  136. });
  137. localStorage.setItem('searchCriteria',"")
  138. }
  139. function getIssueLabel(data) {
  140. let issueYear = data.issueYear
  141. let volume = data.volume;
  142. let issueNo = data.issueNo;
  143. let issueDate = data.issueDate;
  144. if (locale === 'zh-HK') {
  145. return issueYear
  146. + " 第" + volume + "卷,"
  147. + " 第" + issueNo + "期,"
  148. + " " + DateUtils.dateFormat(issueDate, "YYYY年MM月DD日")
  149. + " (" + DateUtils.getWeekdayStr_ZH(issueDate) + ")";
  150. } else if (locale === 'zh-CN') {
  151. return issueYear
  152. + " 第" + volume + "卷,"
  153. + " 第" + issueNo + "期,"
  154. + " " + DateUtils.dateFormat(issueDate, "YYYY年MM月DD日")
  155. + " (" + DateUtils.getWeekdayStr_CN(issueDate) + ")";
  156. }
  157. return issueYear
  158. + " Vol. " + FormatUtils.zeroPad(volume, 3)
  159. + ", No. " + FormatUtils.zeroPad(issueNo, 2)
  160. + ", " + DateUtils.dateFormat(issueDate, "D MMM YYYY (ddd)");
  161. }
  162. return (
  163. <MainCard xs={12} md={12} lg={12}
  164. border={false}
  165. content={false}
  166. sx={{ backgroundColor: '#fff' }}
  167. >
  168. <form onSubmit={handleSubmit(onSubmit)}>
  169. <Grid container sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1 }} width="98%">
  170. {/*row 1*/}
  171. <Grid item justifyContent="space-between" alignItems="center" sx={{mt:1, ml:3,mb:2.5}}>
  172. <Typography variant="pnspsFormHeader" >
  173. Search
  174. </Typography>
  175. </Grid>
  176. {/*row 2*/}
  177. <Grid container display="flex" alignItems={"center"}>
  178. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  179. <Autocomplete
  180. {...register("issueId")}
  181. disablePortal
  182. id="issueId"
  183. size="small"
  184. options={issueCombo}
  185. value={issueSelected}
  186. inputValue={(issueSelected?.id) ? getIssueLabel(issueSelected) : ""}
  187. getOptionLabel={(option) => getIssueLabel(option)}
  188. onChange={(event, newValue) => {
  189. setIssueSelected(newValue);
  190. }}
  191. sx={{
  192. '& .MuiInputBase-root': { alignItems: 'center' },
  193. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  194. '& .MuiOutlinedInput-root': { height: 40 }
  195. }}
  196. renderInput={(params) => (
  197. <TextField {...params}
  198. label="Gazette Issue No."
  199. InputLabelProps={{
  200. shrink: true
  201. }}
  202. />
  203. )}
  204. clearText={intl.formatMessage({ id: "muiClear" })}
  205. closeText={intl.formatMessage({ id: "muiClose" })}
  206. openText={intl.formatMessage({ id: "muiOpen" })}
  207. noOptionsText={intl.formatMessage({ id: "muiNoOptions" })}
  208. />
  209. </Grid>
  210. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  211. <TextField
  212. fullWidth
  213. {...register("appNo")}
  214. id='appNo'
  215. label={"Application No."}
  216. defaultValue={searchCriteria.appNo}
  217. InputLabelProps={{
  218. shrink: true
  219. }}
  220. />
  221. </Grid>
  222. {
  223. orgCombo ?
  224. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  225. <Autocomplete
  226. {...register("orgId")}
  227. disablePortal
  228. id="orgId"
  229. options={orgCombo}
  230. groupBy={(option) => option.groupType}
  231. size="small"
  232. value={orgSelected}
  233. getOptionLabel={(option) => option.name? option.name : ""}
  234. inputValue={orgSelected ? orgSelected.name!=undefined?orgSelected.name:"" : ""}
  235. onChange={(event, newValue) => {
  236. if (newValue !== null) {
  237. setOrgSelected(newValue);
  238. }else{
  239. setOrgSelected({});
  240. }
  241. }}
  242. sx={{
  243. '& .MuiInputBase-root': { alignItems: 'center' },
  244. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  245. '& .MuiOutlinedInput-root': { height: 40 }
  246. }}
  247. renderInput={(params) => (
  248. <TextField {...params}
  249. label="Organisation"
  250. InputLabelProps={{
  251. shrink: true
  252. }}
  253. />
  254. )}
  255. renderGroup={(params) => (
  256. <Grid item key={params.key}>
  257. <Typography fontSize={20} fontStyle="italic" p={1}>
  258. {params.group}
  259. </Typography>
  260. {params.children}
  261. </Grid>
  262. )}
  263. clearText={intl.formatMessage({ id: "muiClear" })}
  264. closeText={intl.formatMessage({ id: "muiClose" })}
  265. openText={intl.formatMessage({ id: "muiOpen" })}
  266. noOptionsText={intl.formatMessage({ id: "muiNoOptions" })}
  267. />
  268. </Grid>
  269. : <></>
  270. }
  271. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  272. <TextField
  273. fullWidth
  274. {...register("dnNo")}
  275. id='dnNo'
  276. label="DN No."
  277. defaultValue={searchCriteria.dnNo}
  278. InputLabelProps={{
  279. shrink: true
  280. }}
  281. />
  282. </Grid>
  283. <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>
  284. <Grid container spacing={1}>
  285. <Grid item xs={6}>
  286. <LocalizationProvider dateAdapter={AdapterDayjs}>
  287. <DemoItem components={['DatePicker']}>
  288. <DatePicker
  289. id="dateFrom"
  290. // onError={(newError) => setReceiptFromError(newError)}
  291. slotProps={{
  292. field: { readOnly: true, },
  293. // textField: {
  294. // helperText: receiptFromErrorMessage,
  295. // },
  296. }}
  297. format="DD/MM/YYYY"
  298. label={"Issue Date (From)"}
  299. value={minDate === null ? null : dayjs(minDate)}
  300. maxDate={maxDate === null ? null : dayjs(maxDate)}
  301. onChange={(newValue) => {
  302. // console.log(newValue)
  303. if(newValue!=null){
  304. setMinDate(newValue);
  305. }
  306. }}
  307. />
  308. </DemoItem >
  309. </LocalizationProvider>
  310. </Grid>
  311. <Grid item xs={6}>
  312. <LocalizationProvider dateAdapter={AdapterDayjs}>
  313. <DemoItem components={['DatePicker']}>
  314. <DatePicker
  315. id="dateTo"
  316. // onError={(newError) => setReceiptFromError(newError)}
  317. slotProps={{
  318. field: { readOnly: true, },
  319. // textField: {
  320. // helperText: receiptFromErrorMessage,
  321. // },
  322. }}
  323. format="DD/MM/YYYY"
  324. label={"Issue Date (To)"}
  325. value={maxDate === null ? null : dayjs(maxDate)}
  326. minDate={minDate === null ? null : dayjs(minDate)}
  327. onChange={(newValue) => {
  328. // console.log(newValue)
  329. if(newValue!=null){
  330. setMaxDate(newValue);
  331. }
  332. }}
  333. />
  334. </DemoItem >
  335. </LocalizationProvider>
  336. </Grid>
  337. </Grid>
  338. </Grid>
  339. <Grid item xs={9} s={6} md={6} lg={3.5} sx={{ml:3, mr:2, mb:3}}>
  340. <Grid container spacing={1}>
  341. <Grid item xs={6}>
  342. <LocalizationProvider dateAdapter={AdapterDayjs}>
  343. <DemoItem components={['DatePicker']}>
  344. <DatePicker
  345. id="dueDateFrom"
  346. // onError={(newError) => setReceiptFromError(newError)}
  347. slotProps={{
  348. field: { readOnly: true, },
  349. textField: {
  350. // helperText: receiptFromErrorMessage,
  351. InputLabelProps: { shrink: true }
  352. },
  353. }}
  354. format="DD/MM/YYYY"
  355. label={"Due Date (From)"}
  356. value={minDueDate === null ? null : dayjs(minDueDate)}
  357. maxDate={maxDueDate === null ? null : dayjs(maxDueDate)}
  358. onChange={(newValue) => {
  359. // console.log(newValue)
  360. setMinDueDate(newValue);
  361. }}
  362. />
  363. </DemoItem >
  364. </LocalizationProvider>
  365. </Grid>
  366. <Grid item xs={6}>
  367. <LocalizationProvider dateAdapter={AdapterDayjs}>
  368. <DemoItem components={['DatePicker']}>
  369. <DatePicker
  370. id="dueDateTo"
  371. // onError={(newError) => setReceiptFromError(newError)}
  372. slotProps={{
  373. field: { readOnly: true, },
  374. textField: {
  375. // helperText: receiptFromErrorMessage,
  376. InputLabelProps: { shrink: true }
  377. },
  378. }}
  379. format="DD/MM/YYYY"
  380. label={"Due Date (To)"}
  381. value={maxDueDate === null ? null : dayjs(maxDueDate)}
  382. minDate={minDueDate === null ? null : dayjs(minDueDate)}
  383. onChange={(newValue) => {
  384. // console.log(newValue)
  385. setMaxDueDate(newValue);
  386. }}
  387. />
  388. </DemoItem >
  389. </LocalizationProvider>
  390. </Grid>
  391. </Grid>
  392. </Grid>
  393. <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}>
  394. <Autocomplete
  395. size="small"
  396. {...register("status")}
  397. id="status"
  398. options={ComboData.denmandNoteStatus}
  399. value={selectedStatus}
  400. onChange={(event, newValue) => {
  401. if(newValue==null){
  402. setSelectedStatus(ComboData.denmandNoteStatus[0]);
  403. }else{
  404. setSelectedStatus(newValue);
  405. }
  406. }}
  407. sx={{
  408. '& .MuiInputBase-root': { alignItems: 'center' },
  409. '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' },
  410. '& .MuiOutlinedInput-root': { height: 40 }
  411. }}
  412. getOptionLabel={(option) => (option?.label != null ? String(option.label) : "")}
  413. renderInput={(params) => (
  414. <TextField
  415. {...params}
  416. label="Status"
  417. InputLabelProps={{
  418. shrink: true
  419. }}
  420. />
  421. )}
  422. clearText={intl.formatMessage({ id: "muiClear" })}
  423. closeText={intl.formatMessage({ id: "muiClose" })}
  424. openText={intl.formatMessage({ id: "muiOpen" })}
  425. noOptionsText={intl.formatMessage({ id: "muiNoOptions" })}
  426. />
  427. </Grid>
  428. </Grid>
  429. {/*last row*/}
  430. <Grid container maxWidth justifyContent="flex-end">
  431. <ThemeProvider theme={PNSPS_BUTTON_THEME}>
  432. <Grid item sx={{ ml: 3, mb:3 }}>
  433. <Button
  434. variant="contained"
  435. color="cancel"
  436. onClick={resetForm}
  437. >
  438. Reset
  439. </Button>
  440. </Grid>
  441. <Grid item sx={{ ml: 3, mr: 3, mb:3}}>
  442. <Button
  443. variant="contained"
  444. type="submit"
  445. disabled={onGridReady}
  446. >
  447. Submit
  448. </Button>
  449. </Grid>
  450. </ThemeProvider>
  451. </Grid>
  452. </Grid>
  453. </form>
  454. </MainCard>
  455. );
  456. };
  457. export default SearchDemandNoteForm;