Frontend completo (Etapas 11-18) e extensões de backend (Etapas 13 e 18)

Adiciona o frontend Next.js em frontend/ (setup, design system,
autenticação/tema, layout/navegação, área master, área tenant completa:
clientes, produtos, vendas, recebimentos, whatsapp, e-mail, alertas,
equipe e perfil). Estende o backend de forma aditiva e autorizada:
cookie httpOnly para refresh token (Etapa 13) e CRUD de equipe +
edição de perfil do tenant (Etapa 18, módulo src/modules/equipe/ novo
e PUT /tenant/perfil). Detalhes completos em Etapas/V2/*.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 09:41:13 -03:00
co-authored by Claude Sonnet 5
parent f9738e54da
commit 323912748f
179 changed files with 29312 additions and 22 deletions
+102
View File
@@ -0,0 +1,102 @@
# Etapa 13 — Autenticação e Tema Dinâmico (Whitelabel)
## Contexto do projeto
Continuação do frontend do **SeConectai Vendas**. Já existem: projeto
configurado (Etapa 11) e a biblioteca de componentes base (Etapa 12). O
backend já expõe toda a API de autenticação (login master/tenant,
refresh, esqueci senha) e o endpoint público de tema por tenant
(definidos nas Etapas 2 e 8 do backend).
## Objetivo desta etapa
Implementar as telas públicas de autenticação, o mecanismo de sessão no
client (armazenamento de token, renovação automática, proteção de
rotas), e a resolução do tema (logo + cor) por tenant antes mesmo do
login.
## Tarefas
1. **Telas públicas (`app/(public)/`)**
- **`/login`**: formulário de e-mail + senha. Deve detectar se o
login é de master ou de tenant (definir estratégia: campo
oculto/toggle, ou dois formulários, ou detecção automática pelo
backend a partir do e-mail — escolher a mais simples de implementar
e documentar a decisão). Erros de credencial inválida devem ser
claros mas não revelar se o e-mail existe ou não (mensagem genérica
"e-mail ou senha inválidos").
- **`/esqueci-senha`**: formulário de e-mail, chama o endpoint de
recuperação, sempre mostra mensagem de sucesso genérica (não
revelar se o e-mail existe no sistema).
- **`/redefinir-senha/[token]`**: formulário de nova senha (com
confirmação), valida força mínima no client espelhando a regra do
backend, trata token expirado/inválido com mensagem clara.
- Todas essas telas devem ser **totalmente responsivas**: em mobile,
formulário ocupa a largura da tela com padding adequado; em
desktop, formulário centralizado com largura máxima (ex: 420px) e
fundo com identidade visual do tema resolvido (ver item 3).
2. **Gerenciamento de sessão (`lib/auth/`)**
- Access token guardado **em memória** (ex: em um Context/store, não
em `localStorage`/`sessionStorage`).
- Refresh token: o backend deve setar como cookie `httpOnly`; o
client não manipula esse cookie diretamente, apenas confia que ele
é enviado automaticamente nas chamadas relevantes.
- Interceptor no `lib/api/client.ts` (gancho deixado pronto na Etapa
11): ao receber 401, tenta chamar o endpoint de refresh
automaticamente; se conseguir, repete a requisição original com o
novo token; se falhar, desloga e redireciona para `/login`.
- Função `logout()` que limpa o estado em memória e chama o endpoint
de logout do backend (revoga o refresh token no servidor).
3. **Middleware de proteção de rotas**
- Middleware do Next.js protegendo `/master/*` e `/app/*`: verifica
se existe sessão válida (ex: checando um cookie de sinalização não
sensível, já que o access token real fica só em memória no client —
definir estratégia de verificação no servidor sem expor o token) e
redireciona para `/login` se não houver.
- Usuário master tentando acessar `/app/*` (ou vice-versa) deve ser
redirecionado para a área correta, não para login.
- Após login bem-sucedido, redirecionar automaticamente para
`/master/dashboard` ou `/app/dashboard` conforme o tipo de usuário
retornado pela API.
4. **Tema dinâmico por tenant (`lib/theme/`)**
- Na tela `/login`, antes de qualquer autenticação, resolver o tema:
se a URL/subdomínio/parâmetro identificar um tenant específico,
chamar o endpoint público `/public/tenants/:slugOuId/tema` e
aplicar `--color-primary` e o logo retornados. Se não houver tenant
identificável (ex: acesso genérico), mostrar o tema padrão da
plataforma.
- Após o login, na área `/app`, resolver o tema a partir do perfil do
tenant autenticado (não precisa mais do endpoint público).
- Implementar a validação de contraste descrita na seção 6 do schema:
se `cor_primaria` do tenant não atingir contraste mínimo (WCAG AA)
contra branco, escurecer automaticamente antes de aplicar como cor
de texto/ícone sobre fundo colorido (manter a cor original para
fundos, ajustar só onde teria problema de legibilidade).
5. **Feedback de erro e loading**
- Todos os formulários desta etapa usam os componentes `FormField`,
`Button` (estado `loading`) e `Toast` já construídos na Etapa 12 —
nenhuma solução de UI paralela aqui.
## Critérios de aceite
- [ ] Login master e login tenant funcionam ponta a ponta com o backend
real
- [ ] Sessão expira corretamente e é renovada automaticamente via
refresh (testar deixando o access token expirar e fazendo uma
ação)
- [ ] Logout limpa a sessão e o backend revoga o refresh token
- [ ] Middleware bloqueia acesso não autenticado a `/master/*` e
`/app/*`, redirecionando para `/login`
- [ ] Usuário master não consegue acessar `/app/*` diretamente pela URL
(e vice-versa) sem ser redirecionado
- [ ] Fluxo completo de esqueci/redefinir senha funciona, incluindo
tratamento de token expirado
- [ ] Tela de login aplica a cor/logo do tenant certo quando o tenant é
identificável, e cai no tema padrão quando não é
- [ ] Cor de tenant com baixo contraste é ajustada automaticamente onde
necessário, sem quebrar a legibilidade
- [ ] Todas as telas desta etapa testadas em 375px, 768px e 1280px