import React, { useState, useCallback } from 'react' import { View, Text, ScrollView, TouchableOpacity, StyleSheet, Alert, RefreshControl, } from 'react-native' import { useFocusEffect } from 'expo-router' import { COLORS } from '../../constants/Config' import { getCSAPDashboard, getCSAPItems, createSR } from '../../services/api' function DonutGauge({ score }: { score: number }) { const color = score >= 85 ? COLORS.success : score >= 70 ? COLORS.warning : COLORS.danger return ( {score}% CSAP ) } const g = StyleSheet.create({ wrap: { alignItems: 'center', marginVertical: 20 }, ring: { width: 120, height: 120, borderRadius: 60, borderWidth: 12, justifyContent: 'center', alignItems: 'center' }, progress: { position: 'absolute', width: 120, height: 120, borderRadius: 60, borderWidth: 12, borderTopColor: 'transparent', borderRightColor: 'transparent' }, inner: { alignItems: 'center' }, score: { fontSize: 26, fontWeight: '800' }, label: { fontSize: 11, color: COLORS.muted, fontWeight: '600' }, }) export default function CSAPDashboardScreen() { const [dashboard, setDashboard] = useState(null) const [items, setItems] = useState([]) const [loading, setLoading] = useState(false) const load = useCallback(async () => { setLoading(true) try { const [d, i] = await Promise.all([getCSAPDashboard(), getCSAPItems()]) setDashboard(d.data) setItems((i.data?.items ?? i.data ?? []).filter((x: any) => x.status === 'non_compliant' || x.result === 'FAIL')) } catch {} finally { setLoading(false) } }, []) useFocusEffect(useCallback(() => { load() }, [load])) const createActionSR = async (item: any) => { Alert.alert('즉시 조치 SR 등록', `"${item.title ?? item.check_item}" 미준수 항목으로 SR을 등록하시겠습니까?`, [ { text: '취소', style: 'cancel' }, { text: '등록', onPress: async () => { try { await createSR({ title: `[CSAP] ${item.title ?? item.check_item}`, description: item.description ?? '미준수 항목 조치 필요', priority: 'HIGH', sr_type: 'OTHER' }) Alert.alert('완료', 'SR이 등록됐습니다.') } catch { Alert.alert('오류', 'SR 등록에 실패했습니다.') } }}, ]) } const score = dashboard?.overall_score ?? dashboard?.compliance_rate ?? 0 return ( }> {/* 영역별 바 */} {(dashboard?.domains ?? []).map((d: any, i: number) => ( {d.name} = 80 ? COLORS.success : COLORS.warning }]} /> {d.rate ?? 0}% ))} {/* 미준수 항목 */} 미준수 항목 ({items.length}건) {items.map((item, i) => ( {item.title ?? item.check_item} {item.description ?? item.detail ?? '-'} createActionSR(item)}> 즉시 조치 SR 등록 ))} ) } const s = StyleSheet.create({ container: { flex: 1, backgroundColor: COLORS.bg }, domainRow: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 6, gap: 8 }, domainName: { width: 80, fontSize: 12, color: COLORS.text }, barBg: { flex: 1, height: 8, backgroundColor: COLORS.border, borderRadius: 4 }, barFill: { height: 8, borderRadius: 4 }, domainRate: { width: 40, fontSize: 12, color: COLORS.muted, textAlign: 'right' }, sectionTitle: { fontSize: 15, fontWeight: '700', color: COLORS.text, padding: 16, paddingBottom: 8 }, card: { backgroundColor: '#fff', borderRadius: 10, margin: 12, marginTop: 0, padding: 14, elevation: 1 }, itemTitle: { fontSize: 14, fontWeight: '600', color: COLORS.text, marginBottom: 4 }, itemDesc: { fontSize: 12, color: COLORS.muted, marginBottom: 10 }, srBtn: { backgroundColor: COLORS.danger, borderRadius: 6, padding: 8, alignItems: 'center' }, srBtnText: { color: '#fff', fontWeight: '700', fontSize: 12 }, })