import { useState, useMemo, useEffect } from 'react'; import { Link } from 'react-router-dom'; import { getAdminPrograms, type AdminProgramSummary } from '../../lib/admin'; import { CAMPAIGN_STATUS } from '../../lib/campaignStatusConfig'; const formatKRW = (n: number) => n === 0 ? '—' : new Intl.NumberFormat('ko-KR').format(n) + '원'; const formatNum = (n: number) => n === 0 ? '—' : n.toLocaleString('ko-KR'); function ProgressBar({ current, target }: { current: number; target: number }) { const pct = target === 0 ? 0 : Math.min(100, (current / target) * 100); return (
{pct.toFixed(0)}%
); } export default function ProgramsPage() { const [searchTerm, setSearchTerm] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); const [programs, setPrograms] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { getAdminPrograms() .then(setPrograms) .finally(() => setLoading(false)); }, []); const filteredPrograms = useMemo(() => { return programs.filter((p) => { const matchSearch = p.title.toLowerCase().includes(searchTerm.toLowerCase()) || p.sponsorName.toLowerCase().includes(searchTerm.toLowerCase()); const matchStatus = statusFilter === 'all' || p.status === statusFilter; return matchSearch && matchStatus; }); }, [programs, searchTerm, statusFilter]); if (loading) { return
프로그램 데이터 동기화 중... [SYNCHRONIZING...]
; } return (

캠페인 운영 관리 [CAMPAIGN OPERATIONS]

플랫폼 전체 탄소 감축 캠페인 라이프사이클 관리

+ 캠페인 생성 [CREATE]
{/* Filters */}
setSearchTerm(e.target.value)} className="w-full px-3 py-2 text-xs border border-border-default bg-paper-white focus:outline-none focus:border-ink-black" />
{/* Program Grid */}
{filteredPrograms.map((p) => { const st = CAMPAIGN_STATUS[p.status as keyof typeof CAMPAIGN_STATUS] || { label: p.status, cls: 'border-border-default' }; return (
{st.label} {p.source === 'db' ? 'DB' : 'DEMO'}

{p.title}

{p.sponsorName}

진행 현황 [PROGRESS] {formatNum(p.currentCo2Kg)} / {formatNum(p.targetCo2Kg)} kg

참여자 [PARTICIPANTS]

{formatNum(p.participantCount)}

예산 [BUDGET]

{formatKRW(p.budgetKrw)}

{p.startDate} ~ {p.endDate || 'Ongoing'}

관리하기 [MANAGE] →
); })}
); }