|
|
|
@@ -15,7 +15,7 @@ import CardActions from "@mui/material/CardActions"; |
|
|
|
import Button from "@mui/material/Button"; |
|
|
|
import RestartAlt from "@mui/icons-material/RestartAlt"; |
|
|
|
import Search from "@mui/icons-material/Search"; |
|
|
|
import dayjs from "dayjs"; |
|
|
|
import dayjs, { Dayjs } from "dayjs"; |
|
|
|
import "dayjs/locale/zh-hk"; |
|
|
|
import { DatePicker } from "@mui/x-date-pickers/DatePicker"; |
|
|
|
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; |
|
|
|
@@ -29,6 +29,8 @@ import { |
|
|
|
} from "@mui/material"; |
|
|
|
import MultiSelect from "@/components/SearchBox/MultiSelect"; |
|
|
|
import { intersectionWith } from "lodash"; |
|
|
|
import { INPUT_DATE_FORMAT, INPUT_TIME_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dayjsToDateTimeString } from "@/app/utils/formatUtil"; |
|
|
|
import { DateTimePicker } from "@mui/x-date-pickers"; |
|
|
|
|
|
|
|
interface BaseCriterion<T extends string> { |
|
|
|
label: string; |
|
|
|
@@ -86,6 +88,10 @@ interface DateRangeCriterion<T extends string> extends BaseCriterion<T> { |
|
|
|
type: "dateRange"; |
|
|
|
} |
|
|
|
|
|
|
|
interface DatetimeRangeCriterion<T extends string> extends BaseCriterion<T> { |
|
|
|
type: "datetimeRange"; |
|
|
|
} |
|
|
|
|
|
|
|
interface DateCriterion<T extends string> extends BaseCriterion<T> { |
|
|
|
type: "date"; |
|
|
|
} |
|
|
|
@@ -95,6 +101,7 @@ export type Criterion<T extends string> = |
|
|
|
| SelectCriterion<T> |
|
|
|
| SelectWithLabelCriterion<T> |
|
|
|
| DateRangeCriterion<T> |
|
|
|
| DatetimeRangeCriterion<T> |
|
|
|
| DateCriterion<T> |
|
|
|
| MultiSelectCriterion<T> |
|
|
|
| AutocompleteCriterion<T>; |
|
|
|
@@ -135,7 +142,7 @@ function SearchBox<T extends string>({ |
|
|
|
: "", |
|
|
|
}; |
|
|
|
|
|
|
|
if (c.type === "dateRange") { |
|
|
|
if (c.type === "dateRange" || c.type === "datetimeRange") { |
|
|
|
tempCriteria = { |
|
|
|
...tempCriteria, |
|
|
|
[c.paramName]: c.defaultValue ?? "", |
|
|
|
@@ -216,6 +223,24 @@ function SearchBox<T extends string>({ |
|
|
|
}; |
|
|
|
}, []); |
|
|
|
|
|
|
|
const makeDatetimeChangeHandler = useCallback((paramName: T) => { |
|
|
|
return (value: Dayjs | null) => { |
|
|
|
setInputs((i) => ({ |
|
|
|
...i, |
|
|
|
[paramName]: value ? dayjsToDateTimeString(value) : null |
|
|
|
})); |
|
|
|
}; |
|
|
|
}, []); |
|
|
|
|
|
|
|
const makeDatetimeToChangeHandler = useCallback((paramName: T) => { |
|
|
|
return (value: Dayjs | null) => { |
|
|
|
setInputs((i) => ({ |
|
|
|
...i, |
|
|
|
[paramName + "To"]: value ? dayjsToDateTimeString(value) : null |
|
|
|
})); |
|
|
|
}; |
|
|
|
}, []); |
|
|
|
|
|
|
|
const handleReset = () => { |
|
|
|
setInputs(defaultInputs); |
|
|
|
onReset?.(); |
|
|
|
@@ -397,6 +422,7 @@ function SearchBox<T extends string>({ |
|
|
|
<Box display="flex"> |
|
|
|
<FormControl fullWidth> |
|
|
|
<DatePicker |
|
|
|
format={`${OUTPUT_DATE_FORMAT}`} |
|
|
|
label={t(c.label)} |
|
|
|
onChange={makeDateChangeHandler(c.paramName)} |
|
|
|
value={ |
|
|
|
@@ -416,6 +442,7 @@ function SearchBox<T extends string>({ |
|
|
|
</Box> |
|
|
|
<FormControl fullWidth> |
|
|
|
<DatePicker |
|
|
|
format={`${OUTPUT_DATE_FORMAT}`} |
|
|
|
label={c.label2 ? t(c.label2) : null} |
|
|
|
onChange={makeDateToChangeHandler(c.paramName)} |
|
|
|
value={ |
|
|
|
@@ -428,6 +455,50 @@ function SearchBox<T extends string>({ |
|
|
|
</Box> |
|
|
|
</LocalizationProvider> |
|
|
|
)} |
|
|
|
{c.type === "datetimeRange" && ( |
|
|
|
<LocalizationProvider |
|
|
|
dateAdapter={AdapterDayjs} |
|
|
|
// TODO: Should maybe use a custom adapterLocale here to support YYYY-MM-DD |
|
|
|
adapterLocale="zh-hk" |
|
|
|
> |
|
|
|
<Box display="flex"> |
|
|
|
<FormControl fullWidth> |
|
|
|
<DateTimePicker |
|
|
|
views={['year','month','day','hours', 'minutes', 'seconds']} |
|
|
|
format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} |
|
|
|
label={t(c.label)} |
|
|
|
onChange={makeDatetimeChangeHandler(c.paramName)} |
|
|
|
value={ |
|
|
|
dayjs(inputs[c.paramName]).isValid() |
|
|
|
? dayjs(inputs[c.paramName]) |
|
|
|
: null |
|
|
|
} |
|
|
|
/> |
|
|
|
</FormControl> |
|
|
|
<Box |
|
|
|
display="flex" |
|
|
|
alignItems="center" |
|
|
|
justifyContent="center" |
|
|
|
marginInline={2} |
|
|
|
> |
|
|
|
{"-"} |
|
|
|
</Box> |
|
|
|
<FormControl fullWidth> |
|
|
|
<DateTimePicker |
|
|
|
views={['year','month','day','hours', 'minutes', 'seconds']} |
|
|
|
format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} |
|
|
|
label={c.label2 ? t(c.label2) : null} |
|
|
|
onChange={makeDatetimeToChangeHandler(c.paramName)} |
|
|
|
value={ |
|
|
|
dayjs(inputs[`${c.paramName}To`]).isValid() |
|
|
|
? dayjs(inputs[`${c.paramName}To`]) |
|
|
|
: null |
|
|
|
} |
|
|
|
/> |
|
|
|
</FormControl> |
|
|
|
</Box> |
|
|
|
</LocalizationProvider> |
|
|
|
)} |
|
|
|
{c.type === "date" && ( |
|
|
|
<LocalizationProvider |
|
|
|
dateAdapter={AdapterDayjs} |
|
|
|
@@ -437,6 +508,7 @@ function SearchBox<T extends string>({ |
|
|
|
<Box display="flex"> |
|
|
|
<FormControl fullWidth> |
|
|
|
<DatePicker |
|
|
|
format={`${OUTPUT_DATE_FORMAT}`} |
|
|
|
label={t(c.label)} |
|
|
|
onChange={makeDateChangeHandler(c.paramName)} |
|
|
|
/> |
|
|
|
|