- web/ com Vite + Svelte 5 + TypeScript; servidor entrega web/dist em "/" (telas antigas seguem em /dashboard, /painel, /braco...) - design system em tokens CSS, tema escuro e claro, fontes locais - estado unico: foto de /estado + um EventSource em /eventos, sem polling - shell com navegacao lateral/inferior, selos de status reais e E-Stop fixo - command palette (Ctrl+K), gestos favoritos com atalhos 1-9, g+letra navega - Ao vivo: camera WebRTC e rastreamento portados para TS, rosto, aparencia, sensores do celular, IA local e feed de acontecimentos - Ajustes: campos do celular agrupados com busca, salvamento otimista e restaurar padrao (GET /app/padrao); motor da conversa, Gemini e token - carinha.html ganha modo ?painel=1 dirigido por postMessage (sem polling) - teste Playwright de ponta a ponta do painel novo Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
27 lines
897 B
TypeScript
27 lines
897 B
TypeScript
/** Rotas por hash (#/conversa): o servidor só precisa entregar index.html em "/". */
|
|
|
|
export type Rota = 'ao-vivo' | 'conversa' | 'reacoes' | 'movimento' | 'ajustes';
|
|
|
|
export const ROTAS: { id: Rota; titulo: string; atalho: string }[] = [
|
|
{ id: 'ao-vivo', titulo: 'Ao vivo', atalho: 'g v' },
|
|
{ id: 'conversa', titulo: 'Conversa', atalho: 'g c' },
|
|
{ id: 'reacoes', titulo: 'Reações', atalho: 'g r' },
|
|
{ id: 'movimento', titulo: 'Movimento', atalho: 'g m' },
|
|
{ id: 'ajustes', titulo: 'Ajustes', atalho: 'g a' },
|
|
];
|
|
|
|
function lerHash(): Rota {
|
|
const id = location.hash.replace(/^#\/?/, '').split('?')[0] as Rota;
|
|
return ROTAS.some((r) => r.id === id) ? id : 'ao-vivo';
|
|
}
|
|
|
|
class Navegacao {
|
|
atual = $state<Rota>(lerHash());
|
|
ir(rota: Rota) {
|
|
location.hash = '/' + rota;
|
|
}
|
|
}
|
|
|
|
export const nav = new Navegacao();
|
|
addEventListener('hashchange', () => (nav.atual = lerHash()));
|