chore: init lms adm fe
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user