73 lines
2.8 KiB
TypeScript
73 lines
2.8 KiB
TypeScript
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
|
|
type PaginationBarProps = {
|
|
totalLabel: string;
|
|
page: number;
|
|
pageSize: number;
|
|
totalItems: number;
|
|
onPageChange: (page: number) => void;
|
|
onPageSizeChange: (pageSize: number) => void;
|
|
};
|
|
|
|
const pageSizeOptions = [10, 20, 50];
|
|
|
|
export function PaginationBar({ totalLabel, page, pageSize, totalItems, onPageChange, onPageSizeChange }: PaginationBarProps) {
|
|
const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
|
|
const pages = Array.from({ length: Math.min(totalPages, 5) }, (_, index) => {
|
|
if (totalPages <= 5) return index + 1;
|
|
const start = Math.min(Math.max(page - 2, 1), totalPages - 4);
|
|
return start + index;
|
|
});
|
|
|
|
return (
|
|
<div className="flex flex-wrap items-center justify-between gap-3 border-t border-[#cbd5e1] px-4 pb-3 pt-6">
|
|
<p className="text-[12px] font-bold text-[#64748b]">{totalLabel}</p>
|
|
|
|
<div className="flex items-center gap-1.5">
|
|
<button
|
|
className="grid h-8 w-8 place-items-center rounded-md border border-[#d1d9e6] bg-white text-[#94a3b8] hover:bg-[#f8fafc] disabled:cursor-default disabled:opacity-35"
|
|
type="button"
|
|
aria-label="이전 페이지"
|
|
disabled={page <= 1}
|
|
onClick={() => onPageChange(Math.max(1, page - 1))}
|
|
>
|
|
<ChevronLeft size={15} aria-hidden="true" />
|
|
</button>
|
|
{pages.map((item) => (
|
|
<button
|
|
key={item}
|
|
className={`grid h-8 w-8 place-items-center rounded-md text-[12px] font-bold ${
|
|
item === page ? 'bg-[#4f46e5] text-white' : 'border border-[#d1d9e6] bg-white text-[#64748b] hover:bg-[#f8fafc]'
|
|
}`}
|
|
type="button"
|
|
aria-current={item === page ? 'page' : undefined}
|
|
onClick={() => onPageChange(item)}
|
|
>
|
|
{item}
|
|
</button>
|
|
))}
|
|
<button
|
|
className="grid h-8 w-8 place-items-center rounded-md border border-[#d1d9e6] bg-white text-[#94a3b8] hover:bg-[#f8fafc] disabled:cursor-default disabled:opacity-35"
|
|
type="button"
|
|
aria-label="다음 페이지"
|
|
disabled={page >= totalPages}
|
|
onClick={() => onPageChange(Math.min(totalPages, page + 1))}
|
|
>
|
|
<ChevronRight size={15} aria-hidden="true" />
|
|
</button>
|
|
</div>
|
|
|
|
<select
|
|
aria-label="페이지당 표시 개수"
|
|
className="h-8 rounded-md border border-[#d1d9e6] bg-white px-2 text-[12px] font-bold text-[#64748b] outline-none hover:bg-[#f8fafc] focus:border-[#4f46e5] focus:ring-2 focus:ring-[#4f46e5]/10"
|
|
value={pageSize}
|
|
onChange={(event) => onPageSizeChange(Number(event.target.value))}
|
|
>
|
|
{pageSizeOptions.map((option) => (
|
|
<option key={option} value={option}>{option}개씩 보기</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
);
|
|
}
|