feat(frontend): proper pagination with page numbers and ellipsis
This commit is contained in:
@@ -18,13 +18,7 @@ import { buildThoughtThreads } from "@/lib/utils";
|
|||||||
import { TopFriends } from "@/components/top-friends";
|
import { TopFriends } from "@/components/top-friends";
|
||||||
import { UsersCount } from "@/components/users-count";
|
import { UsersCount } from "@/components/users-count";
|
||||||
|
|
||||||
import {
|
import { PaginationNav } from "@/components/pagination-nav";
|
||||||
Pagination,
|
|
||||||
PaginationContent,
|
|
||||||
PaginationItem,
|
|
||||||
PaginationNext,
|
|
||||||
PaginationPrevious,
|
|
||||||
} from "@/components/ui/pagination";
|
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
@@ -127,24 +121,11 @@ async function FeedPage({
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{totalPages > 1 && (
|
<PaginationNav
|
||||||
<Pagination className="mt-8">
|
page={page}
|
||||||
<PaginationContent>
|
totalPages={totalPages}
|
||||||
<PaginationItem>
|
buildHref={(p) => `/?page=${p}`}
|
||||||
<PaginationPrevious
|
|
||||||
href={page > 1 ? `/?page=${page - 1}` : "#"}
|
|
||||||
aria-disabled={page <= 1}
|
|
||||||
/>
|
/>
|
||||||
</PaginationItem>
|
|
||||||
<PaginationItem>
|
|
||||||
<PaginationNext
|
|
||||||
href={page < totalPages ? `/?page=${page + 1}` : "#"}
|
|
||||||
aria-disabled={page >= totalPages}
|
|
||||||
/>
|
|
||||||
</PaginationItem>
|
|
||||||
</PaginationContent>
|
|
||||||
</Pagination>
|
|
||||||
)}
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<aside className="hidden lg:block lg:col-span-1">
|
<aside className="hidden lg:block lg:col-span-1">
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
import { getAllUsers } from "@/lib/api";
|
import { getAllUsers } from "@/lib/api";
|
||||||
import { UserListCard } from "@/components/user-list-card";
|
import { UserListCard } from "@/components/user-list-card";
|
||||||
import {
|
import { PaginationNav } from "@/components/pagination-nav";
|
||||||
Pagination,
|
|
||||||
PaginationContent,
|
|
||||||
PaginationItem,
|
|
||||||
PaginationNext,
|
|
||||||
PaginationPrevious,
|
|
||||||
} from "@/components/ui/pagination";
|
|
||||||
|
|
||||||
export default async function AllUsersPage({
|
export default async function AllUsersPage({
|
||||||
searchParams,
|
searchParams,
|
||||||
@@ -29,8 +23,7 @@ export default async function AllUsersPage({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { items, total, per_page } = usersData;
|
const { items, total, per_page } = usersData;
|
||||||
const perPage = per_page;
|
const totalPages = Math.ceil(total / per_page);
|
||||||
const totalPages = Math.ceil(total / perPage);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto max-w-2xl p-4 sm:p-6">
|
<div className="container mx-auto max-w-2xl p-4 sm:p-6">
|
||||||
@@ -42,24 +35,11 @@ export default async function AllUsersPage({
|
|||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<UserListCard users={items} />
|
<UserListCard users={items} />
|
||||||
{totalPages > 1 && (
|
<PaginationNav
|
||||||
<Pagination className="mt-8">
|
page={page}
|
||||||
<PaginationContent>
|
totalPages={totalPages}
|
||||||
<PaginationItem>
|
buildHref={(p) => `/users/all?page=${p}`}
|
||||||
<PaginationPrevious
|
|
||||||
href={page > 1 ? `/users/all?page=${page - 1}` : "#"}
|
|
||||||
aria-disabled={page <= 1}
|
|
||||||
/>
|
/>
|
||||||
</PaginationItem>
|
|
||||||
<PaginationItem>
|
|
||||||
<PaginationNext
|
|
||||||
href={page < totalPages ? `/users/all?page=${page + 1}` : "#"}
|
|
||||||
aria-disabled={page >= totalPages}
|
|
||||||
/>
|
|
||||||
</PaginationItem>
|
|
||||||
</PaginationContent>
|
|
||||||
</Pagination>
|
|
||||||
)}
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
76
thoughts-frontend/components/pagination-nav.tsx
Normal file
76
thoughts-frontend/components/pagination-nav.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user