import { useState, useEffect, useRef, useCallback } from 'react'; import { screeningGuideApi, type MethodologyHistoryResponse } from '../../api/screeningGuideApi'; interface MethodologyTabProps { lang: string; } const CHANGE_TYPE_COLORS: Record = { Addition: '#065f46', Update: '#1d4ed8', Expansion: '#6b21a8', Change: '#92400e', Removal: '#991b1b', New: '#0f766e', }; function getChangeTypeColor(changeType: string): string { return CHANGE_TYPE_COLORS[changeType] ?? '#374151'; } type LangKey = 'KO' | 'EN'; interface LangCache { history: MethodologyHistoryResponse[]; banner: string; } export default function MethodologyTab({ lang }: MethodologyTabProps) { const [history, setHistory] = useState([]); const [banner, setBanner] = useState(''); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedType, setSelectedType] = useState('전체'); const cache = useRef>(new Map()); const fetchData = useCallback((fetchLang: string) => { return Promise.all([ screeningGuideApi.getMethodologyHistory(fetchLang), screeningGuideApi.getMethodologyBanner(fetchLang).catch(() => ({ data: null })), ]).then(([historyRes, bannerRes]) => { const data: LangCache = { history: historyRes.data ?? [], banner: bannerRes.data?.description ?? '', }; cache.current.set(fetchLang as LangKey, data); return data; }); }, []); // 초기 로드: KO/EN 데이터 모두 가져와서 캐싱 useEffect(() => { setLoading(true); setError(null); cache.current.clear(); Promise.all([fetchData('KO'), fetchData('EN')]) .then(() => { const cached = cache.current.get(lang as LangKey); if (cached) { setHistory(cached.history); setBanner(cached.banner); } }) .catch((err: Error) => setError(err.message)) .finally(() => setLoading(false)); }, [fetchData]); // 언어 변경: 캐시에서 스위칭 useEffect(() => { const cached = cache.current.get(lang as LangKey); if (cached) { setHistory(cached.history); setBanner(cached.banner); } }, [lang]); const sortedHistory = [...history].sort((a, b) => b.changeDate.localeCompare(a.changeDate), ); const uniqueTypes = Array.from(new Set(history.map((h) => h.changeType))); const filtered = selectedType === '전체' ? sortedHistory : sortedHistory.filter((h) => h.changeType === selectedType); if (loading) { return (
데이터를 불러오는 중...
); } if (error) { return (
데이터 로딩 실패: {error}
); } return (
{/* 주의사항 배너 */} {banner && (
{banner}
)} {/* 변경 유형 필터 */}
{uniqueTypes.map((type) => { const count = history.filter((h) => h.changeType === type).length; const hex = getChangeTypeColor(type); const isActive = selectedType === type; return ( ); })}
표시: {filtered.length}건 | 최신순 정렬
{/* 타임라인 목록 */}
{['날짜', '변경 유형', '설명'].map((h) => ( ))} {filtered.map((row, i) => { const hex = getChangeTypeColor(row.changeType); return ( ); })}
{h}
{row.changeDate}
{row.changeType} {row.description || '-'}
{filtered.length === 0 && (
해당 유형의 변경 이력이 없습니다.
)}
); }