guardia-messenger/components/SuggestedCommands.tsx
2026-06-03 09:17:03 +09:00

89 lines
3.0 KiB
TypeScript

import { useEffect, useState, useCallback } from 'react'
import { ScrollView, Text, Pressable, StyleSheet, View } from 'react-native'
import { COLORS, API_BASE } from '../constants/Config'
import { getToken } from '../utils/auth'
interface Props {
recentMessages: string[]
room?: string
onSelect: (cmd: string) => void
visible?: boolean
}
const DEFAULT_CMDS = ['/sr create', '/server status', '/dashboard', '/deploy', '/alert list']
export function SuggestedCommands({ recentMessages, room = 'general', onSelect, visible = true }: Props) {
const [suggestions, setSuggestions] = useState<string[]>(DEFAULT_CMDS)
const [loading, setLoading] = useState(false)
const fetchSuggestions = useCallback(async () => {
if (recentMessages.length === 0) return
setLoading(true)
try {
const token = await getToken()
const res = await fetch(`${API_BASE}/api/ux/next-commands`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
recent_messages: recentMessages.slice(-5),
context: room,
}),
})
if (res.ok) {
const data = await res.json()
if (data.commands?.length) setSuggestions(data.commands)
}
} catch {
// 네트워크 오류 시 기본 명령 유지
} finally {
setLoading(false)
}
}, [recentMessages.length, room])
useEffect(() => {
const timer = setTimeout(fetchSuggestions, 600) // 디바운스
return () => clearTimeout(timer)
}, [fetchSuggestions])
async function handleSelect(cmd: string) {
onSelect(cmd)
// 명령 학습 API 호출
try {
const token = await getToken()
await fetch(`${API_BASE}/api/ux/learn`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ command: cmd, room }),
})
} catch {}
}
if (!visible) return null
return (
<View style={S.container}>
<Text style={S.label}> </Text>
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={S.scroll}>
{suggestions.map((cmd, i) => (
<Pressable key={i} onPress={() => handleSelect(cmd)} style={S.chip}>
<Text style={S.chipText}>{cmd}</Text>
</Pressable>
))}
</ScrollView>
</View>
)
}
const S = StyleSheet.create({
container: { paddingVertical: 6, paddingHorizontal: 12,
borderTopWidth: 1, borderTopColor: COLORS.border,
backgroundColor: '#f8fafc' },
label: { fontSize: 10, color: COLORS.muted, marginBottom: 4 },
scroll: { flexDirection: 'row' },
chip: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16,
backgroundColor: '#e0e7ff', marginRight: 6,
borderWidth: 1, borderColor: '#c7d2fe' },
chipText: { fontSize: 12, color: COLORS.gnbBg, fontWeight: '600',
fontFamily: 'monospace' },
})