import { useState, useEffect } from 'react'; import { screeningGuideApi, type RiskCategoryResponse, type RiskIndicatorResponse } from '../../api/screeningGuideApi'; interface RiskTabProps { lang: string; } type ViewMode = 'table' | 'card'; const CAT_COLORS: Record = { 'AIS': 'bg-blue-800', 'Port Calls': 'bg-emerald-800', 'Associated with Russia': 'bg-red-800', 'Behavioural Risk': 'bg-amber-800', 'Safety, Security & Inspections': 'bg-blue-600', 'Flag Risk': 'bg-purple-800', 'Owner & Classification': 'bg-teal-700', }; const CAT_HEX: Record = { 'AIS': '#1e40af', 'Port Calls': '#065f46', 'Associated with Russia': '#991b1b', 'Behavioural Risk': '#92400e', 'Safety, Security & Inspections': '#1d4ed8', 'Flag Risk': '#6b21a8', 'Owner & Classification': '#0f766e', }; function getCatColor(categoryName: string): string { return CAT_COLORS[categoryName] ?? 'bg-slate-700'; } function getCatHex(categoryName: string): string { return CAT_HEX[categoryName] ?? '#374151'; } interface FlatRow { category: string; indicator: RiskIndicatorResponse; } export default function RiskTab({ lang }: RiskTabProps) { const [categories, setCategories] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedCategory, setSelectedCategory] = useState('전체'); const [viewMode, setViewMode] = useState('table'); useEffect(() => { setLoading(true); setError(null); screeningGuideApi .getRiskIndicators(lang) .then((res) => setCategories(res.data ?? [])) .catch((err: Error) => setError(err.message)) .finally(() => setLoading(false)); }, [lang]); const flatRows: FlatRow[] = categories.flatMap((cat) => cat.indicators.map((ind) => ({ category: cat.categoryName, indicator: ind })), ); const filtered: FlatRow[] = selectedCategory === '전체' ? flatRows : flatRows.filter((r) => r.category === selectedCategory); function downloadCSV() { const bom = '\uFEFF'; const headers = [ '카테고리', '필드키', '필드명', '설명', 'RED 조건', 'AMBER 조건', 'GREEN 조건', '데이터 타입', '이력 관리 참고사항', ]; const rows = flatRows.map((r) => [ r.category, r.indicator.fieldKey, r.indicator.fieldName, r.indicator.description, r.indicator.conditionRed, r.indicator.conditionAmber, r.indicator.conditionGreen, r.indicator.dataType, r.indicator.collectionNote, ] .map((v) => `"${(v ?? '').replace(/"/g, '""')}"`) .join(','), ); const csv = bom + [headers.join(','), ...rows].join('\n'); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'MIRS_Risk_Indicators.csv'; a.click(); } if (loading) { return (
데이터를 불러오는 중...
); } if (error) { return (
데이터 로딩 실패: {error}
); } return (
{/* 카테고리 요약 카드 */}
{categories.map((cat) => { const isActive = selectedCategory === cat.categoryName; const hex = getCatHex(cat.categoryName); return ( ); })}
{/* 컨트롤 바 */}
표시:{' '} {filtered.length}개 항목
{/* 테이블 뷰 */} {viewMode === 'table' && (
{[ '카테고리', '필드명', '설명', '🔴 RED', '🟡 AMBER', '🟢 GREEN', '데이터 타입', '이력 관리 참고', ].map((h) => ( ))} {filtered.map((row, i) => { const showCat = i === 0 || filtered[i - 1].category !== row.category; const hex = getCatHex(row.category); return ( ); })}
{h}
{showCat && ( {row.category} )}
{row.indicator.fieldName}
{row.indicator.fieldKey}
{row.indicator.description}
{row.indicator.conditionRed}
{row.indicator.conditionAmber}
{row.indicator.conditionGreen}
{row.indicator.dataType} {row.indicator.collectionNote && `💡 ${row.indicator.collectionNote}`}
)} {/* 카드 뷰 */} {viewMode === 'card' && (
{filtered.map((row, i) => { const hex = getCatHex(row.category); const colorClass = getCatColor(row.category); return (
{row.category} {row.indicator.dataType}
{row.indicator.fieldName}
{row.indicator.fieldKey}
{row.indicator.description}
🔴 RED
{row.indicator.conditionRed}
🟡 AMBER
{row.indicator.conditionAmber}
🟢 GREEN
{row.indicator.conditionGreen}
{row.indicator.collectionNote && (
💡 {row.indicator.collectionNote}
)}
); })}
)}
); }