trithuc-mvc-react 1.8.7 → 1.8.9

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 { Table, TableBody, TableCell, TableContainer, TableRow, useMediaQuery, useTheme } from "@mui/material";
1
+ import { Grid, Table, TableBody, TableCell, TableContainer, TableRow, Typography, useMediaQuery, useTheme } from "@mui/material";
2
2
  import TablePaginationCustom from "../table/TablePagination";
3
3
  import { useEffect, useMemo, useState } from "react";
4
4
 
@@ -14,223 +14,236 @@ import TableToolbar from "./TableToolbar";
14
14
  import { useDataTable } from "./hooks";
15
15
  import { usePermission } from "../../hooks";
16
16
  const DataTable = ({ multipleActions = [] }) => {
17
- const {
18
- tableName,
19
- selectedField,
20
- columns,
21
- dataSearch,
22
- setOpenEditorDialog,
23
- setSelectedEditItem,
24
- setOpenViewDialog,
25
- onEditClick
26
- } = useDataTable();
27
-
28
- const { set: setPermission } = usePermission(tableName);
29
- const queryClient = useQueryClient();
30
- const confirm = useConfirm();
31
- const [selectedItems, setSelectedItems] = useState([]);
32
- const [page, setPage] = useState(0);
33
- const [rowsPerPage, setRowsPerPage] = useState(5);
34
-
35
- const { data, isLoading } = useQuery({
36
- queryKey: [tableName, page, rowsPerPage, dataSearch],
37
- queryFn: () =>
38
- getDatasFromTable({
39
- tableName: tableName,
40
- page: page + 1,
41
- pageSize: rowsPerPage,
42
- data: dataSearch
43
- }),
44
- // keepPreviousData: true,
45
- onSuccess: ({ PermissionModel, status }) => {
46
- if (status) {
47
- // setPermission(PermissionModel);
48
- // console.log("LOAD LAI PermissionModel");
49
- }
50
- }
51
- });
52
- const changeStatusMutation = useMutation(changeStatusDataToTable, {
53
- onSuccess: () => {
54
- toast.success("Thay đổi trạng thái thành công !");
55
- queryClient.invalidateQueries({ queryKey: [tableName] });
56
- },
57
- onError: () => {
58
- toast.error(" Có lỗi xảy ra !");
59
- }
60
- });
61
- const deleteMutation = useMutation(deleteDataFromTable, {
62
- onSuccess: ({ status }) => {
63
- if (status) {
64
- toast.success("Xóa thành công !");
65
- } else {
66
- toast.error(" Có lỗi xảy ra !");
67
- }
68
-
69
- queryClient.invalidateQueries({ queryKey: [tableName] });
70
- },
71
- onError: () => {
72
- toast.error(" Có lỗi xảy ra !");
73
- }
74
- });
75
- const deleteMultipleMutation = useMutation(deleteMultipleDataFromTable, {
76
- onSuccess: () => {
77
- toast.success("Xóa thành công !");
78
- setSelectedItems([]);
79
- queryClient.invalidateQueries({ queryKey: [tableName] });
80
- },
81
- onError: () => {
82
- toast.error(" Có lỗi xảy ra !");
83
- }
84
- });
85
-
86
- const handleDelete = (id) => {
87
- confirm({ description: "Bạn có chắc chắn muốn xóa bản ghi này không?", title: "Xác nhận" })
88
- .then(() => {
89
- deleteMutation.mutate({
90
- id,
91
- tableName
92
- });
93
- })
94
- .catch(() => {});
95
- };
96
- const handleChangeStatus = (Id) => {
97
- changeStatusMutation.mutate({
98
- tableName,
99
- id: Id
17
+ const {
18
+ tableName,
19
+ selectedField,
20
+ columns,
21
+ dataSearch,
22
+ setOpenEditorDialog,
23
+ setSelectedEditItem,
24
+ setOpenViewDialog,
25
+ onEditClick,
26
+ hasTabpanel
27
+ } = useDataTable();
28
+
29
+ const { set: setPermission } = usePermission(tableName);
30
+ const queryClient = useQueryClient();
31
+ const confirm = useConfirm();
32
+ const [selectedItems, setSelectedItems] = useState([]);
33
+ const [page, setPage] = useState(0);
34
+ const [rowsPerPage, setRowsPerPage] = useState(5);
35
+
36
+ const { data, isLoading } = useQuery({
37
+ queryKey: [tableName, page, rowsPerPage, dataSearch],
38
+ queryFn: () =>
39
+ getDatasFromTable({
40
+ tableName: tableName,
41
+ page: page + 1,
42
+ pageSize: rowsPerPage,
43
+ data: dataSearch
44
+ }),
45
+ // keepPreviousData: true,
46
+ onSuccess: ({ PermissionModel, status }) => {
47
+ if (status) {
48
+ // setPermission(PermissionModel);
49
+ // console.log("LOAD LAI PermissionModel");
50
+ }
51
+ }
100
52
  });
101
- };
102
- const handlEdit = (item) => {
103
- setOpenEditorDialog(true);
104
- setSelectedEditItem(item);
105
- onEditClick(item);
106
- };
107
- const handlViewDetail = (item) => {
108
- setOpenViewDialog(true);
109
- setSelectedEditItem(item);
110
- };
111
- const { rows, total } = useMemo(() => {
112
- let rows = data?.data ?? [];
113
- let total = data?.total ?? 0;
114
-
115
- return {
116
- rows: rows,
117
- total
118
- };
119
- }, [data]);
120
-
121
- useEffect(() => {
122
- let PermissionModel = data?.PermissionModel;
123
- PermissionModel && setPermission(PermissionModel);
124
- }, [data]);
125
- useEffect(() => {
126
- const newSelectedItems = selectedItems.filter((selectedId) => {
127
- return rows?.some((row) => row.Id == selectedId);
53
+ const changeStatusMutation = useMutation(changeStatusDataToTable, {
54
+ onSuccess: () => {
55
+ toast.success("Thay đổi trạng thái thành công !");
56
+ queryClient.invalidateQueries({ queryKey: [tableName] });
57
+ },
58
+ onError: () => {
59
+ toast.error(" lỗi xảy ra !");
60
+ }
61
+ });
62
+ const deleteMutation = useMutation(deleteDataFromTable, {
63
+ onSuccess: ({ status }) => {
64
+ if (status) {
65
+ toast.success("Xóa thành công !");
66
+ } else {
67
+ toast.error(" Có lỗi xảy ra !");
68
+ }
69
+
70
+ queryClient.invalidateQueries({ queryKey: [tableName] });
71
+ },
72
+ onError: () => {
73
+ toast.error(" lỗi xảy ra !");
74
+ }
75
+ });
76
+ const deleteMultipleMutation = useMutation(deleteMultipleDataFromTable, {
77
+ onSuccess: () => {
78
+ toast.success("Xóa thành công !");
79
+ setSelectedItems([]);
80
+ queryClient.invalidateQueries({ queryKey: [tableName] });
81
+ },
82
+ onError: () => {
83
+ toast.error(" Có lỗi xảy ra !");
84
+ }
128
85
  });
129
- setSelectedItems(newSelectedItems);
130
- }, [rows]);
131
- const handleChangePage = (event, newPage) => {
132
- setPage(newPage);
133
- };
134
- const isSelected = (Id) => selectedItems.indexOf(Id) !== -1;
135
-
136
- const handleSelect = (event, Id) => {
137
- const selectedIndex = selectedItems.indexOf(Id);
138
- let newSelected = [];
139
-
140
- if (selectedIndex === -1) {
141
- newSelected = newSelected.concat(selectedItems, Id);
142
- } else if (selectedIndex === 0) {
143
- newSelected = newSelected.concat(selectedItems.slice(1));
144
- } else if (selectedIndex === selectedItems.length - 1) {
145
- newSelected = newSelected.concat(selectedItems.slice(0, -1));
146
- } else if (selectedIndex > 0) {
147
- newSelected = newSelected.concat(selectedItems.slice(0, selectedIndex), selectedItems.slice(selectedIndex + 1));
148
- }
149
-
150
- setSelectedItems(newSelected);
151
- };
152
- const handleSelectAllClick = (event) => {
153
- if (event.target.checked) {
154
- const newSelected = rows.map((n) => n[selectedField]);
155
- setSelectedItems(newSelected);
156
- return;
157
- }
158
- setSelectedItems([]);
159
- };
160
-
161
- const handleChangeRowsPerPage = (event) => {
162
- setRowsPerPage(parseInt(event.target.value, 10));
163
- setPage(0);
164
- };
165
- const handleDeleteMultiple = () => {
166
- confirm({ description: `Bạn có chắc chắn muốn xóa ${selectedItems?.length} bản ghi này không?`, title: "Xác nhận" })
167
- .then(() => {
168
- deleteMultipleMutation.mutate({
169
- tableName,
170
- ids: selectedItems
86
+
87
+ const handleDelete = (id) => {
88
+ confirm({ description: "Bạn có chắc chắn muốn xóa bản ghi này không?", title: "Xác nhận" })
89
+ .then(() => {
90
+ deleteMutation.mutate({
91
+ id,
92
+ tableName
93
+ });
94
+ })
95
+ .catch(() => {});
96
+ };
97
+ const handleChangeStatus = (Id) => {
98
+ changeStatusMutation.mutate({
99
+ tableName,
100
+ id: Id
101
+ });
102
+ };
103
+ const handlEdit = (item) => {
104
+ setOpenEditorDialog(true);
105
+ setSelectedEditItem(item);
106
+ onEditClick(item);
107
+ };
108
+ const handlViewDetail = (item) => {
109
+ setOpenViewDialog(true);
110
+ setSelectedEditItem(item);
111
+ };
112
+ const { rows, total } = useMemo(() => {
113
+ let rows = data?.data ?? [];
114
+ let total = data?.total ?? 0;
115
+ return {
116
+ rows: rows,
117
+ total
118
+ };
119
+ }, [data]);
120
+
121
+ useEffect(() => {
122
+ let PermissionModel = data?.PermissionModel;
123
+ PermissionModel && setPermission(PermissionModel);
124
+ }, [data]);
125
+ useEffect(() => {
126
+ const newSelectedItems = selectedItems.filter((selectedId) => {
127
+ return rows?.some((row) => row.Id == selectedId);
171
128
  });
172
- })
173
- .catch(() => {});
174
- };
175
- const theme = useTheme();
176
- const downXL = useMediaQuery(theme.breakpoints.down("xl"));
177
-
178
- return (
179
- <>
180
- <TableContainer sx={{ position: "relative" }}>
181
- <TableToolbar
182
- onSelectAllClick={handleSelectAllClick}
183
- numSelected={selectedItems?.length}
184
- rowCount={rows.length}
185
- onDeleteMultiple={handleDeleteMultiple}
186
- selected={selectedItems}
187
- multipleActions={multipleActions}
188
- />
189
-
190
- <Table className="border" size={downXL ? "small" : "medium"}>
191
- <TableHead
192
- headLabel={columns}
193
- onSelectAllClick={handleSelectAllClick}
194
- numSelected={selectedItems?.length}
195
- rowCount={rows.length}
196
- />
197
- {isLoading ? (
198
- <TableRowsLoader rowsNum={5} colsNum={columns.length + 4} />
199
- ) : (
200
- <TableBody>
201
- {[...rows].map((row, index) => (
202
- <TableRowRender
203
- key={row.Id}
204
- index={index}
205
- row={row}
206
- selected={isSelected(row[selectedField])}
207
- onSelect={handleSelect}
208
- onEdit={handlEdit}
209
- onView={handlViewDetail}
210
- onChangeStatus={handleChangeStatus}
211
- onDelete={handleDelete}
129
+ setSelectedItems(newSelectedItems);
130
+ }, [rows]);
131
+ const handleChangePage = (event, newPage) => {
132
+ setPage(newPage);
133
+ };
134
+ const isSelected = (Id) => selectedItems.indexOf(Id) !== -1;
135
+
136
+ const handleSelect = (event, Id) => {
137
+ const selectedIndex = selectedItems.indexOf(Id);
138
+ let newSelected = [];
139
+
140
+ if (selectedIndex === -1) {
141
+ newSelected = newSelected.concat(selectedItems, Id);
142
+ } else if (selectedIndex === 0) {
143
+ newSelected = newSelected.concat(selectedItems.slice(1));
144
+ } else if (selectedIndex === selectedItems.length - 1) {
145
+ newSelected = newSelected.concat(selectedItems.slice(0, -1));
146
+ } else if (selectedIndex > 0) {
147
+ newSelected = newSelected.concat(selectedItems.slice(0, selectedIndex), selectedItems.slice(selectedIndex + 1));
148
+ }
149
+
150
+ setSelectedItems(newSelected);
151
+ };
152
+ const handleSelectAllClick = (event) => {
153
+ if (event.target.checked) {
154
+ const newSelected = rows.map((n) => n[selectedField]);
155
+ setSelectedItems(newSelected);
156
+ return;
157
+ }
158
+ setSelectedItems([]);
159
+ };
160
+
161
+ const handleChangeRowsPerPage = (event) => {
162
+ setRowsPerPage(parseInt(event.target.value, 10));
163
+ setPage(0);
164
+ };
165
+ const handleDeleteMultiple = () => {
166
+ confirm({ description: `Bạn có chắc chắn muốn xóa ${selectedItems?.length} bản ghi này không?`, title: "Xác nhận" })
167
+ .then(() => {
168
+ deleteMultipleMutation.mutate({
169
+ tableName,
170
+ ids: selectedItems
171
+ });
172
+ })
173
+ .catch(() => {});
174
+ };
175
+ const theme = useTheme();
176
+ const downXL = useMediaQuery(theme.breakpoints.down("xl"));
177
+
178
+ return (
179
+ <>
180
+ <TableContainer sx={{ position: "relative" }}>
181
+ <TableToolbar
182
+ onSelectAllClick={handleSelectAllClick}
183
+ numSelected={selectedItems?.length}
184
+ rowCount={rows.length}
185
+ onDeleteMultiple={handleDeleteMultiple}
186
+ selected={selectedItems}
187
+ multipleActions={multipleActions}
212
188
  />
213
- ))}
214
-
215
- {rows?.length == 0 && (
216
- <TableRow>
217
- <TableCell colSpan={columns.length + 4} align="center">
218
- Không có dữ liệu
219
- </TableCell>
220
- </TableRow>
221
- )}
222
- </TableBody>
223
- )}
224
- </Table>
225
- </TableContainer>
226
- <TablePaginationCustom
227
- count={total}
228
- rowsPerPage={rowsPerPage}
229
- page={page}
230
- onPageChange={handleChangePage}
231
- onRowsPerPageChange={handleChangeRowsPerPage}
232
- />
233
- </>
234
- );
189
+
190
+ <Table className="border" size={downXL ? "small" : "medium"}>
191
+ <TableHead
192
+ headLabel={columns}
193
+ onSelectAllClick={handleSelectAllClick}
194
+ numSelected={selectedItems?.length}
195
+ rowCount={rows.length}
196
+ />
197
+ {isLoading ? (
198
+ <TableRowsLoader rowsNum={5} colsNum={columns.length + 4} />
199
+ ) : (
200
+ <TableBody>
201
+ {[...rows].map((row, index) => (
202
+ <TableRowRender
203
+ key={row.Id}
204
+ index={index}
205
+ row={row}
206
+ selected={isSelected(row[selectedField])}
207
+ onSelect={handleSelect}
208
+ onEdit={handlEdit}
209
+ onView={handlViewDetail}
210
+ onChangeStatus={handleChangeStatus}
211
+ onDelete={handleDelete}
212
+ />
213
+ ))}
214
+
215
+ {rows?.length == 0 && (
216
+ <TableRow>
217
+ <TableCell colSpan={columns.length + 4} align="center">
218
+ Không có dữ liệu
219
+ </TableCell>
220
+ </TableRow>
221
+ )}
222
+ </TableBody>
223
+ )}
224
+ </Table>
225
+ </TableContainer>
226
+
227
+ <Grid container>
228
+ {!hasTabpanel && (
229
+ <Grid item alignSelf={"center"} sx={{ pl: 2 }}>
230
+ <Typography variant="body1">
231
+ Tổng số lượng: <span>{total}</span>
232
+ </Typography>
233
+ </Grid>
234
+ )}
235
+
236
+ <Grid item xs>
237
+ <TablePaginationCustom
238
+ count={total}
239
+ rowsPerPage={rowsPerPage}
240
+ page={page}
241
+ onPageChange={handleChangePage}
242
+ onRowsPerPageChange={handleChangeRowsPerPage}
243
+ />
244
+ </Grid>
245
+ </Grid>
246
+ </>
247
+ );
235
248
  };
236
249
  export default DataTable;
@@ -16,189 +16,191 @@ import { FilterGod } from "./FilterGod";
16
16
  import { usePermission } from "../../hooks";
17
17
 
18
18
  DataManagement.propTypes = {
19
- columns: PropTypes.array,
20
- title: PropTypes.string,
21
- tableName: PropTypes.string,
22
- selectedField: PropTypes.string,
23
- filters: PropTypes.arrayOf(
24
- PropTypes.shape({
25
- field: PropTypes.string,
26
- label: PropTypes.string,
27
- placeHolder: PropTypes.string,
28
- type: PropTypes.oneOf(["text", "number", "date", "autocomplete", "checkbox", "radio", "switch"]),
29
- onChangeAfter: PropTypes.func,
30
- filters: PropTypes.array
31
- })
32
- ),
33
- editorFields: PropTypes.array,
34
- validationSchema: PropTypes.object,
35
- disableStatus: PropTypes.bool,
36
- disableAdd: PropTypes.bool,
37
- disableCellThaoTac: PropTypes.bool,
38
- statusKey: PropTypes.string,
39
- tableActions: PropTypes.array,
40
- disableEditor: PropTypes.bool,
41
- onAddClick: PropTypes.func,
42
- onEditClick: PropTypes.func,
43
- tabPanel: PropTypes.node
19
+ columns: PropTypes.array,
20
+ title: PropTypes.string,
21
+ tableName: PropTypes.string,
22
+ selectedField: PropTypes.string,
23
+ filters: PropTypes.arrayOf(
24
+ PropTypes.shape({
25
+ field: PropTypes.string,
26
+ label: PropTypes.string,
27
+ placeHolder: PropTypes.string,
28
+ type: PropTypes.oneOf(["text", "number", "date", "autocomplete", "checkbox", "radio", "switch"]),
29
+ onChangeAfter: PropTypes.func,
30
+ filters: PropTypes.array
31
+ })
32
+ ),
33
+ editorFields: PropTypes.array,
34
+ validationSchema: PropTypes.object,
35
+ disableStatus: PropTypes.bool,
36
+ disableAdd: PropTypes.bool,
37
+ disableCellThaoTac: PropTypes.bool,
38
+ statusKey: PropTypes.string,
39
+ tableActions: PropTypes.array,
40
+ disableEditor: PropTypes.bool,
41
+ onAddClick: PropTypes.func,
42
+ onEditClick: PropTypes.func,
43
+ tabPanel: PropTypes.node
44
44
  };
45
45
 
46
46
  function DataManagement({
47
- columns = [],
48
- title,
49
- tableName,
50
- selectedField = "Id",
51
- filters: tableFilters = [],
52
- editorFields = [],
53
- validationSchema = {},
54
- statusKey = "Status",
55
- disableStatus = false,
56
- disableAdd = false,
57
- disableCellThaoTac = false,
58
-
59
- tableActions = [],
60
- multipleActions = [],
61
-
62
- disableEditor = false,
63
- onAddClick = () => {},
64
- onEditClick = () => {},
65
- tabPanel,
66
- backParentNavigator,
67
- slotProps = {
68
- header: {
69
- sx: {}
47
+ columns = [],
48
+ title,
49
+ tableName,
50
+ selectedField = "Id",
51
+ filters: tableFilters = [],
52
+ editorFields = [],
53
+ validationSchema = {},
54
+ statusKey = "Status",
55
+ disableStatus = false,
56
+ disableAdd = false,
57
+ disableCellThaoTac = false,
58
+
59
+ tableActions = [],
60
+ multipleActions = [],
61
+
62
+ disableEditor = false,
63
+ onAddClick = () => {},
64
+ onEditClick = () => {},
65
+ tabPanel,
66
+ backParentNavigator,
67
+ slotProps = {
68
+ header: {
69
+ sx: {}
70
+ }
70
71
  }
71
- }
72
72
  }) {
73
- const [openEditorDialog, setOpenEditorDialog] = useState(false);
74
- const [selectedEditItem, setSelectedEditItem] = useState(null);
75
- const [openViewDialog, setOpenViewDialog] = useState(false);
76
-
77
- const { canCreate } = usePermission(tableName);
78
- const { defaults, filters } = useMemo(() => {
79
- const filters = tableFilters.filter(({ type }) => type !== "default");
80
- const defaultFilters = tableFilters.filter(({ type }) => type === "default");
81
-
82
- const defaults = defaultFilters.reduce((prev, { field, value }) => {
83
- prev[field] = value;
84
- return prev;
85
- }, {});
86
- return { defaults, filters };
87
- }, [tableFilters]);
88
-
89
- const theme = useTheme();
90
- const upXL = useMediaQuery(theme.breakpoints.up("xl"));
91
- const elementSize = useMemo(() => {
92
- const elementSize = upXL ? "medium" : "small";
93
- return elementSize;
94
- }, [upXL]);
95
-
96
- useEffect(() => {
97
- setDataSearch({ ...dataSearch, ...defaults });
98
- }, [filters]);
99
-
100
- const [dataSearch, setDataSearch] = useState({ ...defaults });
101
- const values = useMemo(() => {
102
- return {
103
- tableName,
104
- selectedField,
105
- columns,
106
- selectedEditItem,
107
- setSelectedEditItem,
108
- setOpenEditorDialog,
109
- setOpenViewDialog,
110
- dataSearch,
111
- setDataSearch,
112
- validationSchema,
113
- statusKey,
114
- disableStatus,
115
- disableCellThaoTac,
116
- disableAdd,
117
- tableActions,
118
- onEditClick
119
- };
120
- }, [
121
- tableName,
122
- selectedField,
123
- columns,
124
- selectedEditItem,
125
- dataSearch,
126
- setDataSearch,
127
- validationSchema,
128
- tableActions,
129
- openViewDialog,
130
- setOpenViewDialog,
131
- onEditClick
132
- ]);
133
-
134
- const methods = useForm({ defaultValues: {} });
135
- const { reset, setValue } = methods;
136
-
137
- return (
138
- <>
139
- <DataTableContext.Provider value={values}>
140
- <FormProvider {...methods}>
141
- <Stack direction="row" justifyContent={"space-between"} sx={{ mb: upXL ? 2 : 1, ...slotProps?.header?.sx }}>
142
- <Typography variant="h4">{title}</Typography>
143
- <Stack direction="row" spacing={1}>
144
- <Tooltip title="Làm mới">
145
- <IconButton
146
- variant="outlined"
147
- color="primary"
148
- size={elementSize}
149
- onClick={() => {
150
- setDataSearch({ ...defaults });
151
- [...filters].forEach((filter) => {
152
- filter?.onChange?.();
153
- });
154
- reset();
155
- setValue("Search");
156
- }}
157
- >
158
- <Refresh fontSize="inherit" />
159
- </IconButton>
160
- </Tooltip>
161
-
162
- <ExportExcelButton tableName={tableName} data={dataSearch} size={elementSize} />
163
- {canCreate && !disableAdd && (
164
- <Button
165
- size={elementSize}
166
- variant="contained"
167
- startIcon={<Add fontSize="inherit" />}
168
- onClick={(e) => {
169
- if (!disableEditor) {
170
- setOpenEditorDialog(true);
171
- setSelectedEditItem(null);
172
- }
173
- onAddClick(e);
174
- }}
175
- >
176
- Thêm
177
- </Button>
178
- )}
179
- </Stack>
180
- </Stack>
181
-
182
- <Card>
183
- {tabPanel}
184
- <FilterGod filters={filters} elementSize={elementSize} />
185
- {backParentNavigator}
186
-
187
- <DataTable multipleActions={multipleActions} />
188
- </Card>
189
- </FormProvider>
190
-
191
- {disableEditor || (
192
- <EditorDialog
193
- open={openEditorDialog}
194
- onClose={() => setOpenEditorDialog(false)}
195
- defaultValues={selectedEditItem}
196
- fields={editorFields}
197
- />
198
- )}
199
- <ViewDetailDialog open={openViewDialog} onClose={() => setOpenViewDialog(false)} fields={editorFields} />
200
- </DataTableContext.Provider>
201
- </>
202
- );
73
+ const [openEditorDialog, setOpenEditorDialog] = useState(false);
74
+ const [selectedEditItem, setSelectedEditItem] = useState(null);
75
+ const [openViewDialog, setOpenViewDialog] = useState(false);
76
+
77
+ const { canCreate } = usePermission(tableName);
78
+ const { defaults, filters } = useMemo(() => {
79
+ const filters = tableFilters.filter(({ type }) => type !== "default");
80
+ const defaultFilters = tableFilters.filter(({ type }) => type === "default");
81
+
82
+ const defaults = defaultFilters.reduce((prev, { field, value }) => {
83
+ prev[field] = value;
84
+ return prev;
85
+ }, {});
86
+ return { defaults, filters };
87
+ }, [tableFilters]);
88
+
89
+ const theme = useTheme();
90
+ const upXL = useMediaQuery(theme.breakpoints.up("xl"));
91
+ const elementSize = useMemo(() => {
92
+ const elementSize = upXL ? "medium" : "small";
93
+ return elementSize;
94
+ }, [upXL]);
95
+
96
+ useEffect(() => {
97
+ setDataSearch({ ...dataSearch, ...defaults });
98
+ }, [filters]);
99
+
100
+ const [dataSearch, setDataSearch] = useState({ ...defaults });
101
+ const values = useMemo(() => {
102
+ const hasTabpanel = !!tabPanel;
103
+ return {
104
+ tableName,
105
+ selectedField,
106
+ columns,
107
+ selectedEditItem,
108
+ setSelectedEditItem,
109
+ setOpenEditorDialog,
110
+ setOpenViewDialog,
111
+ dataSearch,
112
+ setDataSearch,
113
+ validationSchema,
114
+ statusKey,
115
+ disableStatus,
116
+ disableCellThaoTac,
117
+ disableAdd,
118
+ tableActions,
119
+ onEditClick,
120
+ hasTabpanel
121
+ };
122
+ }, [
123
+ tableName,
124
+ selectedField,
125
+ columns,
126
+ selectedEditItem,
127
+ dataSearch,
128
+ setDataSearch,
129
+ validationSchema,
130
+ tableActions,
131
+ openViewDialog,
132
+ setOpenViewDialog,
133
+ onEditClick,
134
+ ]);
135
+
136
+ const methods = useForm({ defaultValues: {} });
137
+ const { reset, setValue } = methods;
138
+
139
+ return (
140
+ <>
141
+ <DataTableContext.Provider value={values}>
142
+ <FormProvider {...methods}>
143
+ <Stack direction="row" justifyContent={"space-between"} sx={{ mb: upXL ? 2 : 1, ...slotProps?.header?.sx }}>
144
+ <Typography variant="h4">{title}</Typography>
145
+ <Stack direction="row" spacing={1}>
146
+ <Tooltip title="Làm mới">
147
+ <IconButton
148
+ variant="outlined"
149
+ color="primary"
150
+ size={elementSize}
151
+ onClick={() => {
152
+ setDataSearch({ ...defaults });
153
+ [...filters].forEach((filter) => {
154
+ filter?.onChange?.();
155
+ });
156
+ reset();
157
+ setValue("Search");
158
+ }}
159
+ >
160
+ <Refresh fontSize="inherit" />
161
+ </IconButton>
162
+ </Tooltip>
163
+
164
+ <ExportExcelButton tableName={tableName} data={dataSearch} size={elementSize} />
165
+ {canCreate && !disableAdd && (
166
+ <Button
167
+ size={elementSize}
168
+ variant="contained"
169
+ startIcon={<Add fontSize="inherit" />}
170
+ onClick={(e) => {
171
+ if (!disableEditor) {
172
+ setOpenEditorDialog(true);
173
+ setSelectedEditItem(null);
174
+ }
175
+ onAddClick(e);
176
+ }}
177
+ >
178
+ Thêm
179
+ </Button>
180
+ )}
181
+ </Stack>
182
+ </Stack>
183
+
184
+ <Card>
185
+ {tabPanel}
186
+ <FilterGod filters={filters} elementSize={elementSize} />
187
+ {backParentNavigator}
188
+
189
+ <DataTable multipleActions={multipleActions} />
190
+ </Card>
191
+ </FormProvider>
192
+
193
+ {disableEditor || (
194
+ <EditorDialog
195
+ open={openEditorDialog}
196
+ onClose={() => setOpenEditorDialog(false)}
197
+ defaultValues={selectedEditItem}
198
+ fields={editorFields}
199
+ />
200
+ )}
201
+ <ViewDetailDialog open={openViewDialog} onClose={() => setOpenViewDialog(false)} fields={editorFields} />
202
+ </DataTableContext.Provider>
203
+ </>
204
+ );
203
205
  }
204
206
  export default DataManagement;
@@ -1,4 +1,4 @@
1
- import { Grid, TablePagination, Typography, useMediaQuery, useTheme } from "@mui/material";
1
+ import { TablePagination, useMediaQuery, useTheme } from "@mui/material";
2
2
  import PropTypes from "prop-types";
3
3
 
4
4
  TablePaginationCustom.propsType = {
@@ -8,38 +8,27 @@ TablePaginationCustom.propsType = {
8
8
  onPageChange: PropTypes.func,
9
9
  onRowsPerPageChange: PropTypes.func
10
10
  };
11
-
11
+ function defaultLabelDisplayedRows({ from, to, count }) {
12
+ return `${from}–${to} của ${count !== -1 ? count : `more than ${to}`}`;
13
+ }
12
14
  function TablePaginationCustom({ count, rowsPerPage, page, onPageChange, onRowsPerPageChange, ...rest }) {
13
15
  const theme = useTheme();
14
16
  const matchsDownMD = useMediaQuery(theme.breakpoints.down("md"));
15
17
  return (
16
- <>
17
- <Grid container>
18
- <Grid item alignSelf={"center"} sx={{ pl: 2}}>
19
- <Typography variant="body1">
20
- Tổng số lượng: <span>{count}</span>
21
- </Typography>
22
- </Grid>
23
- <Grid item xs>
24
- <TablePagination
25
- {...rest}
26
- rowsPerPageOptions={[5, 10, 25, 100]}
27
- component="div"
28
- count={count}
29
- rowsPerPage={rowsPerPage}
30
- page={page}
31
- onPageChange={onPageChange}
32
- onRowsPerPageChange={onRowsPerPageChange}
33
- showFirstButton={true}
34
- showLastButton={true}
35
- labelRowsPerPage={matchsDownMD ? "Số hàng" : "Số bản ghi trên trang:"}
36
- labelDisplayedRows={function defaultLabelDisplayedRows({ from, to, count }) {
37
- return `${from}–${to} của ${count !== -1 ? count : `more than ${to}`}`;
38
- }}
39
- />
40
- </Grid>
41
- </Grid>
42
- </>
18
+ <TablePagination
19
+ {...rest}
20
+ rowsPerPageOptions={[5, 10, 25, 100]}
21
+ component="div"
22
+ count={count}
23
+ rowsPerPage={rowsPerPage}
24
+ page={page}
25
+ onPageChange={onPageChange}
26
+ onRowsPerPageChange={onRowsPerPageChange}
27
+ showFirstButton={true}
28
+ showLastButton={true}
29
+ labelRowsPerPage={matchsDownMD ? "Số hàng" : "Số bản ghi trên trang:"}
30
+ labelDisplayedRows={defaultLabelDisplayedRows}
31
+ />
43
32
  );
44
33
  }
45
34
  export default TablePaginationCustom;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trithuc-mvc-react",
3
- "version": "1.8.7",
3
+ "version": "1.8.9",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"