trithuc-mvc-react 3.1.1 → 3.1.2

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
@@ -67,6 +67,35 @@ export const getDatasFromTable = async ({ tableName, page, pageSize, data }) =>
67
67
  }
68
68
  };
69
69
 
70
+ export const getDatasFromTableDropdownlist = async ({ tableName, page, pageSize, data }) => {
71
+ try {
72
+ let res;
73
+ // Trường hợp dùng tableName với MVC4
74
+ if (!apiUrl) {
75
+ res = await api.get(`${getBaseUrl()}/Admin/${tableName}/LoadData`, {
76
+ params: {
77
+ json: JSON.stringify(data),
78
+ page,
79
+ pageSize
80
+ }
81
+ });
82
+ } else {
83
+ // Trường hợp dùng api .NET Core
84
+ res = await api.get(`${getBaseUrl()}/${apiUrl}/${tableName}/Dropdownlist`, {
85
+ params: {
86
+ PageNumber: page,
87
+ PageSize: pageSize,
88
+ ...data
89
+ }
90
+ });
91
+ }
92
+ return res.data;
93
+ } catch (error) {
94
+ console.error("Error fetching data:", error);
95
+ throw error;
96
+ }
97
+ };
98
+
70
99
  export const getDataFromTable = async ({ tableName, id }) => {
71
100
  try {
72
101
  if (!apiUrl) {
@@ -27,7 +27,7 @@ const ExportExcelButton = ({ tableName, data, size = "small" }) => {
27
27
  onClick={() => {
28
28
  handleExportExcel(tableName, data);
29
29
  }}
30
- sx={{ ml: 0.5, mr: 0.5 }}
30
+ sx={{ ml: 0.5, mr: 0.5, minWidth: "73px" }}
31
31
  >
32
32
  Excel
33
33
  </Button>
@@ -39,7 +39,7 @@ const ExportExcelButton = ({ tableName, data, size = "small" }) => {
39
39
  onClick={() => {
40
40
  handleExportExcel(tableName, data);
41
41
  }}
42
- sx={{ ml: 0.5, mr: 0.5 }}
42
+ sx={{ ml: 0.5, mr: 0.5, minWidth: "73px" }}
43
43
  >
44
44
  Excel
45
45
  </Button>
@@ -48,7 +48,16 @@ export const TableRowRenderSM = ({
48
48
 
49
49
  return (
50
50
  <TableRow hover key={row[selectedField]} selected={selected} sx={{ width: "100%" }}>
51
- <TableCell colSpan={columns.length} align="left" sx={{ width: "100%" }}>
51
+ <TableCell
52
+ colSpan={columns.length}
53
+ align="left"
54
+ sx={{
55
+ maxWidth: "100%", // Giới hạn tối đa theo container
56
+ wordBreak: "break-word", // Xuống dòng khi vượt quá
57
+ whiteSpace: "normal", // Cho phép xuống dòng
58
+ overflowWrap: "break-word" // Hỗ trợ xuống dòng trong các trình duyệt cũ
59
+ }}
60
+ >
52
61
  {columns.map(({ field, label, type = "text", valueGetter = (row) => row[field], renderCell, valueFormat = (e) => e }) => {
53
62
  const value = renderCell ? renderCell(row) : valueFormat(valueGetter(row));
54
63
  return (
@@ -1,4 +1,4 @@
1
- import { Button, Card, Grid, IconButton, Stack, Tooltip, Typography, useMediaQuery, useTheme } from "@mui/material";
1
+ import { Box, Button, Card, Grid, IconButton, Stack, Tooltip, Typography, useMediaQuery, useTheme } from "@mui/material";
2
2
 
3
3
  import { useEffect, useMemo, useState } from "react";
4
4
 
@@ -16,6 +16,7 @@ import DataTableSM from "./DataTableSM";
16
16
  import ExportExcelButton from "./ExportExcelButton";
17
17
  import { FilterGod } from "./FilterGod";
18
18
  import HuongDanButton from "./HuongDanButton";
19
+ import { useRef } from "react";
19
20
 
20
21
  DataManagement.propTypes = {
21
22
  columns: PropTypes.array,
@@ -58,7 +59,8 @@ DataManagement.propTypes = {
58
59
  disableEditor: PropTypes.bool,
59
60
  onAddClick: PropTypes.func,
60
61
  onEditClick: PropTypes.func,
61
- tabPanel: PropTypes.node
62
+ tabPanel: PropTypes.node,
63
+ titleAddButton: PropTypes.string
62
64
  };
63
65
  const getDefaultValues = (filters = []) => {
64
66
  const defaultValues = {};
@@ -98,7 +100,8 @@ function DataManagement({
98
100
  sx: {}
99
101
  }
100
102
  },
101
- defaultRowsPerPage = 5
103
+ defaultRowsPerPage = 5,
104
+ titleAddButton = "Thêm"
102
105
  }) {
103
106
  const [openEditorDialog, setOpenEditorDialog] = useState(false);
104
107
  const [selectedEditItem, setSelectedEditItem] = useState(null);
@@ -161,7 +164,8 @@ function DataManagement({
161
164
  onEditClick,
162
165
  hasTabpanel,
163
166
  backParentNavigator,
164
- defaultRowsPerPage
167
+ defaultRowsPerPage,
168
+ titleAddButton
165
169
  };
166
170
  }, [
167
171
  reserPage,
@@ -185,79 +189,183 @@ function DataManagement({
185
189
  const isSmallScreen = useMediaQuery(theme.breakpoints.down("sm")); // Xác định màn hình nhỏ
186
190
  const methods = useForm({ defaultValues: getDefaultValues(filters) });
187
191
  const { reset, setValue } = methods;
192
+
193
+ const titleText = title || "";
194
+ const [titleWidth, setTitleWidth] = useState(0);
195
+ const [minWidthValue, setMinWidthValue] = useState(0); // Thêm state cho minWidthValue
196
+
197
+ // Đo chiều rộng của titleText khi render lần đầu
198
+ useEffect(() => {
199
+ const titleElement = document.createElement("span");
200
+ titleElement.style.font = "normal 16px Arial"; // Đảm bảo phông chữ và kích thước giống như bạn dùng trong UI
201
+ titleElement.style.visibility = "hidden"; // Ẩn element tạm thời
202
+ titleElement.textContent = titleText;
203
+
204
+ document.body.appendChild(titleElement);
205
+ setTitleWidth(titleElement.offsetWidth); // Lấy chiều rộng của title
206
+ document.body.removeChild(titleElement); // Xóa element sau khi đo xong
207
+ }, [titleText]);
208
+
209
+ // Khi titleWidth thay đổi, tính toán minWidthValue
210
+ useEffect(() => {
211
+ if (titleWidth > 0) {
212
+ const calculatedMinWidth = Math.max(titleWidth, 150); // Đảm bảo minWidthValue không nhỏ hơn 150px
213
+ setMinWidthValue(calculatedMinWidth);
214
+ }
215
+ }, [titleWidth]); // Phụ thuộc vào titleWidth để đảm bảo minWidthValue được cập nhật khi chiều rộng title thay đổi
216
+
217
+ const rightBoxRef = useRef(null); // Tham chiếu đến khối phải
218
+ const [rightBoxMinWidth, setRightBoxMinWidth] = useState(0); // Lưu chiều rộng của khối phải
219
+
220
+ // Đo chiều rộng của khối phải khi component render và khi thay đổi kích thước cửa sổ
221
+ useEffect(() => {
222
+ // Hàm xử lý resize
223
+ const handleResize = () => {
224
+ const currentWindowWidth = window.innerWidth;
225
+
226
+ // Đo chiều rộng của khối phải trực tiếp từ ref
227
+ const rightBoxWidth = rightBoxRef.current ? rightBoxRef.current.offsetWidth : 0;
228
+
229
+ // Cập nhật chiều rộng khối phải (rightBoxMinWidth) tùy theo kích thước của cửa sổ và khối
230
+ if (currentWindowWidth - (minWidthValue + 30) < rightBoxWidth) {
231
+ // console.log(
232
+ // `currentWindowWidth - minWidthValue 1: ${currentWindowWidth - minWidthValue} - rightBoxWidth: ${rightBoxWidth}`
233
+ // );
234
+ setRightBoxMinWidth(currentWindowWidth - 30); // Điều chỉnh chiều rộng khối phải nếu không đủ không gian
235
+ } else {
236
+ // console.log(
237
+ // `currentWindowWidth - minWidthValue 2: ${currentWindowWidth - minWidthValue} - rightBoxWidth: ${rightBoxWidth}`
238
+ // );
239
+ setRightBoxMinWidth(rightBoxWidth); // Nếu đủ không gian, dùng chiều rộng khối phải
240
+ }
241
+ };
242
+
243
+ // Lần render đầu tiên, tính toán chiều rộng khối phải
244
+ const initialResize = () => {
245
+ const rightBoxWidth = rightBoxRef.current ? rightBoxRef.current.offsetWidth : 0;
246
+ const currentWindowWidth = window.innerWidth;
247
+
248
+ // Cập nhật giá trị minWidth ngay khi render lần đầu
249
+ if (currentWindowWidth - (minWidthValue + 30) < rightBoxWidth) {
250
+ // console.log(
251
+ // `currentWindowWidth - minWidthValue 3: ${currentWindowWidth - minWidthValue} - rightBoxWidth: ${rightBoxWidth}`
252
+ // );
253
+ setRightBoxMinWidth(currentWindowWidth - 30); // Điều chỉnh chiều rộng khối phải nếu không đủ không gian
254
+ } else {
255
+ // console.log(
256
+ // `currentWindowWidth - minWidthValue 4: ${currentWindowWidth - minWidthValue} - rightBoxWidth: ${rightBoxWidth}`
257
+ // );
258
+ setRightBoxMinWidth(rightBoxWidth); // Nếu đủ không gian, dùng chiều rộng của khối phải
259
+ }
260
+ };
261
+
262
+ // Gọi hàm tính toán ngay khi render lần đầu
263
+ if (minWidthValue > 0) {
264
+ initialResize();
265
+ }
266
+
267
+ // Lắng nghe sự kiện thay đổi kích thước cửa sổ
268
+ window.addEventListener("resize", handleResize);
269
+
270
+ // Dọn dẹp sự kiện khi component bị hủy
271
+ return () => {
272
+ window.removeEventListener("resize", handleResize);
273
+ };
274
+ }, [minWidthValue]); // Phụ thuộc vào minWidthValue để tính toán khi nó được cập nhật
275
+
276
+ // In các giá trị trong console để kiểm tra
277
+ // useEffect(() => {
278
+ // console.log("minWidthValue:", minWidthValue);
279
+ // console.log("rightBoxMinWidth:", rightBoxMinWidth);
280
+ // }, [rightBoxMinWidth]);
281
+
188
282
  return (
189
283
  <>
190
284
  <DataTableContext.Provider value={values}>
191
285
  <FormProvider {...methods}>
192
- <Stack direction="row" justifyContent={"space-between"} sx={{ mb: upXL ? 2 : 1, ...slotProps?.header?.sx }}>
193
- <Grid container spacing={{ xs: 1, xl: 1 }}>
194
- <Grid item md={9} xs={12}>
195
- <Typography variant="h4">{title}</Typography>
196
- </Grid>
197
- <Grid item md={3} xs={12} sx={{ display: "flex", justifyContent: "flex-end", alignItems: "center" }}>
198
- <HuongDanButton tableName={tableName} size={elementSize} />
199
- <Tooltip title="Làm mới">
200
- <IconButton
201
- variant="outlined"
202
- color="primary"
203
- size={elementSize}
204
- onClick={() => {
205
- setDataSearch({ ...defaults });
206
- [...filters].forEach((filter) => {
207
- filter?.onChange?.();
208
- });
209
- reset();
210
- setValue("Search");
211
- }}
212
- >
213
- <Refresh fontSize="inherit" />
214
- </IconButton>
215
- </Tooltip>
216
-
217
- {titleButtons?.map((button, index) => (
218
- <div key={index}>
219
- {button}
220
- {/* Các phần tử khác có thể được thêm ở đây nếu cần */}
221
- </div>
222
- ))}
223
- <ExportExcelButton tableName={tableName} data={dataSearch} size={elementSize} />
224
- {canCreate &&
225
- !disableAdd &&
226
- (!isSmallScreen ? (
227
- <Button
228
- size={elementSize}
229
- variant="contained"
230
- startIcon={<Add fontSize="inherit" />}
231
- onClick={(e) => {
232
- if (!disableEditor) {
233
- setOpenEditorDialog(true);
234
- setSelectedEditItem(null);
235
- }
236
- onAddClick(e);
237
- }}
238
- sx={{ ml: 0.5, mr: 0.5 }}
239
- >
240
- Thêm
241
- </Button>
242
- ) : (
243
- <Button
244
- size={elementSize}
245
- variant="contained"
246
- startIcon={<Add fontSize="inherit" />}
247
- onClick={(e) => {
248
- if (!disableEditor) {
249
- setOpenEditorDialog(true);
250
- setSelectedEditItem(null);
251
- }
252
- onAddClick(e);
253
- }}
254
- sx={{ ml: 0.5, mr: 0.5 }}
255
- >
256
- Thêm
257
- </Button>
258
- ))}
259
- </Grid>
260
- </Grid>
286
+ <Stack
287
+ direction="row"
288
+ sx={{
289
+ mb: upXL ? 1 : 1,
290
+ flexWrap: "wrap",
291
+ alignItems: "center",
292
+ gap: 1,
293
+ ...slotProps?.header?.sx
294
+ }}
295
+ >
296
+ {/* Khối trái */}
297
+ <Box
298
+ sx={{
299
+ flexGrow: 1,
300
+ Width: `${minWidthValue}px`,
301
+ textAlign: "left",
302
+ whiteSpace: "normal",
303
+ wordBreak: "break-word"
304
+ }}
305
+ >
306
+ <Typography variant="h4">{titleText}</Typography>
307
+ </Box>
308
+
309
+ {/* Khối phải */}
310
+ <Box
311
+ ref={rightBoxRef} // Tham chiếu đến phần tử này
312
+ sx={{
313
+ display: "flex",
314
+ flexWrap: "nowrap",
315
+ justifyContent: "flex-end",
316
+ alignItems: "center",
317
+ flexShrink: 0,
318
+ // minWidth: "300px", // Đảm bảo chiều rộng tối thiểu
319
+ width: rightBoxMinWidth ? `${rightBoxMinWidth}px` : "auto" // Sử dụng chiều rộng đo được
320
+ }}
321
+ >
322
+ <HuongDanButton tableName={tableName} size={elementSize} />
323
+ <Tooltip title="Làm mới">
324
+ <IconButton
325
+ variant="outlined"
326
+ color="primary"
327
+ size={elementSize}
328
+ onClick={() => {
329
+ setDataSearch({ ...defaults });
330
+ [...filters].forEach((filter) => {
331
+ filter?.onChange?.();
332
+ });
333
+ reset();
334
+ setValue("Search");
335
+ }}
336
+ >
337
+ <Refresh fontSize="inherit" />
338
+ </IconButton>
339
+ </Tooltip>
340
+
341
+ {titleButtons?.map((button, index) => (
342
+ <div key={index}>{button}</div>
343
+ ))}
344
+
345
+ <ExportExcelButton tableName={tableName} data={dataSearch} size={elementSize} />
346
+
347
+ {canCreate && !disableAdd && (
348
+ <Button
349
+ size={elementSize}
350
+ variant="contained"
351
+ startIcon={<Add fontSize="inherit" />}
352
+ onClick={(e) => {
353
+ if (!disableEditor) {
354
+ setOpenEditorDialog(true);
355
+ setSelectedEditItem(null);
356
+ }
357
+ onAddClick(e);
358
+ }}
359
+ sx={{
360
+ ml: 0.5,
361
+ mr: 0.5,
362
+ minWidth: "73px"
363
+ }}
364
+ >
365
+ {titleAddButton}
366
+ </Button>
367
+ )}
368
+ </Box>
261
369
  </Stack>
262
370
 
263
371
  <Card className="custom-card-DataManagement">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trithuc-mvc-react",
3
- "version": "3.1.1",
3
+ "version": "3.1.2",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"