import { ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react'; import type { VisibilityMode } from '@/hooks/useTableVisibility'; export interface ColumnDef { key: string; label: string; render: (item: T) => React.ReactNode; sortable?: boolean; visibilityLevel: VisibilityMode; } interface EntityTableProps { columns: ColumnDef[]; rows: T[]; pinnedRows: T[]; pinnedLabel: string; showPinned: boolean; selectedId: number | null; onRowClick: (id: number) => void; sortKey: string; sortDir: 'asc' | 'desc'; onSort: (key: string) => void; visibilityMode: VisibilityMode; loading?: boolean; } const LEVEL_ORDER: VisibilityMode[] = ['essential', 'filtered', 'all']; function isVisible(colLevel: VisibilityMode, mode: VisibilityMode): boolean { return LEVEL_ORDER.indexOf(colLevel) <= LEVEL_ORDER.indexOf(mode); } function SkeletonRow({ colCount }: { colCount: number }) { return ( {Array.from({ length: colCount }).map((_, i) => (
))} ); } export function EntityTable({ columns, rows, pinnedRows, pinnedLabel, showPinned, selectedId, onRowClick, sortKey, sortDir, onSort, visibilityMode, loading = false, }: EntityTableProps) { const visibleColumns = columns.filter((col) => isVisible(col.visibilityLevel, visibilityMode)); const colCount = visibleColumns.length; const showPinnedSection = showPinned && pinnedRows.length > 0; const SortIcon = ({ colKey }: { colKey: string }) => { if (sortKey !== colKey) return ; return sortDir === 'asc' ? ( ) : ( ); }; const DataRow = ({ item }: { item: T }) => ( onRowClick(item.id)} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onRowClick(item.id); } }} tabIndex={0} role="row" aria-selected={selectedId === item.id} > {visibleColumns.map((col) => ( {col.render(item)} ))} ); return (
{visibleColumns.map((col) => ( ))} {loading ? ( Array.from({ length: 6 }).map((_, i) => ) ) : ( <> {showPinnedSection && ( <> {pinnedRows.map((item) => ( ))} )} {rows.map((item) => ( ))} )}
{col.sortable ? ( ) : ( col.label )}
{pinnedLabel}
); }