import React, { useState, useCallback } from 'react' import { View, Text, FlatList, Modal, TextInput, TouchableOpacity, StyleSheet, Alert, RefreshControl, ActivityIndicator, } from 'react-native' import { useFocusEffect } from 'expo-router' import { COLORS } from '../../constants/Config' import { getSLAExceptionPending, requestSLAException } from '../../services/api' export default function SLAExceptionScreen() { const [items, setItems] = useState([]) const [loading, setLoading] = useState(false) const [modal, setModal] = useState(null) const [reason, setReason] = useState('') const [deadline, setDeadline] = useState('') const [saving, setSaving] = useState(false) const load = useCallback(async () => { setLoading(true) try { const r = await getSLAExceptionPending() setItems(r.data?.items ?? r.data ?? []) } catch { setItems([]) } finally { setLoading(false) } }, []) useFocusEffect(useCallback(() => { load() }, [load])) const open = (item: any) => { setModal(item); setReason(''); setDeadline('') } const submit = async () => { if (!reason.trim() || !deadline.trim()) { Alert.alert('오류', '사유와 새 기한을 입력해주세요.'); return } setSaving(true) try { await requestSLAException(modal.sr_id, { reason, new_deadline: deadline }) setModal(null); load() } catch { Alert.alert('오류', '제출 중 오류가 발생했습니다.') } finally { setSaving(false) } } const renderItem = ({ item }: { item: any }) => ( open(item)}> {item.title} {item.sla_breached ? 'SLA 위반' : 'SLA 임박'} 기한: {item.sla_deadline?.slice(0, 10) ?? '-'} 탭하여 예외 승인 요청 ) return ( String(i.sr_id)} renderItem={renderItem} refreshControl={} ListEmptyComponent={SLA 예외 대기 항목이 없습니다.} contentContainerStyle={{ padding: 12 }} /> SLA 예외 승인 요청 {modal?.title} setModal(null)}> 취소 {saving ? '제출 중...' : '제출'} ) } const s = StyleSheet.create({ container: { flex: 1, backgroundColor: COLORS.bg }, card: { backgroundColor: '#fff', borderRadius: 10, padding: 14, marginBottom: 8, elevation: 1 }, title: { fontSize: 14, fontWeight: '600', color: COLORS.text, marginBottom: 6 }, row: { flexDirection: 'row', alignItems: 'center', gap: 8, marginBottom: 4 }, badge: { borderRadius: 4, paddingHorizontal: 6, paddingVertical: 2 }, badgeText: { fontSize: 11, color: '#fff', fontWeight: '700' }, meta: { fontSize: 12, color: COLORS.muted }, hint: { fontSize: 11, color: COLORS.accent, marginTop: 4 }, empty: { textAlign: 'center', color: COLORS.muted, marginTop: 40 }, overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end' }, modalBox: { backgroundColor: '#fff', borderTopLeftRadius: 16, borderTopRightRadius: 16, padding: 20 }, modalTitle: { fontSize: 17, fontWeight: '800', color: COLORS.text, marginBottom: 8 }, modalSR: { fontSize: 13, color: COLORS.muted, marginBottom: 12 }, input: { borderWidth: 1, borderColor: COLORS.border, borderRadius: 8, padding: 10, marginBottom: 10, fontSize: 14, color: COLORS.text }, modalBtns: { flexDirection: 'row', gap: 10, marginTop: 4 }, btn: { flex: 1, borderRadius: 8, padding: 12, alignItems: 'center' }, btnText: { fontWeight: '700', fontSize: 14 }, })