trithuc-mvc-react 1.6.12 → 1.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/DataManagement/DataTable.jsx +1 -1
- package/components/DataManagement/EditorForm.jsx +13 -6
- package/components/DataManagement/FilterGod.jsx +19 -17
- package/components/date/DateRangePicker.jsx +154 -111
- package/components/date/StaticDateRangePicker.jsx +258 -294
- package/components/date/context.js +0 -0
- package/components/date/index.jsx +64 -0
- package/package.json +1 -1
- package/styles/index.css +0 -275
- package/components/date/index.js +0 -1
|
@@ -44,8 +44,7 @@ function EditorForm({ fields, submitRef }) {
|
|
|
44
44
|
if (typeof fileValue == "string") {
|
|
45
45
|
fileValue = JSON.parse(fileValue);
|
|
46
46
|
}
|
|
47
|
-
}
|
|
48
|
-
catch (e) {
|
|
47
|
+
} catch (e) {
|
|
49
48
|
fileValue = [];
|
|
50
49
|
}
|
|
51
50
|
setValue(field, fileValue);
|
|
@@ -54,7 +53,13 @@ function EditorForm({ fields, submitRef }) {
|
|
|
54
53
|
}
|
|
55
54
|
});
|
|
56
55
|
} else {
|
|
57
|
-
fields.forEach(({ field, defaultValue, type }) => {
|
|
56
|
+
fields.forEach(({ field, defaultValue, type, keyValue, onChange }) => {
|
|
57
|
+
if (type == "autocomplete" && defaultValue) {
|
|
58
|
+
onChange?.({
|
|
59
|
+
[keyValue]: defaultValue
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
58
63
|
if (type === "switch" && defaultValue === undefined) {
|
|
59
64
|
methods.setValue(field, true);
|
|
60
65
|
} else {
|
|
@@ -62,7 +67,6 @@ function EditorForm({ fields, submitRef }) {
|
|
|
62
67
|
}
|
|
63
68
|
});
|
|
64
69
|
}
|
|
65
|
-
|
|
66
70
|
}, [selectedEditItem]);
|
|
67
71
|
|
|
68
72
|
const saveMutation = useMutation(saveDataToTable, {
|
|
@@ -109,9 +113,12 @@ function EditorForm({ fields, submitRef }) {
|
|
|
109
113
|
}
|
|
110
114
|
});
|
|
111
115
|
};
|
|
116
|
+
const onValid = (data) => {
|
|
117
|
+
console.log(data);
|
|
118
|
+
};
|
|
112
119
|
return (
|
|
113
120
|
<FormProvider {...methods}>
|
|
114
|
-
<Box component={"form"} onSubmit={methods.handleSubmit(onSubmit)}>
|
|
121
|
+
<Box component={"form"} onSubmit={methods.handleSubmit(onSubmit, onValid)}>
|
|
115
122
|
<Grid container spacing={2}>
|
|
116
123
|
{fields.map(
|
|
117
124
|
({
|
|
@@ -122,7 +129,7 @@ function EditorForm({ fields, submitRef }) {
|
|
|
122
129
|
childrenFields,
|
|
123
130
|
datas,
|
|
124
131
|
loading = false,
|
|
125
|
-
onChange = () => {
|
|
132
|
+
onChange = () => {},
|
|
126
133
|
keyLabel,
|
|
127
134
|
keyValue,
|
|
128
135
|
keyValueLabel,
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { Accordion, AccordionSummary, Box,
|
|
1
|
+
import { Accordion, AccordionSummary, Box, Slider, Typography } from "@mui/material";
|
|
2
2
|
import { useFormContext } from "react-hook-form";
|
|
3
3
|
import Grid from "@mui/material/Unstable_Grid2";
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
import { FilterElement } from "./FilterElement";
|
|
6
6
|
import { useDataTable } from "./hooks";
|
|
7
7
|
|
|
8
|
-
import AccordionDetails from
|
|
9
|
-
import ExpandMoreIcon from
|
|
8
|
+
import AccordionDetails from "@mui/material/AccordionDetails";
|
|
9
|
+
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|
10
|
+
import { DateRangePicker } from "../date";
|
|
11
|
+
import { ArraySchema } from "yup";
|
|
10
12
|
|
|
11
13
|
export const FilterGod = ({ filters, elementSize = "small" }) => {
|
|
12
14
|
const { handleSubmit } = useFormContext();
|
|
@@ -14,15 +16,12 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
|
|
|
14
16
|
const { setDataSearch, dataSearch } = useDataTable();
|
|
15
17
|
|
|
16
18
|
return (
|
|
17
|
-
<Box
|
|
18
|
-
component={"form"}
|
|
19
|
-
onSubmit={handleSubmit(onSubmit)}
|
|
20
|
-
>
|
|
19
|
+
<Box component={"form"} onSubmit={handleSubmit(onSubmit)}>
|
|
21
20
|
<Accordion>
|
|
22
21
|
<AccordionSummary
|
|
23
22
|
sx={{
|
|
24
23
|
minHeight: 40,
|
|
25
|
-
|
|
24
|
+
"& .MuiAccordionSummary-content": {
|
|
26
25
|
my: 1
|
|
27
26
|
}
|
|
28
27
|
}}
|
|
@@ -36,15 +35,21 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
|
|
|
36
35
|
<Grid container spacing={1}>
|
|
37
36
|
{filters.map(({ field, size, ...rest }) => {
|
|
38
37
|
if (rest.type === "date-range") {
|
|
38
|
+
let label = ["từ ngày", "tới ngày"];
|
|
39
|
+
|
|
40
|
+
if (Array.isArray(field.label)) {
|
|
41
|
+
label = field.label;
|
|
42
|
+
}
|
|
39
43
|
return (
|
|
40
44
|
<Grid key={field.toString()} md={size?.md} xs={size?.xs} sm={size?.sm}>
|
|
41
45
|
<DateRangePicker
|
|
46
|
+
label={label}
|
|
42
47
|
onChange={(value) => {
|
|
43
|
-
setDataSearch(
|
|
44
|
-
...
|
|
48
|
+
setDataSearch({
|
|
49
|
+
...dataSearch,
|
|
45
50
|
[field[0]]: value[0],
|
|
46
51
|
[field[1]]: value[1]
|
|
47
|
-
})
|
|
52
|
+
});
|
|
48
53
|
}}
|
|
49
54
|
size={elementSize}
|
|
50
55
|
value={[dataSearch?.[field[0]], dataSearch?.[field[1]]]}
|
|
@@ -55,10 +60,7 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
|
|
|
55
60
|
|
|
56
61
|
if (rest.type === "slider-range") {
|
|
57
62
|
return (
|
|
58
|
-
<Grid
|
|
59
|
-
key={field.toString()}
|
|
60
|
-
md={size?.md} xs={size?.xs} sm={size?.sm}
|
|
61
|
-
>
|
|
63
|
+
<Grid key={field.toString()} md={size?.md} xs={size?.xs} sm={size?.sm}>
|
|
62
64
|
<Slider
|
|
63
65
|
onChange={(e, value) => {
|
|
64
66
|
setDataSearch({
|
|
@@ -78,7 +80,7 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
|
|
|
78
80
|
);
|
|
79
81
|
}
|
|
80
82
|
return (
|
|
81
|
-
<Grid key={field} md={size?.md} xs={size?.xs} sm={size?.sm}
|
|
83
|
+
<Grid key={field} md={size?.md} xs={size?.xs} sm={size?.sm}>
|
|
82
84
|
<FilterElement name={field} {...rest} size={elementSize} />
|
|
83
85
|
</Grid>
|
|
84
86
|
);
|
|
@@ -5,139 +5,182 @@ import StaticDateRangePicker from "./StaticDateRangePicker";
|
|
|
5
5
|
import moment from "moment";
|
|
6
6
|
import { memo, useEffect, useRef, useState } from "react";
|
|
7
7
|
import * as dateFns from "date-fns";
|
|
8
|
+
import { useTheme, useMediaQuery } from "@mui/material";
|
|
9
|
+
import { useDateRangeContext } from ".";
|
|
10
|
+
let timeoutStart = null;
|
|
11
|
+
let timeoutEnd = null;
|
|
12
|
+
let timeoutProper = null;
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
const DateRangePicker = ({ onChange = () => {}, value }) => {
|
|
14
|
+
const DateRangePicker = ({ label = ["Từ ngày", "Đến ngày"] }) => {
|
|
11
15
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
16
|
+
const { dateRange, setDateRange, setIsFocusStart, setIsFocusEnd, isFocusStart, isFocusEnd, setIsFocusPoper, isFocusPoper } =
|
|
17
|
+
useDateRangeContext();
|
|
12
18
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
const handleFocus1 = (event) => {
|
|
20
|
+
if (timeoutStart) {
|
|
21
|
+
clearTimeout(timeoutStart);
|
|
22
|
+
}
|
|
23
|
+
setIsFocusStart(true);
|
|
24
|
+
setAnchorEl(containerRef.current);
|
|
25
|
+
};
|
|
26
|
+
const handleFocus2 = (event) => {
|
|
27
|
+
if (timeoutEnd) {
|
|
28
|
+
clearTimeout(timeoutEnd);
|
|
29
|
+
}
|
|
30
|
+
setIsFocusEnd(true);
|
|
31
|
+
setAnchorEl(containerRef.current);
|
|
32
|
+
};
|
|
33
|
+
const handleBlur1 = (event) => {
|
|
34
|
+
if (timeoutStart) {
|
|
35
|
+
clearTimeout(timeoutStart);
|
|
36
|
+
}
|
|
37
|
+
timeoutStart = setTimeout(() => {
|
|
38
|
+
setIsFocusStart(false);
|
|
39
|
+
}, 300);
|
|
40
|
+
// setIsFocusStart(false);
|
|
19
41
|
setAnchorEl(containerRef.current);
|
|
20
42
|
};
|
|
43
|
+
const handleBlur2 = (event) => {
|
|
44
|
+
if (timeoutEnd) {
|
|
45
|
+
clearTimeout(timeoutEnd);
|
|
46
|
+
}
|
|
47
|
+
setAnchorEl(containerRef.current);
|
|
48
|
+
timeoutEnd = setTimeout(() => {
|
|
49
|
+
setIsFocusEnd(false);
|
|
50
|
+
}, 300);
|
|
51
|
+
};
|
|
21
52
|
const handleClose = () => {
|
|
22
53
|
setAnchorEl(null);
|
|
23
54
|
};
|
|
24
|
-
const handleClickAway = () => {
|
|
25
|
-
|
|
55
|
+
const handleClickAway = (e) => {
|
|
56
|
+
timeoutProper = setTimeout(() => {
|
|
57
|
+
setIsFocusPoper(false);
|
|
58
|
+
}, 500);
|
|
59
|
+
};
|
|
60
|
+
const handleClickPopper = (e) => {
|
|
61
|
+
if (timeoutProper) {
|
|
62
|
+
clearTimeout(timeoutProper);
|
|
63
|
+
}
|
|
64
|
+
if (!isFocusPoper) {
|
|
65
|
+
setIsFocusPoper(true);
|
|
66
|
+
}
|
|
26
67
|
};
|
|
27
68
|
|
|
28
|
-
const open =
|
|
69
|
+
const open = isFocusStart || isFocusEnd || isFocusPoper;
|
|
70
|
+
|
|
71
|
+
// console.log("open", open);
|
|
29
72
|
const containerRef = useRef(null);
|
|
73
|
+
const theme = useTheme();
|
|
74
|
+
const downXl = useMediaQuery(theme.breakpoints.down("xl"));
|
|
75
|
+
const elementSize = downXl ? "small" : "medium";
|
|
30
76
|
|
|
31
77
|
useEffect(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
78
|
+
setAnchorEl(containerRef.current);
|
|
79
|
+
}, []);
|
|
80
|
+
// useEffect(() => {
|
|
81
|
+
// console.log("CHANGEEEE");
|
|
82
|
+
// }, [isFocusStart, isFocusEnd]);
|
|
83
|
+
// useEffect(() => {
|
|
84
|
+
// if (dateFns.isBefore(dateRange.startDate, dateRange.endDate) || dateFns.isSameDay(dateRange.startDate, dateRange.endDate)) {
|
|
85
|
+
// onChange([dateRange.startDate, dateRange.endDate]);
|
|
86
|
+
// }
|
|
87
|
+
// }, [dateRange]);
|
|
36
88
|
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}, [value]);
|
|
89
|
+
// useEffect(() => {
|
|
90
|
+
// if (!value) return;
|
|
91
|
+
// if (dateFns.isSameDay(dateRange.startDate, value[0]) && dateFns.isSameDay(dateRange.endDate, value[1])) {
|
|
92
|
+
// return;
|
|
93
|
+
// }
|
|
94
|
+
// setDateRange({
|
|
95
|
+
// startDate: value?.[0],
|
|
96
|
+
// endDate: value?.[1]
|
|
97
|
+
// });
|
|
98
|
+
// }, [value]);
|
|
47
99
|
|
|
48
100
|
return (
|
|
49
101
|
<>
|
|
102
|
+
<Stack ref={containerRef} direction={"row"} alignContent={"center"} spacing={1}>
|
|
103
|
+
<DateField
|
|
104
|
+
sx={{ flex: 1 }}
|
|
105
|
+
format={DEFAULT_DATE_FORMAT}
|
|
106
|
+
onFocus={handleFocus1}
|
|
107
|
+
onBlur={handleBlur1}
|
|
108
|
+
label={label[0]}
|
|
109
|
+
onChange={(value) => {
|
|
110
|
+
setDateRange((d) => ({
|
|
111
|
+
...d,
|
|
112
|
+
startDate: value ? value.toDate() : null
|
|
113
|
+
}));
|
|
114
|
+
}}
|
|
115
|
+
value={dateRange.startDate && moment(dateRange.startDate)}
|
|
116
|
+
size={elementSize}
|
|
117
|
+
maxDate={dateRange.endDate ?? moment(dateRange.endDate)}
|
|
118
|
+
/>
|
|
119
|
+
<Typography variant="body1" sx={{ height: "24px", alignSelf: "center" }}>
|
|
120
|
+
–
|
|
121
|
+
</Typography>
|
|
122
|
+
<DateField
|
|
123
|
+
sx={{ flex: 1 }}
|
|
124
|
+
format={DEFAULT_DATE_FORMAT}
|
|
125
|
+
label={label[1]}
|
|
126
|
+
onFocus={handleFocus2}
|
|
127
|
+
onBlur={handleBlur2}
|
|
128
|
+
onChange={(value) => {
|
|
129
|
+
setDateRange((d) => ({
|
|
130
|
+
...d,
|
|
131
|
+
endDate: value ? value.toDate() : null
|
|
132
|
+
}));
|
|
133
|
+
}}
|
|
134
|
+
value={dateRange.endDate && moment(dateRange.endDate)}
|
|
135
|
+
size={elementSize}
|
|
136
|
+
minDate={dateRange.startDate ?? moment(dateRange.startDate)}
|
|
137
|
+
/>
|
|
138
|
+
</Stack>
|
|
50
139
|
<ClickAwayListener onClickAway={handleClickAway}>
|
|
51
|
-
<
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}));
|
|
62
|
-
}}
|
|
63
|
-
value={dateRange.startDate && moment(dateRange.startDate)}
|
|
64
|
-
size="small"
|
|
65
|
-
maxDate={dateRange.endDate ?? moment(dateRange.endDate)}
|
|
66
|
-
/>
|
|
67
|
-
<Typography variant="body1" sx={{ height: "24px", alignSelf: "center" }}>
|
|
68
|
-
–
|
|
69
|
-
</Typography>
|
|
70
|
-
<DateField
|
|
71
|
-
sx={{ flex: 1 }}
|
|
72
|
-
format={DEFAULT_DATE_FORMAT}
|
|
73
|
-
label="Tới ngày"
|
|
74
|
-
onFocus={handleFocus}
|
|
75
|
-
onChange={(value) => {
|
|
76
|
-
setDateRange((d) => ({
|
|
77
|
-
...d,
|
|
78
|
-
endDate: value.toDate()
|
|
79
|
-
}));
|
|
80
|
-
|
|
81
|
-
}}
|
|
82
|
-
value={dateRange.endDate && moment(dateRange.endDate)}
|
|
83
|
-
size="small"
|
|
84
|
-
minDate={dateRange.startDate ?? moment(dateRange.startDate)}
|
|
85
|
-
/>
|
|
140
|
+
<Popper
|
|
141
|
+
sx={{
|
|
142
|
+
zIndex: 1036
|
|
143
|
+
}}
|
|
144
|
+
keepMounted
|
|
145
|
+
placement="bottom-start"
|
|
146
|
+
open={open}
|
|
147
|
+
anchorEl={anchorEl}
|
|
148
|
+
onClose={handleClose}
|
|
149
|
+
onClick={handleClickPopper}
|
|
86
150
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
151
|
+
// modifiers={[
|
|
152
|
+
// {
|
|
153
|
+
// name: "flip",
|
|
154
|
+
// enabled: true,
|
|
155
|
+
// options: {
|
|
156
|
+
// altBoundary: true,
|
|
157
|
+
// rootBoundary: "viewport",
|
|
158
|
+
// padding: 8
|
|
159
|
+
// }
|
|
160
|
+
// },
|
|
161
|
+
// {
|
|
162
|
+
// name: "preventOverflow",
|
|
163
|
+
// enabled: true,
|
|
164
|
+
// options: {
|
|
165
|
+
// altAxis: true,
|
|
166
|
+
// altBoundary: true,
|
|
167
|
+
// tether: true,
|
|
168
|
+
// rootBoundary: "document",
|
|
169
|
+
// padding: 8
|
|
170
|
+
// }
|
|
171
|
+
// }
|
|
172
|
+
// ]}
|
|
173
|
+
>
|
|
174
|
+
<StaticDateRangePicker
|
|
175
|
+
value={dateRange}
|
|
176
|
+
onUpdate={(value) => {
|
|
177
|
+
setDateRange(value);
|
|
90
178
|
}}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
open={open}
|
|
94
|
-
anchorEl={anchorEl}
|
|
95
|
-
onClose={handleClose}
|
|
96
|
-
disablePortal={false}
|
|
97
|
-
modifiers={[
|
|
98
|
-
{
|
|
99
|
-
name: "flip",
|
|
100
|
-
enabled: true,
|
|
101
|
-
options: {
|
|
102
|
-
altBoundary: true,
|
|
103
|
-
rootBoundary: "viewport",
|
|
104
|
-
padding: 8
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
name: "preventOverflow",
|
|
109
|
-
enabled: true,
|
|
110
|
-
options: {
|
|
111
|
-
altAxis: true,
|
|
112
|
-
altBoundary: true,
|
|
113
|
-
tether: true,
|
|
114
|
-
rootBoundary: "document",
|
|
115
|
-
padding: 8
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
]}
|
|
119
|
-
>
|
|
120
|
-
<StaticDateRangePicker
|
|
121
|
-
value={dateRange}
|
|
122
|
-
onUpdate={(value) => {
|
|
123
|
-
setDateRange(value);
|
|
124
|
-
}}
|
|
125
|
-
/>
|
|
126
|
-
</Popper>
|
|
127
|
-
</Stack>
|
|
179
|
+
/>
|
|
180
|
+
</Popper>
|
|
128
181
|
</ClickAwayListener>
|
|
129
182
|
</>
|
|
130
183
|
);
|
|
131
184
|
};
|
|
132
|
-
const DateRangePickerMemo = memo(DateRangePicker, (prevProps, nextProps) => {
|
|
133
|
-
try {
|
|
134
|
-
if (dateFns.isSameDay(prevProps.value[0], nextProps.value[0]) && dateFns.isSameDay(prevProps.value[1], nextProps.value[1])) {
|
|
135
|
-
return true; // props are equal
|
|
136
|
-
}
|
|
137
|
-
} catch (error) {
|
|
138
|
-
console.log(error);
|
|
139
|
-
}
|
|
140
185
|
|
|
141
|
-
|
|
142
|
-
});
|
|
143
|
-
export default DateRangePickerMemo;
|
|
186
|
+
export default DateRangePicker;
|