trithuc-mvc-react 3.1.9 → 3.2.1
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Accordion, AccordionSummary, Box, IconButton, Slider, Typography } from "@mui/material";
|
|
1
|
+
import { Accordion, AccordionSummary, Box, Button, IconButton, Slider, Typography } from "@mui/material";
|
|
2
2
|
import { Grid } from "@mui/material";
|
|
3
3
|
import { useFormContext } from "react-hook-form";
|
|
4
4
|
import { FilterElement } from "./FilterElement";
|
|
@@ -14,7 +14,7 @@ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
|
|
|
14
14
|
import "dayjs/locale/vi";
|
|
15
15
|
import { toast } from "react-toastify";
|
|
16
16
|
import { debounce } from "lodash";
|
|
17
|
-
export const FilterGod = ({ tableName, filters, elementSize = "small", setPage = () => {} }) => {
|
|
17
|
+
export const FilterGod = ({ tableName, filters, filterButtons, elementSize = "small", setPage = () => {} }) => {
|
|
18
18
|
const { handleSubmit } = useFormContext();
|
|
19
19
|
const onSubmit = (data) => console.log(data);
|
|
20
20
|
const { setDataSearch, dataSearch } = useDataTable();
|
|
@@ -54,10 +54,9 @@ export const FilterGod = ({ tableName, filters, elementSize = "small", setPage =
|
|
|
54
54
|
|
|
55
55
|
<AccordionDetails>
|
|
56
56
|
<Grid container spacing={1}>
|
|
57
|
-
{filters.map(({ field, size, ...rest }) => {
|
|
57
|
+
{filters.map(({ field, label, size, ...rest }) => {
|
|
58
58
|
if (rest.type === "date-range") {
|
|
59
|
-
const [label1, label2] = Array.isArray(
|
|
60
|
-
|
|
59
|
+
const [label1, label2] = Array.isArray(label) ? label : ["Từ ngày", "Đến ngày"];
|
|
61
60
|
const handleClear = (key) => {
|
|
62
61
|
setDataSearch((prev) => ({
|
|
63
62
|
...prev,
|
|
@@ -188,6 +187,18 @@ export const FilterGod = ({ tableName, filters, elementSize = "small", setPage =
|
|
|
188
187
|
</Grid>
|
|
189
188
|
);
|
|
190
189
|
})}
|
|
190
|
+
{filterButtons.map(({ title, size, onClick, element, sx }, idx) => (
|
|
191
|
+
<Button
|
|
192
|
+
key={idx}
|
|
193
|
+
size={size}
|
|
194
|
+
variant="outlined"
|
|
195
|
+
onClick={() => onClick({ dataSearch })}
|
|
196
|
+
startIcon={element}
|
|
197
|
+
sx={{ ...sx }}
|
|
198
|
+
>
|
|
199
|
+
{title}
|
|
200
|
+
</Button>
|
|
201
|
+
))}
|
|
191
202
|
</Grid>
|
|
192
203
|
</AccordionDetails>
|
|
193
204
|
</Accordion>
|
|
@@ -50,7 +50,7 @@ DataManagement.propTypes = {
|
|
|
50
50
|
onChangeAfter: PropTypes.func
|
|
51
51
|
})
|
|
52
52
|
).isRequired,
|
|
53
|
-
|
|
53
|
+
filterButtons: PropTypes.array,
|
|
54
54
|
editorFields: PropTypes.array,
|
|
55
55
|
validationSchema: PropTypes.object,
|
|
56
56
|
disableStatus: PropTypes.bool,
|
|
@@ -65,7 +65,8 @@ DataManagement.propTypes = {
|
|
|
65
65
|
tabPanel: PropTypes.node,
|
|
66
66
|
titleAddButton: PropTypes.string,
|
|
67
67
|
thongKe: PropTypes.object,
|
|
68
|
-
bieuDo: PropTypes.object
|
|
68
|
+
bieuDo: PropTypes.object,
|
|
69
|
+
disableHead: PropTypes.bool
|
|
69
70
|
};
|
|
70
71
|
const getDefaultValues = (filters = []) => {
|
|
71
72
|
const defaultValues = {};
|
|
@@ -84,6 +85,7 @@ function DataManagement({
|
|
|
84
85
|
tableName,
|
|
85
86
|
selectedField = "Id",
|
|
86
87
|
filters: tableFilters = [],
|
|
88
|
+
filterButtons = [],
|
|
87
89
|
editorFields = [],
|
|
88
90
|
validationSchema = {},
|
|
89
91
|
statusKey = "Status",
|
|
@@ -108,7 +110,8 @@ function DataManagement({
|
|
|
108
110
|
defaultRowsPerPage = 5,
|
|
109
111
|
titleAddButton = "Thêm",
|
|
110
112
|
thongKe,
|
|
111
|
-
bieuDo
|
|
113
|
+
bieuDo,
|
|
114
|
+
disableHead = false
|
|
112
115
|
}) {
|
|
113
116
|
const [openEditorDialog, setOpenEditorDialog] = useState(false);
|
|
114
117
|
const [selectedEditItem, setSelectedEditItem] = useState(null);
|
|
@@ -177,7 +180,8 @@ function DataManagement({
|
|
|
177
180
|
defaultRowsPerPage,
|
|
178
181
|
titleAddButton,
|
|
179
182
|
thongKe,
|
|
180
|
-
bieuDo
|
|
183
|
+
bieuDo,
|
|
184
|
+
disableHead
|
|
181
185
|
};
|
|
182
186
|
}, [
|
|
183
187
|
reserPage,
|
|
@@ -198,7 +202,8 @@ function DataManagement({
|
|
|
198
202
|
backParentNavigator,
|
|
199
203
|
defaultRowsPerPage,
|
|
200
204
|
thongKe,
|
|
201
|
-
bieuDo
|
|
205
|
+
bieuDo,
|
|
206
|
+
disableHead
|
|
202
207
|
]);
|
|
203
208
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down("sm")); // Xác định màn hình nhỏ
|
|
204
209
|
const methods = useForm({ defaultValues: getDefaultValues(filters) });
|
|
@@ -297,130 +302,138 @@ function DataManagement({
|
|
|
297
302
|
<>
|
|
298
303
|
<DataTableContext.Provider value={values}>
|
|
299
304
|
<FormProvider {...methods}>
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
mb: upXL ? 1 : 1,
|
|
304
|
-
flexWrap: "wrap",
|
|
305
|
-
alignItems: "center",
|
|
306
|
-
gap: 1,
|
|
307
|
-
...slotProps?.header?.sx
|
|
308
|
-
}}
|
|
309
|
-
>
|
|
310
|
-
{/* Khối trái */}
|
|
311
|
-
<Box
|
|
312
|
-
sx={{
|
|
313
|
-
flexGrow: 1,
|
|
314
|
-
Width: `${minWidthValue}px`,
|
|
315
|
-
textAlign: "left",
|
|
316
|
-
whiteSpace: "normal",
|
|
317
|
-
wordBreak: "break-word"
|
|
318
|
-
}}
|
|
319
|
-
>
|
|
320
|
-
<Typography variant={isSmallScreen ? "body2" : "subtitle1"}>{titleText}</Typography>
|
|
321
|
-
</Box>
|
|
322
|
-
|
|
323
|
-
{/* Khối phải */}
|
|
324
|
-
<Box
|
|
325
|
-
ref={rightBoxRef} // Tham chiếu đến phần tử này
|
|
305
|
+
{!disableHead && (
|
|
306
|
+
<Stack
|
|
307
|
+
direction="row"
|
|
326
308
|
sx={{
|
|
327
|
-
|
|
328
|
-
flexWrap: "
|
|
329
|
-
justifyContent: "flex-end",
|
|
309
|
+
mb: upXL ? 1 : 1,
|
|
310
|
+
flexWrap: "wrap",
|
|
330
311
|
alignItems: "center",
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
width: rightBoxMinWidth ? `${rightBoxMinWidth}px` : "auto" // Sử dụng chiều rộng đo được
|
|
312
|
+
gap: 1,
|
|
313
|
+
...slotProps?.header?.sx
|
|
334
314
|
}}
|
|
335
315
|
>
|
|
336
|
-
{
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
316
|
+
{/* Khối trái */}
|
|
317
|
+
<Box
|
|
318
|
+
sx={{
|
|
319
|
+
flexGrow: 1,
|
|
320
|
+
Width: `${minWidthValue}px`,
|
|
321
|
+
textAlign: "left",
|
|
322
|
+
whiteSpace: "normal",
|
|
323
|
+
wordBreak: "break-word"
|
|
324
|
+
}}
|
|
325
|
+
>
|
|
326
|
+
<Typography variant={isSmallScreen ? "body2" : "subtitle1"}>{titleText}</Typography>
|
|
327
|
+
</Box>
|
|
328
|
+
|
|
329
|
+
{/* Khối phải */}
|
|
330
|
+
<Box
|
|
331
|
+
ref={rightBoxRef} // Tham chiếu đến phần tử này
|
|
332
|
+
sx={{
|
|
333
|
+
display: "flex",
|
|
334
|
+
flexWrap: "nowrap",
|
|
335
|
+
justifyContent: "flex-end",
|
|
336
|
+
alignItems: "center",
|
|
337
|
+
flexShrink: 0,
|
|
338
|
+
// minWidth: "300px", // Đảm bảo chiều rộng tối thiểu
|
|
339
|
+
width: rightBoxMinWidth ? `${rightBoxMinWidth}px` : "auto" // Sử dụng chiều rộng đo được
|
|
340
|
+
}}
|
|
341
|
+
>
|
|
342
|
+
{(viewMode === "thongke" || viewMode === "bieudo") && (
|
|
343
|
+
<Tooltip title="Danh sách dữ liệu">
|
|
344
|
+
<IconButton size={elementSize} color="primary" onClick={() => setViewMode("table")} sx={{ ml: 0.5, mr: 0.5 }}>
|
|
345
|
+
<TableChartIcon fontSize="inherit" />
|
|
346
|
+
</IconButton>
|
|
347
|
+
</Tooltip>
|
|
348
|
+
)}
|
|
349
|
+
|
|
350
|
+
{canThongKe && (
|
|
351
|
+
<Tooltip title="Thống kê">
|
|
352
|
+
<IconButton
|
|
353
|
+
size={elementSize}
|
|
354
|
+
color={viewMode === "thongke" ? "secondary" : "primary"}
|
|
355
|
+
onClick={() => setViewMode("thongke")}
|
|
356
|
+
sx={{ ml: 0.5, mr: 0.5 }}
|
|
357
|
+
>
|
|
358
|
+
<BarChartIcon fontSize="inherit" />
|
|
359
|
+
</IconButton>
|
|
360
|
+
</Tooltip>
|
|
361
|
+
)}
|
|
362
|
+
|
|
363
|
+
{canBieuDo && (
|
|
364
|
+
<Tooltip title="Biểu đồ">
|
|
365
|
+
<IconButton
|
|
366
|
+
size={elementSize}
|
|
367
|
+
color={viewMode === "bieudo" ? "secondary" : "primary"}
|
|
368
|
+
onClick={() => setViewMode("bieudo")}
|
|
369
|
+
sx={{ ml: 0.5, mr: 0.5 }}
|
|
370
|
+
>
|
|
371
|
+
<PieChartIcon fontSize="inherit" />
|
|
372
|
+
</IconButton>
|
|
373
|
+
</Tooltip>
|
|
374
|
+
)}
|
|
343
375
|
|
|
344
|
-
|
|
345
|
-
<Tooltip title="
|
|
376
|
+
<HuongDanButton tableName={tableName} size={elementSize} />
|
|
377
|
+
<Tooltip title="Làm mới">
|
|
346
378
|
<IconButton
|
|
379
|
+
variant="outlined"
|
|
380
|
+
color="primary"
|
|
347
381
|
size={elementSize}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
382
|
+
onClick={() => {
|
|
383
|
+
setDataSearch({ ...defaults });
|
|
384
|
+
[...filters].forEach((filter) => {
|
|
385
|
+
filter?.onChange?.();
|
|
386
|
+
});
|
|
387
|
+
reset();
|
|
388
|
+
setValue("Search");
|
|
389
|
+
}}
|
|
351
390
|
>
|
|
352
|
-
<
|
|
391
|
+
<Refresh fontSize="inherit" />
|
|
353
392
|
</IconButton>
|
|
354
393
|
</Tooltip>
|
|
355
|
-
)}
|
|
356
394
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
395
|
+
{titleButtons?.map((button, index) => (
|
|
396
|
+
<div key={index}>{button}</div>
|
|
397
|
+
))}
|
|
398
|
+
|
|
399
|
+
<ExportExcelButton tableName={tableName} data={dataSearch} size={elementSize} />
|
|
400
|
+
|
|
401
|
+
{canCreate && !disableAdd && (
|
|
402
|
+
<Button
|
|
360
403
|
size={elementSize}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
404
|
+
variant="contained"
|
|
405
|
+
startIcon={<Add fontSize="inherit" />}
|
|
406
|
+
onClick={(e) => {
|
|
407
|
+
if (!disableEditor) {
|
|
408
|
+
setOpenEditorDialog(true);
|
|
409
|
+
setSelectedEditItem(null);
|
|
410
|
+
}
|
|
411
|
+
onAddClick(e);
|
|
412
|
+
}}
|
|
413
|
+
sx={{
|
|
414
|
+
ml: 0.5,
|
|
415
|
+
mr: 0.5,
|
|
416
|
+
minWidth: "73px"
|
|
417
|
+
}}
|
|
364
418
|
>
|
|
365
|
-
|
|
366
|
-
</
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
<Tooltip title="Làm mới">
|
|
372
|
-
<IconButton
|
|
373
|
-
variant="outlined"
|
|
374
|
-
color="primary"
|
|
375
|
-
size={elementSize}
|
|
376
|
-
onClick={() => {
|
|
377
|
-
setDataSearch({ ...defaults });
|
|
378
|
-
[...filters].forEach((filter) => {
|
|
379
|
-
filter?.onChange?.();
|
|
380
|
-
});
|
|
381
|
-
reset();
|
|
382
|
-
setValue("Search");
|
|
383
|
-
}}
|
|
384
|
-
>
|
|
385
|
-
<Refresh fontSize="inherit" />
|
|
386
|
-
</IconButton>
|
|
387
|
-
</Tooltip>
|
|
388
|
-
|
|
389
|
-
{titleButtons?.map((button, index) => (
|
|
390
|
-
<div key={index}>{button}</div>
|
|
391
|
-
))}
|
|
392
|
-
|
|
393
|
-
<ExportExcelButton tableName={tableName} data={dataSearch} size={elementSize} />
|
|
394
|
-
|
|
395
|
-
{canCreate && !disableAdd && (
|
|
396
|
-
<Button
|
|
397
|
-
size={elementSize}
|
|
398
|
-
variant="contained"
|
|
399
|
-
startIcon={<Add fontSize="inherit" />}
|
|
400
|
-
onClick={(e) => {
|
|
401
|
-
if (!disableEditor) {
|
|
402
|
-
setOpenEditorDialog(true);
|
|
403
|
-
setSelectedEditItem(null);
|
|
404
|
-
}
|
|
405
|
-
onAddClick(e);
|
|
406
|
-
}}
|
|
407
|
-
sx={{
|
|
408
|
-
ml: 0.5,
|
|
409
|
-
mr: 0.5,
|
|
410
|
-
minWidth: "73px"
|
|
411
|
-
}}
|
|
412
|
-
>
|
|
413
|
-
{titleAddButton}
|
|
414
|
-
</Button>
|
|
415
|
-
)}
|
|
416
|
-
</Box>
|
|
417
|
-
</Stack>
|
|
419
|
+
{titleAddButton}
|
|
420
|
+
</Button>
|
|
421
|
+
)}
|
|
422
|
+
</Box>
|
|
423
|
+
</Stack>
|
|
424
|
+
)}
|
|
418
425
|
|
|
419
426
|
<Card className="custom-card-DataManagement">
|
|
420
427
|
{tabPanel}
|
|
421
428
|
{viewMode === "table" && (
|
|
422
429
|
<>
|
|
423
|
-
<FilterGod
|
|
430
|
+
<FilterGod
|
|
431
|
+
tableName={tableName}
|
|
432
|
+
filters={filters}
|
|
433
|
+
filterButtons={filterButtons}
|
|
434
|
+
elementSize={elementSize}
|
|
435
|
+
setPage={setPage}
|
|
436
|
+
/>
|
|
424
437
|
{backParentNavigator}
|
|
425
438
|
{!isSmallScreen ? (
|
|
426
439
|
<DataTable
|
|
@@ -8,37 +8,77 @@ function defaultLabelDisplayedRows({ from, to, count }) {
|
|
|
8
8
|
function TablePaginationCustom({ count, rowsPerPage, page, onPageChange, onRowsPerPageChange, ...rest }) {
|
|
9
9
|
const theme = useTheme();
|
|
10
10
|
const matchsDownMD = useMediaQuery(theme.breakpoints.down("md"));
|
|
11
|
-
|
|
12
|
-
return (
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
11
|
+
const isSmallScreen = useMediaQuery(theme.breakpoints.down("sm"));
|
|
12
|
+
return !isSmallScreen ? (
|
|
13
|
+
<TablePagination
|
|
14
|
+
{...rest}
|
|
15
|
+
rowsPerPageOptions={[5, 10, 20, 25, 50, 100]}
|
|
16
|
+
component="div"
|
|
17
|
+
count={count}
|
|
18
|
+
rowsPerPage={rowsPerPage}
|
|
19
|
+
page={page}
|
|
20
|
+
onPageChange={onPageChange}
|
|
21
|
+
onRowsPerPageChange={onRowsPerPageChange}
|
|
22
|
+
showFirstButton
|
|
23
|
+
showLastButton
|
|
24
|
+
labelRowsPerPage={matchsDownMD ? "Số hàng" : "Số bản ghi trên trang:"}
|
|
25
|
+
labelDisplayedRows={defaultLabelDisplayedRows}
|
|
26
|
+
sx={{
|
|
27
|
+
width: "100%",
|
|
28
|
+
"& .MuiTablePagination-toolbar": {
|
|
29
|
+
justifyContent: "flex-end",
|
|
30
|
+
flexWrap: "wrap", // Cho nó xuống dòng nếu thiếu chỗ
|
|
31
|
+
paddingLeft: "8px",
|
|
32
|
+
paddingRight: "8px"
|
|
33
|
+
},
|
|
34
|
+
"& .MuiTablePagination-selectLabel, & .MuiTablePagination-displayedRows": {
|
|
35
|
+
fontSize: "0.7rem"
|
|
36
|
+
},
|
|
37
|
+
"& .MuiTablePagination-select": {
|
|
38
|
+
minWidth: "60px"
|
|
39
|
+
}
|
|
40
|
+
}}
|
|
41
|
+
/>
|
|
42
|
+
) : (
|
|
43
|
+
<TablePagination
|
|
44
|
+
{...rest}
|
|
45
|
+
rowsPerPageOptions={[5, 10, 20, 25, 50, 100]}
|
|
46
|
+
component="div"
|
|
47
|
+
count={count}
|
|
48
|
+
rowsPerPage={rowsPerPage}
|
|
49
|
+
page={page}
|
|
50
|
+
onPageChange={onPageChange}
|
|
51
|
+
onRowsPerPageChange={onRowsPerPageChange}
|
|
52
|
+
showFirstButton
|
|
53
|
+
showLastButton
|
|
54
|
+
labelRowsPerPage={matchsDownMD ? "Số hàng" : "Số bản ghi trên trang:"}
|
|
55
|
+
labelDisplayedRows={defaultLabelDisplayedRows}
|
|
56
|
+
sx={{
|
|
57
|
+
width: "100%",
|
|
58
|
+
overflowX: "auto",
|
|
59
|
+
"& .MuiTablePagination-toolbar": {
|
|
60
|
+
display: "flex",
|
|
61
|
+
flexWrap: "wrap", // Cho xuống dòng nếu không đủ chỗ
|
|
62
|
+
justifyContent: "space-between",
|
|
63
|
+
paddingLeft: "6px",
|
|
64
|
+
paddingRight: "6px",
|
|
65
|
+
gap: "4px", // Giảm khoảng cách
|
|
66
|
+
minHeight: "auto"
|
|
67
|
+
},
|
|
68
|
+
"& .MuiTablePagination-selectLabel, & .MuiTablePagination-displayedRows": {
|
|
69
|
+
fontSize: "0.65rem"
|
|
70
|
+
},
|
|
71
|
+
"& .MuiTablePagination-select": {
|
|
72
|
+
fontSize: "0.65rem",
|
|
73
|
+
minWidth: "50px"
|
|
74
|
+
},
|
|
75
|
+
"& .MuiTablePagination-actions > button": {
|
|
76
|
+
fontSize: "0.7rem",
|
|
77
|
+
minWidth: "24px",
|
|
78
|
+
padding: "2px"
|
|
79
|
+
}
|
|
80
|
+
}}
|
|
81
|
+
/>
|
|
42
82
|
);
|
|
43
83
|
}
|
|
44
84
|
|