"use client"; import React, { useState } from "react"; import { ColumnDef, flexRender, getCoreRowModel, useReactTable, getPaginationRowModel, getSortedRowModel, SortingState, getFilteredRowModel, ColumnFiltersState, Column } from "@tanstack/react-table"; import { Input } from "@/shared/components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/shared/components/ui/table"; import { Button } from "@/shared/components/ui/button"; import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, ChevronsUpDown } from "lucide-react"; interface DataTableProps { columns: ColumnDef[]; data: TData[]; searchColumn?: string; searchPlaceholder?: string; pageSize?: number; } export function createSortableHeader(label: string) { const SortableHeader = ({ column }: { column: Column }) => { return ( ); }; SortableHeader.displayName = `SortableHeader(${label})`; return SortableHeader; } export function DataTable({ columns, data, searchColumn, searchPlaceholder = "Search...", pageSize = 10 }: Readonly>) { const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); const [searchValue, setSearchValue] = useState(""); const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, state: { sorting, columnFilters, }, initialState: { pagination: { pageSize, }, }, }); const handleSearch = (value: string) => { setSearchValue(value); if (searchColumn) { table.getColumn(searchColumn)?.setFilterValue(value); } }; const renderPageNumbers = () => { const currentPage = table.getState().pagination.pageIndex + 1; const pageCount = table.getPageCount(); const pagesToShow = 5; const halfPagesToShow = Math.floor(pagesToShow / 2); let startPage = Math.max(1, currentPage - halfPagesToShow); let endPage = Math.min(pageCount, currentPage + halfPagesToShow); if (currentPage <= halfPagesToShow) { endPage = Math.min(pagesToShow, pageCount); } if (currentPage >= pageCount - halfPagesToShow) { startPage = Math.max(1, pageCount - pagesToShow + 1); } const pages = []; for (let i = startPage; i <= endPage; i++) { pages.push( ); } return (
{currentPage > halfPagesToShow + 1 && pageCount > pagesToShow && ( <> ... )} {pages} {currentPage < pageCount - halfPagesToShow && pageCount > pagesToShow && ( <> ... )}
); }; return (
{/* Search Input */} {searchColumn && (
handleSearch(e.target.value)} className="max-w-sm" />
)} {/* Table */} {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {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())} ))} )) ) : ( No results. )}
{/* Pagination */}
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} results
{renderPageNumbers()}
); }