"use client"; import { useState } from "react"; import { type ColumnDef, flexRender, getCoreRowModel, useReactTable, getSortedRowModel, type SortingState, getFilteredRowModel, type ColumnFiltersState, getPaginationRowModel, } from "@tanstack/react-table"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, Filter, } from "lucide-react"; import { Skeleton } from "@/components/ui/skeleton"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; interface DataTableProps { columns: ColumnDef[]; data: TData[]; loading?: boolean; onRowClick?: (row: TData) => void; pageSize?: number; } export function DataTable({ columns, data, loading = false, onRowClick, pageSize = 5, }: DataTableProps) { const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); const [columnVisibility, setColumnVisibility] = useState({}); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: pageSize, }); const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), onSortingChange: setSorting, getSortedRowModel: getSortedRowModel(), onColumnFiltersChange: setColumnFilters, getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: setColumnVisibility, getPaginationRowModel: getPaginationRowModel(), onPaginationChange: setPagination, state: { sorting, columnFilters, columnVisibility, pagination, }, }); if (loading) { return (
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} ))} ))} {Array.from({ length: pagination.pageSize }).map((_, index) => ( {columns.map((_, colIndex) => ( ))} ))}
); } return (
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : (
{flexRender( header.column.columnDef.header, header.getContext() )} {{ asc: " 🔼", desc: " 🔽", }[header.column.getIsSorted() as string] ?? null}
{header.column.getCanFilter() && (
header.column.setFilterValue(e.target.value) } className="h-8" />
)}
)}
))}
))}
{table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( onRowClick && onRowClick(row.original)} > {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} )) ) : ( No results. )}
{/* Pagination Controls */}
Showing{" "} {table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1}{" "} to{" "} {Math.min( (table.getState().pagination.pageIndex + 1) * table.getState().pagination.pageSize, table.getFilteredRowModel().rows.length )}{" "} of {table.getFilteredRowModel().rows.length} entries

Rows per page

Page {table.getState().pagination.pageIndex + 1} of{" "} {table.getPageCount()}
); }