import type React from "react"; export interface DataTableColumn { key: string; header: React.ReactNode; render?: (item: T) => React.ReactNode; className?: string; numeric?: boolean; } export interface DataTableProps { columns: DataTableColumn[]; data: T[]; keyExtractor: (item: T) => string | number; onRowClick?: (item: T) => void; renderMobileCard?: (item: T, onClick?: () => void) => React.ReactNode; emptyText?: string; } export function DataTable({ columns, data, keyExtractor, onRowClick, renderMobileCard, emptyText = "No data available", }: DataTableProps) { const handleKeyDown = (e: React.KeyboardEvent, item: T) => { if (onRowClick && (e.key === "Enter" || e.key === " ")) { e.preventDefault(); onRowClick(item); } }; if (data.length === 0) { return
{emptyText}
; } return (
{/* Mobile layout */} {renderMobileCard && (
{data.map(item => { const key = String(keyExtractor(item)); const onClick = onRowClick ? () => onRowClick(item) : undefined; return (
{renderMobileCard(item, onClick)}
); })}
)} {/* Desktop layout */}
{columns.map(col => { const headerClasses = [ "stats-table-th", col.numeric ? "stats-text-right" : "stats-text-left", col.className || "", ] .filter(Boolean) .join(" "); return ( ); })} {data.map(item => { const key = String(keyExtractor(item)); const isClickable = typeof onRowClick === "function"; const rowClasses = ["stats-table-tr", isClickable ? "stats-table-tr-clickable" : ""] .filter(Boolean) .join(" "); return ( onRowClick!(item) : undefined} onKeyDown={isClickable ? e => handleKeyDown(e, item) : undefined} tabIndex={isClickable ? 0 : undefined} role={isClickable ? "button" : undefined} > {columns.map(col => { const cellClasses = [ "stats-table-td", col.numeric ? "stats-text-right" : "stats-text-left", col.className || "", ] .filter(Boolean) .join(" "); return ( ); })} ); })}
{col.header}
{col.render ? col.render(item) : ((item as Record)[col.key] as React.ReactNode)}
); }