'use client' import { flexRender, getCoreRowModel, useReactTable, type ColumnDef, type ColumnSort, type RowSelectionState, type SortingState, type Table, type VisibilityState } from '@tanstack/react-table' import { createContext, useContext, useEffect, useState, type ReactNode } from 'react' import { useSearchParams } from 'react-router' import { Card, CardContent } from '@repo/ui/components/ui/card' import { Table as Table_, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@repo/ui/components/ui/table' import { cn } from '@repo/ui/lib/utils' import { DataTablePagination } from './pagination' interface DataTableProps { children?: ReactNode columns: ColumnDef[] data: TData[] setSelectedRows?: (selectedRows: TData[]) => void pageIndex: number sort: SortingState pageSize: number rowCount: number hiddenColumn?: string[] } const TableContext = createContext<{ table: Table } | null>(null) export function useDataTable() { const ctx = useContext(TableContext) as { table: Table } | null if (!ctx) { throw new Error('TableContext is null') } return ctx } export function DataTable({ children, columns, data, sort, pageIndex, pageSize, rowCount, setSelectedRows, hiddenColumn = [] }: DataTableProps) { const columnVisibilityInit = Object.fromEntries( hiddenColumn.map((column) => [column, false]) ) const [searchParams, setSearchParams] = useSearchParams() const [columnVisibility, setColumnVisibility] = useState(columnVisibilityInit) const [rowSelection, setRowSelection] = useState({}) const sortParam = searchParams.get('sort') const sorting = sortParam ? sortParam.split(',').map((s) => { const [id, dir] = s.split(':') return { id, desc: dir === 'desc' } }) : sort const setPagination = (updater: any) => { const newState = typeof updater === 'function' ? updater({ pageIndex, pageSize }) : updater setRowSelection({}) setSearchParams((searchParams) => { searchParams.set('p', newState?.pageIndex.toString()) searchParams.set('perPage', newState?.pageSize.toString()) return searchParams }) } const setSorting = (updater: any) => { const newSorting = typeof updater === 'function' ? updater(sorting) : updater setSearchParams((searchParams) => { if (newSorting.length) { const sort = newSorting .map((s: ColumnSort) => `${s.id}:${s.desc ? 'desc' : 'asc'}`) .join(',') searchParams.set('sort', sort) } return searchParams }) } const table = useReactTable({ data, columns, rowCount, state: { sorting, rowSelection, columnVisibility, pagination: { pageIndex, pageSize } }, manualSorting: true, manualPagination: true, enableRowSelection: true, getRowId: (row: any) => row.id, getCoreRowModel: getCoreRowModel(), onRowSelectionChange: setRowSelection, onSortingChange: setSorting, onColumnVisibilityChange: setColumnVisibility, onPaginationChange: setPagination }) useEffect(() => { const selected = table.getSelectedRowModel().flatRows.map((r) => r.original) setSelectedRows?.(selected) }, [rowSelection]) return (
{children} {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() )} ))} )) ) : ( Nenhum resultado. )}
) }