trithuc-mvc-react 3.5.3 → 3.5.5
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,207 +1,348 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import React, { useEffect, useState, useMemo } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Button,
|
|
5
|
+
Typography,
|
|
6
|
+
Paper,
|
|
7
|
+
Divider,
|
|
8
|
+
alpha,
|
|
9
|
+
Collapse,
|
|
10
|
+
Badge,
|
|
11
|
+
Grid,
|
|
12
|
+
useTheme,
|
|
13
|
+
Tooltip,
|
|
14
|
+
Zoom
|
|
15
|
+
} from "@mui/material";
|
|
16
|
+
import { styled } from "@mui/material/styles";
|
|
17
|
+
import { LocalizationProvider, DatePicker } from "@mui/x-date-pickers";
|
|
18
|
+
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
|
|
19
|
+
import SearchRoundedIcon from "@mui/icons-material/SearchRounded";
|
|
20
|
+
import KeyboardArrowDownRoundedIcon from "@mui/icons-material/KeyboardArrowDownRounded";
|
|
21
|
+
import KeyboardArrowUpRoundedIcon from "@mui/icons-material/KeyboardArrowUpRounded";
|
|
22
|
+
import TuneRoundedIcon from "@mui/icons-material/TuneRounded";
|
|
23
|
+
import moment from "moment";
|
|
24
|
+
import { debounce } from "lodash";
|
|
25
|
+
import "dayjs/locale/vi";
|
|
26
|
+
|
|
4
27
|
import { FilterElement } from "./FilterElement";
|
|
5
28
|
import { useDataTable } from "./hooks";
|
|
6
29
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
30
|
+
// --- Styled Components ---
|
|
31
|
+
|
|
32
|
+
const MainCard = styled(Paper)(({ theme }) => ({
|
|
33
|
+
padding: theme.spacing(1),
|
|
34
|
+
borderRadius: "12px",
|
|
35
|
+
border: `1px solid ${alpha(theme.palette.divider, 0.1)}`,
|
|
36
|
+
boxShadow: "0 10px 40px -10px rgba(0,0,0,0.05)",
|
|
37
|
+
backgroundColor: theme.palette.background.paper
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
const AdvancedSection = styled(Box)(({ theme }) => ({
|
|
41
|
+
marginTop: theme.spacing(2),
|
|
42
|
+
padding: theme.spacing(2),
|
|
43
|
+
borderRadius: "10px",
|
|
44
|
+
backgroundColor: alpha(theme.palette.primary.main, 0.02),
|
|
45
|
+
border: `1px solid ${alpha(theme.palette.primary.main, 0.1)}`,
|
|
46
|
+
position: "relative",
|
|
47
|
+
"&::before": {
|
|
48
|
+
content: '""',
|
|
49
|
+
position: "absolute",
|
|
50
|
+
top: 0,
|
|
51
|
+
left: 0,
|
|
52
|
+
right: 0,
|
|
53
|
+
height: "4px",
|
|
54
|
+
background: `linear-gradient(90deg, ${theme.palette.primary.main}, ${theme.palette.info.main})`,
|
|
55
|
+
borderRadius: "20px 20px 0 0",
|
|
56
|
+
opacity: 0.6
|
|
57
|
+
}
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
const StyledToggleButton = styled(Button, {
|
|
61
|
+
shouldForwardProp: (prop) => prop !== "expanded"
|
|
62
|
+
})(({ theme, expanded }) => ({
|
|
63
|
+
textTransform: "none",
|
|
64
|
+
fontWeight: 600,
|
|
65
|
+
fontSize: "0.75rem",
|
|
66
|
+
borderRadius: "6px",
|
|
67
|
+
padding: theme.spacing(1, 2),
|
|
68
|
+
color: expanded ? theme.palette.primary.main : theme.palette.text.secondary,
|
|
69
|
+
backgroundColor: expanded ? alpha(theme.palette.primary.main, 0.1) : "transparent",
|
|
70
|
+
"&:hover": {
|
|
71
|
+
backgroundColor: alpha(theme.palette.primary.main, 0.15)
|
|
72
|
+
}
|
|
73
|
+
}));
|
|
74
|
+
|
|
75
|
+
const ActionButton = styled(Button)(({ theme }) => ({
|
|
76
|
+
borderRadius: "14px",
|
|
77
|
+
padding: "10px 24px",
|
|
78
|
+
fontWeight: 700,
|
|
79
|
+
textTransform: "none",
|
|
80
|
+
transition: "all 0.2s ease-in-out",
|
|
81
|
+
"&:hover": {
|
|
82
|
+
transform: "translateY(-2px)",
|
|
83
|
+
boxShadow: `0 8px 20px -6px ${alpha(theme.palette.primary.main, 0.5)}`
|
|
84
|
+
},
|
|
85
|
+
"&:active": {
|
|
86
|
+
transform: "translateY(0)"
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
89
|
+
|
|
17
90
|
export const FilterGod = ({ tableName, filters, filterButtons, elementSize = "small", setPage = () => {} }) => {
|
|
18
|
-
const
|
|
19
|
-
const onSubmit = (data) => console.log(data);
|
|
91
|
+
const theme = useTheme();
|
|
20
92
|
const { setDataSearch, dataSearch } = useDataTable();
|
|
21
|
-
//
|
|
22
|
-
const
|
|
23
|
-
|
|
93
|
+
// Đoạn code hoàn chỉnh cho useMemo trong FilterGod
|
|
94
|
+
const { basicFilters, advancedFilters } = useMemo(() => {
|
|
95
|
+
return {
|
|
96
|
+
// Ưu tiên hiển thị các bộ lọc có gắn tag isAdvanced: true
|
|
97
|
+
basicFilters: filters.filter((f) => f.isAdvanced === true),
|
|
98
|
+
|
|
99
|
+
// Đưa các bộ lọc còn lại (không phải params ẩn) vào vùng Collapse
|
|
100
|
+
advancedFilters: filters.filter(
|
|
101
|
+
(f) => f.isAdvanced !== true && f.type !== "default" && f.field // Đảm bảo có field để hiển thị
|
|
102
|
+
)
|
|
103
|
+
};
|
|
104
|
+
}, [filters]);
|
|
105
|
+
|
|
106
|
+
const [showAdvanced, setShowAdvanced] = useState(
|
|
107
|
+
() => JSON.parse(localStorage.getItem(`${tableName}-showAdvanced`)) ?? false
|
|
24
108
|
);
|
|
25
109
|
|
|
26
|
-
// Lưu trạng thái vào localStorage mỗi khi thay đổi
|
|
27
110
|
useEffect(() => {
|
|
28
|
-
localStorage.setItem(`${tableName}-
|
|
29
|
-
}, [
|
|
111
|
+
localStorage.setItem(`${tableName}-showAdvanced`, JSON.stringify(showAdvanced));
|
|
112
|
+
}, [showAdvanced]);
|
|
30
113
|
|
|
31
|
-
const
|
|
114
|
+
const renderDateRange = (filter) => {
|
|
115
|
+
const { field, label } = filter;
|
|
116
|
+
const [label1, label2] = Array.isArray(label) ? label : ["Từ ngày", "Đến ngày"];
|
|
32
117
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
118
|
+
const handleDateChange = debounce((newValue, fieldKey) => {
|
|
119
|
+
let formattedDate = null;
|
|
120
|
+
if (newValue && moment(newValue).isValid()) {
|
|
121
|
+
formattedDate = fieldKey.toLowerCase().includes("from")
|
|
122
|
+
? moment(newValue).startOf("day").format("YYYY-MM-DD HH:mm")
|
|
123
|
+
: moment(newValue).endOf("day").format("YYYY-MM-DD HH:mm");
|
|
124
|
+
}
|
|
125
|
+
setDataSearch((prev) => ({ ...prev, [fieldKey]: formattedDate }));
|
|
126
|
+
setPage(0);
|
|
127
|
+
}, 500);
|
|
128
|
+
|
|
129
|
+
const innerDatePicker = (fieldKey, lbl) => (
|
|
130
|
+
<LocalizationProvider dateAdapter={AdapterMoment} adapterLocale="vi">
|
|
131
|
+
<DatePicker
|
|
132
|
+
label={lbl}
|
|
133
|
+
format="DD/MM/YYYY"
|
|
134
|
+
value={dataSearch?.[fieldKey] ? moment(dataSearch?.[fieldKey]) : null}
|
|
135
|
+
onChange={(val) => handleDateChange(val, fieldKey)}
|
|
136
|
+
slotProps={{
|
|
137
|
+
textField: {
|
|
138
|
+
fullWidth: true,
|
|
139
|
+
size: elementSize,
|
|
140
|
+
sx: {
|
|
141
|
+
"& .MuiOutlinedInput-root": {
|
|
142
|
+
borderRadius: "6px",
|
|
143
|
+
backgroundColor: alpha(theme.palette.common.white, 0.5)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
44
146
|
}
|
|
45
147
|
}}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
</
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
148
|
+
/>
|
|
149
|
+
</LocalizationProvider>
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<Grid container spacing={1} key={field.toString()}>
|
|
154
|
+
<Grid size={{ xs: 12, sm: 6 }}>{innerDatePicker(field[0], label1)}</Grid>
|
|
155
|
+
<Grid size={{ xs: 12, sm: 6 }}>{innerDatePicker(field[1], label2)}</Grid>
|
|
156
|
+
</Grid>
|
|
157
|
+
);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<Box sx={{ mb: 1 }}>
|
|
162
|
+
<MainCard elevation={0}>
|
|
163
|
+
{/* Header Header */}
|
|
164
|
+
<Box sx={{ mb: 2, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
|
165
|
+
<Tooltip
|
|
166
|
+
title={
|
|
167
|
+
<Box sx={{ p: 1 }}>
|
|
168
|
+
<Typography
|
|
169
|
+
variant="caption"
|
|
170
|
+
display="block"
|
|
171
|
+
sx={{
|
|
172
|
+
fontWeight: 800,
|
|
173
|
+
mb: 0.5,
|
|
174
|
+
color: theme.palette.primary.light, // Làm nổi bật tiêu đề hướng dẫn
|
|
175
|
+
textTransform: "uppercase",
|
|
176
|
+
letterSpacing: "0.5px"
|
|
177
|
+
}}
|
|
178
|
+
>
|
|
179
|
+
Hướng dẫn lọc dữ liệu
|
|
180
|
+
</Typography>
|
|
181
|
+
<Typography variant="caption" sx={{ lineHeight: 1.6, opacity: 0.9 }}>
|
|
182
|
+
Sử dụng các tiêu chí <b>Cơ bản</b> phía dưới hoặc kết hợp thêm
|
|
183
|
+
<b style={{ color: theme.palette.primary.light }}> Bộ lọc nâng cao </b>
|
|
184
|
+
để tìm kiếm kết quả chính xác nhất.
|
|
185
|
+
</Typography>
|
|
186
|
+
</Box>
|
|
187
|
+
}
|
|
188
|
+
placement="right"
|
|
189
|
+
arrow
|
|
190
|
+
TransitionComponent={Zoom}
|
|
191
|
+
slotProps={{
|
|
192
|
+
tooltip: {
|
|
193
|
+
sx: {
|
|
194
|
+
backgroundColor: alpha(theme.palette.grey[900], 0.95), // Màu nền tối sang trọng
|
|
195
|
+
color: "#fff",
|
|
196
|
+
borderRadius: "12px",
|
|
197
|
+
padding: "10px 14px",
|
|
198
|
+
boxShadow: `0 8px 24px ${alpha(theme.palette.common.black, 0.2)}`,
|
|
199
|
+
maxWidth: 250,
|
|
200
|
+
border: `1px solid ${alpha(theme.palette.primary.main, 0.2)}`
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
arrow: {
|
|
204
|
+
sx: { color: alpha(theme.palette.grey[900], 0.95) }
|
|
205
|
+
}
|
|
206
|
+
}}
|
|
207
|
+
>
|
|
208
|
+
<Box
|
|
209
|
+
sx={{
|
|
210
|
+
display: "flex",
|
|
211
|
+
alignItems: "center",
|
|
212
|
+
gap: 1.2,
|
|
213
|
+
cursor: "help",
|
|
214
|
+
p: "4px 8px",
|
|
215
|
+
ml: -1, // Cân bằng lề trái khi hover
|
|
216
|
+
borderRadius: "8px",
|
|
217
|
+
transition: "all 0.2s ease",
|
|
218
|
+
"&:hover": {
|
|
219
|
+
backgroundColor: alpha(theme.palette.primary.main, 0.05), // Hiệu ứng nền nhẹ khi hover
|
|
220
|
+
"& .search-icon": {
|
|
221
|
+
transform: "scale(1.1) rotate(-5deg)", // Icon động nhẹ
|
|
222
|
+
color: theme.palette.primary.dark
|
|
84
223
|
}
|
|
224
|
+
}
|
|
225
|
+
}}
|
|
226
|
+
>
|
|
227
|
+
<SearchRoundedIcon
|
|
228
|
+
className="search-icon"
|
|
229
|
+
sx={{
|
|
230
|
+
fontSize: "1.35rem",
|
|
231
|
+
color: theme.palette.primary.main,
|
|
232
|
+
transition: "all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)",
|
|
233
|
+
opacity: 0.9
|
|
234
|
+
}}
|
|
235
|
+
/>
|
|
85
236
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
237
|
+
<Typography
|
|
238
|
+
sx={{
|
|
239
|
+
fontWeight: 700,
|
|
240
|
+
fontSize: "0.85rem",
|
|
241
|
+
letterSpacing: "0.2px",
|
|
242
|
+
color: "text.primary",
|
|
243
|
+
position: "relative",
|
|
244
|
+
"&::after": {
|
|
245
|
+
// Thanh trang trí nhỏ dưới chữ
|
|
246
|
+
content: '""',
|
|
247
|
+
position: "absolute",
|
|
248
|
+
bottom: -2,
|
|
249
|
+
left: 0,
|
|
250
|
+
width: "40%",
|
|
251
|
+
height: "2px",
|
|
252
|
+
backgroundColor: alpha(theme.palette.primary.main, 0.3),
|
|
253
|
+
borderRadius: "2px"
|
|
104
254
|
}
|
|
255
|
+
}}
|
|
256
|
+
>
|
|
257
|
+
Bộ Lọc Dữ Liệu
|
|
258
|
+
</Typography>
|
|
259
|
+
</Box>
|
|
260
|
+
</Tooltip>
|
|
105
261
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
startAdornment: (
|
|
139
|
-
<IconButton onClick={() => handleClear(fieldKey)} aria-label="clear">
|
|
140
|
-
<ClearIcon />
|
|
141
|
-
</IconButton>
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
actionBar: { actions: ["clear"] }
|
|
146
|
-
}}
|
|
147
|
-
value={dataSearch?.[fieldKey] ? moment(dataSearch?.[fieldKey]) : null}
|
|
148
|
-
onChange={(newValue) => handleDateChange(newValue, fieldKey, compareKey, compareType)}
|
|
149
|
-
size={elementSize}
|
|
150
|
-
/>
|
|
151
|
-
</LocalizationProvider>
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<Grid sx={{ mb: "5px" }} container key={field.toString()} size={{ ...size }}>
|
|
156
|
-
<Grid size={{ xs: 12, md: 6 }}>{renderDatePicker(field[0], label1, field[1], "max")}</Grid>
|
|
157
|
-
<Grid size={{ xs: 12, md: 6 }}>{renderDatePicker(field[1], label2, field[0], "min")}</Grid>
|
|
158
|
-
</Grid>
|
|
159
|
-
);
|
|
160
|
-
}
|
|
262
|
+
<Box sx={{ display: "flex", gap: 1 }}>
|
|
263
|
+
{advancedFilters.length > 0 && (
|
|
264
|
+
<Tooltip
|
|
265
|
+
title={showAdvanced ? "" : "Mở rộng bộ lọc với các tiêu chí nâng cao"}
|
|
266
|
+
placement="top"
|
|
267
|
+
arrow
|
|
268
|
+
disableInteractive
|
|
269
|
+
>
|
|
270
|
+
<Box component="span">
|
|
271
|
+
{" "}
|
|
272
|
+
{/* Box span giúp Tooltip hoạt động ổn định kể cả khi Badge có vấn đề */}
|
|
273
|
+
<Badge
|
|
274
|
+
badgeContent={advancedFilters.length}
|
|
275
|
+
color="primary"
|
|
276
|
+
variant="dot"
|
|
277
|
+
invisible={showAdvanced}
|
|
278
|
+
sx={{ "& .MuiBadge-dot": { top: 4, right: 4 } }}
|
|
279
|
+
>
|
|
280
|
+
<StyledToggleButton
|
|
281
|
+
expanded={showAdvanced}
|
|
282
|
+
onClick={() => setShowAdvanced(!showAdvanced)}
|
|
283
|
+
startIcon={<TuneRoundedIcon />}
|
|
284
|
+
endIcon={showAdvanced ? <KeyboardArrowUpRoundedIcon /> : <KeyboardArrowDownRoundedIcon />}
|
|
285
|
+
>
|
|
286
|
+
{showAdvanced ? "Thu gọn" : "Nâng cao"}
|
|
287
|
+
</StyledToggleButton>
|
|
288
|
+
</Badge>
|
|
289
|
+
</Box>
|
|
290
|
+
</Tooltip>
|
|
291
|
+
)}
|
|
292
|
+
</Box>
|
|
293
|
+
</Box>
|
|
161
294
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
<FilterElement name={field.toString()} label={label} placeholder={placeHolder} {...rest} setPage={setPage} />
|
|
295
|
+
{/* 1. Basic Filters */}
|
|
296
|
+
<Grid container spacing={2.5}>
|
|
297
|
+
{basicFilters.map((f) => (
|
|
298
|
+
<Grid key={f.field.toString()} size={f.size || { xs: 12, md: 4, lg: 3 }}>
|
|
299
|
+
{f.type === "date-range" ? (
|
|
300
|
+
renderDateRange(f)
|
|
301
|
+
) : (
|
|
302
|
+
<FilterElement {...f} name={f.field.toString()} setPage={setPage} size={elementSize} />
|
|
303
|
+
)}
|
|
304
|
+
</Grid>
|
|
305
|
+
))}
|
|
306
|
+
</Grid>
|
|
307
|
+
|
|
308
|
+
{/* 2. Advanced Filters */}
|
|
309
|
+
<Collapse in={showAdvanced} timeout={400}>
|
|
310
|
+
<AdvancedSection>
|
|
311
|
+
<Grid container spacing={2.5}>
|
|
312
|
+
{advancedFilters.map((f) => (
|
|
313
|
+
<Grid key={f.field.toString()} size={f.size || { xs: 12, md: 4, lg: 3 }}>
|
|
314
|
+
{f.type === "date-range" ? (
|
|
315
|
+
renderDateRange(f)
|
|
316
|
+
) : (
|
|
317
|
+
<FilterElement {...f} name={f.field.toString()} setPage={setPage} size={elementSize} />
|
|
318
|
+
)}
|
|
187
319
|
</Grid>
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
320
|
+
))}
|
|
321
|
+
</Grid>
|
|
322
|
+
</AdvancedSection>
|
|
323
|
+
</Collapse>
|
|
324
|
+
{filterButtons.length > 0 && (
|
|
325
|
+
<>
|
|
326
|
+
<Divider sx={{ my: 3, opacity: 0.6 }} />
|
|
327
|
+
<Box sx={{ display: "flex", justifyContent: "flex-end", gap: 2 }}>
|
|
328
|
+
{filterButtons.map((btn, idx) => (
|
|
329
|
+
<ActionButton
|
|
330
|
+
key={idx}
|
|
331
|
+
size={elementSize}
|
|
332
|
+
variant={btn.variant || "contained"}
|
|
333
|
+
color={btn.color || "primary"}
|
|
334
|
+
onClick={() => btn.onClick({ dataSearch })}
|
|
335
|
+
startIcon={btn.element}
|
|
336
|
+
disableElevation
|
|
337
|
+
sx={btn.sx}
|
|
338
|
+
>
|
|
339
|
+
{btn.title}
|
|
340
|
+
</ActionButton>
|
|
341
|
+
))}
|
|
342
|
+
</Box>
|
|
343
|
+
</>
|
|
344
|
+
)}
|
|
345
|
+
</MainCard>
|
|
205
346
|
</Box>
|
|
206
347
|
);
|
|
207
348
|
};
|
|
@@ -12,7 +12,7 @@ function TablePaginationCustom({ count, rowsPerPage, page, onPageChange, onRowsP
|
|
|
12
12
|
return !isSmallScreen ? (
|
|
13
13
|
<TablePagination
|
|
14
14
|
{...rest}
|
|
15
|
-
rowsPerPageOptions={[5, 10, 20, 25, 50, 100]}
|
|
15
|
+
rowsPerPageOptions={[5, 10, 20, 25, 50, 100, 1000]}
|
|
16
16
|
component="div"
|
|
17
17
|
count={count}
|
|
18
18
|
rowsPerPage={rowsPerPage}
|
|
@@ -42,7 +42,7 @@ function TablePaginationCustom({ count, rowsPerPage, page, onPageChange, onRowsP
|
|
|
42
42
|
) : (
|
|
43
43
|
<TablePagination
|
|
44
44
|
{...rest}
|
|
45
|
-
rowsPerPageOptions={[5, 10, 20, 25, 50, 100]}
|
|
45
|
+
rowsPerPageOptions={[5, 10, 20, 25, 50, 100, 1000]}
|
|
46
46
|
component="div"
|
|
47
47
|
count={count}
|
|
48
48
|
rowsPerPage={rowsPerPage}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trithuc-mvc-react",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.5",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@mui/icons-material": "^7.0.2",
|
|
38
38
|
"@mui/lab": "^7.0.0-beta.11",
|
|
39
|
-
"@mui/material": "^7.
|
|
40
|
-
"@mui/system": "^
|
|
39
|
+
"@mui/material": "^7.3.7",
|
|
40
|
+
"@mui/system": "^7.3.7",
|
|
41
41
|
"@mui/x-date-pickers": "^7.28.3",
|
|
42
42
|
"@mui/x-tree-view": "^7.28.1",
|
|
43
43
|
"dayjs": "^1.11.13",
|
|
44
44
|
"material-ui-confirm": "^4.0.0",
|
|
45
|
-
"react": "
|
|
46
|
-
"react-dom": "
|
|
45
|
+
"react": "^18.3.1",
|
|
46
|
+
"react-dom": "^18.3.1",
|
|
47
47
|
"react-hook-form": "^7.55.0",
|
|
48
48
|
"react-query": "^3.39.3",
|
|
49
49
|
"react-toastify": "^11.0.5"
|