100 lines
3.6 KiB
TypeScript
100 lines
3.6 KiB
TypeScript
"use client";
|
|
|
|
import {
|
|
ChevronLeftIcon,
|
|
ChevronRightIcon,
|
|
DoubleArrowLeftIcon,
|
|
DoubleArrowRightIcon,
|
|
} from "@radix-ui/react-icons";
|
|
import { Button, cn } from "@common/components";
|
|
|
|
export type VerificationResultHistoryPaginationProps = {
|
|
pageCount: number;
|
|
pageIndex: number;
|
|
onPageIndexChange: (pageIndex: number) => void;
|
|
className?: string;
|
|
};
|
|
|
|
export function VerificationResultHistoryPagination({
|
|
pageCount,
|
|
pageIndex: currentPage,
|
|
onPageIndexChange,
|
|
className,
|
|
}: VerificationResultHistoryPaginationProps) {
|
|
const maxVisiblePages = 10;
|
|
let startPage = Math.max(0, currentPage - maxVisiblePages / 2);
|
|
const endPage = Math.min(pageCount, startPage + maxVisiblePages);
|
|
|
|
if (endPage - startPage < maxVisiblePages) {
|
|
startPage = Math.max(0, endPage - maxVisiblePages);
|
|
}
|
|
|
|
const pageNumbers = Array(endPage - startPage)
|
|
.fill(0)
|
|
.map((_, i) => startPage + i);
|
|
|
|
const canPrevious = currentPage > 0;
|
|
const canNext = pageCount > 0 && currentPage < pageCount - 1;
|
|
|
|
return (
|
|
<div className={cn("mt-2 flex items-center justify-center gap-1 rounded-md border border-border/70 bg-muted/20 px-2 py-2", className)}>
|
|
<Button
|
|
variant="ghost"
|
|
color="white"
|
|
className="hidden size-8 p-0 lg:flex"
|
|
onClick={() => onPageIndexChange(0)}
|
|
disabled={!canPrevious}
|
|
>
|
|
<span className="sr-only">첫 페이지로</span>
|
|
<DoubleArrowLeftIcon className="size-4" />
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
color="white"
|
|
className="size-8 p-0"
|
|
onClick={() => onPageIndexChange(currentPage - 1)}
|
|
disabled={!canPrevious}
|
|
>
|
|
<span className="sr-only">이전 페이지로</span>
|
|
<ChevronLeftIcon className="size-4" />
|
|
</Button>
|
|
<div className="flex items-center justify-center text-sm font-medium">
|
|
{pageNumbers.map((pageNumber) => (
|
|
<Button
|
|
key={pageNumber}
|
|
variant="ghost"
|
|
className={cn(
|
|
"inline-block h-8 min-w-8 border border-transparent !bg-transparent px-2 py-1 text-foreground hover:!bg-accent",
|
|
currentPage === pageNumber &&
|
|
"!bg-primary !font-bold !text-primary-foreground hover:!bg-primary",
|
|
)}
|
|
onClick={() => onPageIndexChange(pageNumber)}
|
|
>
|
|
{pageNumber + 1}
|
|
</Button>
|
|
))}
|
|
</div>
|
|
<Button
|
|
variant="ghost"
|
|
color="white"
|
|
className="size-8 p-0"
|
|
onClick={() => onPageIndexChange(currentPage + 1)}
|
|
disabled={!canNext}
|
|
>
|
|
<span className="sr-only">다음 페이지로</span>
|
|
<ChevronRightIcon className="size-4" />
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
color="white"
|
|
className="hidden size-8 p-0 lg:flex"
|
|
onClick={() => onPageIndexChange(Math.max(0, pageCount - 1))}
|
|
disabled={!canNext}
|
|
>
|
|
<span className="sr-only">마지막 페이지로</span>
|
|
<DoubleArrowRightIcon className="size-4" />
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|