diff --git a/src/components/SharedTable.js b/src/components/SharedTable.js index 08f730c8..841b83fc 100644 --- a/src/components/SharedTable.js +++ b/src/components/SharedTable.js @@ -1,82 +1,124 @@ -import React from "react"; +import React, { useState, useCallback, useRef } from "react"; -const SharedTable = ({ - rows = [], - columns = [], - onEdit, - onDelete, - page, - setPage, - pageSize, - setPageSize, +const SharedTable = ({ + rows = [], + columns = [], + onEdit, + onDelete, + page, + setPage, + pageSize, + setPageSize, totalCount, loading, - error + error }) => { const totalPages = Math.max(1, Math.ceil(totalCount / pageSize)); + const [colWidths, setColWidths] = useState(null); + const gridRef = useRef(null); + + const snapshotWidths = useCallback(() => { + if (!gridRef.current) return null; + const headerCells = gridRef.current.querySelectorAll("[data-col]"); + const widths = {}; + headerCells.forEach((cell) => { + widths[cell.dataset.col] = cell.getBoundingClientRect().width; + }); + return widths; + }, []); + + const handleMouseDown = useCallback((e, colKey) => { + e.preventDefault(); + const startX = e.clientX; + + const currentWidths = snapshotWidths(); + if (!currentWidths) return; + setColWidths(currentWidths); + + const colIndex = columns.findIndex((c) => c.key === colKey); + const nextColKey = colIndex < columns.length - 1 ? columns[colIndex + 1].key : null; + const startWidth = currentWidths[colKey] || 100; + const nextStartWidth = nextColKey ? (currentWidths[nextColKey] || 100) : 0; + + const onMove = (moveEvent) => { + let diff = moveEvent.clientX - startX; + const minCol = 50; + if (startWidth + diff < minCol) diff = minCol - startWidth; + if (nextColKey && nextStartWidth - diff < minCol) diff = nextStartWidth - minCol; + setColWidths((prev) => { + const updated = { ...prev, [colKey]: startWidth + diff }; + if (nextColKey) updated[nextColKey] = nextStartWidth - diff; + return updated; + }); + }; + + const onUp = () => { + document.removeEventListener("mousemove", onMove); + document.removeEventListener("mouseup", onUp); + document.body.style.cursor = ""; + document.body.style.userSelect = ""; + }; + + document.body.style.cursor = "col-resize"; + document.body.style.userSelect = "none"; + document.addEventListener("mousemove", onMove); + document.addEventListener("mouseup", onUp); + }, [snapshotWidths]); if (loading) return
Loading...
; if (error) return
{error}
; + const gridTemplate = colWidths + ? ["40px", ...columns.map((col) => `${colWidths[col.key] || 100}px`), "80px"].join(" ") + : ["40px", ...columns.map(() => "1fr"), "80px"].join(" "); + return (
- - - - + {columns.map((col) => ( - +
+ {col.render ? col.render(row[col.key], row) : row[col.key]} +
))} - - - - - {rows.map((row, idx) => ( - - - {columns.map((col) => ( - - ))} - - - ))} - -
+
+
+ +
+ {columns.map((col) => ( +
+ {col.label} + handleMouseDown(e, col.key)} + /> +
+ ))} +
Actions
+ + {rows.map((row, idx) => ( + +
-
- {col.label} - Actions
- - - {col.render - ? col.render(row[col.key], row) - : row[col.key]} - -
- {onEdit && ( - - )} - {onDelete && ( - - )} -
-
+
+
+ {onEdit && ( + + )} + {onDelete && ( + + )} +
+
+ + ))} +
- {/* Pagination */}