/** * overview.js — Lógica de supervisão da Visão Geral * Monitora métricas do robô, bateria, IA Gemini, reações e gerencia ações rápidas. */ (() => { const el = id => document.getElementById(id); let reload = null; let start = 0; let ultimoEstadoOnline = null; function adicionarEvento(texto, tipo = 'info') { const feed = el('overviewFeed'); if (!feed) return; const item = document.createElement('div'); item.style.cssText = 'display:flex;align-items:center;gap:10px;animation:fadeInMsg .2s ease-out'; const cor = tipo === 'online' ? '#10b981' : tipo === 'alerta' ? '#f59e0b' : 'var(--ciano)'; const hora = new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); item.innerHTML = ` ${texto} ${hora} `; feed.prepend(item); while (feed.children.length > 7) { feed.removeChild(feed.lastChild); } } async function refresh() { try { const [s, c, t] = await Promise.all(['/app/status', '/conversa/status', '/treinamento/status'].map(async p => { const r = await fetch(p, { cache: 'no-store', signal: AbortSignal.timeout(3000) }); if (!r.ok) throw Error('Servidor indisponível'); return r.json(); })); // Estado do Celular if (el('overviewPhone')) { el('overviewPhone').textContent = s.online ? 'Conectado' : 'Desconectado'; el('overviewPhone').style.color = s.online ? '#34d399' : 'var(--fraco)'; } if (el('overviewIP')) { el('overviewIP').textContent = s.celular_ip || (s.online ? 'IP Detectado' : 'Abra o Carinha no celular'); } // Registra evento de conexão/desconexão if (ultimoEstadoOnline !== null && ultimoEstadoOnline !== s.online) { if (s.online) { adicionarEvento('Galaxy S10 conectado e sincronizado', 'online'); if (window.RobotAudio) window.RobotAudio.happy(); } else { adicionarEvento('Galaxy S10 desconectou da Central', 'alerta'); } } ultimoEstadoOnline = s.online; // Bateria if (el('overviewBattery')) { const nivel = s.online && s.estado?.bateria?.nivel != null ? s.estado.bateria.nivel + '%' : '—'; el('overviewBattery').textContent = nivel; if (s.estado?.bateria?.nivel != null) { if (s.estado.bateria.nivel <= 20) { el('overviewBattery').style.color = '#fb7185'; } else { el('overviewBattery').style.color = '#f0f6fc'; } } } if (el('overviewCharge')) { const carregando = s.estado?.bateria?.carregando; el('overviewCharge').textContent = carregando ? '⚡ Carregando na tomada' : 'Operando na bateria'; el('overviewCharge').style.color = carregando ? 'var(--ciano)' : 'var(--fraco)'; } // Inteligência IA if (el('overviewAI')) { el('overviewAI').textContent = c.provedor === 'gemini' ? 'Google Gemini' : 'Qwen Local'; } if (el('overviewModel')) { el('overviewModel').textContent = c.modelo || 'IA Pronta'; } // Biblioteca de reações if (el('overviewReactions')) { el('overviewReactions').textContent = Array.isArray(t.reacoes) ? t.reacoes.length : '0'; } // Botão de recarga if (el('overviewReload')) { el('overviewReload').disabled = !s.online; } // Confirmação de recarga remota if (reload && s.recarga?.id === reload && s.recarga.confirmada) { el('overviewMessage').textContent = '✅ Tela atualizada: Galaxy S10 confirmou o recarregamento.'; adicionarEvento('Tela do Galaxy S10 recarregada com sucesso', 'online'); reload = null; } else if (reload && Date.now() - start > 12000) { el('overviewMessage').textContent = '⚠️ Sem confirmação. Reabra o app Carinha no celular.'; reload = null; } } catch (e) { if (el('overviewMessage')) el('overviewMessage').textContent = e.message; } } // Ação de recarregar a tela do celular if (el('overviewReload')) { el('overviewReload').onclick = async () => { try { if (window.RobotAudio) window.RobotAudio.click(); const r = await fetch('/app/recarregar', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{}' }); const d = await r.json(); if (!r.ok) throw Error(d.erro); el('overviewMessage').textContent = d.mensagem; adicionarEvento('Solicitação de recarga enviada ao celular...'); const s = await (await fetch('/app/status')).json(); reload = s.recarga?.id; start = Date.now(); } catch (e) { el('overviewMessage').textContent = 'Erro: ' + e.message; } }; } // Botões de Expressão Rápida (Mood Buttons) document.querySelectorAll('.btn-mood').forEach(btn => { btn.onclick = async () => { const gesto = btn.getAttribute('data-gesto'); if (!gesto) return; try { if (window.RobotAudio) window.RobotAudio.tocarGesto(gesto); await fetch('/gesto/' + encodeURIComponent(gesto)); adicionarEvento(`Expressão disparada: ${gesto}`); btn.style.transform = 'scale(0.94)'; setTimeout(() => btn.style.transform = '', 160); } catch (err) { console.error('Falha ao acionar gesto:', err); } }; }); // Botão de Teste Sonoro if (el('overviewSfxHappy')) { el('overviewSfxHappy').onclick = () => { if (window.RobotAudio) { window.RobotAudio.happy(); adicionarEvento('Sintetizador gerou trinado alegre'); } }; } refresh(); setInterval(refresh, 3500); })();