import React, { useState, useCallback } from 'react' import { View, Text, FlatList, StyleSheet, RefreshControl, TouchableOpacity } from 'react-native' import { useFocusEffect } from 'expo-router' import { COLORS } from '../../constants/Config' import client from '../../services/api' const SEV_COLOR: Record = { CRITICAL: COLORS.danger, HIGH: '#f97316', MEDIUM: COLORS.warning, LOW: COLORS.muted } export default function ThreatFeedScreen() { const [items, setItems] = useState([]) const [expanded, setExpanded] = useState(null) const [loading, setLoading] = useState(false) const load = useCallback(async () => { setLoading(true) try { const r = await client.get('/api/ai-soc/threats'); setItems(r.data?.threats ?? r.data?.items ?? []) } catch { setItems([]) } finally { setLoading(false) } }, []) useFocusEffect(useCallback(() => { load() }, [load])) return ( String(i)} refreshControl={} ListEmptyComponent={위협 인텔리전스 피드가 없습니다.} style={{ backgroundColor: COLORS.bg }} contentContainerStyle={{ padding: 12 }} renderItem={({ item, index }) => { const sev = item.severity ?? item.level ?? 'MEDIUM' const color = SEV_COLOR[sev] ?? COLORS.muted const isOpen = expanded === index return ( setExpanded(isOpen ? null : index)} style={s.card} activeOpacity={0.8}> {item.title ?? item.threat_name} {item.source ?? 'TI Feed'} · {item.detected_at?.slice(0, 10) ?? ''} {sev} {isOpen && ( {item.description ?? item.details ?? '상세 정보 없음'} {item.ioc && IoC: {item.ioc}} {item.mitigation && 대응: {item.mitigation}} )} ) }} /> ) } const s = StyleSheet.create({ card: { backgroundColor: '#fff', borderRadius: 10, padding: 14, marginBottom: 8, elevation: 1 }, row: { flexDirection: 'row', alignItems: 'center', gap: 8 }, sevDot: { width: 10, height: 10, borderRadius: 5 }, title: { fontSize: 13, fontWeight: '700', color: COLORS.text, flex: 1 }, meta: { fontSize: 11, color: COLORS.muted, marginTop: 2 }, sev: { fontSize: 11, fontWeight: '700' }, detail: { marginTop: 10, paddingTop: 10, borderTopWidth: 1, borderTopColor: COLORS.border }, detailText: { fontSize: 13, color: COLORS.text, lineHeight: 20, marginBottom: 6 }, ioc: { fontSize: 12, color: COLORS.danger, fontFamily: 'monospace' }, mitigation: { fontSize: 12, color: COLORS.success, marginTop: 4 }, empty: { textAlign: 'center', color: COLORS.muted, marginTop: 40 }, })