import { useState } from "react"; import { useNavigate } from "react-router-dom"; import "./DataTable.css"; /** * Enterprise-style data table with sortable columns, compact rows, * and inline status badges. */ export function DataTable({ columns, data, onRowClick, getRowLink, emptyMessage = "No data." }) { const navigate = useNavigate(); const [sortKey, setSortKey] = useState(null); const [sortDir, setSortDir] = useState("asc"); const handleSort = (key) => { if (!key) return; if (sortKey === key) { setSortDir((d) => (d === "asc" ? "desc" : "asc")); } else { setSortKey(key); setSortDir("asc"); } }; let sortedData = data; if (sortKey) { sortedData = [...data].sort((a, b) => { const aVal = a[sortKey] ?? ""; const bVal = b[sortKey] ?? ""; if (aVal < bVal) return sortDir === "asc" ? -1 : 1; if (aVal > bVal) return sortDir === "asc" ? 1 : -1; return 0; }); } if (!data || data.length === 0) { return

{emptyMessage}

; } const handleRowClick = (e, row) => { if (e.target.closest("button, a, input, select, textarea")) { return; } if (onRowClick) { onRowClick(row); } else if (getRowLink) { const link = getRowLink(row); if (link) navigate(link); } }; return (
{columns.map((col) => ( ))} {sortedData.map((row, i) => { const rowLink = getRowLink ? getRowLink(row) : null; const isClickable = Boolean(onRowClick || rowLink); return ( isClickable && handleRowClick(e, row)} > {columns.map((col) => ( ))} ); })}
col.sortable && handleSort(col.key)} style={col.width ? { width: col.width } : undefined} > {col.label} {col.sortable && sortKey === col.key && ( {sortDir === "asc" ? " ↑" : " ↓"} )}
{col.render ? col.render(row[col.key], row) : row[col.key]}
); }