trithuc-mvc-react 3.4.4 → 3.4.6
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
CHANGED
|
@@ -87,28 +87,49 @@ export default api;
|
|
|
87
87
|
export const getDatasFromTable = async ({ tableName, page, pageSize, data }) => {
|
|
88
88
|
try {
|
|
89
89
|
let res;
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
if (!apiUrl) {
|
|
92
|
+
// MVC4
|
|
92
93
|
res = await api.get(`${getBaseUrl()}/Admin/${tableName}/LoadData`, {
|
|
93
94
|
params: {
|
|
94
|
-
json: JSON.stringify(data),
|
|
95
|
+
json: JSON.stringify(data ?? {}),
|
|
95
96
|
page,
|
|
96
97
|
pageSize
|
|
97
98
|
}
|
|
98
99
|
});
|
|
99
100
|
} else {
|
|
100
|
-
//
|
|
101
|
+
// .NET Core
|
|
101
102
|
res = await api.get(`${getBaseUrl()}/${apiUrl}/${tableName}`, {
|
|
102
103
|
params: {
|
|
103
104
|
PageNumber: page,
|
|
104
105
|
PageSize: pageSize,
|
|
105
|
-
...data
|
|
106
|
+
...(data ?? {})
|
|
106
107
|
}
|
|
107
108
|
});
|
|
108
109
|
}
|
|
110
|
+
|
|
111
|
+
// 🔴 ĐIỂM FIX QUAN TRỌNG NHẤT
|
|
112
|
+
if (!res || res.data == null) {
|
|
113
|
+
// console.warn("API returned empty response:", {
|
|
114
|
+
// tableName,
|
|
115
|
+
// page,
|
|
116
|
+
// pageSize
|
|
117
|
+
// });
|
|
118
|
+
|
|
119
|
+
// ✅ RETURN OBJECT MẶC ĐỊNH – KHÔNG ĐƯỢC undefined
|
|
120
|
+
return {
|
|
121
|
+
data: [],
|
|
122
|
+
PermissionModel: {},
|
|
123
|
+
CountTrangThai: null,
|
|
124
|
+
status: false
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
109
128
|
return res.data;
|
|
110
129
|
} catch (error) {
|
|
111
|
-
console.error("Error fetching data:", error);
|
|
130
|
+
// console.error("Error fetching data:", error);
|
|
131
|
+
|
|
132
|
+
// ✅ THROW → React Query onError xử lý
|
|
112
133
|
throw error;
|
|
113
134
|
}
|
|
114
135
|
};
|
|
@@ -144,188 +165,278 @@ export const getDatasFromTableDropdownlist = async ({ tableName, page, pageSize,
|
|
|
144
165
|
|
|
145
166
|
export const getDataFromTable = async ({ tableName, id }) => {
|
|
146
167
|
try {
|
|
168
|
+
let res;
|
|
169
|
+
|
|
147
170
|
if (!apiUrl) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
params: {
|
|
151
|
-
id
|
|
152
|
-
}
|
|
171
|
+
// MVC4
|
|
172
|
+
res = await api.get(`${getBaseUrl()}/Admin/${tableName}/GetDetail`, {
|
|
173
|
+
params: { id }
|
|
153
174
|
});
|
|
154
|
-
return res.data;
|
|
155
175
|
} else {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
return res.data;
|
|
176
|
+
// .NET Core
|
|
177
|
+
res = await api.get(`${getBaseUrl()}/${apiUrl}/${tableName}/${id}`);
|
|
159
178
|
}
|
|
179
|
+
|
|
180
|
+
// 🔴 FIX CỐT LÕI: KHÔNG BAO GIỜ return undefined
|
|
181
|
+
if (!res || res.data == null) {
|
|
182
|
+
// console.warn("API returned empty detail:", { tableName, id });
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
data: null,
|
|
186
|
+
status: false,
|
|
187
|
+
message: "Không tìm thấy dữ liệu"
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return res.data;
|
|
160
192
|
} catch (error) {
|
|
161
|
-
console.error("Error fetching
|
|
162
|
-
throw error;
|
|
193
|
+
// console.error("Error fetching detail:", error);
|
|
194
|
+
throw error; // React Query onError xử lý
|
|
163
195
|
}
|
|
164
196
|
};
|
|
165
197
|
|
|
166
198
|
export const deleteDataFromTable = async ({ tableName, id }) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
199
|
+
try {
|
|
200
|
+
let res;
|
|
201
|
+
|
|
202
|
+
if (!apiUrl) {
|
|
203
|
+
// MVC4
|
|
204
|
+
res = await api.post(`${getBaseUrl()}/Admin/${tableName}/Delete`, { id });
|
|
205
|
+
} else {
|
|
206
|
+
// .NET Core
|
|
207
|
+
const ids = Array.isArray(id) ? id : [id];
|
|
208
|
+
|
|
209
|
+
res = await api.delete(`${getBaseUrl()}/${apiUrl}/${tableName}`, {
|
|
210
|
+
data: ids,
|
|
211
|
+
headers: {
|
|
212
|
+
"Content-Type": "application/json-patch+json"
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// 🔴 FIX QUAN TRỌNG NHẤT
|
|
218
|
+
if (!res || res.data == null) {
|
|
219
|
+
// console.warn("Delete API returned empty response:", { tableName, id });
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
status: true,
|
|
223
|
+
message: "Xóa thành công"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
182
227
|
return res.data;
|
|
228
|
+
} catch (error) {
|
|
229
|
+
// console.error("Error deleting data:", error);
|
|
230
|
+
throw error; // React Query mutation onError xử lý
|
|
183
231
|
}
|
|
184
232
|
};
|
|
233
|
+
|
|
185
234
|
export const deleteMultipleDataFromTable = async ({ tableName, ids }) => {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
235
|
+
try {
|
|
236
|
+
let res;
|
|
237
|
+
|
|
238
|
+
if (!apiUrl) {
|
|
239
|
+
// MVC4
|
|
240
|
+
res = await api.post(`${getBaseUrl()}/Admin/${tableName}/DeleteMulti`, {
|
|
241
|
+
ids
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
// .NET Core
|
|
245
|
+
res = await api.delete(`${getBaseUrl()}/${apiUrl}/${tableName}`, {
|
|
246
|
+
data: ids,
|
|
247
|
+
headers: {
|
|
248
|
+
"Content-Type": "application/json-patch+json"
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// 🔴 FIX QUAN TRỌNG NHẤT CHO REACT QUERY v5
|
|
254
|
+
if (!res || res.data == null) {
|
|
255
|
+
// console.warn("DeleteMultiple API returned empty response:", {
|
|
256
|
+
// tableName,
|
|
257
|
+
// ids
|
|
258
|
+
// });
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
status: true,
|
|
262
|
+
message: "Xóa nhiều bản ghi thành công"
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
198
266
|
return res.data;
|
|
267
|
+
} catch (error) {
|
|
268
|
+
// console.error("Error deleting multiple data:", error);
|
|
269
|
+
throw error; // để useMutation onError xử lý
|
|
199
270
|
}
|
|
200
271
|
};
|
|
272
|
+
|
|
201
273
|
export const saveDataToTable = async ({ tableName, data }) => {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const res = await api.post(`${getBaseUrl()}/${apiUrl}/${tableName}`, data);
|
|
211
|
-
return res.data;
|
|
274
|
+
try {
|
|
275
|
+
let res;
|
|
276
|
+
|
|
277
|
+
if (!apiUrl) {
|
|
278
|
+
// MVC4
|
|
279
|
+
res = await api.post(`${getBaseUrl()}/Admin/${tableName}/SaveData`, {
|
|
280
|
+
json: JSON.stringify({ ...data })
|
|
281
|
+
});
|
|
212
282
|
} else {
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
283
|
+
// .NET Core
|
|
284
|
+
if (!data?.Id || data.Id === "0") {
|
|
285
|
+
// CREATE
|
|
286
|
+
res = await api.post(`${getBaseUrl()}/${apiUrl}/${tableName}`, data);
|
|
287
|
+
} else {
|
|
288
|
+
// UPDATE
|
|
289
|
+
res = await api.put(`${getBaseUrl()}/${apiUrl}/${tableName}/${data.Id}`, data);
|
|
290
|
+
}
|
|
216
291
|
}
|
|
292
|
+
|
|
293
|
+
// 🔴 FIX BẮT BUỘC CHO REACT QUERY v5
|
|
294
|
+
if (!res || res.data == null) {
|
|
295
|
+
// console.warn("SaveData API returned empty response:", {
|
|
296
|
+
// tableName,
|
|
297
|
+
// data
|
|
298
|
+
// });
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
status: true,
|
|
302
|
+
message: "Lưu dữ liệu thành công"
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return res.data;
|
|
307
|
+
} catch (error) {
|
|
308
|
+
// console.error("Error saving data:", error);
|
|
309
|
+
throw error; // để useMutation onError xử lý
|
|
217
310
|
}
|
|
218
311
|
};
|
|
312
|
+
|
|
219
313
|
export const changeStatusDataToTable = async ({ tableName, id, fieldName }) => {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
});
|
|
247
|
-
return res.data;
|
|
248
|
-
}
|
|
249
|
-
} catch (error) {
|
|
250
|
-
console.error("Error changing status:", error);
|
|
251
|
-
// Xử lý lỗi tùy thuộc vào nhu cầu của bạn, có thể ném ra hoặc trả về giá trị mặc định
|
|
252
|
-
throw error; // Hoặc return { success: false, message: error.message };
|
|
314
|
+
try {
|
|
315
|
+
let res;
|
|
316
|
+
|
|
317
|
+
if (!apiUrl) {
|
|
318
|
+
// MVC4
|
|
319
|
+
res = await api.post(`${getBaseUrl()}/Admin/${tableName}/ChangeStatus`, { id });
|
|
320
|
+
} else {
|
|
321
|
+
// .NET Core
|
|
322
|
+
res = await api.post(
|
|
323
|
+
`${getBaseUrl()}/${apiUrl}/${tableName}/ChangeStatus`,
|
|
324
|
+
fieldName ? { id, fieldName } : { id }
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 🔴 FIX BẮT BUỘC CHO REACT QUERY v5
|
|
329
|
+
if (!res || res.data == null) {
|
|
330
|
+
// console.warn("ChangeStatus API returned empty response", {
|
|
331
|
+
// tableName,
|
|
332
|
+
// id,
|
|
333
|
+
// fieldName
|
|
334
|
+
// });
|
|
335
|
+
|
|
336
|
+
return {
|
|
337
|
+
status: true,
|
|
338
|
+
message: "Thay đổi trạng thái thành công"
|
|
339
|
+
};
|
|
253
340
|
}
|
|
341
|
+
|
|
342
|
+
return res.data;
|
|
343
|
+
} catch (error) {
|
|
344
|
+
// console.error("Error changing status:", error);
|
|
345
|
+
throw error; // để useMutation onError xử lý
|
|
254
346
|
}
|
|
255
347
|
};
|
|
256
348
|
|
|
257
349
|
export const exportExcel = async ({ tableName, data }) => {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return res.data;
|
|
265
|
-
} else {
|
|
266
|
-
const res = await api.get(
|
|
267
|
-
`${getBaseUrl()}/${apiUrl}/${tableName}/ExportData`,
|
|
268
|
-
{
|
|
350
|
+
try {
|
|
351
|
+
let res;
|
|
352
|
+
|
|
353
|
+
if (!apiUrl) {
|
|
354
|
+
// MVC4
|
|
355
|
+
res = await api.get(`${getBaseUrl()}/Admin/${tableName}/ExportData`, {
|
|
269
356
|
params: {
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
357
|
+
json: JSON.stringify(data)
|
|
358
|
+
},
|
|
359
|
+
responseType: "blob"
|
|
360
|
+
});
|
|
361
|
+
} else {
|
|
362
|
+
// .NET Core
|
|
363
|
+
res = await api.get(`${getBaseUrl()}/${apiUrl}/${tableName}/ExportData`, {
|
|
364
|
+
params: { ...data },
|
|
365
|
+
responseType: "blob"
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// 🔴 BẮT BUỘC: luôn return value
|
|
370
|
+
if (!res || !res.data) {
|
|
371
|
+
throw new Error("Export Excel failed: empty response");
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return res.data; // Blob
|
|
375
|
+
} catch (error) {
|
|
376
|
+
// console.error("Error exporting excel:", error);
|
|
377
|
+
throw error;
|
|
280
378
|
}
|
|
281
379
|
};
|
|
282
380
|
|
|
283
381
|
export const uploadFile = async (formData) => {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
// 3. Log tất cả key-value trong FormData để kiểm tra
|
|
291
|
-
// console.log("===== FormData Contents =====");
|
|
292
|
-
// formData.forEach((value, key) => {
|
|
293
|
-
// console.log(key, value);
|
|
294
|
-
// });
|
|
295
|
-
if (!apiUrl) {
|
|
296
|
-
const res = await api.post(`${getBaseUrl()}/Handler/fileUploader.ashx`, formData, {
|
|
297
|
-
headers: {
|
|
298
|
-
"Content-Type": "multipart/form-data"
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
return res.data;
|
|
302
|
-
} else {
|
|
303
|
-
const res = await api.post(`${getBaseUrl()}/${apiUrl}/FileUploader`, formData, {
|
|
304
|
-
headers: {
|
|
305
|
-
"Content-Type": "multipart/form-data"
|
|
306
|
-
}
|
|
382
|
+
try {
|
|
383
|
+
// Clone FormData để tránh append trùng
|
|
384
|
+
const fd = new FormData();
|
|
385
|
+
formData.forEach((value, key) => {
|
|
386
|
+
fd.append(key, value);
|
|
307
387
|
});
|
|
388
|
+
|
|
389
|
+
// Append currentUrl 1 lần
|
|
390
|
+
fd.append("currentUrl", window.location.href);
|
|
391
|
+
|
|
392
|
+
let res;
|
|
393
|
+
|
|
394
|
+
if (!apiUrl) {
|
|
395
|
+
// MVC / ashx
|
|
396
|
+
res = await api.post(`${getBaseUrl()}/Handler/fileUploader.ashx`, fd);
|
|
397
|
+
} else {
|
|
398
|
+
// .NET Core
|
|
399
|
+
res = await api.post(`${getBaseUrl()}/${apiUrl}/FileUploader`, fd);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 🔴 FIX BẮT BUỘC REACT QUERY v5
|
|
403
|
+
if (!res || res.data == null) {
|
|
404
|
+
// console.warn("Upload API returned empty response");
|
|
405
|
+
|
|
406
|
+
return {
|
|
407
|
+
status: true,
|
|
408
|
+
message: "Upload thành công"
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
308
412
|
return res.data;
|
|
413
|
+
} catch (error) {
|
|
414
|
+
// console.error("Error uploading file:", error);
|
|
415
|
+
throw error;
|
|
309
416
|
}
|
|
310
417
|
};
|
|
311
418
|
|
|
312
|
-
export const huongDan = async ({ data }) => {
|
|
313
|
-
|
|
419
|
+
export const huongDan = async ({ data } = {}) => {
|
|
420
|
+
try {
|
|
421
|
+
// Không có apiUrl → luôn return array
|
|
422
|
+
if (!apiUrl) {
|
|
423
|
+
return [];
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const res = await api.get(`${getBaseUrl()}/${apiUrl}/HuongDanSuDung/Dropdownlist`, {
|
|
427
|
+
params: { ...data }
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// 🔴 BẮT BUỘC: không để undefined
|
|
431
|
+
if (!res || res.data == null) {
|
|
432
|
+
// console.warn("HuongDan API returned empty response");
|
|
433
|
+
return [];
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Đảm bảo luôn là array
|
|
437
|
+
return Array.isArray(res.data) ? res.data : [];
|
|
438
|
+
} catch (error) {
|
|
439
|
+
// console.error("Error fetching huongDan:", error);
|
|
314
440
|
return [];
|
|
315
|
-
} else {
|
|
316
|
-
const res = await api.get(
|
|
317
|
-
`${getBaseUrl()}/${apiUrl}/HuongDanSuDung/Dropdownlist`,
|
|
318
|
-
{
|
|
319
|
-
params: {
|
|
320
|
-
...data
|
|
321
|
-
}
|
|
322
|
-
},
|
|
323
|
-
{
|
|
324
|
-
headers: {
|
|
325
|
-
"Content-Type": "application/json-patch+json" // Đảm bảo Content-Type là đúng
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
);
|
|
329
|
-
return res.data;
|
|
330
441
|
}
|
|
331
442
|
};
|
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Grid,
|
|
3
|
+
Table,
|
|
4
|
+
TableBody,
|
|
5
|
+
TableCell,
|
|
6
|
+
TableContainer,
|
|
7
|
+
TableRow,
|
|
8
|
+
Typography,
|
|
9
|
+
useMediaQuery,
|
|
10
|
+
useTheme
|
|
11
|
+
} from "@mui/material";
|
|
2
12
|
import { useEffect, useMemo, useState } from "react";
|
|
3
13
|
import TablePaginationCustom from "../table/TablePagination";
|
|
4
14
|
|
|
5
15
|
import { useConfirm } from "material-ui-confirm";
|
|
6
16
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
7
17
|
import { toast } from "react-toastify";
|
|
8
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
changeStatusDataToTable,
|
|
20
|
+
deleteDataFromTable,
|
|
21
|
+
deleteMultipleDataFromTable,
|
|
22
|
+
getDatasFromTable
|
|
23
|
+
} from "../../api";
|
|
9
24
|
import TableRowsLoader from "../table/TableRowsLoader";
|
|
10
25
|
import { TableHead } from "./TableHead";
|
|
11
26
|
|
|
@@ -66,11 +81,12 @@ const DataTable = ({ multipleActions = [], page, setPage = () => {}, disableEdit
|
|
|
66
81
|
setOrderBy(property);
|
|
67
82
|
};
|
|
68
83
|
|
|
84
|
+
// 1️⃣ Xoá defaultQueryOptions khỏi useQuery
|
|
69
85
|
const { data, isLoading } = useQuery({
|
|
70
86
|
queryKey: [tableName, page, rowsPerPage, dataSearch, order, orderBy],
|
|
71
87
|
queryFn: () =>
|
|
72
88
|
getDatasFromTable({
|
|
73
|
-
tableName
|
|
89
|
+
tableName,
|
|
74
90
|
page: page + 1,
|
|
75
91
|
pageSize: rowsPerPage,
|
|
76
92
|
data: {
|
|
@@ -81,96 +97,76 @@ const DataTable = ({ multipleActions = [], page, setPage = () => {}, disableEdit
|
|
|
81
97
|
})
|
|
82
98
|
}
|
|
83
99
|
}),
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
keepPreviousData: true,
|
|
101
|
+
placeholderData: () => ({
|
|
102
|
+
data: [],
|
|
103
|
+
PermissionModel: {},
|
|
104
|
+
CountTrangThai: null,
|
|
105
|
+
status: false
|
|
106
|
+
}),
|
|
107
|
+
staleTime: 60_000,
|
|
108
|
+
gcTime: 30 * 60_000, // ✅ v5 (cacheTime → gcTime)
|
|
109
|
+
refetchOnWindowFocus: true,
|
|
110
|
+
refetchInterval: 30_000,
|
|
111
|
+
onSuccess: ({ PermissionModel = {}, CountTrangThai, status }) => {
|
|
87
112
|
if (dataSearch?.TrangThaiXuLy !== undefined) {
|
|
88
|
-
PermissionModel.TrangThaiXuLy = dataSearch
|
|
113
|
+
PermissionModel.TrangThaiXuLy = dataSearch.TrangThaiXuLy;
|
|
89
114
|
}
|
|
115
|
+
|
|
90
116
|
setPermission(PermissionModel);
|
|
91
117
|
|
|
92
118
|
if (CountTrangThai) {
|
|
93
119
|
const keyCounter = `${tableName}_${userId}_TrangThaiXuLyCounter`;
|
|
94
120
|
localStorage.setItem(keyCounter, JSON.stringify(CountTrangThai));
|
|
95
|
-
|
|
96
|
-
|
|
121
|
+
queryClient.invalidateQueries({
|
|
122
|
+
queryKey: [tableName, "CountAllTrangThaiXuly"]
|
|
123
|
+
});
|
|
97
124
|
}
|
|
98
125
|
|
|
99
126
|
if (status) {
|
|
100
|
-
|
|
101
|
-
// Cuộn lên đầu trang khi tải dữ liệu thành công
|
|
102
|
-
window.scrollTo({
|
|
103
|
-
top: 0, // Vị trí pixel muốn cuộn tới
|
|
104
|
-
behavior: "smooth" // Tùy chọn cuộn mượt
|
|
105
|
-
});
|
|
127
|
+
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
106
128
|
}
|
|
107
129
|
}
|
|
108
130
|
});
|
|
109
131
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
toast.success("Thay đổi trạng thái thành công !");
|
|
116
|
-
}
|
|
132
|
+
// 2️⃣ Mutation cũng cần sửa, bỏ defaultMutationOptions nếu có
|
|
133
|
+
const changeStatusMutation = useMutation({
|
|
134
|
+
mutationFn: changeStatusDataToTable,
|
|
135
|
+
onSuccess: ({ status = false, message = "Có lỗi xảy ra !" }) => {
|
|
136
|
+
toast.success(status ? message : "Thay đổi trạng thái thành công !");
|
|
117
137
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
118
138
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
119
139
|
},
|
|
120
140
|
onError: (error) => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
toast.error(message);
|
|
124
|
-
} else {
|
|
125
|
-
// Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
|
|
126
|
-
toast.error("Đã xảy ra lỗi không mong muốn.");
|
|
127
|
-
}
|
|
141
|
+
const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
|
|
142
|
+
toast.error(message);
|
|
128
143
|
}
|
|
129
144
|
});
|
|
130
|
-
const deleteMutation = useMutation(deleteDataFromTable, {
|
|
131
|
-
onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }) => {
|
|
132
|
-
if (status) {
|
|
133
|
-
if (URL_APPLICATION_API) {
|
|
134
|
-
toast.success(message);
|
|
135
|
-
} else {
|
|
136
|
-
toast.success("Xóa thành công !");
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
toast.error(" Có lỗi xảy ra !");
|
|
140
|
-
}
|
|
141
145
|
|
|
146
|
+
const deleteMutation = useMutation({
|
|
147
|
+
mutationFn: deleteDataFromTable,
|
|
148
|
+
onSuccess: ({ status = false, message = "Có lỗi xảy ra !" }) => {
|
|
149
|
+
toast[status ? "success" : "error"](status ? message : "Có lỗi xảy ra !");
|
|
142
150
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
143
151
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
144
152
|
},
|
|
145
153
|
onError: (error) => {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
toast.error(message);
|
|
149
|
-
} else {
|
|
150
|
-
// Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
|
|
151
|
-
toast.error("Đã xảy ra lỗi không mong muốn.");
|
|
152
|
-
}
|
|
154
|
+
const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
|
|
155
|
+
toast.error(message);
|
|
153
156
|
}
|
|
154
157
|
});
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
toast.success("Xóa thành công !");
|
|
161
|
-
}
|
|
158
|
+
|
|
159
|
+
const deleteMultipleMutation = useMutation({
|
|
160
|
+
mutationFn: deleteMultipleDataFromTable,
|
|
161
|
+
onSuccess: ({ status = false, message = "Có lỗi xảy ra !" }) => {
|
|
162
|
+
toast[status ? "success" : "error"](status ? message : "Xóa thành công !");
|
|
162
163
|
setSelectedItems([]);
|
|
163
164
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
164
165
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
165
166
|
},
|
|
166
167
|
onError: (error) => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
toast.error(message);
|
|
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
|
-
}
|
|
168
|
+
const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
|
|
169
|
+
toast.error(message);
|
|
174
170
|
}
|
|
175
171
|
});
|
|
176
172
|
// Hàm gọi khi người dùng muốn xóa một bản ghi
|
|
@@ -370,7 +366,12 @@ const DataTable = ({ multipleActions = [], page, setPage = () => {}, disableEdit
|
|
|
370
366
|
/>
|
|
371
367
|
</Grid>
|
|
372
368
|
</Grid>
|
|
373
|
-
<DeleteConfirmationDialog
|
|
369
|
+
<DeleteConfirmationDialog
|
|
370
|
+
open={openDialog}
|
|
371
|
+
onClose={handleDialogClose}
|
|
372
|
+
onConfirm={handleDialogClose}
|
|
373
|
+
id={deleteId}
|
|
374
|
+
/>
|
|
374
375
|
<DeleteMultipleConfirmationDialog
|
|
375
376
|
open={openDeleteMultipleDialog}
|
|
376
377
|
onClose={handleDeleteMultipleDialogClose}
|
|
@@ -80,11 +80,12 @@ const DataTableSM = ({ multipleActions = [], page, setPage = () => {}, disableEd
|
|
|
80
80
|
setOrderBy(property);
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
// 1️⃣ Xoá defaultQueryOptions khỏi useQuery
|
|
83
84
|
const { data, isLoading } = useQuery({
|
|
84
85
|
queryKey: [tableName, page, rowsPerPage, dataSearch, order, orderBy],
|
|
85
86
|
queryFn: () =>
|
|
86
87
|
getDatasFromTable({
|
|
87
|
-
tableName
|
|
88
|
+
tableName,
|
|
88
89
|
page: page + 1,
|
|
89
90
|
pageSize: rowsPerPage,
|
|
90
91
|
data: {
|
|
@@ -95,107 +96,76 @@ const DataTableSM = ({ multipleActions = [], page, setPage = () => {}, disableEd
|
|
|
95
96
|
})
|
|
96
97
|
}
|
|
97
98
|
}),
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
keepPreviousData: true,
|
|
100
|
+
placeholderData: () => ({
|
|
101
|
+
data: [],
|
|
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 }) => {
|
|
101
111
|
if (dataSearch?.TrangThaiXuLy !== undefined) {
|
|
102
|
-
PermissionModel.TrangThaiXuLy = dataSearch
|
|
112
|
+
PermissionModel.TrangThaiXuLy = dataSearch.TrangThaiXuLy;
|
|
103
113
|
}
|
|
114
|
+
|
|
104
115
|
setPermission(PermissionModel);
|
|
105
116
|
|
|
106
117
|
if (CountTrangThai) {
|
|
107
118
|
const keyCounter = `${tableName}_${userId}_TrangThaiXuLyCounter`;
|
|
108
119
|
localStorage.setItem(keyCounter, JSON.stringify(CountTrangThai));
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
queryClient.invalidateQueries({
|
|
121
|
+
queryKey: [tableName, "CountAllTrangThaiXuly"]
|
|
122
|
+
});
|
|
111
123
|
}
|
|
112
124
|
|
|
113
125
|
if (status) {
|
|
114
|
-
|
|
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
|
-
});
|
|
126
|
+
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
129
|
});
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
+
|
|
131
|
+
// 2️⃣ Mutation cũng cần sửa, bỏ defaultMutationOptions nếu có
|
|
132
|
+
const changeStatusMutation = useMutation({
|
|
133
|
+
mutationFn: changeStatusDataToTable,
|
|
134
|
+
onSuccess: ({ status = false, message = "Có lỗi xảy ra !" }) => {
|
|
135
|
+
toast.success(status ? message : "Thay đổi trạng thái thành công !");
|
|
130
136
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
131
137
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
132
138
|
},
|
|
133
139
|
onError: (error) => {
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
}
|
|
140
|
+
const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
|
|
141
|
+
toast.error(message);
|
|
145
142
|
}
|
|
146
143
|
});
|
|
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
|
-
}
|
|
158
144
|
|
|
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 !");
|
|
159
149
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
160
150
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
161
151
|
},
|
|
162
152
|
onError: (error) => {
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
}
|
|
153
|
+
const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
|
|
154
|
+
toast.error(message);
|
|
174
155
|
}
|
|
175
156
|
});
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
toast.success("Xóa thành công !");
|
|
182
|
-
}
|
|
157
|
+
|
|
158
|
+
const deleteMultipleMutation = useMutation({
|
|
159
|
+
mutationFn: deleteMultipleDataFromTable,
|
|
160
|
+
onSuccess: ({ status = false, message = "Có lỗi xảy ra !" }) => {
|
|
161
|
+
toast[status ? "success" : "error"](status ? message : "Xóa thành công !");
|
|
183
162
|
setSelectedItems([]);
|
|
184
163
|
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
185
164
|
queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
|
|
186
165
|
},
|
|
187
166
|
onError: (error) => {
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
}
|
|
167
|
+
const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
|
|
168
|
+
toast.error(message);
|
|
199
169
|
}
|
|
200
170
|
});
|
|
201
171
|
// Hàm gọi khi người dùng muốn xóa một bản ghi
|
|
@@ -91,35 +91,30 @@ function EditorForm({ fields, submitRef }) {
|
|
|
91
91
|
}
|
|
92
92
|
}, [selectedEditItem]);
|
|
93
93
|
|
|
94
|
-
const saveMutation = useMutation(
|
|
94
|
+
const saveMutation = useMutation({
|
|
95
|
+
mutationFn: saveDataToTable,
|
|
95
96
|
onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }, { data: { Id } }) => {
|
|
96
97
|
if (status) {
|
|
97
|
-
|
|
98
|
-
|
|
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);
|
|
98
|
+
toast.success(URL_APPLICATION_API ? message : Id === 0 ? "Thêm thành công!" : "Cập nhật thành công!");
|
|
99
|
+
queryClient.invalidateQueries({ queryKey: [tableName] });
|
|
103
100
|
setOpenEditorDialog(false);
|
|
104
101
|
} else {
|
|
105
|
-
console.log(status, Id);
|
|
106
102
|
toast.error(message);
|
|
107
103
|
}
|
|
108
104
|
},
|
|
109
105
|
onError: (error) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// Chuyển đổi đối tượng lỗi thành chuỗi để hiển thị
|
|
106
|
+
const errors = error?.response?.data?.errors;
|
|
107
|
+
if (errors) {
|
|
113
108
|
const errorMessages = Object.entries(errors)
|
|
114
109
|
.map(([field, messages]) => `${field}: ${messages.join(", ")}`)
|
|
115
110
|
.join("\n");
|
|
116
111
|
toast.error(errorMessages);
|
|
117
112
|
} else {
|
|
118
|
-
// Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
|
|
119
113
|
toast.error("Đã xảy ra lỗi không mong muốn.");
|
|
120
114
|
}
|
|
121
115
|
}
|
|
122
116
|
});
|
|
117
|
+
|
|
123
118
|
const onSubmit = (data) => {
|
|
124
119
|
fields.reduce((data, { type, field, datas, keyValueLabel, keyValue, keyLabel }) => {
|
|
125
120
|
if (type === "date") {
|