'use client'; import { useState, useMemo } from 'react'; import { useReactTable, getCoreRowModel, getSortedRowModel, getPaginationRowModel, getFilteredRowModel, ColumnDef, SortingState, ColumnFiltersState, FilterFn, } from '@tanstack/react-table'; import { rankItem } from '@tanstack/match-sorter-utils'; // Типы данных type Person = { id: number; name: string; age: number; email: string; department: string; salary: number; }; // Кастомная функция фильтрации const fuzzyFilter: FilterFn = (row, columnId, value, addMeta) => { const itemRank = rankItem(row.getValue(columnId), value); addMeta({ itemRank }); return itemRank.passed; }; // Определяем тип для фильтров declare module '@tanstack/react-table' { interface FilterFns { fuzzy: FilterFn; } } export default function DataTable() { // Данные const [data] = useState([ { id: 1, name: 'Иван Петров', age: 28, email: 'ivan@example.com', department: 'IT', salary: 80000 }, { id: 2, name: 'Анна Сидорова', age: 32, email: 'anna@example.com', department: 'HR', salary: 65000 }, { id: 3, name: 'Сергей Иванов', age: 45, email: 'sergey@example.com', department: 'Финансы', salary: 95000 }, { id: 4, name: 'Мария Кузнецова', age: 26, email: 'maria@example.com', department: 'Маркетинг', salary: 60000 }, { id: 5, name: 'Алексей Смирнов', age: 38, email: 'alex@example.com', department: 'IT', salary: 85000 }, { id: 6, name: 'Ольга Васнецова', age: 29, email: 'olga@example.com', department: 'HR', salary: 62000 }, { id: 7, name: 'Дмитрий Орлов', age: 41, email: 'dmitry@example.com', department: 'Финансы', salary: 92000 }, { id: 8, name: 'Екатерина Новикова', age: 35, email: 'ekaterina@example.com', department: 'Маркетинг', salary: 70000 }, ]); // Состояния const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); const [globalFilter, setGlobalFilter] = useState(''); const [rowSelection, setRowSelection] = useState({}); // Определение колонок const columns = useMemo[]>( () => [ { id: 'select', header: ({ table }) => ( ), cell: ({ row }) => ( ), enableSorting: false, enableColumnFilter: false, }, { accessorKey: 'id', header: 'ID', cell: (info) => info.getValue(), }, { accessorKey: 'name', header: 'Имя', cell: (info) => info.getValue(), filterFn: fuzzyFilter, }, { accessorKey: 'age', header: 'Возраст', cell: (info) => info.getValue(), }, { accessorKey: 'email', header: 'Email', cell: (info) => info.getValue(), }, { accessorKey: 'department', header: 'Отдел', cell: (info) => info.getValue(), }, { accessorKey: 'salary', header: 'Зарплата', cell: (info) => `$${Number(info.getValue()).toLocaleString()}`, }, ], [] ); // Создание таблицы const table = useReactTable({ data, columns, filterFns: { fuzzy: fuzzyFilter, }, state: { sorting, columnFilters, globalFilter, rowSelection, }, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, onGlobalFilterChange: setGlobalFilter, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getPaginationRowModel: getPaginationRowModel(), getFilteredRowModel: getFilteredRowModel(), globalFilterFn: fuzzyFilter, // Используем саму функцию, а не строку }); return (

Таблица сотрудников

{/* Глобальный поиск */}
setGlobalFilter(e.target.value)} className="px-4 py-2 border rounded-md w-full max-w-md" />
{/* Фильтры по колонкам */}
{table.getAllColumns() .filter(column => column.getCanFilter() && column.id !== 'select') .map(column => (
{column.id === 'department' ? ( ) : column.id === 'age' ? ( column.setFilterValue(e.target.value ? parseInt(e.target.value) : undefined)} className="px-3 py-1 border rounded w-32" /> ) : ( column.setFilterValue(e.target.value)} className="px-3 py-1 border rounded" /> )}
))}
{/* Таблица */}
{table.getHeaderGroups().map(headerGroup => ( {headerGroup.headers.map(header => ( ))} ))} {table.getRowModel().rows.map(row => ( {row.getVisibleCells().map(cell => ( ))} ))}
{header.isPlaceholder ? null : typeof header.column.columnDef.header === 'string' ? header.column.columnDef.header : header.column.id} {{ asc: ' 🔼', desc: ' 🔽', }[header.column.getIsSorted() as string] ?? null}
{typeof cell.column.columnDef.cell === 'function' ? cell.column.columnDef.cell(cell.getContext()) : cell.getValue() as string}
{/* Пагинация */}
Страница{' '} {table.getState().pagination.pageIndex + 1} из {table.getPageCount()} Всего строк: {data.length} | Отфильтровано: {table.getFilteredRowModel().rows.length}
); }