# Guia de frontend do EcomSmart Hub por módulos

Versão 1 · 12/09/2026 · para o programador frontend (Angular 21) · companheiro do protótipo v3 e da identidade v2.4

Este guia diz **o que construir, como e por quê**. O protótipo mostra a tela; aqui está a razão de cada decisão, para que o dev resolva sozinho o que o protótipo não cobre. Quando houver conflito, vale: identidade v2.4 (skill `identidade-ecomsmart`) → este guia → protótipo.

## 1. Princípios de UX que governam tudo

1. **Um modelo mental para os cinco módulos.** Todo módulo tem as mesmas cinco abas na mesma ordem (Dashboard, Configurar, Mensagens, Histórico, Assistente). O lojista aprende uma vez. Custo: um pouco de repetição de código; ganho: zero curva de aprendizado ao ativar o segundo módulo, que é exatamente o momento da venda.
2. **Duas portas para a mesma configuração.** Formulário em cards numerados **e** conversa com o assistente escrevem no mesmo modelo (`ConfigModulo`). O lojista que gosta de controle usa o formulário; o que tem pressa conversa. Nunca são dois sistemas: alterar num lado aparece no outro.
3. **Nada é enviado sem confirmação explícita.** O assistente executa leitura na hora (contar público, simular) e mostra a escrita como proposta num card; só o clique em "Confirmar" executa. É a regra que permite dar poder ao assistente sem medo.
4. **Módulo bloqueado é visível, não escondido.** Aparece no menu com cadeado, abre a prévia desfocada com um argumento real da base. Esconder mata o upsell e gera a pergunta "onde está o RFV?".
5. **Estado em forma, não só em cor.** Pílula, ponto, cadeado, borda esquerda. Cor semântica (verde, âmbar, vermelho) é reforço. Acessível e legível em tema escuro.
6. **O dado é o destaque.** KPIs em Figtree 700 tabular; azul quando é dinheiro ou taxa de resultado. Nada mais é azul além de ações e dados.
7. **Mobile é primeira classe, não adaptação.** Barra inferior fixa, uma decisão por tela, tabelas viram cards, assistente em folha inferior, abas roláveis. Layouts são desenhados para 390 px e crescem, não o contrário.
8. **Backend é a fonte de verdade de gating, mensagens e limiares.** Guards e textos no front só melhoram UX. Se o backend diz `alerta: true`, a tela mostra alerta; ela não recompara números.

## 2. Arquitetura de navegação

Três áreas, três layouts, três bundles lazy:

| Área | Layout | Rotas | Quem vê |
|---|---|---|---|
| Público | `public-layout` (header marketing + rodapé em bloco) | `/lp/:slug`, `/cadastro`, `/login`, `/precos` | anônimo |
| Onboarding | `onboarding-layout` (barra de passos, sem menu, fundo Névoa) | `/onboarding/:passo` (empresa, modulos, pagamento, whatsapp, loja, pronto) | logado, `Empresa.onboarding.concluido = false` |
| App | `app-shell` (sidebar navy no web · barra inferior no mobile) | `/app`, `/app/modulos`, `/app/m/:modulo/:aba`, `/app/m/:modulo/ativar`, `/app/assistente`, `/app/conta/(assinatura|mcp|configuracoes)`, `/app/base/(clientes|pedidos|produtos|rfv)` | logado |

Regras:

- **A aba é rota.** `/app/m/carrinho/configurar` recarrega na aba certa, é compartilhável e aparece no histórico do navegador. Estado interno de aba (signal solto) é proibido.
- **`moduleGuard(key)` não redireciona.** Resolve `bloqueado: true` via `route.data` e o `modulo-shell` renderiza a prévia com paywall. O guard atual (redirect + toast) sai.
- **Breadcrumb** no web (`Início › Módulos › Carrinho`), botão "‹ Módulos" no header do mobile.
- **Barra inferior mobile**: Início (`/app`), Módulos (`/app/modulos`), Assistente (`/app/assistente`), Conta (`/app/conta/assinatura`). Dentro de um módulo, o item Módulos fica ativo.
- **Voltar do assistente por módulo** leva ao Dashboard do módulo, não ao Início.
- **Query params** guardam filtros de Histórico e Mensagens (período, status), para o link colado abrir igual.

## 3. Shell do app

Web: sidebar 232 px, navy `#0B1033`, item ativo com 12 % de branco, seções `Meus módulos` (5 itens com ponto colorido; bloqueado com opacidade 55 % e cadeado à direita; trial com etiqueta âmbar), `Minha base`, `Conta`. Header branco com nome da empresa, pílula de canal (`WhatsApp Oficial · conectado`, verde só aqui), medidor de mensagens do ciclo (`3.240 / 10.000` + barra), etiqueta de trial e avatar.

Mobile: header de 52 px (logo ou "‹ Módulo"), conteúdo, barra inferior de 4 itens com ícone em linha 22 px e rótulo 10,5 px. O medidor de mensagens fica no header em texto pequeno.

Assistente: no web, painel fixo de 360 px à direita em toda tela de módulo (não é modal, não sobrepõe); no mobile, botão "Abrir assistente" no card e tela própria (aba Assistente). Mesmo componente `<hub-assistente>` nos dois.

Tema: claro por padrão, escuro por escolha (`data-theme`), tokens da identidade. Toda tela é testada nos dois.

## 4. O padrão de módulo (`modulo-shell`)

Componente único que recebe `ModuloDef` e renderiza cabeçalho + abas + `<router-outlet>` da aba. As abas são componentes por módulo que implementam uma interface comum.

| Aba | Propósito | Conteúdo fixo | Por quê |
|---|---|---|---|
| Dashboard | responder "está funcionando e quanto rende?" em 5 segundos | 4 KPIs · card "Configuração atual" (4 linhas + Editar) · funil de 4 etapas · gráfico mensal monocromático · painel do assistente (web) | KPI primeiro porque é a promessa do produto; a configuração resumida evita ir à aba Configurar só para conferir |
| Configurar | alterar com controle e revisão | cards numerados na ordem: Nome → Canal → Mensagem → Regra → Agendamento → Revisão (módulos sem campanha adaptam, ver §6) · faixa "Prefere conversar?" no topo · prévia e impacto à direita | cards numerados dão sensação de progresso e evitam formulário infinito; a Revisão com variáveis do template evita disparo com `{{2}}` sem fonte |
| Mensagens | gerir templates e qualidade do canal | rating do número no topo · tabela (nome, categoria Meta, status, "usar em", nota) · variáveis · classificação · erros recentes | rating do número é o que antecede queda de entrega; nota do template quase sempre `UNKNOWN` e não é alarme |
| Histórico | auditar e provar receita | chips de filtro · alerta de saúde (15 dias) · lista/tabela (quando, quem, o quê, status, resultado) · detalhe por linha | receita atribuída por vínculo ou janela é o argumento de renovação; o detalhe com payload e código da Meta é o que suporte precisa |
| Assistente ✦ | criar e alterar conversando | chat com passos · opções prontas · cards de leitura · prévia WhatsApp · card de confirmação · resumo em construção (web) | é o diferencial do produto e o caminho mais curto para o lojista sem tempo |

Cabeçalho do módulo: breadcrumb, ícone com cor do módulo (único lugar de cor de módulo além do ponto do menu), nome, uma linha de descrição (web), pílula de status (`Ativo`, `Trial`, `Pausado`, `Aguardando canal`), botão "✦ Configurar conversando". Banner de trial acima quando aplicável.

## 5. Estrutura conversacional (assistente)

### 5.1 Contrato de eventos (SSE) `POST /api/assistente/conversar/`

| Evento | Payload | Renderização |
|---|---|---|
| `texto` | `{ html }` | balão do assistente (permite `<b>`) |
| `opcoes` | `{ itens: [{label, valor, recomendada?}] }` | chips; a recomendada vem com borda azul; clique envia `valor` como mensagem do usuário |
| `tool_leitura` | `{ nome, args, resultado }` | card com borda esquerda verde: nome da tool em 600 e resultado em uma linha |
| `previa_whatsapp` | `{ texto, botoes? }` | balão estilo WhatsApp (fundo `#0B141A`, bolha `#202C33`) |
| `proposta_escrita` | `{ id, titulo, resumo: [[chave, valor]], acoes: [{tool, args}] }` | card com borda azul, lista chave/valor, botões "Confirmar" e "Editar algo", nota "Nada é enviado sem este clique." |
| `resumo` | `{ itens: [[chave, valor, ok]] }` | atualiza o painel "Resumo em construção" |
| `erro` | `{ mensagem }` | balão com borda esquerda vermelha e botão "Tentar de novo" |

`POST /api/assistente/confirmar/:id` executa `acoes` em transação e devolve `tool_escrita` (renderiza o card verde com "✓ executado"). "Editar algo" envia a mensagem "quero alterar X" e o backend reabre o slot.

### 5.2 Regras de interface

- Barra de passos no topo do chat (`passos[]` vem do backend por módulo) mostra onde a conversa está.
- Texto livre sempre permitido; opções são atalho, não restrição.
- Rascunho salvo por usuário e módulo (`ConversaAssistente`); voltar à aba retoma de onde parou, com botão "Recomeçar".
- "Ver como formulário" leva à aba Configurar com o `ConfigModulo` parcial carregado e os cards já preenchidos marcados.
- Toda mensagem do assistente que cita número traz a fonte (matriz de tal data, canal tal). O front não inventa números.
- Altura do chat: preenche a viewport menos o cabeçalho; input fixo embaixo; rolagem só na lista de mensagens.
- Mobile: o resumo em construção vira `<details>` recolhido acima do chat, com contagem `3/5`.

### 5.3 Slots por módulo (o que a conversa precisa fechar)

| Módulo | Passos | Slots obrigatórios | Tools de leitura | Tools de escrita (na confirmação) |
|---|---|---|---|---|
| Carrinho | Origem · Canal · Régua · Regras · Confirmar | origem, canal, n_mensagens, delays[], templates[], cupom?, regras (valor mínimo, dias, frequência) | `carrinho.simular_regua`, `canais.status`, `templates.listar` | `carrinho.atualizar_regua`, `cupons.criar`, `carrinho.ativar` |
| Disparo RFV | Objetivo · Público · Mensagem · Agendamento · Confirmar | familia (reativacao/sazonal/novidade/informativo), segmentos[], modo_template, templates{}, quando | `rfv.resumo`, `rfv.contar_publico`, `templates.listar`, `campanhas.estimar_custo` | `campanhas.criar_*`, `campanhas.agendar` |
| Retenção | Boas-vindas · Aniversário · Regras · Confirmar | bv.delay, bv.horario, bv.template, bv.agrupador, aniv.horario, aniv.beneficio, aniv.template | `retencao.previa_dia`, `templates.listar` | `retencao.boas_vindas.configurar/ativar`, `retencao.aniversario.configurar/ativar` |
| E-commerceFlow | Catálogo · IA · Flows · Teste · Publicar | estoque_min, colecoes?, tom, proibicoes[], pagamentos[], horario_humano | `catalogo.status`, `flow.simular_conversa` | `flow.regras.atualizar`, `prompts.nova_versao`, `flow.publicar` |
| Campanhas Inteligentes | Diagnóstico · Objetivos · Cupons · Aprovação · Confirmar | objetivos[], cupom (valor, mínimo, validade), modo_aprovacao | `campanhas.analisar_estoque`, `campanhas.sugerir_ofertas`, `campanhas.simular_margem` | `campanhas.aprovar_objetivo`, `cupons.regras`, `campanhas.ativar_objetivos` |

Gates que a conversa respeita e explica: sem RFV calculado (Disparo, Retenção, Campanhas) o assistente diz o motivo exato do backend e oferece "me avise quando estiver pronto"; sem canal conectado, oferece o Embedded Signup; cota perto do limite, avisa antes de agendar.

## 6. Cada módulo em detalhe

### 6.1 Recuperação de Carrinho (`carrinho`)

Objetivo do usuário: "não perder venda que já estava quase fechada". Ele quer ver carrinhos chegando e dinheiro voltando.

- **Dashboard**: KPIs Carrinhos capturados · Recuperados · Receita confirmada (azul) · ROI (azul). Card de configuração mostra Origens, Canal, Régua, Regra. Funil Enviadas → Entregues → Lidas → Convertidas. Gráfico "Mensagens por dia". Mostrar "Saúde das origens" (webhook recebendo ou só coletando) como pílula no card de configuração: estado `coletando` (webhook chega mas envio não configurado) tem que ficar visível, senão parece bug.
- **Configurar** (por integração, não por empresa): 1 Origens (lista de integrações com webhook/sync e status), 2 Canal, 3 Régua (1 a 3 mensagens: delay, template, cupom), 4 Regra de envio (valor mínimo, dias da semana, frequência por cliente), 5 Revisão. Sem card "Nome" porque é automação contínua. Delay mínimo 30 min (backend). Sem gate de RFV (decisão de produto: público do carrinho está fora da matriz).
- **Mensagens**: templates `carrinho_*`; variáveis `{{1}}` nome, `{{2}}` cupom, `{{3}}` link do carrinho.
- **Histórico**: por carrinho (cliente, etapa da régua, status, receita recuperada por vínculo com pedido). Aba secundária "Webhooks recebidos" com payload cru sob demanda (só carrega ao abrir a linha: 3 KB por evento).
- **Assistente**: ver §5.3. Cupom criado na loja via integração.
- **Reaproveitar**: `features/comunicacoes/recuperacao-carrinho/` (casca + `configuracao-carrinho`), `recuperacao-cancelados/` como sub-aba "Cancelados" do Histórico e da Configuração (mesma família), `comm-webhooks-recebidos`, `comm-alerta-erro-envios`.
- **Aceite**: régua salva e ativa em ≤ 5 cliques a partir do Dashboard; carrinho de teste aparece em ≤ 60 s; estado `coletando` visível; mobile completo.

### 6.2 Disparo para Base RFV (`disparo`)

Objetivo: "mandar a mensagem certa para o grupo certo sem queimar meu número".

- **Dashboard**: KPIs Clientes segmentados · Enviadas (30 d) · Conversão (azul) · Receita gerada (azul). Card "Segmentação RFV" com data da matriz e link para a aba RFV. Lista das últimas campanhas com status.
- **Sub-navegação interna** (segunda linha de chips, não abas): Campanhas (reativação, sazonal, novidades, giftback, informativo, manual) · RFV (a `analise-rfv` atual, com matriz e desempenho por segmento). Por quê chips e não abas: manter as cinco abas iguais em todos os módulos; a família da campanha é um filtro dentro de Campanhas.
- **Configurar** (criar campanha): 1 Nome, 2 Canal, 3 Mensagem (modo único ou por segmento, `comm-mensagem-segmentada`), 4 Público (cards de segmento com contagem de contactáveis, slider de limite), 5 Agendamento (data, cadência fixa por tipo de canal, previsão `comm-resumo-disparo` no rodapé do card), 6 Revisão. Gate de RFV: sem matriz, esconde o formulário e mostra `ui-rfm-gate` com a mesma mensagem do backend.
- **Mensagens**: templates por família; classificação "usar em" (reativação, sazonal, informativo…). Informativo não mostra dinheiro em nenhum lugar.
- **Histórico**: por campanha (família, envios, segmentos, status, receita e ROI; informativo mostra "sem receita"). Filtro por família e período.
- **Assistente**: cria a campanha em 4 perguntas; sempre informa contactáveis, custo e duração antes de pedir confirmação.
- **Reaproveitar**: `CampanhaOneShotState`, `TemplatePorSegmentoState`, `comm-rfm-segmento-cards`, `comm-mensagem-segmentada`, `comm-resumo-disparo`, `comm-desempenho-segmentos-familia`, telas `reativacao/`, `sazonais/`, `informativos/`, `novidades/`, `giftback/`, `analise-rfv/`.
- **Aceite**: criar e agendar campanha em ≤ 3 min; gate de RFV com motivo; custo e duração visíveis antes de agendar; uma campanha só pode ser agendada se todos os segmentos escolhidos têm template.

### 6.3 Retenção (`retencao`)

Objetivo: "ligar uma vez e esquecer, sabendo que está rodando".

- **Dashboard**: KPIs Boas-vindas enviadas · Aniversários enviados · Convertidos · Receita gerada (azul). Dois cards lado a lado, um por automação, com toggle Ligada/Desligada, próximo disparo e KPIs próprios. Prévia do dia: "amanhã 12 aniversariantes segmentados".
- **Configurar**: 1 Canal (é o primeiro porque as duas automações compartilham), 2 Boas-vindas (delay, horário, template, agrupador de canais), 3 Aniversariantes (horário, benefício, template), 4 Regra de envio (informativa: sem enriquecido, anti-duplicação, só segmentados), 5 Revisão. Toggle de ativação exige RFV; desligar e editar nunca exigem.
- **Mensagens**: `boas_vindas_*`, `aniversario_*`.
- **Histórico**: por dia e automação (envios, convertidos, receita), com a saúde dos envios acima da lista.
- **Assistente**: dois blocos de perguntas; sempre mostra a prévia do dia seguinte antes de confirmar.
- **Reaproveitar**: `aniversariantes/`, `boas-vindas/`, `RetencaoAutomacaoState`, `comm-funil-envios`, `chartEnviosMensaisOptions`.
- **Aceite**: ligar as duas automações em ≤ 2 min; toggle bloqueado com motivo quando sem RFV; prévia do dia correta.

### 6.4 E-commerceFlow (`flow`)

Objetivo: "vender dentro do WhatsApp sem atendente".

- **Dashboard**: KPIs Conversas com IA · Flows abertos · Pedidos no WhatsApp · Ticket médio (azul). Card "Funil do Flow" (conversa → flow aberto → pedido). Lista de conversas recentes com desfecho.
- **Sub-navegação interna** (chips): Catálogo (produtos sincronizados, elegíveis, fotos faltando) · IA vendedora (os 5 nós com versão, editor de prompt com diff e "testar") · Flows (telas do Flow JSON, publicar, testar em número de teste) · Conversas (o bate-papo atual filtrado pelo canal do Flow, com etiqueta "IA" ou "humano").
- **Configurar**: 1 Catálogo (regras de elegibilidade), 2 Canal (precisa Flows habilitado; se não, instrução), 3 IA vendedora (tom, proibições, versão ativa por nó), 4 Flows (pagamentos aceitos, frete, campos), 5 Atendimento humano (horário, fila), 6 Revisão.
- **Mensagens**: templates de abertura e pós-compra (`UTILITY`), lembrete de Pix.
- **Histórico**: por conversa (cliente, caminho percorrido, desfecho, pedido, valor). Detalhe abre a transcrição.
- **Assistente**: configura regras e prompts e permite **simular a conversa como cliente** dentro do chat (tool `flow.simular_conversa`), que é o teste de aceitação natural.
- **Reaproveitar**: `agentes-ia/` (editor de prompts e versões), `comunicacoes/conversas/`, `ecommerce/produtos`.
- **Aceite**: publicar Flow e fechar pedido de teste em ≤ 10 min; simulação funciona na aba Assistente; catálogo mostra o que está fora e por quê.

### 6.5 Campanhas Inteligentes (`campanhas`)

Objetivo: "que o sistema me diga o que ofertar e eu só aprove".

- **Dashboard**: KPIs Objetivos ativos · Clientes elegíveis · Ofertas aprovadas hoje · Margem preservada (azul). Fila do dia: "3 sugestões aguardando aprovação" com botão único. Gráfico de pedidos por objetivo.
- **Sub-navegação interna** (chips): Objetivos (O1 a O14, cada um com toggle, elegíveis hoje, tier, descrição de uma linha) · Aprovações (fila diária: cliente, objetivo, produto sugerido, cupom, aprovar/rejeitar em lote) · Cupons (regras por faixa).
- **Configurar**: 1 Objetivos ativos, 2 Regras de cupom (faixas, mínimo, validade, frequência por cliente), 3 Canal, 4 Aprovação (manual ou automática até um teto), 5 Revisão.
- **Mensagens**: um template por objetivo, com variáveis de produto e cupom.
- **Histórico**: por sugestão diária (objetivo, clientes, cupom, decisão, pedidos e receita).
- **Assistente**: começa por diagnóstico (estoque, afinidade, VIPs) e conduz à escolha de objetivos; simula margem antes de confirmar.
- **Reaproveitar**: tela "Ofertas sugeridas" e a lógica de objetivos da Gestão (a portar para o Hub), `giftback/` para faixas de cupom, `novidades/` para o painel BI de produto.
- **Aceite**: aprovar a fila do dia em 1 clique; toda sugestão mostra margem estimada; rejeição pede motivo em um chip (preço, público, produto) para alimentar o motor.

## 7. Telas fora dos módulos (resumo; detalhes na spec de 11/09)

- **Landing por módulo**: ordem fixa nav → hero → banner Profundo → título/parágrafo → benefícios → bloco de 3 dados → preço → assistente → outros módulos → FAQ → rodapé. Pré-render estático, schema FAQPage e Product.
- **Cadastro**: CNPJ primeiro, autocomplete com debounce 300 ms e mínimo 8 dígitos, depois nome, WhatsApp, e-mail, senha ou Google.
- **Onboarding**: 6 passos, retomável, provisionamento em paralelo com a conexão do WhatsApp, polling de status.
- **Início**: KPIs consolidados, 5 cards de módulo (ativo com 2 KPIs; bloqueado com argumento e "Testar grátis"), sugestão do assistente com base real.
- **Módulos (lista)**: estado e chips das 5 abas.
- **Bloqueado / Ativar**: prévia com KPIs de exemplo e overlay; checkout adiciona item Stripe e oferece os outros módulos.
- **Assinatura & uso**: cota por módulo, custo Meta repassado, faturas, portal Stripe.
- **Conectar Claude / GPT**: URL do MCP, token com escopos, instruções por cliente, atividade recente.

## 8. Inventário de componentes

Existentes em `shared/` a manter: `ui-button`, `ui-input`, `ui-select`, `ui-modal`, `ui-table`, `responsive-table`, `bottom-sheet`, `ui-tabs`, `ui-toast`, `stat-card`, `date-range-picker`, `paginator`, `empty-state`, `skeleton`, `funil`, `rfm-matriz`, `rfm-gate`, `ui-canal-status-badge`, `ui-template-vars-resumo`, `ui-checkbox-dropdown`, `comm-*` de comunicações.

Novos: `modulo-shell` (cabeçalho + abas + outlet), `modulo-kpis` (4 KPIs com regra do azul), `modulo-config-cards` (cards numerados genéricos), `hub-assistente` (chat SSE com os 7 eventos), `hub-assistente-resumo`, `ui-quota-bar`, `ui-trial-banner`, `ui-locked-inline`, `ui-locked-preview` (overlay de paywall), `ui-confirm-dialog` (com número de afetados), `ui-breadcrumb`, `mobile-tabbar`, `ui-chip-filter` (com query params), `wa-preview` (bolha WhatsApp).

Tokens: substituir em `src/tailwind.input.css` conforme identidade v2.4 (Figtree, `#0A5BF0`, `#0B1033`, `#F6F8FC`, tema escuro azul-noite) e remover Inter.

## 9. Estados, acessibilidade e desempenho

- Todo componente de dados tem os estados: carregando (skeleton), vazio (ícone, título, texto, ação), erro (o que houve, o que fazer, tentar de novo), sem permissão (bloqueado inline). KPI em carregamento mostra "—".
- Confirmação obrigatória em: cancelar campanha, desligar automação, apagar template, cancelar módulo, publicar Flow. Sempre com o número de pessoas afetadas.
- Foco visível em tudo; chips e abas navegáveis por teclado; `aria-live` para toasts; contraste AA conferido nos dois temas; alvo de toque ≥ 44 px no mobile.
- Números: `Intl.NumberFormat('pt-BR')`, `tabular-nums` em colunas, ROI nulo é "—".
- Desempenho: lazy por área e por módulo; listas de histórico paginadas no backend; payload de webhook só ao abrir; SSE do assistente com reconexão; imagens de landing em `webp`.

## 10. Definição de pronto por tela

Uma tela só está pronta quando: funciona nos dois temas e nos dois tamanhos; tem os 4 estados; usa só tokens da identidade; tem rota própria e deep link; passa no checklist da skill `identidade-ecomsmart`; tem spec com pelo menos o cenário feliz e o de erro; e os textos passam no "diga / não diga" (sem "ilimitado", sem "chatbot", CTA com verbo).

## 11. Ordem de implementação sugerida

1. Tokens + `app-shell` novo (sidebar, header, mobile tabbar, tema) e `modulo-shell` com abas por rota.
2. Módulo Carrinho completo (5 abas) migrando as telas existentes. Serve de referência para os outros.
3. `hub-assistente` com os 7 eventos e o wizard do Carrinho.
4. Retenção e Disparo RFV (migração das telas existentes para as abas).
5. Público + onboarding + billing (dependem de Stripe e CNPJ no backend).
6. Campanhas Inteligentes e E-commerceFlow (dependem de backend novo).
