"use client";
import { useRouter, useSearchParams } from "next/navigation";
import { Button } from "./Button";
interface CursorPaginationProps {
hasNextPage: boolean;
hasPrevPage: boolean;
pageSize: number;
currentCount: number;
pageSizeOptions?: number[];
nextCursor?: string | null;
}
export function CursorPagination({
hasNextPage,
hasPrevPage,
pageSize,
currentCount,
pageSizeOptions = [20, 50, 100],
nextCursor,
}: CursorPaginationProps) {
const router = useRouter();
const searchParams = useSearchParams();
const goToNext = () => {
if (!nextCursor) return;
const params = new URLSearchParams(searchParams);
params.set("cursor", nextCursor);
router.push(`?${params.toString()}`);
};
const goToFirst = () => {
const params = new URLSearchParams(searchParams);
params.delete("cursor");
router.push(`?${params.toString()}`);
};
const changePageSize = (size: number) => {
const params = new URLSearchParams(searchParams);
params.set("limit", size.toString());
params.delete("cursor");
router.push(`?${params.toString()}`);
};
return (
{/* Page size selector */}
Show
per page
{/* Count info */}
Showing {currentCount} items
{/* Navigation */}
{hasPrevPage && (
)}
);
}
interface OffsetPaginationProps {
currentPage: number;
totalPages: number;
pageSize: number;
totalItems: number;
pageSizeOptions?: number[];
}
export function OffsetPagination({
currentPage,
totalPages,
pageSize,
totalItems,
pageSizeOptions = [20, 50, 100],
}: OffsetPaginationProps) {
const router = useRouter();
const searchParams = useSearchParams();
const goToPage = (page: number) => {
const params = new URLSearchParams(searchParams);
params.set("page", page.toString());
router.push(`?${params.toString()}`);
};
const changePageSize = (size: number) => {
const params = new URLSearchParams(searchParams);
params.set("limit", size.toString());
params.set("page", "1");
router.push(`?${params.toString()}`);
};
const startItem = (currentPage - 1) * pageSize + 1;
const endItem = Math.min(currentPage * pageSize, totalItems);
const getPageNumbers = () => {
const pages: (number | string)[] = [];
const maxVisiblePages = 5;
if (totalPages <= maxVisiblePages) {
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
if (currentPage <= 3) {
for (let i = 1; i <= 4; i++) {
pages.push(i);
}
pages.push("...");
pages.push(totalPages);
} else if (currentPage >= totalPages - 2) {
pages.push(1);
pages.push("...");
for (let i = totalPages - 3; i <= totalPages; i++) {
pages.push(i);
}
} else {
pages.push(1);
pages.push("...");
for (let i = currentPage - 1; i <= currentPage + 1; i++) {
pages.push(i);
}
pages.push("...");
pages.push(totalPages);
}
}
return pages;
};
return (
{/* Page size selector */}
Show
per page
{/* Page info */}
{startItem}-{endItem} of {totalItems}
{/* Page navigation */}
{getPageNumbers().map((page, index) => (
{page === "..." ? (
...
) : (
)}
))}
);
}