trithuc-mvc-react 3.4.6 → 3.4.8
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/api/index.js +150 -261
- package/components/DataManagement/DataTable.jsx +69 -49
- package/components/DataManagement/DataTableSM.jsx +81 -51
- package/components/DataManagement/EditorForm.jsx +13 -8
- package/components/DataManagement/TableRowRenderSM.jsx +179 -78
- package/components/DataManagement/index.jsx +30 -39
- package/package.json +2 -2
|
@@ -13,7 +13,7 @@ import { useEffect, useMemo, useState } from "react";
|
|
|
13
13
|
import TablePaginationCustom from "../table/TablePagination";
|
|
14
14
|
|
|
15
15
|
import { useConfirm } from "material-ui-confirm";
|
|
16
|
-
import { useMutation, useQuery, useQueryClient } from "
|
|
16
|
+
import { useMutation, useQuery, useQueryClient } from "react-query";
|
|
17
17
|
import { toast } from "react-toastify";
|
|
18
18
|
import {
|
|
19
19
|
changeStatusDataToTable,
|
|
@@ -62,16 +62,16 @@ const DataTableSM = ({ multipleActions = [], page, setPage = () => {}, disableEd
|
|
|
62
62
|
const [rowsPerPage, setRowsPerPage] = useState(defaultRowsPerPage);
|
|
63
63
|
const [openDialog, setOpenDialog] = useState(false);
|
|
64
64
|
const [deleteId, setDeleteId] = useState(null);
|
|
65
|
-
const
|
|
65
|
+
const [orderBy, setOrderBy] = useState("");
|
|
66
|
+
const [order, setOrder] = useState("asc");
|
|
66
67
|
|
|
67
|
-
const [orderBy, setOrderBy] = useState(defaultSortColumn?.field || "");
|
|
68
|
-
const [order, setOrder] = useState(defaultSortColumn?.defaultOrder || "asc");
|
|
69
68
|
useEffect(() => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
if (!Array.isArray(columns) || columns.length === 0) return;
|
|
70
|
+
|
|
71
|
+
const defaultSortColumn = columns.find((c) => c.defaultSort) || columns[0];
|
|
72
|
+
|
|
73
|
+
setOrderBy(defaultSortColumn.field);
|
|
74
|
+
setOrder(defaultSortColumn.defaultOrder || "asc");
|
|
75
75
|
}, [columns]);
|
|
76
76
|
|
|
77
77
|
const handleRequestSort = (event, property) => {
|
|
@@ -80,12 +80,11 @@ const DataTableSM = ({ multipleActions = [], page, setPage = () => {}, disableEd
|
|
|
80
80
|
setOrderBy(property);
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
// 1️⃣ Xoá defaultQueryOptions khỏi useQuery
|
|
84
83
|
const { data, isLoading } = useQuery({
|
|
85
84
|
queryKey: [tableName, page, rowsPerPage, dataSearch, order, orderBy],
|
|
86
85
|
queryFn: () =>
|
|
87
86
|
getDatasFromTable({
|
|
88
|
-
tableName,
|
|
87
|
+
tableName: tableName,
|
|
89
88
|
page: page + 1,
|
|
90
89
|
pageSize: rowsPerPage,
|
|
91
90
|
data: {
|
|
@@ -96,76 +95,107 @@ const DataTableSM = ({ multipleActions = [], page, setPage = () => {}, disableEd
|
|
|
96
95
|
})
|
|
97
96
|
}
|
|
98
97
|
}),
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
PermissionModel: {},
|
|
103
|
-
CountTrangThai: null,
|
|
104
|
-
status: false
|
|
105
|
-
}),
|
|
106
|
-
staleTime: 60_000,
|
|
107
|
-
gcTime: 30 * 60_000, // ✅ v5 (cacheTime → gcTime)
|
|
108
|
-
refetchOnWindowFocus: true,
|
|
109
|
-
refetchInterval: 30_000,
|
|
110
|
-
onSuccess: ({ PermissionModel = {}, CountTrangThai, status }) => {
|
|
98
|
+
defaultQueryOptions,
|
|
99
|
+
// keepPreviousData: true,
|
|
100
|
+
onSuccess: ({ PermissionModel, CountTrangThai, status }) => {
|
|
111
101
|
if (dataSearch?.TrangThaiXuLy !== undefined) {
|
|
112
|
-
PermissionModel.TrangThaiXuLy = dataSearch
|
|
102
|
+
PermissionModel.TrangThaiXuLy = dataSearch?.TrangThaiXuLy;
|
|
113
103
|
}
|
|
114
|
-
|
|
115
104
|
setPermission(PermissionModel);
|
|
116
105
|
|
|
117
106
|
if (CountTrangThai) {
|
|
118
107
|
const keyCounter = `${tableName}_${userId}_TrangThaiXuLyCounter`;
|
|
119
108
|
localStorage.setItem(keyCounter, JSON.stringify(CountTrangThai));
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
});
|
|
109
|
+
// 👉 Invalidate query để Tab reload ngay
|
|
110
|
+
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
123
111
|
}
|
|
124
112
|
|
|
125
113
|
if (status) {
|
|
126
|
-
|
|
114
|
+
// console.log("LOAD LAI PermissionModel");
|
|
115
|
+
// Cuộn lên đầu trang khi tải dữ liệu thành công
|
|
116
|
+
window.scrollTo({
|
|
117
|
+
top: 0, // Vị trí pixel muốn cuộn tới
|
|
118
|
+
behavior: "smooth" // Tùy chọn cuộn mượt
|
|
119
|
+
});
|
|
127
120
|
}
|
|
128
121
|
}
|
|
129
122
|
});
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
123
|
+
const changeStatusMutation = useMutation(changeStatusDataToTable, {
|
|
124
|
+
onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }) => {
|
|
125
|
+
if (URL_APPLICATION_API) {
|
|
126
|
+
toast.success(message);
|
|
127
|
+
} else {
|
|
128
|
+
toast.success("Thay đổi trạng thái thành công !");
|
|
129
|
+
}
|
|
136
130
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
137
131
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
138
132
|
},
|
|
139
133
|
onError: (error) => {
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
if (error.response && error.response.data && error.response.data.errors) {
|
|
135
|
+
const errors = error.response.data.errors;
|
|
136
|
+
// Chuyển đổi đối tượng lỗi thành chuỗi để hiển thị
|
|
137
|
+
const errorMessages = Object.entries(errors)
|
|
138
|
+
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
|
|
139
|
+
.join("\n");
|
|
140
|
+
toast.error(errorMessages);
|
|
141
|
+
} else {
|
|
142
|
+
// Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
|
|
143
|
+
toast.error("Đã xảy ra lỗi không mong muốn.");
|
|
144
|
+
}
|
|
142
145
|
}
|
|
143
146
|
});
|
|
147
|
+
const deleteMutation = useMutation(deleteDataFromTable, {
|
|
148
|
+
onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }) => {
|
|
149
|
+
if (status) {
|
|
150
|
+
if (URL_APPLICATION_API) {
|
|
151
|
+
toast.success(message);
|
|
152
|
+
} else {
|
|
153
|
+
toast.success("Xóa thành công !");
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
toast.error(" Có lỗi xảy ra !");
|
|
157
|
+
}
|
|
144
158
|
|
|
145
|
-
const deleteMutation = useMutation({
|
|
146
|
-
mutationFn: deleteDataFromTable,
|
|
147
|
-
onSuccess: ({ status = false, message = "Có lỗi xảy ra !" }) => {
|
|
148
|
-
toast[status ? "success" : "error"](status ? message : "Có lỗi xảy ra !");
|
|
149
159
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
150
160
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
151
161
|
},
|
|
152
162
|
onError: (error) => {
|
|
153
|
-
|
|
154
|
-
|
|
163
|
+
if (error.response && error.response.data && error.response.data.errors) {
|
|
164
|
+
const errors = error.response.data.errors;
|
|
165
|
+
// Chuyển đổi đối tượng lỗi thành chuỗi để hiển thị
|
|
166
|
+
const errorMessages = Object.entries(errors)
|
|
167
|
+
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
|
|
168
|
+
.join("\n");
|
|
169
|
+
toast.error(errorMessages);
|
|
170
|
+
} else {
|
|
171
|
+
// Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
|
|
172
|
+
toast.error("Đã xảy ra lỗi không mong muốn.");
|
|
173
|
+
}
|
|
155
174
|
}
|
|
156
175
|
});
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
176
|
+
const deleteMultipleMutation = useMutation(deleteMultipleDataFromTable, {
|
|
177
|
+
onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }) => {
|
|
178
|
+
if (URL_APPLICATION_API) {
|
|
179
|
+
toast.success(message);
|
|
180
|
+
} else {
|
|
181
|
+
toast.success("Xóa thành công !");
|
|
182
|
+
}
|
|
162
183
|
setSelectedItems([]);
|
|
163
184
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
164
185
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
165
186
|
},
|
|
166
187
|
onError: (error) => {
|
|
167
|
-
|
|
168
|
-
|
|
188
|
+
if (error.response && error.response.data && error.response.data.errors) {
|
|
189
|
+
const errors = error.response.data.errors;
|
|
190
|
+
// Chuyển đổi đối tượng lỗi thành chuỗi để hiển thị
|
|
191
|
+
const errorMessages = Object.entries(errors)
|
|
192
|
+
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
|
|
193
|
+
.join("\n");
|
|
194
|
+
toast.error(errorMessages);
|
|
195
|
+
} else {
|
|
196
|
+
// Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
|
|
197
|
+
toast.error("Đã xảy ra lỗi không mong muốn.");
|
|
198
|
+
}
|
|
169
199
|
}
|
|
170
200
|
});
|
|
171
201
|
// Hàm gọi khi người dùng muốn xóa một bản ghi
|
|
@@ -349,7 +379,7 @@ const DataTableSM = ({ multipleActions = [], page, setPage = () => {}, disableEd
|
|
|
349
379
|
/> */}
|
|
350
380
|
{isLoading ? (
|
|
351
381
|
<TableBody>
|
|
352
|
-
<TableRowsLoader rowsNum={10} colsNum={
|
|
382
|
+
<TableRowsLoader rowsNum={10} colsNum={1} />
|
|
353
383
|
</TableBody>
|
|
354
384
|
) : (
|
|
355
385
|
<TableBody>
|
|
@@ -8,7 +8,7 @@ import { useEffect } from "react";
|
|
|
8
8
|
|
|
9
9
|
import { URL_APPLICATION, URL_APPLICATION_API } from "@/constants";
|
|
10
10
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
11
|
-
import { useMutation, useQueryClient } from "
|
|
11
|
+
import { useMutation, useQueryClient } from "react-query";
|
|
12
12
|
import { toast } from "react-toastify";
|
|
13
13
|
import { saveDataToTable } from "../../api";
|
|
14
14
|
import FormField from "./FormField";
|
|
@@ -91,30 +91,35 @@ function EditorForm({ fields, submitRef }) {
|
|
|
91
91
|
}
|
|
92
92
|
}, [selectedEditItem]);
|
|
93
93
|
|
|
94
|
-
const saveMutation = useMutation({
|
|
95
|
-
mutationFn: saveDataToTable,
|
|
94
|
+
const saveMutation = useMutation(saveDataToTable, {
|
|
96
95
|
onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }, { data: { Id } }) => {
|
|
97
96
|
if (status) {
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
if (URL_APPLICATION_API) {
|
|
98
|
+
toast.success(message);
|
|
99
|
+
} else {
|
|
100
|
+
toast.success(Id == 0 ? "Thêm thành công!" : "Cập nhật thành công!");
|
|
101
|
+
}
|
|
102
|
+
queryClient.invalidateQueries(tableName);
|
|
100
103
|
setOpenEditorDialog(false);
|
|
101
104
|
} else {
|
|
105
|
+
console.log(status, Id);
|
|
102
106
|
toast.error(message);
|
|
103
107
|
}
|
|
104
108
|
},
|
|
105
109
|
onError: (error) => {
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
if (error.response && error.response.data && error.response.data.errors) {
|
|
111
|
+
const errors = error.response.data.errors;
|
|
112
|
+
// Chuyển đổi đối tượng lỗi thành chuỗi để hiển thị
|
|
108
113
|
const errorMessages = Object.entries(errors)
|
|
109
114
|
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
|
|
110
115
|
.join("\n");
|
|
111
116
|
toast.error(errorMessages);
|
|
112
117
|
} else {
|
|
118
|
+
// Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
|
|
113
119
|
toast.error("Đã xảy ra lỗi không mong muốn.");
|
|
114
120
|
}
|
|
115
121
|
}
|
|
116
122
|
});
|
|
117
|
-
|
|
118
123
|
const onSubmit = (data) => {
|
|
119
124
|
fields.reduce((data, { type, field, datas, keyValueLabel, keyValue, keyLabel }) => {
|
|
120
125
|
if (type === "date") {
|
|
@@ -44,7 +44,7 @@ export const TableRowRenderSM = ({
|
|
|
44
44
|
|
|
45
45
|
const theme = useTheme();
|
|
46
46
|
const downXl = useMediaQuery(theme.breakpoints.down("xl"));
|
|
47
|
-
|
|
47
|
+
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
|
|
48
48
|
return (
|
|
49
49
|
<TableRow hover key={row[selectedField]} selected={selected}>
|
|
50
50
|
<TableCell
|
|
@@ -77,17 +77,54 @@ export const TableRowRenderSM = ({
|
|
|
77
77
|
>
|
|
78
78
|
{/* Hiển thị các cột dữ liệu */}
|
|
79
79
|
<Grid container spacing={1}>
|
|
80
|
-
{columns.map(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
{columns.map(({ field, label, valueGetter = (row) => row[field], renderCell, valueFormat = (e) => e }) => {
|
|
81
|
+
const rawValue = renderCell ? renderCell(row) : valueFormat(valueGetter(row));
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<Grid
|
|
85
|
+
key={`${row[selectedField]}-${field}`}
|
|
86
|
+
size={12}
|
|
87
|
+
sx={{
|
|
88
|
+
minWidth: 0,
|
|
89
|
+
maxWidth: "100%",
|
|
90
|
+
overflow: "hidden"
|
|
91
|
+
}}
|
|
92
|
+
>
|
|
93
|
+
<Typography
|
|
94
|
+
component="div"
|
|
95
|
+
variant="body2"
|
|
96
|
+
sx={{
|
|
97
|
+
lineHeight: 1.4,
|
|
98
|
+
wordBreak: "break-word",
|
|
99
|
+
overflowWrap: "anywhere",
|
|
100
|
+
whiteSpace: "normal"
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
<Box component="span" fontWeight={600}>
|
|
104
|
+
{label}:
|
|
105
|
+
</Box>
|
|
106
|
+
|
|
107
|
+
<Box
|
|
108
|
+
sx={{
|
|
109
|
+
maxWidth: "100%",
|
|
110
|
+
overflow: "hidden",
|
|
111
|
+
|
|
112
|
+
// 🔥 ÉP CO TOÀN BỘ COMPONENT CON
|
|
113
|
+
"& *": {
|
|
114
|
+
maxWidth: "100%",
|
|
115
|
+
minWidth: 0,
|
|
116
|
+
boxSizing: "border-box"
|
|
117
|
+
}
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
{rawValue}
|
|
121
|
+
</Box>
|
|
122
|
+
</Typography>
|
|
123
|
+
</Grid>
|
|
124
|
+
);
|
|
125
|
+
})}
|
|
90
126
|
</Grid>
|
|
127
|
+
|
|
91
128
|
{/* Công tắc trạng thái */}
|
|
92
129
|
{!disableStatus && canEdit && (
|
|
93
130
|
<Box sx={{ mt: 1 }}>
|
|
@@ -100,74 +137,138 @@ export const TableRowRenderSM = ({
|
|
|
100
137
|
)}
|
|
101
138
|
|
|
102
139
|
{/* Các nút thao tác */}
|
|
103
|
-
<Box
|
|
104
|
-
mt={2}
|
|
105
|
-
pt={1}
|
|
106
|
-
display="flex"
|
|
107
|
-
gap={1}
|
|
108
|
-
flexWrap="wrap"
|
|
109
|
-
justifyContent="flex-end"
|
|
110
|
-
borderTop="1px solid"
|
|
111
|
-
borderColor="divider"
|
|
112
|
-
>
|
|
140
|
+
<Box mt={2} pt={1} borderTop="1px solid" borderColor="divider" display="flex" flexDirection="column" gap={1}>
|
|
113
141
|
{!disableCellThaoTac && (
|
|
114
142
|
<>
|
|
115
|
-
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
143
|
+
<Box display="grid" gridTemplateColumns={isMobile ? "repeat(3, 1fr)" : "auto"} gap={1}>
|
|
144
|
+
{!disableEdit && canEdit && (
|
|
145
|
+
<Button
|
|
146
|
+
fullWidth
|
|
147
|
+
size={isMobile ? "small" : "medium"}
|
|
148
|
+
variant="contained"
|
|
149
|
+
color="primary"
|
|
150
|
+
onClick={() => onEdit(row)}
|
|
151
|
+
startIcon={<EditOutlined />}
|
|
152
|
+
sx={{
|
|
153
|
+
...modernButtonStyle,
|
|
154
|
+
|
|
155
|
+
// compact mobile
|
|
156
|
+
minHeight: 36,
|
|
157
|
+
paddingX: 1,
|
|
158
|
+
|
|
159
|
+
// icon - text spacing
|
|
160
|
+
gap: 0.5,
|
|
161
|
+
"& .MuiButton-startIcon": {
|
|
162
|
+
marginRight: 0.5,
|
|
163
|
+
marginLeft: 0
|
|
164
|
+
},
|
|
165
|
+
"& .MuiButton-startIcon svg": {
|
|
166
|
+
fontSize: 18
|
|
167
|
+
}
|
|
168
|
+
}}
|
|
169
|
+
>
|
|
170
|
+
Cập nhật
|
|
171
|
+
</Button>
|
|
172
|
+
)}
|
|
173
|
+
|
|
174
|
+
{canView && !tableActions?.some(({ permissionType }) => permissionType === "view") && (
|
|
175
|
+
<Button
|
|
176
|
+
fullWidth
|
|
177
|
+
size={isMobile ? "small" : "medium"}
|
|
178
|
+
variant="outlined"
|
|
179
|
+
color="info"
|
|
180
|
+
onClick={() => onView(row)}
|
|
181
|
+
startIcon={<RemoveRedEyeOutlinedIcon />}
|
|
182
|
+
sx={{
|
|
183
|
+
...modernButtonStyle,
|
|
184
|
+
|
|
185
|
+
// compact mobile
|
|
186
|
+
minHeight: 36,
|
|
187
|
+
paddingX: 1,
|
|
188
|
+
|
|
189
|
+
// icon - text spacing
|
|
190
|
+
gap: 0.5,
|
|
191
|
+
"& .MuiButton-startIcon": {
|
|
192
|
+
marginRight: 0.5,
|
|
193
|
+
marginLeft: 0
|
|
194
|
+
},
|
|
195
|
+
"& .MuiButton-startIcon svg": {
|
|
196
|
+
fontSize: 18
|
|
197
|
+
}
|
|
198
|
+
}}
|
|
199
|
+
>
|
|
200
|
+
Xem
|
|
201
|
+
</Button>
|
|
202
|
+
)}
|
|
203
|
+
|
|
204
|
+
{!disableDelete && canDelete && (
|
|
205
|
+
<Button
|
|
206
|
+
fullWidth
|
|
207
|
+
size={isMobile ? "small" : "medium"}
|
|
208
|
+
variant="outlined"
|
|
209
|
+
color="error"
|
|
210
|
+
onClick={() => onDelete(row[selectedField])}
|
|
211
|
+
startIcon={<DeleteOutlineIcon />}
|
|
212
|
+
sx={{
|
|
213
|
+
...modernButtonStyle,
|
|
214
|
+
|
|
215
|
+
// compact mobile
|
|
216
|
+
minHeight: 36,
|
|
217
|
+
paddingX: 1,
|
|
218
|
+
|
|
219
|
+
// icon - text spacing
|
|
220
|
+
gap: 0.5,
|
|
221
|
+
"& .MuiButton-startIcon": {
|
|
222
|
+
marginRight: 0.5,
|
|
223
|
+
marginLeft: 0
|
|
224
|
+
},
|
|
225
|
+
"& .MuiButton-startIcon svg": {
|
|
226
|
+
fontSize: 18
|
|
227
|
+
}
|
|
228
|
+
}}
|
|
229
|
+
>
|
|
230
|
+
Xóa
|
|
231
|
+
</Button>
|
|
232
|
+
)}
|
|
233
|
+
|
|
234
|
+
{tableActionsOnTable.map(
|
|
235
|
+
({ title, onClick, element, visible = true }, idx) =>
|
|
236
|
+
(typeof visible === "function" ? visible(row) : visible) && (
|
|
237
|
+
<Button
|
|
238
|
+
key={idx}
|
|
239
|
+
fullWidth
|
|
240
|
+
size="small"
|
|
241
|
+
variant="outlined"
|
|
242
|
+
onClick={() => onClick(row)}
|
|
243
|
+
startIcon={element}
|
|
244
|
+
sx={{
|
|
245
|
+
...modernButtonStyle,
|
|
246
|
+
|
|
247
|
+
// compact mobile
|
|
248
|
+
minHeight: 36,
|
|
249
|
+
paddingX: 1,
|
|
250
|
+
|
|
251
|
+
// icon - text spacing
|
|
252
|
+
gap: 0.5,
|
|
253
|
+
"& .MuiButton-startIcon": {
|
|
254
|
+
marginRight: 0.5,
|
|
255
|
+
marginLeft: 0
|
|
256
|
+
},
|
|
257
|
+
"& .MuiButton-startIcon svg": {
|
|
258
|
+
fontSize: 18
|
|
259
|
+
}
|
|
260
|
+
}}
|
|
261
|
+
>
|
|
262
|
+
{title === "xem chi tiết" ? "Xem" : title}
|
|
263
|
+
</Button>
|
|
264
|
+
)
|
|
265
|
+
)}
|
|
266
|
+
</Box>
|
|
267
|
+
|
|
268
|
+
{/* More menu luôn nằm riêng 1 hàng */}
|
|
269
|
+
<Box display="flex" justifyContent="flex-end">
|
|
270
|
+
<MoreMenu actions={tableActionsOnMoreMenu} data={row} />
|
|
271
|
+
</Box>
|
|
171
272
|
</>
|
|
172
273
|
)}
|
|
173
274
|
</Box>
|
|
@@ -180,7 +281,7 @@ const modernButtonStyle = {
|
|
|
180
281
|
fontWeight: 400,
|
|
181
282
|
fontSize: "0.65rem",
|
|
182
283
|
borderRadius: 2,
|
|
183
|
-
minWidth:
|
|
284
|
+
minWidth: 0,
|
|
184
285
|
textTransform: "none",
|
|
185
286
|
px: 1,
|
|
186
287
|
py: 0.5,
|