// Smart App City — AI Chat Screen import React, { useState, useRef, useEffect } from 'react'; import { View, Text, TextInput, TouchableOpacity, ScrollView, StyleSheet, KeyboardAvoidingView, Platform, } from 'react-native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { Colors, Typography, Spacing, BorderRadius, Shadows } from '../../../src/theme/colors'; type Props = { navigation: NativeStackNavigationProp }; interface Message { id: string; text: string; isBot: boolean; timestamp: Date; } const QUICK_PROMPTS = [ { id: '1', text: '🌤️ Météo aujourd\'hui', prompt: 'Quelle est la météo à Martinique aujourd\'hui ?' }, { id: '2', text: '🚌 Prochain bus', prompt: 'Quel est le prochain bus pour Fort-de-France ?' }, { id: '3', text: '⚡ Consommation énergie', prompt: 'Quelle est ma consommation d\'énergie cette semaine ?' }, { id: '4', text: '🚨 Alertes en cours', prompt: 'Y a-t-il des alertes en cours à Martinique ?' }, ]; const BOT_RESPONSES: Record = { '🌤️ Météo': '☀️ Aujourd\'hui à Fort-de-France : 28°C, ensoleillé avec quelques nuages. Humidité 72%, vent 12 km/h NE. Indice UV 8 — pensez à la crème solaire !', '🚌 Prochain bus': '🚌 Le prochain bus L1 (Centre-Ville → Schoelcher) arrive dans 8 min. Le L3 (Aimé Césaires) dans 12 min. Source : CFTA temps réel.', '⚡ Consommation': '⚡ Votre consommation cette semaine : 45 kWh, soit 12% de moins que la semaine dernière. Estimation mensuelle : 180 kWh. Bon travail !', '🚨 Alertes': '🚨 1 alerte en cours : Qualité de l\'air dégradée à Schoelcher (AQI 85). Évitez les efforts prolongés en extérieur. Pas d\'alerte météo.', }; export default function ChatScreen({ navigation }: Props) { const [messages, setMessages] = useState([ { id: '0', text: 'Bonjour ! Je suis Smart City IA 🤖\n\nJe peux vous aider avec :\n• 🌤️ Météo en temps réel\n• 🚌 Transports\n• ⚡ Énergie\n• 🚨 Alertes\n\nComment puis-je vous aider ?', isBot: true, timestamp: new Date(), }, ]); const [input, setInput] = useState(''); const [isTyping, setIsTyping] = useState(false); const scrollRef = useRef(null); useEffect(() => { scrollRef.current?.scrollToEnd({ animated: true }); }, [messages]); const sendMessage = (text: string) => { if (!text.trim()) return; const userMsg: Message = { id: Date.now().toString(), text: text.trim(), isBot: false, timestamp: new Date(), }; setMessages((prev) => [...prev, userMsg]); setInput(''); setIsTyping(true); // Simulate bot response setTimeout(() => { const response = getBotResponse(text); const botMsg: Message = { id: (Date.now() + 1).toString(), text: response, isBot: true, timestamp: new Date(), }; setMessages((prev) => [...prev, botMsg]); setIsTyping(false); }, 1000 + Math.random() * 1000); }; const getBotResponse = (text: string): string => { const lower = text.toLowerCase(); for (const [key, response] of Object.entries(BOT_RESPONSES)) { if (lower.includes(key.slice(2).toLowerCase())) return response; } if (lower.includes('météo') || lower.includes('weather')) return BOT_RESPONSES['🌤️ Météo']; if (lower.includes('bus') || lower.includes('transport')) return BOT_RESPONSES['🚌 Prochain bus']; if (lower.includes('énergie') || lower.includes('energie') || lower.includes('consommation')) return BOT_RESPONSES['⚡ Consommation']; if (lower.includes('alerte') || lower.includes('danger')) return BOT_RESPONSES['🚨 Alertes']; return 'Je comprends votre question. Laissez-moi consulter les données en temps réel... 🔍\n\nPour l\'instant, voici les services disponibles : météo, transports, énergie, et alertes. Essayez l\'un des raccourcis ci-dessous !'; }; return ( {/* Header */} 🤖 Smart City IA En ligne {/* Quick prompts */} {QUICK_PROMPTS.map((p) => ( sendMessage(p.prompt)}> {p.text} ))} {/* Messages */} {messages.map((msg) => ( {msg.isBot && 🤖} {msg.text} {msg.timestamp.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' })} ))} {isTyping && ( 🤖 Écrit... )} {/* Input */} sendMessage(input)} disabled={!input.trim() || isTyping} > ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: Colors.neutral50 }, header: { flexDirection: 'row', alignItems: 'center', backgroundColor: Colors.primary[500], paddingTop: 50, paddingBottom: Spacing.base, paddingHorizontal: Spacing.base, gap: Spacing.base, }, botAvatar: { width: 44, height: 44, borderRadius: BorderRadius.lg, backgroundColor: 'rgba(255,255,255,0.2)', justifyContent: 'center', alignItems: 'center', }, botEmoji: { fontSize: 24 }, title: { fontSize: Typography.sizes.md, fontWeight: Typography.weights.bold, color: Colors.white }, statusRow: { flexDirection: 'row', alignItems: 'center', gap: 4, marginTop: 2 }, statusDot: { width: 6, height: 6, borderRadius: 3, backgroundColor: Colors.success }, statusText: { fontSize: Typography.sizes.xs, color: 'rgba(255,255,255,0.8)' }, promptsScroll: { padding: Spacing.base }, promptChip: { backgroundColor: Colors.white, borderRadius: BorderRadius.full, paddingHorizontal: Spacing.base, paddingVertical: Spacing.sm, marginRight: Spacing.sm, borderWidth: 1, borderColor: Colors.neutral200, }, promptText: { fontSize: Typography.sizes.sm, color: Colors.neutral700 }, messagesList: { flex: 1, paddingHorizontal: Spacing.base }, messageRow: { flexDirection: 'row', marginBottom: Spacing.sm, gap: Spacing.sm }, botRow: { justifyContent: 'flex-start' }, userRow: { justifyContent: 'flex-end' }, botAvatarSmall: { width: 28, height: 28, borderRadius: BorderRadius.md, backgroundColor: Colors.primary[100], justifyContent: 'center', alignItems: 'center', }, botEmojiSmall: { fontSize: 14 }, messageBubble: { maxWidth: '75%', borderRadius: BorderRadius.lg, padding: Spacing.base, ...Shadows.sm, }, botBubble: { backgroundColor: Colors.white, borderBottomLeftRadius: 4, }, userBubble: { backgroundColor: Colors.primary[500], borderBottomRightRadius: 4, }, messageText: { fontSize: Typography.sizes.base, lineHeight: 20 }, botText: { color: Colors.neutral900 }, userText: { color: Colors.white }, messageTime: { fontSize: 9, marginTop: 4 }, botTime: { color: Colors.neutral400 }, userTime: { color: 'rgba(255,255,255,0.6)' }, typingText: { color: Colors.neutral400, fontStyle: 'italic' }, inputBar: { flexDirection: 'row', alignItems: 'flex-end', backgroundColor: Colors.white, paddingHorizontal: Spacing.base, paddingVertical: Spacing.sm, borderTopWidth: 1, borderTopColor: Colors.neutral200, gap: Spacing.sm, }, input: { flex: 1, backgroundColor: Colors.neutral50, borderRadius: BorderRadius.full, paddingHorizontal: Spacing.base, paddingVertical: Spacing.sm, fontSize: Typography.sizes.base, color: Colors.neutral900, maxHeight: 100, }, sendBtn: { width: 40, height: 40, borderRadius: 20, backgroundColor: Colors.primary[500], justifyContent: 'center', alignItems: 'center', }, sendIcon: { color: Colors.white, fontSize: 18 }, });