import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { Card, CardContent } from '@shared/components/ui/card'; import { Badge } from '@shared/components/ui/badge'; import { Activity, AlertTriangle, Ship, Eye, Anchor, Radar, Shield, Bell, Clock, Target, ChevronRight } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; import { AreaChart, PieChart } from '@lib/charts'; import { useKpiStore } from '@stores/kpiStore'; import { useEventStore } from '@stores/eventStore'; /* SFR-12: 모니터링 및 경보 현황판(대시보드) */ // KPI UI 매핑 (icon, color는 store에 없으므로 라벨 기반 매핑) const KPI_UI_MAP: Record = { '실시간 탐지': { icon: Radar, color: '#3b82f6' }, 'EEZ 침범': { icon: AlertTriangle, color: '#ef4444' }, '다크베셀': { icon: Eye, color: '#f97316' }, '불법환적 의심': { icon: Anchor, color: '#a855f7' }, '추적 중': { icon: Target, color: '#06b6d4' }, '나포/검문': { icon: Shield, color: '#10b981' }, }; const TREND = Array.from({ length: 24 }, (_, i) => ({ h: `${i}시`, risk: 30 + Math.floor(Math.random() * 50), alarms: Math.floor(Math.random() * 8) })); // 위반 유형 → 차트 색상 매핑 const PIE_COLOR_MAP: Record = { 'EEZ 침범': '#ef4444', '다크베셀': '#f97316', 'MMSI 변조': '#eab308', '불법환적': '#a855f7', '어구 불법': '#6b7280', }; const LV: Record = { CRITICAL: 'text-red-400 bg-red-500/15', HIGH: 'text-orange-400 bg-orange-500/15', MEDIUM: 'text-yellow-400 bg-yellow-500/15', LOW: 'text-blue-400 bg-blue-500/15' }; export function MonitoringDashboard() { const { t } = useTranslation('dashboard'); const kpiStore = useKpiStore(); const eventStore = useEventStore(); useEffect(() => { if (!kpiStore.loaded) kpiStore.load(); }, [kpiStore.loaded, kpiStore.load]); useEffect(() => { if (!eventStore.loaded) eventStore.load(); }, [eventStore.loaded, eventStore.load]); // KPI: store metrics + UI 매핑 const KPI = kpiStore.metrics.map((m) => ({ label: m.label, value: m.value, icon: KPI_UI_MAP[m.label]?.icon ?? Radar, color: KPI_UI_MAP[m.label]?.color ?? '#3b82f6', })); // PIE: store violationTypes → 차트 데이터 변환 const PIE = kpiStore.violationTypes.map((v) => ({ name: v.type, value: v.pct, color: PIE_COLOR_MAP[v.type] ?? '#6b7280', })); // 이벤트: store events → 첫 6개, time 포맷 변환 const EVENTS = eventStore.events.slice(0, 6).map((e) => ({ time: e.time.includes(' ') ? e.time.split(' ')[1].slice(0, 5) : e.time, level: e.level, title: e.title, detail: e.detail, })); return (

{t('monitoring.title')}

{t('monitoring.desc')}

{KPI.map(k => (
{k.value} {k.label}
))}
24시간 위험도·경보 추이
탐지 유형 분포
{PIE.map(d => (
{d.name}
{d.value}%
))}
실시간 이벤트 타임라인
{EVENTS.map((e, i) => (
{e.time} {e.level} {e.title} {e.detail}
))}
); }