import { useEffect, useState } from 'react' import { View, Text, Modal, FlatList, TouchableOpacity, StyleSheet, ActivityIndicator, } from 'react-native' import { COLORS, PRIORITY_COLOR } from '../constants/Config' import { getSRTemplates } from '../services/api' export interface SRTemplate { id: number | string name: string title?: string category?: string sr_type?: string priority?: string description?: string } interface Props { visible: boolean onClose: () => void onSelect: (tpl: SRTemplate) => void } const FALLBACK: SRTemplate[] = [ { id: 'deploy', name: '배포 요청', title: '[배포] 서비스 배포 요청', category: 'DEPLOY', priority: 'HIGH', description: '대상 서버 / 브랜치 / 배포 시간을 기재하세요.' }, { id: 'restart', name: '서비스 재기동', title: '[재기동] 서비스 재시작 요청', category: 'RESTART', priority: 'MEDIUM', description: '재기동 대상 서비스명을 기재하세요.' }, { id: 'log', name: '로그 확인', title: '[로그] 로그 조회 요청', category: 'LOG', priority: 'LOW', description: '조회 기간 / 키워드를 기재하세요.' }, { id: 'incident',name: '장애 신고', title: '[장애] 긴급 장애 신고', category: 'OTHER', priority: 'CRITICAL',description: '발생 시각 / 증상 / 영향 범위를 기재하세요.' }, ] /** * 기능 #10 — SR 템플릿 선택 모달 * GET /api/tasks/templates → 실패 시 기본 템플릿 사용 */ export default function SRTemplates({ visible, onClose, onSelect }: Props) { const [items, setItems] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { if (!visible) return let alive = true setLoading(true) ;(async () => { try { const res = await getSRTemplates() const list: SRTemplate[] = res.data?.content ?? res.data?.items ?? res.data ?? [] if (alive) setItems(list.length ? list : FALLBACK) } catch { if (alive) setItems(FALLBACK) } finally { if (alive) setLoading(false) } })() return () => { alive = false } }, [visible]) return ( SR 템플릿 선택 {loading ? ( ) : ( String(t.id)} renderItem={({ item }) => ( { onSelect(item); onClose() }}> {item.name} {!!item.description && {item.description}} {!!item.priority && ( {item.priority} )} )} /> )} ) } const s = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.4)', justifyContent: 'flex-end' }, sheet: { backgroundColor: '#fff', borderTopLeftRadius: 18, borderTopRightRadius: 18, maxHeight: '70%', paddingBottom: 24 }, head: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 18, borderBottomWidth: 1, borderBottomColor: COLORS.border }, title: { fontSize: 16, fontWeight: '700', color: COLORS.text }, close: { fontSize: 22, color: COLORS.muted }, row: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 18, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: COLORS.border, gap: 10 }, name: { fontSize: 14, fontWeight: '600', color: COLORS.text }, desc: { fontSize: 12, color: COLORS.muted, marginTop: 3 }, pri: { paddingHorizontal: 8, paddingVertical: 3, borderRadius: 10 }, priText: { fontSize: 10, fontWeight: '700' }, })