feat: initial commit - Carinha Control Panel v1.0 com UI glassmorphism, watch-bar, emojis, braco robotico e conversa IA
This commit is contained in:
+159
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* 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 = `
|
||||
<span class="badge-dot" style="background:${cor};box-shadow:0 0 8px ${cor}"></span>
|
||||
<span style="color:var(--texto)">${texto}</span>
|
||||
<span style="margin-left:auto;font-size:11px;font-family:'JetBrains Mono',monospace;color:var(--fraco)">${hora}</span>
|
||||
`;
|
||||
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);
|
||||
})();
|
||||
Reference in New Issue
Block a user