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 CHANGED
@@ -87,49 +87,28 @@ export default api;
87
87
  export const getDatasFromTable = async ({ tableName, page, pageSize, data }) => {
88
88
  try {
89
89
  let res;
90
-
90
+ // Trường hợp dùng tableName với MVC4
91
91
  if (!apiUrl) {
92
- // MVC4
93
92
  res = await api.get(`${getBaseUrl()}/Admin/${tableName}/LoadData`, {
94
93
  params: {
95
- json: JSON.stringify(data ?? {}),
94
+ json: JSON.stringify(data),
96
95
  page,
97
96
  pageSize
98
97
  }
99
98
  });
100
99
  } else {
101
- // .NET Core
100
+ // Trường hợp dùng api .NET Core
102
101
  res = await api.get(`${getBaseUrl()}/${apiUrl}/${tableName}`, {
103
102
  params: {
104
103
  PageNumber: page,
105
104
  PageSize: pageSize,
106
- ...(data ?? {})
105
+ ...data
107
106
  }
108
107
  });
109
108
  }
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
-
128
109
  return res.data;
129
110
  } catch (error) {
130
- // console.error("Error fetching data:", error);
131
-
132
- // ✅ THROW → React Query onError xử lý
111
+ console.error("Error fetching data:", error);
133
112
  throw error;
134
113
  }
135
114
  };
@@ -165,278 +144,188 @@ export const getDatasFromTableDropdownlist = async ({ tableName, page, pageSize,
165
144
 
166
145
  export const getDataFromTable = async ({ tableName, id }) => {
167
146
  try {
168
- let res;
169
-
170
147
  if (!apiUrl) {
171
- // MVC4
172
- res = await api.get(`${getBaseUrl()}/Admin/${tableName}/GetDetail`, {
173
- params: { id }
148
+ const url = `${getBaseUrl()}/Admin/${tableName}/GetDetail`;
149
+ const res = await api.get(url, {
150
+ params: {
151
+ id
152
+ }
174
153
  });
154
+ return res.data;
175
155
  } else {
176
- // .NET Core
177
- res = await api.get(`${getBaseUrl()}/${apiUrl}/${tableName}/${id}`);
156
+ const url = `${getBaseUrl()}/${apiUrl}/${tableName}/${id}`;
157
+ const res = await api.get(url);
158
+ return res.data;
178
159
  }
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;
192
160
  } catch (error) {
193
- // console.error("Error fetching detail:", error);
194
- throw error; // React Query onError xử lý
161
+ console.error("Error fetching data:", error);
162
+ throw error;
195
163
  }
196
164
  };
197
165
 
198
166
  export const deleteDataFromTable = async ({ tableName, id }) => {
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
-
167
+ if (!apiUrl) {
168
+ // Khi không có apiUrl, thực hiện DELETE đến URL cụ thể với tableName
169
+ const res = await api.post(`${getBaseUrl()}/Admin/${tableName}/Delete`, {
170
+ id
171
+ });
172
+ return res.data;
173
+ } else {
174
+ // Khi có apiUrl, chuyển id thành mảng string và thực hiện DELETE
175
+ const ids = Array.isArray(id) ? id : [id]; // Chuyển id thành mảng nếu chưa phải là mảng
176
+ const res = await api.delete(`${getBaseUrl()}/${apiUrl}/${tableName}`, {
177
+ data: ids, // Truyền ids như là dữ liệu của body
178
+ headers: {
179
+ "Content-Type": "application/json-patch+json" // Đảm bảo Content-Type là đúng
180
+ }
181
+ });
227
182
  return res.data;
228
- } catch (error) {
229
- // console.error("Error deleting data:", error);
230
- throw error; // React Query mutation onError xử lý
231
183
  }
232
184
  };
233
-
234
185
  export const deleteMultipleDataFromTable = async ({ tableName, ids }) => {
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
-
186
+ if (!apiUrl) {
187
+ const res = await api.post(`${getBaseUrl()}/Admin/${tableName}/DeleteMulti`, {
188
+ ids
189
+ });
190
+ return res.data;
191
+ } else {
192
+ const res = await api.delete(`${getBaseUrl()}/${apiUrl}/${tableName}`, {
193
+ data: ids, // Truyền ids như là dữ liệu của body
194
+ headers: {
195
+ "Content-Type": "application/json-patch+json" // Đảm bảo Content-Type là đúng
196
+ }
197
+ });
266
198
  return res.data;
267
- } catch (error) {
268
- // console.error("Error deleting multiple data:", error);
269
- throw error; // để useMutation onError xử lý
270
199
  }
271
200
  };
272
-
273
201
  export const saveDataToTable = async ({ tableName, 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
- });
202
+ if (!apiUrl) {
203
+ const res = await api.post(`${getBaseUrl()}/Admin/${tableName}/SaveData`, {
204
+ json: JSON.stringify({ ...data })
205
+ });
206
+ return res.data;
207
+ } else {
208
+ if (!data.Id || data.Id === "0") {
209
+ // Khi không có ID, thực hiện POST đến apiUrl
210
+ const res = await api.post(`${getBaseUrl()}/${apiUrl}/${tableName}`, data);
211
+ return res.data;
282
212
  } else {
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
- }
213
+ // Khi có ID, thực hiện PUT đến apiUrl với ID trong URL
214
+ const res = await api.put(`${getBaseUrl()}/${apiUrl}/${tableName}/${data.Id}`, data);
215
+ return res.data;
291
216
  }
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ý
310
217
  }
311
218
  };
312
-
313
219
  export const changeStatusDataToTable = async ({ tableName, id, fieldName }) => {
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
- };
340
- }
341
-
220
+ if (!apiUrl) {
221
+ const res = await api.post(`${getBaseUrl()}/Admin/${tableName}/ChangeStatus`, {
222
+ id
223
+ });
342
224
  return res.data;
343
- } catch (error) {
344
- // console.error("Error changing status:", error);
345
- throw error; // để useMutation onError xử lý
225
+ } else {
226
+ try {
227
+ if (fieldName) {
228
+ const res = await api.post(
229
+ `${getBaseUrl()}/${apiUrl ? `${apiUrl}/` : "Admin/"}${tableName}/ChangeStatus`,
230
+ {
231
+ id,
232
+ fieldName
233
+ },
234
+ {
235
+ headers: {
236
+ "Content-Type": "application/json-patch+json" // Đảm bảo Content-Type là đúng
237
+ }
238
+ }
239
+ );
240
+ return res.data;
241
+ } else {
242
+ const res = await api.post(`${getBaseUrl()}/${apiUrl ? `${apiUrl}/` : "Admin/"}${tableName}/ChangeStatus`, id, {
243
+ headers: {
244
+ "Content-Type": "application/json-patch+json" // Đảm bảo Content-Type là đúng
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 };
253
+ }
346
254
  }
347
255
  };
348
256
 
349
257
  export const exportExcel = async ({ tableName, data }) => {
350
- try {
351
- let res;
352
-
353
- if (!apiUrl) {
354
- // MVC4
355
- res = await api.get(`${getBaseUrl()}/Admin/${tableName}/ExportData`, {
258
+ if (!apiUrl) {
259
+ const res = await api.get(`${getBaseUrl()}/Admin/${tableName}/ExportData`, {
260
+ params: {
261
+ json: JSON.stringify(data)
262
+ }
263
+ });
264
+ return res.data;
265
+ } else {
266
+ const res = await api.get(
267
+ `${getBaseUrl()}/${apiUrl}/${tableName}/ExportData`,
268
+ {
356
269
  params: {
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;
270
+ ...data
271
+ }
272
+ },
273
+ {
274
+ headers: {
275
+ "Content-Type": "application/json-patch+json" // Đảm bảo Content-Type là đúng
276
+ }
277
+ }
278
+ );
279
+ return res.data;
378
280
  }
379
281
  };
380
282
 
381
283
  export const uploadFile = async (formData) => {
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);
284
+ // 1. Lấy URL hiện tại
285
+ const currentUrl = window.location.href;
286
+
287
+ // 2. Append vào formData
288
+ formData.append("currentUrl", currentUrl);
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
+ }
387
307
  });
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
-
412
308
  return res.data;
413
- } catch (error) {
414
- // console.error("Error uploading file:", error);
415
- throw error;
416
309
  }
417
310
  };
418
311
 
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);
312
+ export const huongDan = async ({ data }) => {
313
+ if (!apiUrl) {
440
314
  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;
441
330
  }
442
331
  };
@@ -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 "@tanstack/react-query";
16
+ import { useMutation, useQuery, useQueryClient } from "react-query";
17
17
  import { toast } from "react-toastify";
18
18
  import {
19
19
  changeStatusDataToTable,
@@ -63,16 +63,17 @@ const DataTable = ({ multipleActions = [], page, setPage = () => {}, disableEdit
63
63
  const [rowsPerPage, setRowsPerPage] = useState(defaultRowsPerPage);
64
64
  const [openDialog, setOpenDialog] = useState(false);
65
65
  const [deleteId, setDeleteId] = useState(null);
66
- const defaultSortColumn = columns.find((c) => c.defaultSort);
67
66
 
68
- const [orderBy, setOrderBy] = useState(defaultSortColumn?.field || "");
69
- const [order, setOrder] = useState(defaultSortColumn?.defaultOrder || "asc");
67
+ const [orderBy, setOrderBy] = useState("");
68
+ const [order, setOrder] = useState("asc");
69
+
70
70
  useEffect(() => {
71
- const defaultSortColumn = columns.find((c) => c.defaultSort);
72
- if (defaultSortColumn) {
73
- setOrderBy(defaultSortColumn.field);
74
- setOrder(defaultSortColumn.defaultOrder || "asc");
75
- }
71
+ if (!Array.isArray(columns) || columns.length === 0) return;
72
+
73
+ const defaultSortColumn = columns.find((c) => c.defaultSort) || columns[0];
74
+
75
+ setOrderBy(defaultSortColumn.field);
76
+ setOrder(defaultSortColumn.defaultOrder || "asc");
76
77
  }, [columns]);
77
78
 
78
79
  const handleRequestSort = (event, property) => {
@@ -81,12 +82,11 @@ const DataTable = ({ multipleActions = [], page, setPage = () => {}, disableEdit
81
82
  setOrderBy(property);
82
83
  };
83
84
 
84
- // 1️⃣ Xoá defaultQueryOptions khỏi useQuery
85
85
  const { data, isLoading } = useQuery({
86
86
  queryKey: [tableName, page, rowsPerPage, dataSearch, order, orderBy],
87
87
  queryFn: () =>
88
88
  getDatasFromTable({
89
- tableName,
89
+ tableName: tableName,
90
90
  page: page + 1,
91
91
  pageSize: rowsPerPage,
92
92
  data: {
@@ -97,76 +97,96 @@ const DataTable = ({ multipleActions = [], page, setPage = () => {}, disableEdit
97
97
  })
98
98
  }
99
99
  }),
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 }) => {
100
+ defaultQueryOptions,
101
+ // keepPreviousData: true,
102
+ onSuccess: ({ PermissionModel, CountTrangThai, status }) => {
112
103
  if (dataSearch?.TrangThaiXuLy !== undefined) {
113
- PermissionModel.TrangThaiXuLy = dataSearch.TrangThaiXuLy;
104
+ PermissionModel.TrangThaiXuLy = dataSearch?.TrangThaiXuLy;
114
105
  }
115
-
116
106
  setPermission(PermissionModel);
117
107
 
118
108
  if (CountTrangThai) {
119
109
  const keyCounter = `${tableName}_${userId}_TrangThaiXuLyCounter`;
120
110
  localStorage.setItem(keyCounter, JSON.stringify(CountTrangThai));
121
- queryClient.invalidateQueries({
122
- queryKey: [tableName, "CountAllTrangThaiXuly"]
123
- });
111
+ // 👉 Invalidate query để Tab reload ngay
112
+ queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
124
113
  }
125
114
 
126
115
  if (status) {
127
- window.scrollTo({ top: 0, behavior: "smooth" });
116
+ // console.log("LOAD LAI PermissionModel");
117
+ // Cuộn lên đầu trang khi tải dữ liệu thành công
118
+ window.scrollTo({
119
+ top: 0, // Vị trí pixel muốn cuộn tới
120
+ behavior: "smooth" // Tùy chọn cuộn mượt
121
+ });
128
122
  }
129
123
  }
130
124
  });
131
125
 
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 !");
126
+ const changeStatusMutation = useMutation(changeStatusDataToTable, {
127
+ onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }) => {
128
+ if (URL_APPLICATION_API) {
129
+ toast.success(message);
130
+ } else {
131
+ toast.success("Thay đổi trạng thái thành công !");
132
+ }
137
133
  queryClient.invalidateQueries({ queryKey: [tableName] });
138
134
  queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
139
135
  },
140
136
  onError: (error) => {
141
- const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
142
- toast.error(message);
137
+ if (error.response && error.response.data) {
138
+ const message = error.response.data.message;
139
+ toast.error(message);
140
+ } else {
141
+ // Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
142
+ toast.error("Đã xảy ra lỗi không mong muốn.");
143
+ }
143
144
  }
144
145
  });
146
+ const deleteMutation = useMutation(deleteDataFromTable, {
147
+ onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }) => {
148
+ if (status) {
149
+ if (URL_APPLICATION_API) {
150
+ toast.success(message);
151
+ } else {
152
+ toast.success("Xóa thành công !");
153
+ }
154
+ } else {
155
+ toast.error(" Có lỗi xảy ra !");
156
+ }
145
157
 
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 !");
150
158
  queryClient.invalidateQueries({ queryKey: [tableName] });
151
159
  queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
152
160
  },
153
161
  onError: (error) => {
154
- const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
155
- toast.error(message);
162
+ if (error.response && error.response.data) {
163
+ const message = error.response.data.message;
164
+ toast.error(message);
165
+ } else {
166
+ // Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
167
+ toast.error("Đã xảy ra lỗi không mong muốn.");
168
+ }
156
169
  }
157
170
  });
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 !");
171
+ const deleteMultipleMutation = useMutation(deleteMultipleDataFromTable, {
172
+ onSuccess: ({ status = false, message = " Có lỗi xảy ra !" }) => {
173
+ if (URL_APPLICATION_API) {
174
+ toast.success(message);
175
+ } else {
176
+ toast.success("Xóa thành công !");
177
+ }
163
178
  setSelectedItems([]);
164
179
  queryClient.invalidateQueries({ queryKey: [tableName] });
165
180
  queryClient.invalidateQueries({ queryKey: [tableName, "CountAllTrangThaiXuly"] });
166
181
  },
167
182
  onError: (error) => {
168
- const message = error?.response?.data?.message || "Đã xảy ra lỗi không mong muốn.";
169
- toast.error(message);
183
+ if (error.response && error.response.data) {
184
+ const message = error.response.data.message;
185
+ toast.error(message);
186
+ } else {
187
+ // Nếu lỗi không theo định dạng mong đợi, hiển thị thông tin lỗi chung
188
+ toast.error("Đã xảy ra lỗi không mong muốn.");
189
+ }
170
190
  }
171
191
  });
172
192
  // Hàm gọi khi người dùng muốn xóa một bản ghi