"use client"; import { useState, useMemo } from "react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; export interface Column { key: string; label: string; render?: (row: T) => React.ReactNode; } interface DataTableProps { data: T[]; columns: Column[]; searchKey?: string; filterKey?: string; filterOptions?: string[]; actions?: (row: T) => React.ReactNode; } // eslint-disable-next-line @typescript-eslint/no-explicit-any export function DataTable>({ data, columns, searchKey, filterKey, filterOptions, actions, }: DataTableProps) { const [search, setSearch] = useState(""); const [filter, setFilter] = useState("all"); const filtered = useMemo(() => { let rows = data; if (search && searchKey) { const q = search.toLowerCase(); rows = rows.filter((r) => String(r[searchKey] ?? "") .toLowerCase() .includes(q) ); } if (filter !== "all" && filterKey) { rows = rows.filter((r) => String(r[filterKey]) === filter); } return rows; }, [data, search, searchKey, filter, filterKey]); return (
{searchKey && ( setSearch(e.target.value)} className="h-8 rounded-lg glass-input px-3 text-sm text-foreground placeholder:text-muted-foreground/50 w-64" /> )} {filterKey && filterOptions && ( )}
{columns.map((col) => ( {col.label} ))} {actions && Actions} {filtered.length === 0 ? ( No results ) : ( filtered.map((row, i) => ( {columns.map((col) => ( {col.render ? col.render(row) : String(row[col.key] ?? "")} ))} {actions && ( {actions(row)} )} )) )}
); }