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 },
})