chore: init lms adm fe

This commit is contained in:
2026-07-07 17:23:40 +09:00
commit d682e9a382
57 changed files with 12065 additions and 0 deletions
+72
View File
@@ -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>
);
}