Files
home/Projects/kompose/news/apps/web/src/components/pagination.tsx
2025-10-10 16:43:21 +02:00

118 lines
2.5 KiB
TypeScript

import {
Pagination as UIPagination,
PaginationContent,
Button,
} from "@repo/ui";
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
type PaginationProps = {
page: number;
totalPages: number;
onPageChange: (page: number) => void;
hasNextPage: boolean;
};
export function Pagination({
page,
totalPages,
onPageChange,
hasNextPage,
}: PaginationProps) {
const totalButtons = 7;
const renderPageButton = (pageNumber: number) => (
<Button
key={pageNumber}
variant={page === pageNumber ? "default" : "outline"}
size="icon"
onClick={() => onPageChange(pageNumber)}
>
{pageNumber}
</Button>
);
const renderEllipsis = (key: string) => (
<Button key={key} variant="outline" size="icon" disabled>
<MoreHorizontal className="h-4 w-4" />
</Button>
);
const renderPaginationButtons = () => {
const buttons = [];
if (totalPages <= totalButtons) {
for (let i = 1; i <= totalPages; i++) {
buttons.push(renderPageButton(i));
}
} else {
buttons.push(renderPageButton(1));
if (page > 3) {
buttons.push(renderEllipsis("start-ellipsis"));
}
let start = Math.max(2, page - 1);
let end = Math.min(totalPages - 1, page + 1);
if (page <= 3) {
end = Math.min(totalPages - 1, totalButtons - 2);
}
if (page >= totalPages - 2) {
start = Math.max(2, totalPages - (totalButtons - 2));
}
for (let i = start; i <= end; i++) {
buttons.push(renderPageButton(i));
}
if (page < totalPages - 2) {
buttons.push(renderEllipsis("end-ellipsis"));
}
buttons.push(renderPageButton(totalPages));
}
while (buttons.length < totalButtons) {
buttons.push(
<Button
key={`filler-${buttons.length}`}
variant="outline"
size="icon"
disabled
>
{" "}
</Button>,
);
}
return buttons;
};
return (
<UIPagination className="select-none">
<PaginationContent className="flex items-center justify-center space-x-2">
<Button
variant="outline"
size="icon"
onClick={() => onPageChange(Math.max(1, page - 1))}
disabled={page === 1}
>
<ChevronLeft className="h-4 w-4" />
<span className="sr-only">Previous page</span>
</Button>
{renderPaginationButtons()}
<Button
variant="outline"
size="icon"
onClick={() => onPageChange(Math.min(totalPages, page + 1))}
disabled={!hasNextPage}
>
<ChevronRight className="h-4 w-4" />
<span className="sr-only">Next page</span>
</Button>
</PaginationContent>
</UIPagination>
);
}