import { useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { ChevronUp, ChevronDown, Search, ChevronsLeft, ChevronsRight, ChevronLeft, ChevronRight } from 'lucide-react'; import { cn } from '@/lib/utils'; export function DataTable({ columns, data, onRowClick, emptyMessage = 'No data found', searchable = true, className }) { const [search, setSearch] = useState(''); const [sortCol, setSortCol] = useState(null); const [sortDir, setSortDir] = useState('asc'); const [page, setPage] = useState(1); const perPage = 15; const filtered = search ? data.filter(row => columns.some(col => { const val = col.accessor ? row[col.accessor] : ''; return String(val ?? '').toLowerCase().includes(search.toLowerCase()); })) : data; const sorted = sortCol ? [...filtered].sort((a, b) => { const va = a[sortCol] ?? ''; const vb = b[sortCol] ?? ''; const cmp = String(va).localeCompare(String(vb), undefined, { numeric: true }); return sortDir === 'asc' ? cmp : -cmp; }) : filtered; const totalPages = Math.ceil(sorted.length / perPage); const paginated = sorted.slice((page - 1) * perPage, page * perPage); const handleSort = (accessor) => { if (sortCol === accessor) { setSortDir(d => d === 'asc' ? 'desc' : 'asc'); } else { setSortCol(accessor); setSortDir('asc'); } setPage(1); }; return (
{searchable && (
{ setSearch(e.target.value); setPage(1); }} className="w-full pl-9 pr-4 py-2 bg-white/5 border border-white/10 rounded-lg text-sm text-white placeholder:text-white/30 focus:outline-none focus:border-cyan-500/50 focus:bg-white/[0.07] transition-all" />
)}
{columns.map(col => ( ))} {paginated.length === 0 ? ( ) : ( paginated.map((row, i) => ( onRowClick?.(row)} className={cn( 'border-b border-white/[0.05] last:border-0 transition-colors', onRowClick && 'cursor-pointer hover:bg-white/[0.03]' )} > {columns.map(col => ( ))} )) )}
col.accessor && handleSort(col.accessor)} >
{col.header} {col.accessor && sortCol === col.accessor && ( sortDir === 'asc' ? : )}
{emptyMessage}
{col.render ? col.render(row) : row[col.accessor]}
{totalPages > 1 && (
{filtered.length} results
Page {page} of {totalPages}
)}
); }