'use client'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPlus } from '@fortawesome/free-solid-svg-icons'; import { Checkbox } from '@/components/ui/checkbox'; import type { GoalConfigItem } from '@/types/response/donation/goalConfig'; import { PER_PAGE_OPTIONS } from '@/constants/donation'; import { GOAL_STYLES, formatDateTime } from '../types'; type Props = { items: GoalConfigItem[]; loading: boolean; saving: boolean; checkedIDs: Set; setCheckedIDs: React.Dispatch>>; page: number; setPage: React.Dispatch>; perPage: number; setPerPage: React.Dispatch>; onNew: () => void; onEdit: (item: GoalConfigItem) => void; onBatchDelete: () => void; }; export default function GoalListPanel({ items, loading, saving, checkedIDs, setCheckedIDs, page, setPage, perPage, setPerPage, onNew, onEdit, onBatchDelete }: Props) { // ── 페이징 ─────────────────────────────────────── const totalPages = Math.max(1, Math.ceil(items.length / perPage)); const pagedItems = items.slice((page - 1) * perPage, page * perPage); const handlePerPageChange = (value: number) => { setPerPage(value); setPage(1); }; // ── 전체선택 ───────────────────────────────────── const visibleIDs = pagedItems.map(i => i.id); const checkedCount = visibleIDs.filter(id => checkedIDs.has(id)).length; const allChecked = pagedItems.length > 0 && checkedCount === visibleIDs.length; const isIndeterminate = checkedCount > 0 && checkedCount < visibleIDs.length; const handleSelectAll = () => { setCheckedIDs(prev => { const next = new Set(prev); if (allChecked) { visibleIDs.forEach(id => next.delete(id)); } else { visibleIDs.forEach(id => next.add(id)); } return next; }); }; const handleToggleCheck = (id: number) => { setCheckedIDs(prev => { const next = new Set(prev); if (next.has(id)) { next.delete(id); } else { next.add(id); } return next; }); }; return (
총 {items.length}개 {checkedIDs.size > 0 && ( ({checkedIDs.size}개 선택) )}
{loading ? (
준비 중...
) : items.length === 0 ? (
등록된 목표 설정이 없습니다.
) : ( {pagedItems.map(item => { const isChecked = checkedIDs.has(item.id); const percent = item.targetAmount > 0 ? Math.min((item.startAmount / item.targetAmount) * 100, 100) : 0; return ( ); })}
제목 현황 시작금액 목표금액 기간 스타일 활성 비고
handleToggleCheck(item.id)} aria-label={`${item.id} 선택`} /> {item.title}
{item.startAmount.toLocaleString()} / {item.targetAmount.toLocaleString()} {item.isShowPercent && ` (${Math.round(percent)}%)`}
{item.startAmount.toLocaleString()}원 {item.targetAmount.toLocaleString()}원 {formatDateTime(item.startAt)} ~ {formatDateTime(item.endAt)} {GOAL_STYLES.find(s => s.value === item.style)?.label ?? item.style} {item.isActive ? '활성' : '비활성'}
)}
{totalPages > 1 && (
{Array.from({ length: totalPages }, (_, i) => i + 1).map(p => ( ))}
)}
); }