import React, { useState, useEffect } from 'react'; import { View, Text, ScrollView, TouchableOpacity, StyleSheet, ActivityIndicator } from 'react-native'; import { ITSM_BASE } from '../../services/api'; interface Decision { id: string; question: string; recommendation: string; confidence: number; alternatives: string[]; impact: string; ts: string } const MOCK_DECISIONS: Decision[] = [ { id: 'D-001', question: 'db-01 디스크 85% — 즉시 조치 필요?', recommendation: '로그 파일 정리 + SR 등록', confidence: 0.91, alternatives: ['서버 증설 요청', '아카이브 이전', '임시 파일 삭제'], impact: '서비스 중단 없이 2시간 내 해결 가능', ts: new Date().toISOString() }, { id: 'D-002', question: '토요일 오전 2시 긴급 패치 배포 승인?', recommendation: '승인 — 위험 낮음, 영향 범위 최소', confidence: 0.78, alternatives: ['일정 연기 (다음 주)', '부분 배포 (1개 서버만)'], impact: '서비스 다운타임 예상 15분', ts: new Date().toISOString() }, ]; export default function AIDecisionScreen() { const [decisions, setDecisions] = useState(MOCK_DECISIONS); const [loading, setLoading] = useState(false); const [selected, setSelected] = useState(null); const fetchDecisions = async () => { setLoading(true); try { const r = await fetch(`${ITSM_BASE}/api/ai/decisions/pending`); if (r.ok) { const d = await r.json(); if (d.items?.length) setDecisions(d.items); } } catch {} setLoading(false); }; useEffect(() => { fetchDecisions(); }, []); const applyDecision = async (dec: Decision, choice: string) => { try { await fetch(`${ITSM_BASE}/api/ai/decisions/${dec.id}/apply`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ choice }), }); setDecisions(prev => prev.filter(d => d.id !== dec.id)); setSelected(null); } catch {} }; if (selected) { return ( setSelected(null)}> ← 목록으로 {selected.question} AI 신뢰도 {Math.round(selected.confidence * 100)}% AI 권고 {selected.recommendation} 예상 영향 {selected.impact} 선택지 {[selected.recommendation, ...selected.alternatives].map((alt, i) => ( applyDecision(selected, alt)}> {i === 0 ? '✅ ' : ''}{alt} ))} ); } return ( AI 의사결정 지원 GUARDiA AI가 운영 결정을 도와드립니다 {loading && } {decisions.map(dec => ( setSelected(dec)}> = 0.85 ? '#44bb44' : '#ffbb00' }]}> {Math.round(dec.confidence * 100)}% {dec.question} {dec.recommendation} {new Date(dec.ts).toLocaleString()} ))} {decisions.length === 0 && 대기 중인 AI 의사결정 없음} ); } const s = StyleSheet.create({ container: { flex: 1, backgroundColor: '#0A0E1A', padding: 16 }, title: { color: '#fff', fontSize: 20, fontWeight: '700', marginBottom: 4 }, sub: { color: '#888', fontSize: 13, marginBottom: 16 }, backBtn: { marginBottom: 16 }, backText: { color: '#00A0C8', fontSize: 15 }, detailTitle: { color: '#fff', fontSize: 17, fontWeight: '700', marginBottom: 16 }, confCard: { backgroundColor: '#1A1F2E', borderRadius: 12, padding: 16, marginBottom: 12, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderWidth: 1, borderColor: '#333' }, confLabel: { color: '#aaa', fontSize: 14 }, confVal: { color: '#44bb44', fontSize: 28, fontWeight: '700' }, card: { backgroundColor: '#1A1F2E', borderRadius: 12, padding: 16, marginBottom: 12, borderWidth: 1, borderColor: '#333' }, sectionLbl: { color: '#888', fontSize: 12, marginBottom: 8, fontWeight: '600' }, recommendation: { color: '#fff', fontSize: 15, fontWeight: '600' }, impact: { color: '#aaa', fontSize: 14 }, altBtn: { backgroundColor: '#1A1F2E', borderRadius: 10, padding: 14, marginBottom: 10, borderWidth: 1, borderColor: '#333' }, altBtnPrimary: { backgroundColor: '#003366', borderColor: '#00A0C8' }, altBtnText: { color: '#aaa', fontSize: 14 }, altBtnTextPrimary: { color: '#fff', fontWeight: '700' }, decCard: { backgroundColor: '#1A1F2E', borderRadius: 12, padding: 14, marginBottom: 10, borderWidth: 1, borderColor: '#333' }, decHeader: { flexDirection: 'row', marginBottom: 8 }, confBadge: { paddingHorizontal: 8, paddingVertical: 3, borderRadius: 6 }, confBadgeText: { color: '#fff', fontSize: 11, fontWeight: '700' }, question: { color: '#fff', fontWeight: '600', fontSize: 14, marginBottom: 6 }, recoPreview: { color: '#00A0C8', fontSize: 12, marginBottom: 6 }, ts: { color: '#555', fontSize: 11 }, empty: { color: '#555', textAlign: 'center', marginTop: 40, fontSize: 14 }, });