import { useState, useRef, useCallback } from 'react'; import { View, Text, TextInput, FlatList, TouchableOpacity, StyleSheet, KeyboardAvoidingView, Platform, ActivityIndicator, Alert, } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useAuthContext } from '../../lib/AuthContext'; import * as api from '../../lib/api'; type Message = { id: string; role: 'user' | 'assistant'; content: string; timestamp: Date; }; export default function ChatScreen() { const { token } = useAuthContext(); const [messages, setMessages] = useState([ { id: '0', role: 'assistant', content: 'Ahoj! Jsem vas AI asistent pro Task Team. Mohu vam pomoci s ukoly, planovani a organizaci. Na co se chcete zeptat?', timestamp: new Date(), }, ]); const [input, setInput] = useState(''); const [sending, setSending] = useState(false); const flatListRef = useRef(null); const sendMessage = useCallback(async () => { if (!input.trim() || !token || sending) return; const userMsg: Message = { id: Date.now().toString(), role: 'user', content: input.trim(), timestamp: new Date(), }; setMessages((prev) => [...prev, userMsg]); setInput(''); setSending(true); try { const res = await api.sendChatMessage(token, userMsg.content); const aiMsg: Message = { id: (Date.now() + 1).toString(), role: 'assistant', content: res.data?.reply || 'Omlouvam se, nepodarilo se zpracovat odpoved.', timestamp: new Date(), }; setMessages((prev) => [...prev, aiMsg]); } catch (err: any) { const errMsg: Message = { id: (Date.now() + 1).toString(), role: 'assistant', content: `Chyba: ${err.message}`, timestamp: new Date(), }; setMessages((prev) => [...prev, errMsg]); } finally { setSending(false); } }, [input, token, sending]); const renderMessage = ({ item }: { item: Message }) => { const isUser = item.role === 'user'; return ( {!isUser && ( )} {item.content} {item.timestamp.toLocaleTimeString('cs-CZ', { hour: '2-digit', minute: '2-digit', })} ); }; return ( item.id} renderItem={renderMessage} contentContainerStyle={styles.listContent} onContentSizeChange={() => flatListRef.current?.scrollToEnd({ animated: true }) } /> {sending ? ( ) : ( )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F8FAFC' }, listContent: { padding: 12, paddingBottom: 4 }, msgRow: { flexDirection: 'row', marginBottom: 12, maxWidth: '85%' }, msgRowUser: { alignSelf: 'flex-end' }, msgRowAi: { alignSelf: 'flex-start' }, avatar: { width: 32, height: 32, borderRadius: 16, backgroundColor: '#EFF6FF', alignItems: 'center', justifyContent: 'center', marginRight: 8, marginTop: 4, }, bubble: { borderRadius: 16, padding: 12, maxWidth: '100%' }, bubbleUser: { backgroundColor: '#3B82F6', borderBottomRightRadius: 4, }, bubbleAi: { backgroundColor: '#fff', borderBottomLeftRadius: 4, borderWidth: 1, borderColor: '#E2E8F0', }, bubbleText: { fontSize: 15, lineHeight: 21, color: '#1E293B' }, timestamp: { fontSize: 10, color: '#94A3B8', marginTop: 4, textAlign: 'right' }, inputBar: { flexDirection: 'row', alignItems: 'flex-end', padding: 12, backgroundColor: '#fff', borderTopWidth: 1, borderTopColor: '#E2E8F0', }, input: { flex: 1, borderWidth: 1, borderColor: '#E2E8F0', borderRadius: 20, paddingHorizontal: 16, paddingVertical: 10, fontSize: 15, maxHeight: 100, backgroundColor: '#F8FAFC', }, sendBtn: { width: 42, height: 42, borderRadius: 21, backgroundColor: '#3B82F6', alignItems: 'center', justifyContent: 'center', marginLeft: 8, }, sendBtnDisabled: { backgroundColor: '#94A3B8' }, });