import { useEffect, useState } from 'react' import { View, Text, TextInput, TouchableOpacity, StyleSheet, ActivityIndicator, Alert, } from 'react-native' import { COLORS } from '../constants/Config' import { getSRComments, addSRComment } from '../services/api' interface CommentItem { id: number | string content: string author?: string is_internal?: boolean created_at?: string } interface Props { srId: number } /** * 기능 #13 — 내부/외부 코멘트 구분 컴포넌트 * 내부: 자물쇠(담당자 전용), 외부: 지구본(기관 공개) * POST /api/tasks/{id}/comments { content, is_internal } */ export default function Comment({ srId }: Props) { const [items, setItems] = useState([]) const [loading, setLoading] = useState(true) const [text, setText] = useState('') const [isInternal, setIsInternal] = useState(true) const [sending, setSending] = useState(false) const load = async () => { try { const res = await getSRComments(srId) setItems(res.data?.content ?? res.data?.items ?? res.data ?? []) } catch { setItems([]) } finally { setLoading(false) } } useEffect(() => { load() }, [srId]) const submit = async () => { if (!text.trim()) return setSending(true) try { await addSRComment(srId, text.trim(), isInternal) setText('') await load() } catch (e: any) { Alert.alert('오류', e.response?.data?.detail ?? '코멘트 등록 실패') } finally { setSending(false) } } return ( {loading ? ( ) : items.length === 0 ? ( 코멘트가 없습니다. ) : ( items.map(c => ( {c.is_internal ? '🔒 내부' : '🌐 외부'} {c.author ?? '담당자'} {c.content} {!!c.created_at && {c.created_at.slice(0, 16).replace('T', ' ')}} )) )} {/* 입력 영역 */} setIsInternal(true)} > 🔒 내부 setIsInternal(false)} > 🌐 외부 {sending ? : 등록} ) } const s = StyleSheet.create({ empty: { color: COLORS.muted, fontSize: 12, paddingVertical: 8 }, bubble: { borderRadius: 10, padding: 12, marginBottom: 8, borderLeftWidth: 3 }, internal: { backgroundColor: '#FFF7ED', borderLeftColor: COLORS.warning }, external: { backgroundColor: COLORS.light, borderLeftColor: COLORS.accent }, bubbleHead: { flexDirection: 'row', justifyContent: 'space-between', marginBottom: 4 }, tag: { fontSize: 11, fontWeight: '700', color: COLORS.text }, author: { fontSize: 11, color: COLORS.muted }, content: { fontSize: 13, color: COLORS.text, lineHeight: 18 }, time: { fontSize: 10, color: COLORS.muted, marginTop: 4 }, toggleRow: { flexDirection: 'row', gap: 8, marginTop: 12, marginBottom: 8 }, toggle: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16, borderWidth: 1, borderColor: COLORS.border }, toggleActive: { backgroundColor: COLORS.primary, borderColor: COLORS.primary }, toggleText: { fontSize: 12, color: COLORS.text }, toggleTextActive: { color: '#fff', fontWeight: '700' }, inputRow: { flexDirection: 'row', alignItems: 'flex-end', gap: 8 }, input: { flex: 1, borderWidth: 1.5, borderColor: COLORS.border, borderRadius: 9, padding: 10, fontSize: 13, color: COLORS.text, maxHeight: 100 }, sendBtn: { backgroundColor: COLORS.accent, borderRadius: 9, paddingHorizontal: 16, paddingVertical: 11 }, sendText: { color: '#fff', fontSize: 13, fontWeight: '700' }, })