77 lines
1.8 KiB
TypeScript
77 lines
1.8 KiB
TypeScript
import {
|
|
Pagination,
|
|
PaginationContent,
|
|
PaginationEllipsis,
|
|
PaginationItem,
|
|
PaginationLink,
|
|
PaginationNext,
|
|
PaginationPrevious,
|
|
} from "@/components/ui/pagination";
|
|
|
|
interface Props {
|
|
page: number;
|
|
totalPages: number;
|
|
buildHref: (page: number) => string;
|
|
}
|
|
|
|
function pageNumbers(
|
|
page: number,
|
|
totalPages: number
|
|
): (number | "ellipsis")[] {
|
|
if (totalPages <= 7) {
|
|
return Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
}
|
|
|
|
const pages: (number | "ellipsis")[] = [1];
|
|
|
|
if (page > 3) pages.push("ellipsis");
|
|
|
|
const start = Math.max(2, page - 1);
|
|
const end = Math.min(totalPages - 1, page + 1);
|
|
for (let i = start; i <= end; i++) pages.push(i);
|
|
|
|
if (page < totalPages - 2) pages.push("ellipsis");
|
|
|
|
pages.push(totalPages);
|
|
|
|
return pages;
|
|
}
|
|
|
|
export function PaginationNav({ page, totalPages, buildHref }: Props) {
|
|
if (totalPages <= 1) return null;
|
|
|
|
return (
|
|
<Pagination className="mt-8">
|
|
<PaginationContent>
|
|
<PaginationItem>
|
|
<PaginationPrevious
|
|
href={page > 1 ? buildHref(page - 1) : "#"}
|
|
aria-disabled={page <= 1}
|
|
/>
|
|
</PaginationItem>
|
|
|
|
{pageNumbers(page, totalPages).map((p, i) =>
|
|
p === "ellipsis" ? (
|
|
<PaginationItem key={`ellipsis-${i}`}>
|
|
<PaginationEllipsis />
|
|
</PaginationItem>
|
|
) : (
|
|
<PaginationItem key={p}>
|
|
<PaginationLink href={buildHref(p)} isActive={p === page}>
|
|
{p}
|
|
</PaginationLink>
|
|
</PaginationItem>
|
|
)
|
|
)}
|
|
|
|
<PaginationItem>
|
|
<PaginationNext
|
|
href={page < totalPages ? buildHref(page + 1) : "#"}
|
|
aria-disabled={page >= totalPages}
|
|
/>
|
|
</PaginationItem>
|
|
</PaginationContent>
|
|
</Pagination>
|
|
);
|
|
}
|