DataTable.tsx
1 import { cn } from '@/lib/utils' 2 3 interface Column<T> { 4 key: string 5 header: string 6 render: (row: T) => React.ReactNode 7 className?: string 8 } 9 10 interface DataTableProps<T> { 11 columns: Column<T>[] 12 data: T[] 13 keyExtractor: (row: T) => string | number 14 emptyMessage?: string 15 className?: string 16 } 17 18 export function DataTable<T>({ 19 columns, 20 data, 21 keyExtractor, 22 emptyMessage = 'No data', 23 className, 24 }: DataTableProps<T>) { 25 return ( 26 <table className={cn('w-full border-collapse text-sm', className)}> 27 <thead> 28 <tr> 29 {columns.map(col => ( 30 <th 31 key={col.key} 32 className={cn( 33 'px-4 py-3 text-left font-semibold text-xs uppercase tracking-wider text-[#8b949e] border-b border-[#30363d]', 34 col.className, 35 )} 36 > 37 {col.header} 38 </th> 39 ))} 40 </tr> 41 </thead> 42 <tbody> 43 {data.length === 0 ? ( 44 <tr> 45 <td 46 colSpan={columns.length} 47 className="px-4 py-8 text-center text-[#6e7681]" 48 > 49 {emptyMessage} 50 </td> 51 </tr> 52 ) : ( 53 data.map(row => ( 54 <tr 55 key={keyExtractor(row)} 56 className="border-b border-[#30363d] last:border-b-0 hover:bg-[#21262d] transition-colors" 57 > 58 {columns.map(col => ( 59 <td key={col.key} className={cn('px-4 py-3', col.className)}> 60 {col.render(row)} 61 </td> 62 ))} 63 </tr> 64 )) 65 )} 66 </tbody> 67 </table> 68 ) 69 }