"use client" import { ColumnDef, flexRender, getCoreRowModel, useReactTable, getPaginationRowModel, getSortedRowModel, SortingState, ColumnFiltersState, getFilteredRowModel, } from "@tanstack/react-table"; import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table"; import {Input} from "@/components/ui/input"; import {ReactNode, useMemo, useState} from "react"; import {TablePagination} from "./table-pagination"; import {Checkbox} from "@/components/ui/checkbox"; import {Button} from "@/components/ui/button"; import {useRouter} from "next/navigation"; interface DataTableProps { columns: ColumnDef[]; data: TData[]; enableFilter?: boolean; enableSelect?: boolean; enablePagination?: boolean; paginationOptions?: { pageSize: number[]; pageVisible: number; className?: string; }; filterOptions?: { title?: string; key: string; }; emptyButton?: { text: string; variant: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined; path: string; }; highlightRow?: (row: TData) => boolean; selectedActions?: (rows: TData[]) => ReactNode; } export function DataTable({ columns, data, enableFilter = false, enablePagination = true, enableSelect = true, paginationOptions = {pageSize: [10, 20, 30, 40, 50, 100], pageVisible: 3}, filterOptions = {key: "id", title: "Filter by ID"}, emptyButton, highlightRow, selectedActions, }: DataTableProps) { const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); const [rowSelection, setRowSelection] = useState({}); const finalColumns = useMemo(() => { const selectColumnExists = columns.some((column) => column.id === "select"); if (enableSelect && data.length > 0 && !selectColumnExists) { return [ { id: "select", header: ({table}: {table: any}) => ( table.toggleAllPageRowsSelected(!!value)} aria-label="Select all" /> ), cell: ({row}: {row: any}) => ( row.toggleSelected(!!value)} aria-label="Select row" /> ), enableSorting: false, enableHiding: false, }, ...columns, ]; } return columns; }, [columns, enableSelect, data.length]); const table = useReactTable({ data, columns: finalColumns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), onSortingChange: setSorting, getSortedRowModel: getSortedRowModel(), onColumnFiltersChange: setColumnFilters, getFilteredRowModel: getFilteredRowModel(), onRowSelectionChange: setRowSelection, getRowId: (row: any) => row.id || row.uuid, autoResetPageIndex: false, autoResetExpanded: false, enableRowSelection: true, state: { sorting, columnFilters, rowSelection, }, }); const router = useRouter(); return (
{enableFilter || selectedActions && (
{enableFilter && ( table.getColumn(filterOptions.key)?.setFilterValue(event.target.value)} className="max-w-sm" /> )} {/*{selectedActions && table.getSelectedRowModel().rows.length > 0 && (*/} {selectedActions && ( selectedActions(table.getSelectedRowModel().rows.map(row => row.original)) )}
)}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { return ( {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} ); })} ))} {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} )) ) : ( {emptyButton ? ( ) : (
No data available
)}
)}
{enableSelect && table.getFilteredRowModel().rows.length >= 1 && (
{table.getFilteredSelectedRowModel().rows.length} of {table.getFilteredRowModel().rows.length} row(s) selected.
)} {enablePagination && table.getFilteredRowModel().rows.length >= 1 && ( { const rowCount = table.getFilteredRowModel().rows.length; const allSizes = paginationOptions.pageSize.sort((a, b) => a - b); const validSizes = allSizes.filter((size) => size <= rowCount); const nextSize = allSizes.find((size) => size > rowCount); if (nextSize) validSizes.push(nextSize); return validSizes; })()} className={paginationOptions.className} /> )}
); }