From 2e7f5756828f77cb08cde808c328757de57c1522 Mon Sep 17 00:00:00 2001 From: Esdras Renan Date: Mon, 20 Oct 2025 21:05:50 -0300 Subject: [PATCH] feat: standardize table pagination styling --- .../admin/clients/admin-clients-manager.tsx | 39 +--- src/components/data-table.tsx | 128 +++---------- src/components/ui/table-pagination.tsx | 177 ++++++++++++++++++ 3 files changed, 215 insertions(+), 129 deletions(-) create mode 100644 src/components/ui/table-pagination.tsx diff --git a/src/components/admin/clients/admin-clients-manager.tsx b/src/components/admin/clients/admin-clients-manager.tsx index 7fa9afb..a5941a8 100644 --- a/src/components/admin/clients/admin-clients-manager.tsx +++ b/src/components/admin/clients/admin-clients-manager.tsx @@ -13,13 +13,7 @@ import { useReactTable, SortingState, } from "@tanstack/react-table" -import { - IconChevronLeft, - IconChevronRight, - IconFilter, - IconTrash, - IconUser, -} from "@tabler/icons-react" +import { IconFilter, IconTrash, IconUser } from "@tabler/icons-react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" @@ -49,6 +43,7 @@ import { TableRow, } from "@/components/ui/table" import { Avatar, AvatarFallback } from "@/components/ui/avatar" +import { TablePagination } from "@/components/ui/table-pagination" export type AdminClient = { id: string @@ -386,29 +381,13 @@ export function AdminClientsManager({ initialClients }: { initialClients: AdminC -
-
- Página {table.getState().pagination.pageIndex + 1} de {table.getPageCount() || 1} -
-
- - -
-
+ `${selected} de ${total} selecionados`} + /> - -
-
- {table.getFilteredSelectedRowModel().rows.length} of{" "} - {table.getFilteredRowModel().rows.length} row(s) selected. -
-
-
- - -
-
- Page {table.getState().pagination.pageIndex + 1} of{" "} - {table.getPageCount()} -
-
- - - - -
-
-
- + + + `${selected} of ${total} row${total === 1 ? "" : "s"} selected.` + } + className="pb-4" + /> + = { + table: Table + pageSizeOptions?: number[] + rowsPerPageLabel?: string + showSelectedRows?: boolean + selectionLabel?: (selected: number, total: number) => React.ReactNode + className?: string +} + +function buildPaginationRange(currentPage: number, pageCount: number) { + if (pageCount <= 7) { + return Array.from({ length: pageCount }, (_, index) => index + 1) + } + + const range: Array = [1] + const left = Math.max(2, currentPage - 1) + const right = Math.min(pageCount - 1, currentPage + 1) + + if (left > 2) { + range.push("ellipsis-left") + } + + for (let page = left; page <= right; page += 1) { + range.push(page) + } + + if (right < pageCount - 1) { + range.push("ellipsis-right") + } + + range.push(pageCount) + return range +} + +export function TablePagination({ + table, + pageSizeOptions = [10, 20, 30, 50], + rowsPerPageLabel = "Itens por página", + showSelectedRows = false, + selectionLabel, + className, +}: TablePaginationProps) { + const pageIndex = table.getState().pagination.pageIndex + const pageSize = table.getState().pagination.pageSize + const pageCount = Math.max(table.getPageCount(), 1) + const currentPage = Math.min(pageIndex + 1, pageCount) + + const totalRows = table.getFilteredRowModel().rows.length + const currentRows = table.getRowModel().rows.length + + const rangeStart = totalRows === 0 ? 0 : pageIndex * pageSize + 1 + const rangeEnd = totalRows === 0 ? 0 : rangeStart + currentRows - 1 + + const selectedCount = table.getFilteredSelectedRowModel().rows.length + + const paginationRange = useMemo( + () => buildPaginationRange(currentPage, pageCount), + [currentPage, pageCount] + ) + + const handlePageChange = (pageNumber: number) => { + table.setPageIndex(pageNumber - 1) + } + + return ( +
+ {showSelectedRows ? ( +
+ {selectionLabel + ? selectionLabel(selectedCount, totalRows) + : `${selectedCount} de ${totalRows} selecionados`} +
+ ) : ( +
Paginação de tabela
+ )} + +
+ {pageSizeOptions.length > 0 ? ( +
+ {rowsPerPageLabel} + +
+ ) : null} + +
+ + {totalRows === 0 + ? "Nenhum registro" + : `Mostrando ${rangeStart}-${rangeEnd} de ${totalRows}`} + + + + + table.previousPage()} + /> + + {paginationRange.map((item, index) => { + if (typeof item === "number") { + return ( + + { + event.preventDefault() + handlePageChange(item) + }} + > + {item} + + + ) + } + return ( + + + + ) + })} + + table.nextPage()} + /> + + + +
+
+
+ ) +}