feat(frontend): proper pagination with page numbers and ellipsis

This commit is contained in:
2026-05-15 04:21:11 +02:00
parent 40d8234225
commit 895b892cf2
3 changed files with 89 additions and 52 deletions

View File

@@ -18,13 +18,7 @@ import { buildThoughtThreads } from "@/lib/utils";
import { TopFriends } from "@/components/top-friends";
import { UsersCount } from "@/components/users-count";
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination";
import { PaginationNav } from "@/components/pagination-nav";
import { redirect } from "next/navigation";
export const metadata: Metadata = {
@@ -127,24 +121,11 @@ async function FeedPage({
</p>
)}
</div>
{totalPages > 1 && (
<Pagination className="mt-8">
<PaginationContent>
<PaginationItem>
<PaginationPrevious
href={page > 1 ? `/?page=${page - 1}` : "#"}
aria-disabled={page <= 1}
<PaginationNav
page={page}
totalPages={totalPages}
buildHref={(p) => `/?page=${p}`}
/>
</PaginationItem>
<PaginationItem>
<PaginationNext
href={page < totalPages ? `/?page=${page + 1}` : "#"}
aria-disabled={page >= totalPages}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
)}
</main>
<aside className="hidden lg:block lg:col-span-1">

View File

@@ -1,12 +1,6 @@
import { getAllUsers } from "@/lib/api";
import { UserListCard } from "@/components/user-list-card";
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination";
import { PaginationNav } from "@/components/pagination-nav";
export default async function AllUsersPage({
searchParams,
@@ -29,8 +23,7 @@ export default async function AllUsersPage({
}
const { items, total, per_page } = usersData;
const perPage = per_page;
const totalPages = Math.ceil(total / perPage);
const totalPages = Math.ceil(total / per_page);
return (
<div className="container mx-auto max-w-2xl p-4 sm:p-6">
@@ -42,24 +35,11 @@ export default async function AllUsersPage({
</header>
<main>
<UserListCard users={items} />
{totalPages > 1 && (
<Pagination className="mt-8">
<PaginationContent>
<PaginationItem>
<PaginationPrevious
href={page > 1 ? `/users/all?page=${page - 1}` : "#"}
aria-disabled={page <= 1}
<PaginationNav
page={page}
totalPages={totalPages}
buildHref={(p) => `/users/all?page=${p}`}
/>
</PaginationItem>
<PaginationItem>
<PaginationNext
href={page < totalPages ? `/users/all?page=${page + 1}` : "#"}
aria-disabled={page >= totalPages}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
)}
</main>
</div>
);

View File

@@ -0,0 +1,76 @@
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>
);
}