"use client"; import { useState, useMemo } from "react"; import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { PaginationProps, PaginationConfig } from "@/lib/types"; const DEFAULT_CONFIG: PaginationConfig = { itemsPerPage: 20, maxVisiblePages: 5, showFirstLast: true, showPrevNext: true, }; export function Pagination({ currentPage, totalPages, totalItems, itemsPerPage, onPageChange, onItemsPerPageChange, config = {}, className = "", }: PaginationProps) { const [localItemsPerPage, setLocalItemsPerPage] = useState(itemsPerPage); const finalConfig = useMemo( () => ({ ...DEFAULT_CONFIG, ...config }), [config] ); // Calcular índices dos itens const startIndex = (currentPage - 1) * itemsPerPage + 1; const endIndex = Math.min(currentPage * itemsPerPage, totalItems); // Gerar array de páginas visíveis com responsividade const visiblePages = useMemo(() => { const pages: (number | string)[] = []; // Reduzir maxVisiblePages em mobile (assumindo que usaremos classes Tailwind) const isMobile = typeof window !== "undefined" && window.innerWidth < 640; const maxVisible = isMobile ? 3 : finalConfig.maxVisiblePages; if (totalPages <= maxVisible) { // Se total de páginas é menor que o máximo, mostrar todas for (let i = 1; i <= totalPages; i++) { pages.push(i); } } else { // Lógica para mostrar páginas com ellipsis const halfVisible = Math.floor(maxVisible / 2); let startPage = Math.max(1, currentPage - halfVisible); const endPage = Math.min(totalPages, startPage + maxVisible - 1); // Ajustar se estivermos no final if (endPage - startPage + 1 < maxVisible) { startPage = Math.max(1, endPage - maxVisible + 1); } // Primeira página (ocultar em mobile) if (startPage > 1 && !isMobile) { pages.push(1); if (startPage > 2) { pages.push("..."); } } // Páginas do meio for (let i = startPage; i <= endPage; i++) { pages.push(i); } // Última página (ocultar em mobile) if (endPage < totalPages && !isMobile) { if (endPage < totalPages - 1) { pages.push("..."); } pages.push(totalPages); } } return pages; }, [currentPage, totalPages, finalConfig]); const handleItemsPerPageChange = (newItemsPerPage: string) => { const newValue = parseInt(newItemsPerPage); setLocalItemsPerPage(newValue); if (onItemsPerPageChange) { onItemsPerPageChange(newValue); } }; const canGoPrevious = currentPage > 1; const canGoNext = currentPage < totalPages; if (totalPages <= 1) { return null; } return (
{/* Layout Mobile: Múltiplas linhas */}
{/* Linha 1: Informação de resultados */}
{startIndex}-{endIndex} de {totalItems} resultado {totalItems !== 1 ? "s" : ""}
{/* Linha 2: Controles de navegação */}
{/* Página anterior */} {/* Números das páginas */} {visiblePages.map((page, index) => (
{page === "..." ? ( ... ) : ( )}
))} {/* Próxima página */}
{/* Linha 3: Seletor de itens por página (opcional) */} {onItemsPerPageChange && (
Por página:
)}
{/* Layout Desktop: Linha única */}
{/* Informações dos itens */}
Mostrando {startIndex} a {endIndex} de {totalItems} resultado {totalItems !== 1 ? "s" : ""}
{/* Controles de paginação */}
{/* Seletor de itens por página */} {onItemsPerPageChange && (
Por página:
)} {/* Botões de navegação */}
{/* Primeira página */} {finalConfig.showFirstLast && ( )} {/* Página anterior */} {finalConfig.showPrevNext && ( )} {/* Números das páginas */} {visiblePages.map((page, index) => (
{page === "..." ? ( ... ) : ( )}
))} {/* Próxima página */} {finalConfig.showPrevNext && ( )} {/* Última página */} {finalConfig.showFirstLast && ( )}
); }