// AI Assistant — conversational chat with Sofia // As respostas vêm de window.SofiaAPI (Edge Function `sofia-chat`). // Se a chave OpenAI não estiver configurada, o client cai automaticamente // num fallback local (mock leve) sem quebrar a experiência. const AIScreen = ({ state, setState, navigate, showToast, user }) => { // Carrega histórico salvo em state.aiMessages (persiste via cloud-sync). // Se não houver histórico, mostra mensagem de boas-vindas personalizada (não o mock antigo do Lucas). const userFirstName = (user && user.name && String(user.name).split(' ')[0]) || (user && user.email && user.email.split('@')[0]) || 'aí'; const welcomeMsg = { from: 'ai', text: `Olá, ${userFirstName}! 👋 Sou a Sofia, sua assistente pessoal. Posso te ajudar com tarefas, finanças, hábitos, metas e até consultar seu cofre pessoal. O que você quer fazer agora?`, }; const initialMessages = (state && Array.isArray(state.aiMessages) && state.aiMessages.length > 0) ? state.aiMessages : [welcomeMsg]; const [messages, setMessages] = React.useState(initialMessages); const [input, setInput] = React.useState(''); const [typing, setTyping] = React.useState(false); const [voiceMode, setVoiceMode] = React.useState(false); const scrollRef = React.useRef(null); React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [messages, typing]); // Persiste mensagens no state global (cloud-sync salva automaticamente). // Mantém só as últimas 50 pra não inchar (Sofia usa só as 6 mais recentes pro contexto). const persistMessages = (next) => { if (!setState) return; const trimmed = next.length > 50 ? next.slice(-50) : next; setState(s => ({ ...s, aiMessages: trimmed })); }; const send = async (text) => { if (!text.trim()) return; const userMsg = { from: 'me', text }; const afterUser = [...messages, userMsg]; setMessages(afterUser); persistMessages(afterUser); setInput(''); setTyping(true); const userName = (user && (user.name || user.email)) || (state && state.userName) || 'Lucas'; const userState = window.SofiaAPI ? window.SofiaAPI.buildUserState(state, userName) : null; try { const res = window.SofiaAPI ? await window.SofiaAPI.chat({ messages, userState, newMessage: text }) : { reply: 'Sofia ainda não está disponível. Volte daqui a pouco ✨', mode: 'mock' }; setTyping(false); const afterAi = [...afterUser, { from: 'ai', text: res.reply }]; setMessages(afterAi); persistMessages(afterAi); if (res.mode === 'rate_limit' && showToast) { showToast('Limite diário atingido', 'flame'); } } catch (e) { setTyping(false); const afterError = [...afterUser, { from: 'ai', text: 'Tive um problema agora, tenta de novo em alguns segundos? ✨' }]; setMessages(afterError); persistMessages(afterError); } }; if (voiceMode) return setVoiceMode(false)} onSend={(t) => { setVoiceMode(false); send(t); }} />; return (
{/* Header */}
Sofia
Sua assistente pessoal · Online
Premium
{/* Messages */}
Hoje, 9:24
{messages.map((m, i) => )} {typing && } {/* Suggestions chips */} {messages.length < 8 && !typing && (
Sugestões para você
{suggestionsAI.map((s, i) => ( ))}
)}
{/* Input bar */}