import React, { useState } from 'react'; import { ColumnDef, ColumnFiltersState, RowData, SortingState, VisibilityState, flexRender, getCoreRowModel, getFacetedRowModel, getFacetedUniqueValues, useReactTable, } from '@tanstack/react-table'; import { useTranslation } from 'react-i18next'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { TableSkeleton } from '@/components/ui/table-skeleton'; import { ServerSidePagination } from '@/components/server-side-pagination'; import { Project, ProjectConnection } from '../data/schema'; import { DataTableToolbar } from './data-table-toolbar'; declare module '@tanstack/react-table' { // eslint-disable-next-line @typescript-eslint/no-unused-vars interface ColumnMeta { className: string; } } interface DataTableProps { columns: ColumnDef[]; loading?: boolean; data: Project[]; pageInfo?: ProjectConnection['pageInfo']; pageSize: number; totalCount?: number; onNextPage: () => void; onPreviousPage: () => void; onPageSizeChange: (pageSize: number) => void; searchFilter: string; onSearchFilterChange: (value: string) => void; } export function ProjectsTable({ columns, data, loading, pageInfo, pageSize, totalCount, onNextPage, onPreviousPage, onPageSizeChange, searchFilter, onSearchFilterChange, }: DataTableProps) { const { t } = useTranslation(); const [rowSelection, setRowSelection] = useState({}); const [columnVisibility, setColumnVisibility] = useState({}); const [columnFilters, setColumnFilters] = useState([]); const [sorting, setSorting] = useState([]); // Sync server state to local column filters (for UI display) React.useEffect(() => { const newFilters: ColumnFiltersState = []; if (searchFilter) { // Use 'search' as a virtual column ID for the combined search newFilters.push({ id: 'search', value: searchFilter }); } setColumnFilters(newFilters); }, [searchFilter]); const handleColumnFiltersChange = (updater: ColumnFiltersState | ((prev: ColumnFiltersState) => ColumnFiltersState)) => { const newFilters = typeof updater === 'function' ? updater(columnFilters) : updater; setColumnFilters(newFilters); // Extract search filter value const searchFilterValue = newFilters.find((f) => f.id === 'search')?.value; // Only update if values actually change to prevent reset issues const newSearchFilter = typeof searchFilterValue === 'string' ? searchFilterValue : ''; if (newSearchFilter !== searchFilter) { onSearchFilterChange(newSearchFilter); } }; const table = useReactTable({ data, columns, state: { sorting, columnVisibility, rowSelection, columnFilters, }, enableRowSelection: true, onRowSelectionChange: setRowSelection, onSortingChange: setSorting, onColumnFiltersChange: handleColumnFiltersChange, onColumnVisibilityChange: setColumnVisibility, getCoreRowModel: getCoreRowModel(), manualFiltering: true, manualPagination: true, getFacetedRowModel: getFacetedRowModel(), getFacetedUniqueValues: getFacetedUniqueValues(), }); return (
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { return ( {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} ); })} ))} {loading ? ( ) : table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} )) ) : ( {t('common.noData')} )}
); }