Initial SeConectai briefing system
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# 00 — Arquitetura: Sistema de Briefing de Site
|
||||
|
||||
## Objetivo
|
||||
Cliente se cadastra (pessoa física ou empresa) → faz login → preenche o briefing de 19 seções (149 perguntas) com rascunho automático e botão Ajuda por pergunta → envia → Tiago visualiza, exporta e muda o status no painel admin.
|
||||
|
||||
## Fluxos
|
||||
1. **Cadastro:** Nome completo, CPF, WhatsApp, E-mail, senha. Se "É para empresa?": Razão Social, CNPJ, Endereço (CEP, logradouro, número, complemento, bairro, cidade, UF). Aceite de LGPD obrigatório.
|
||||
2. **Login / recuperação de senha** por e-mail.
|
||||
3. **Meus briefings:** o cliente cria um briefing (um cliente pode ter mais de um, ex.: um site por empresa) e continua de onde parou.
|
||||
4. **Preenchimento:** tela por seção, barra de progresso, botão Ajuda por pergunta (popup), autosave, anexos na seção 19.
|
||||
5. **Envio:** confirmação do cliente (texto da seção "Confirmação do cliente") → status ENVIADO, bloqueia edição (admin pode reabrir).
|
||||
6. **Admin:** lista de clientes e briefings, detalhe com todas as respostas e anexos, mudança de status, exportação PDF, edição das perguntas/ajudas.
|
||||
|
||||
## Decisão central: formulário dirigido por dados
|
||||
Seções, perguntas e textos de ajuda ficam no banco e vêm do arquivo `briefing-seed.json` (gerado dos .docx originais: 19 seções, 149 perguntas, todas com ajuda). O frontend renderiza o formulário a partir desses dados; nada de 149 campos escritos à mão.
|
||||
|
||||
Tipos de pergunta (`TipoPergunta`): `TEXTAREA` (117), `RADIO` (11), `CHECKBOX` (6), `ANEXO` (15, seção 19). Toda pergunta tem também um campo opcional de **complemento** em texto (o documento original permite escrever junto das caixas marcadas, ex.: "Outro: qual?").
|
||||
|
||||
## Modelo de dados (Prisma, resumo)
|
||||
- `User` (id, email único, senhaHash, papel: CLIENTE | ADMIN, criadoEm)
|
||||
- `Cliente` (userId único, nomeCompleto, cpfCifrado, cpfHash único, whatsapp, tipo: PF | PJ, razaoSocial?, cnpj?, cep?, logradouro?, numero?, complemento?, bairro?, cidade?, uf?, lgpdAceiteEm)
|
||||
- `Secao` (id, ordem, titulo, descricao, ativo)
|
||||
- `Pergunta` (id, secaoId, ordem, rotulo, dica, tipo, opcoes Json, obrigatoria default false, permiteComplemento, ativo)
|
||||
- `Ajuda` (perguntaId único, oQueResponder, porQuePerguntamos, miniExemplo)
|
||||
- `Briefing` (id, clienteId, titulo, status: RASCUNHO | ENVIADO | EM_ANALISE | CONCLUIDO, confirmadoEm?, enviadoEm?, criadoEm, atualizadoEm)
|
||||
- `Resposta` (briefingId, perguntaId, texto?, selecionadas Json?, único por briefing+pergunta)
|
||||
- `Anexo` (briefingId, perguntaId, nomeOriginal, caminho, mime, tamanho, criadoEm)
|
||||
- `PasswordResetToken` (userId, tokenHash, expiraEm, usadoEm?)
|
||||
|
||||
## Princípios (do padrão SeConectai)
|
||||
- **Nunca apagar dados históricos:** briefing enviado não é deletado; reabrir muda o status, não perde respostas.
|
||||
- **Dados sensíveis por desenho:** CPF cifrado (AES-256-GCM, chave em variável de ambiente) + `cpfHash` (HMAC-SHA256) para unicidade/busca. CPF nunca vai para log nem para o JSON de listagens.
|
||||
- **Validação dupla:** Zod no cliente e no servidor (server actions / route handlers).
|
||||
- **Permissões:** cliente só enxerga os próprios briefings; admin enxerga todos. Toda leitura/escrita checa o dono no servidor.
|
||||
- **Incremental:** mudanças futuras via migrations Prisma numeradas, sem reescrever o schema base.
|
||||
|
||||
## Estrutura de pastas alvo
|
||||
```
|
||||
/app
|
||||
/(publico)/cadastro, /login, /recuperar-senha, /redefinir-senha
|
||||
/(cliente)/briefings, /briefings/[id], /briefings/[id]/[secao], /briefings/[id]/revisao
|
||||
/(admin)/admin, /admin/clientes, /admin/briefings/[id], /admin/perguntas
|
||||
/api/anexos/[id] (download autenticado)
|
||||
/components (ui shadcn, form/, ajuda/)
|
||||
/lib (auth, db, crypto, validators, storage, pdf, mail)
|
||||
/prisma (schema.prisma, seed.ts, briefing-seed.json)
|
||||
/storage/uploads (volume Docker, fora de /public)
|
||||
```
|
||||
|
||||
## Ordem de execução
|
||||
01 setup → 02 schema → 03 seed → 04 auth/cadastro → 05 motor do formulário → 06 popup de ajuda → 07 rascunho e envio → 08 anexos → 09 painel admin → 10 PDF e notificações → 11 LGPD/segurança → 12 deploy. Acompanhar em `99-progresso.md`.
|
||||
@@ -0,0 +1,23 @@
|
||||
# 01 — Setup do projeto e Docker
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Tarefa
|
||||
1. Criar projeto Next.js 14+ com TypeScript, App Router, Tailwind e ESLint (`src` opcional — siga a estrutura do doc 00).
|
||||
2. Instalar: `prisma @prisma/client zod react-hook-form @hookform/resolvers next-auth@beta @auth/core argon2 nodemailer @tanstack/react-query lucide-react`, e iniciar shadcn/ui (componentes: button, input, textarea, label, checkbox, radio-group, dialog, form, card, progress, badge, table, select, sonner, tabs, alert).
|
||||
3. Criar `docker-compose.yml` com `app` (Node 20) e `db` (postgres:16, volume nomeado `pgdata`), `healthcheck` no db, rede interna. Volume `uploads` montado em `/app/storage/uploads`.
|
||||
4. Criar `Dockerfile` multi-stage (deps → build → runner, `output: "standalone"`).
|
||||
5. `.env.example` com: `DATABASE_URL`, `AUTH_SECRET`, `APP_URL`, `CPF_ENC_KEY` (32 bytes base64), `CPF_HASH_KEY`, `SMTP_HOST/PORT/USER/PASS/FROM`, `ADMIN_EMAIL`, `ADMIN_INITIAL_PASSWORD`, `EVOLUTION_API_URL/KEY/INSTANCE` e `ADMIN_WHATSAPP` (opcionais), `UPLOAD_DIR`, `UPLOAD_MAX_MB=25`.
|
||||
6. Layout base pt-BR (`<html lang="pt-BR">`), tema simples e responsivo (mobile primeiro: clientes vão preencher pelo celular).
|
||||
7. Script `npm run dev`, `build`, `db:migrate`, `db:seed`, `lint`.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] `docker compose up` sobe app + banco sem erro; página inicial abre em `http://localhost:3000`.
|
||||
- [ ] `.env.example` completo; `.env` no `.gitignore`.
|
||||
- [ ] `npm run lint` e `npm run build` passam.
|
||||
- [ ] Nenhuma dependência fora da stack.
|
||||
|
||||
Ao final, atualize `99-progresso.md` (marque 01).
|
||||
@@ -0,0 +1,26 @@
|
||||
# 02 — Banco de dados e schema Prisma
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapa 01 concluída em `99-progresso.md`.
|
||||
|
||||
## Tarefa
|
||||
Implementar em `prisma/schema.prisma` o modelo descrito no doc 00 (seção "Modelo de dados"), com:
|
||||
- enums `Papel {CLIENTE ADMIN}`, `TipoPessoa {PF PJ}`, `TipoPergunta {TEXTAREA RADIO CHECKBOX ANEXO}`, `StatusBriefing {RASCUNHO ENVIADO EM_ANALISE CONCLUIDO}`.
|
||||
- `@@unique([briefingId, perguntaId])` em `Resposta`; `@@unique([ordem])` em `Secao` e `@@unique([secaoId, ordem])` em `Pergunta`; índices em `Briefing.clienteId`, `Briefing.status`, `Anexo.briefingId`.
|
||||
- `onDelete: Cascade` apenas de `Briefing → Resposta/Anexo`; **não** colocar cascade de `Cliente → Briefing` (preservar histórico).
|
||||
- campos `criadoEm`/`atualizadoEm` (`@default(now())`, `@updatedAt`).
|
||||
- `opcoes` e `selecionadas` como `Json`.
|
||||
|
||||
Gerar a migration inicial `0001_init` e o client Prisma; criar `lib/db.ts` com singleton do PrismaClient.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] `npx prisma migrate dev` aplica sem erro no Postgres do Docker.
|
||||
- [ ] `npx prisma validate` ok; `prisma studio` mostra todas as tabelas.
|
||||
- [ ] Nenhuma coluna de CPF em texto puro (apenas `cpfCifrado` e `cpfHash`).
|
||||
|
||||
Atualize `99-progresso.md` (02).
|
||||
@@ -0,0 +1,35 @@
|
||||
# 03 — Seed do briefing (seções, perguntas e ajudas)
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapa 02 concluída.
|
||||
|
||||
## Arquivo de dados
|
||||
`prisma/briefing-seed.json` (fornecido junto com este guia; copie para `prisma/`). Estrutura:
|
||||
```json
|
||||
{ "meta": { "comoPreencher": [..], "avisoSenhas": "..", "confirmacaoCliente": ".." },
|
||||
"secoes": [ { "ordem": 1, "titulo": "..", "descricao": "..",
|
||||
"perguntas": [ { "ordem": 1, "rotulo": "..", "dica": "..", "tipo": "TEXTAREA|RADIO|CHECKBOX|ANEXO",
|
||||
"opcoes": ["..."], "permiteComplemento": true,
|
||||
"ajuda": { "oQueResponder": "..", "porQuePerguntamos": "..", "miniExemplo": ".." } } ] } ] }
|
||||
```
|
||||
O arquivo tem 19 seções e 149 perguntas; todas têm `ajuda`.
|
||||
|
||||
## Tarefa
|
||||
1. Criar `prisma/seed.ts` **idempotente** (upsert por `secao.ordem` e por `secaoId+ordem`): cria `Secao`, `Pergunta` e `Ajuda`. Reexecutar o seed atualiza textos sem duplicar e **sem apagar respostas** existentes.
|
||||
2. Guardar `meta` (como preencher, aviso de senhas, confirmação do cliente) em uma tabela `Configuracao (chave, valor Json)` — adicionar via migration `0002_configuracao`.
|
||||
3. No mesmo seed, criar o usuário ADMIN a partir de `ADMIN_EMAIL`/`ADMIN_INITIAL_PASSWORD` (hash argon2), apenas se não existir.
|
||||
4. Configurar `prisma.seed` no `package.json`.
|
||||
5. Criar `lib/briefing-queries.ts` com `getEstruturaBriefing()` que retorna seções → perguntas → ajuda, ordenadas, em uma única consulta.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Após `npm run db:seed`: 19 seções, 149 perguntas, 149 ajudas.
|
||||
- [ ] Rodar o seed duas vezes não duplica nada.
|
||||
- [ ] Contagem por tipo: TEXTAREA 117, RADIO 11, CHECKBOX 6, ANEXO 15.
|
||||
- [ ] Admin criado; senha só em hash.
|
||||
|
||||
Atualize `99-progresso.md` (03).
|
||||
@@ -0,0 +1,35 @@
|
||||
# 04 — Autenticação e cadastro do cliente
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapas 01–03 concluídas.
|
||||
|
||||
## Tarefa
|
||||
### Cadastro (`/cadastro`)
|
||||
Campos: **Nome completo, CPF, WhatsApp, E-mail, Senha (mín. 8) e confirmação**. Seletor "Este site é para uma empresa?" — se sim, exibir **Razão Social, CNPJ e Endereço** (CEP com busca opcional no ViaCEP *no navegador*, logradouro, número, complemento, bairro, cidade, UF). Checkbox obrigatório de aceite da Política de Privacidade/LGPD (guardar `lgpdAceiteEm`).
|
||||
|
||||
Validações Zod (cliente + servidor) em `lib/validators.ts`: CPF e CNPJ com dígito verificador; WhatsApp brasileiro (DDD + 9 dígitos, normalizar para `+55DDDNÚMERO`); e-mail normalizado em minúsculas; máscara de entrada para CPF/CNPJ/WhatsApp/CEP.
|
||||
|
||||
Servidor: criar `User` + `Cliente` em transação; CPF → `lib/crypto.ts` (`encrypt`/`decrypt` AES-256-GCM com `CPF_ENC_KEY`, `hashCpf` HMAC-SHA256 com `CPF_HASH_KEY`); rejeitar e-mail ou CPF já cadastrados com mensagem genérica que não revele qual existe; senha com argon2.
|
||||
|
||||
### Login e sessão
|
||||
Auth.js v5 com provider Credentials, JWT, cookie httpOnly/secure/sameSite=lax; sessão contém `userId` e `papel`. `middleware.ts` protege `/briefings*` (CLIENTE) e `/admin*` (ADMIN) e redireciona para `/login`. Limitar tentativas de login (rate limit simples em memória por IP+e-mail).
|
||||
|
||||
### Recuperar senha
|
||||
`/recuperar-senha` (pede e-mail; resposta sempre igual exista ou não a conta) → e-mail com link de token aleatório (guardar só o hash, expira em 1 h, uso único) → `/redefinir-senha`. Enviar por SMTP via `lib/mail.ts` (nodemailer).
|
||||
|
||||
### Após o login
|
||||
Cliente cai em `/briefings` (lista vazia com botão "Iniciar meu briefing"). Admin cai em `/admin`.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Cadastro PF e PJ funcionam; campos de empresa só aparecem/são exigidos no modo PJ.
|
||||
- [ ] CPF/CNPJ inválidos são recusados; CPF não aparece em texto puro no banco nem em logs.
|
||||
- [ ] E-mail/CPF duplicado é recusado sem revelar qual.
|
||||
- [ ] Rotas protegidas redirecionam; cliente não acessa `/admin`.
|
||||
- [ ] Recuperação de senha funciona de ponta a ponta (token expira e é de uso único).
|
||||
|
||||
Atualize `99-progresso.md` (04).
|
||||
@@ -0,0 +1,30 @@
|
||||
# 05 — Motor do formulário do briefing
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapas 01–04 concluídas.
|
||||
|
||||
## Tarefa
|
||||
1. **Criar briefing:** botão "Iniciar meu briefing" cria `Briefing` RASCUNHO. Os campos do cabeçalho do documento original (Empresa/Marca, Responsável, Data, Contato) são pré-preenchidos com os dados do cadastro e exibidos na primeira tela, editáveis.
|
||||
2. **Tela de abertura** `/briefings/[id]`: mostra o "Como preencher" e o aviso de senhas (vindos de `Configuracao`), lista das 19 seções com progresso por seção (respondidas/total) e botão "Continuar de onde parei".
|
||||
3. **Tela de seção** `/briefings/[id]/[secao]`: título e descrição da seção; cada pergunta renderizada por `components/form/PerguntaField.tsx`, escolhendo o componente pelo `tipo`:
|
||||
- `TEXTAREA`: textarea com contador discreto.
|
||||
- `RADIO`: grupo de opções (uma escolha).
|
||||
- `CHECKBOX`: múltipla escolha.
|
||||
- `ANEXO`: tratado na etapa 08 (aqui, deixar placeholder).
|
||||
Se `permiteComplemento`, exibir abaixo um campo curto "Complemento / outro". O rótulo mostra `rotulo`, e `dica` aparece como texto de apoio. Cada pergunta tem espaço reservado para o botão Ajuda (etapa 06).
|
||||
4. **Navegação:** Anterior/Próxima seção, menu lateral (drawer no celular) com as 19 seções e indicadores de concluída/parcial; barra de progresso geral.
|
||||
5. **Estado:** React Hook Form por seção; valores iniciais carregados de `Resposta`. Persistência vem na etapa 07.
|
||||
6. **"Respondida":** considerar respondida se houver texto não vazio ou ao menos uma opção marcada. Perguntas não são obrigatórias por padrão (`obrigatoria=false`); o documento aceita "Não se aplica" / "A definir" — exibir esses dois como atalhos (chips) em campos de texto que preenchem o valor ao toque.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] As 19 seções renderizam a partir do banco, sem campo escrito à mão.
|
||||
- [ ] Os 4 tipos funcionam com os valores corretos (inclusive complemento).
|
||||
- [ ] Navegação entre seções e progresso corretos; usável em tela de 360 px.
|
||||
- [ ] Cliente não consegue abrir briefing de outro cliente (404).
|
||||
|
||||
Atualize `99-progresso.md` (05).
|
||||
@@ -0,0 +1,29 @@
|
||||
# 06 — Botão Ajuda com popup por pergunta
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapa 05 concluída.
|
||||
|
||||
## Tarefa
|
||||
Criar `components/ajuda/AjudaButton.tsx` e usá-lo em **toda** pergunta que tenha `ajuda`:
|
||||
- Botão pequeno ao lado do rótulo: ícone `HelpCircle` + texto "Ajuda" (o texto some só em telas muito estreitas, mantendo `aria-label="Ajuda sobre: {rotulo}"`).
|
||||
- Ao clicar, abre um `Dialog` (shadcn) com:
|
||||
- **Título:** o `rotulo` da pergunta.
|
||||
- **O que responder** — `oQueResponder`
|
||||
- **Por que perguntamos** — `porQuePerguntamos`
|
||||
- **Mini exemplo** — `miniExemplo`, em caixa destacada, com aviso fixo: "Os exemplos servem apenas como referência. Substitua pelas informações reais da sua empresa."
|
||||
- Rodapé: botão Fechar; opcional "Usar 'Não se aplica'" / "Usar 'A definir'" que preenche o campo e fecha o popup (apenas em campos de texto).
|
||||
- Acessibilidade: foco preso no diálogo, fecha com Esc e clique fora, foco volta ao botão, leitura por leitor de tela.
|
||||
- Dados de ajuda já vêm junto da estrutura (consulta única da etapa 03); não fazer requisição por clique.
|
||||
- Se a pergunta não tiver ajuda, não renderizar o botão.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Todas as 149 perguntas exibem o botão e abrem o texto correto do guia (conferir por amostragem de pelo menos 1 pergunta por seção).
|
||||
- [ ] Popup funciona em celular e desktop, com teclado e leitor de tela.
|
||||
- [ ] Abrir/fechar o popup não perde o que foi digitado no campo.
|
||||
|
||||
Atualize `99-progresso.md` (06).
|
||||
@@ -0,0 +1,23 @@
|
||||
# 07 — Rascunho automático, revisão e envio
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapas 05 e 06 concluídas.
|
||||
|
||||
## Tarefa
|
||||
1. **Autosave:** ao parar de digitar (debounce ~800 ms) e ao mudar de seção, salvar via server action `salvarRespostas(briefingId, secaoId, valores)` com upsert em `Resposta`. Validar com Zod, checar que o briefing pertence ao usuário e está em RASCUNHO. Indicador "Salvo às HH:MM" / "Salvando…" / "Erro ao salvar — tentar de novo". Aviso ao sair com alterações não salvas.
|
||||
2. **Idempotência:** salvar valor vazio remove/zera a resposta daquela pergunta sem afetar outras; concorrência: última gravação vence, com `atualizadoEm`.
|
||||
3. **Revisão** `/briefings/[id]/revisao`: lista todas as seções com respostas, destaca perguntas em branco (sem bloquear) e permite voltar para editar com um clique.
|
||||
4. **Envio:** exibir o texto "Confirmação do cliente" (de `Configuracao`) com checkbox obrigatório; ao confirmar, `status=ENVIADO`, `confirmadoEm` e `enviadoEm` preenchidos, edição bloqueada (somente leitura). Se houver perguntas em branco, avisar e pedir confirmação extra, sem impedir.
|
||||
5. Admin pode reabrir (volta a RASCUNHO) — preservando todas as respostas (etapa 09 expõe a ação; aqui criar a função de serviço `reabrirBriefing`).
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Fechar o navegador no meio e voltar mantém tudo que foi digitado.
|
||||
- [ ] Briefing ENVIADO não aceita novas gravações (servidor recusa, não só a interface).
|
||||
- [ ] Nenhuma resposta de outro cliente/briefing é acessível ou gravável.
|
||||
|
||||
Atualize `99-progresso.md` (07).
|
||||
@@ -0,0 +1,26 @@
|
||||
# 08 — Anexos (seção 19: checklist de materiais)
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapa 07 concluída.
|
||||
|
||||
## Tarefa
|
||||
A seção 19 do briefing tem 15 itens do tipo `ANEXO` (logotipo, manual de identidade, fotos, vídeos, textos, catálogo, lista de serviços, depoimentos, cases, certificações, dados de contato, redes sociais, referências de sites, política/termos, domínio e hospedagem sem senhas).
|
||||
|
||||
1. Em cada item `ANEXO`: caixa "Estou enviando este material" (equivale ao ☐ do documento), campo de texto para links (Drive, Dropbox, YouTube) e área de upload de arquivos.
|
||||
2. **Upload** via route handler com `multipart/form-data`: máximo `UPLOAD_MAX_MB` por arquivo e 20 arquivos por pergunta; permitir imagens (png, jpg, webp, svg), pdf, docx/doc, xlsx/xls, pptx, zip, mp4/mov; validar extensão **e** tipo MIME **e** conteúdo básico (magic bytes); nome do arquivo no disco = UUID (nunca o nome original); salvar em `UPLOAD_DIR` (volume Docker, **fora de `/public`**).
|
||||
3. **Download** apenas via `/api/anexos/[id]`, autenticado: dono do briefing ou ADMIN. Cabeçalhos `Content-Disposition: attachment` e `X-Content-Type-Options: nosniff`.
|
||||
4. Listar anexos com nome, tamanho e botão remover (somente em RASCUNHO). Barra de progresso por arquivo.
|
||||
5. Aviso fixo na seção: "Não envie senhas. Informe apenas provedores e responsáveis."
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Upload/remoção funcionam; arquivo inválido ou grande demais é recusado com mensagem clara.
|
||||
- [ ] Acessar a URL do arquivo sem login ou como outro cliente retorna 403/404.
|
||||
- [ ] Nenhum arquivo fica acessível por URL pública estática.
|
||||
- [ ] Briefing ENVIADO não aceita novos uploads/remoções.
|
||||
|
||||
Atualize `99-progresso.md` (08).
|
||||
@@ -0,0 +1,25 @@
|
||||
# 09 — Painel administrativo
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapas 01–08 concluídas.
|
||||
|
||||
## Tarefa
|
||||
Área `/admin` (somente ADMIN, checado no middleware **e** em cada server action):
|
||||
1. **Início:** contadores (briefings por status, novos nos últimos 7 dias) e últimos envios.
|
||||
2. **Clientes** `/admin/clientes`: tabela com busca (nome, e-mail, WhatsApp, CNPJ, razão social) e filtro PF/PJ; detalhe do cliente com dados cadastrais e seus briefings. CPF exibido **mascarado** (`***.123.456-**`) e só revelado completo por botão "Mostrar CPF" que registra o acesso em auditoria (`AuditoriaAcesso`: adminId, clienteId, ação, data — migration `0003`).
|
||||
3. **Briefings** `/admin/briefings/[id]`: todas as respostas por seção (em modo leitura, com as opções marcadas e o complemento), anexos com download, linha do tempo de status. Ações: mudar status (ENVIADO → EM_ANALISE → CONCLUIDO), **reabrir para edição**, adicionar nota interna (`NotaInterna`, invisível ao cliente).
|
||||
4. **Perguntas** `/admin/perguntas`: editar rótulo, dica, textos de ajuda (o que responder / por que perguntamos / mini exemplo), ordem, ativo e obrigatória, sem mexer em código. Desativar uma pergunta nunca apaga respostas já dadas.
|
||||
5. Link de WhatsApp (`wa.me`) no detalhe do cliente para contato rápido.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Usuário CLIENTE não acessa nenhuma rota/ação admin (testar chamada direta).
|
||||
- [ ] Editar um texto de ajuda reflete no popup do cliente imediatamente.
|
||||
- [ ] Reabrir briefing preserva respostas e anexos.
|
||||
- [ ] Revelar CPF gera registro de auditoria.
|
||||
|
||||
Atualize `99-progresso.md` (09).
|
||||
@@ -0,0 +1,22 @@
|
||||
# 10 — Exportação em PDF e notificações
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapa 09 concluída.
|
||||
|
||||
## Tarefa
|
||||
1. **PDF do briefing** (`/api/briefings/[id]/pdf`, dono ou ADMIN): documento com dados do cliente, 19 seções, perguntas e respostas (opções marcadas com ☒/☐), lista de anexos (nomes, sem o conteúdo) e a confirmação do cliente com data/hora. Gerar no servidor (ex.: `@react-pdf/renderer`). Botão "Baixar PDF" para o cliente (após envio) e para o admin.
|
||||
2. **E-mails** (SMTP, `lib/mail.ts`, templates simples em pt-BR): confirmação de cadastro, briefing enviado (ao cliente, com resumo e PDF), aviso de novo briefing enviado (ao admin).
|
||||
3. **WhatsApp opcional (Evolution API):** se `EVOLUTION_API_URL/KEY/INSTANCE` e `ADMIN_WHATSAPP` estiverem definidos, avisar o admin quando um briefing for enviado. **Antes de implementar, consultar a versão da Evolution API da instância e confirmar o formato do payload** (não assumir). Falha de WhatsApp/e-mail nunca pode impedir o envio do briefing: registrar erro e seguir (fila simples com retry ou tabela `EnvioNotificacao` com status).
|
||||
4. Dados sensíveis: PDF e e-mails **não** incluem CPF completo.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] PDF gerado corretamente com todas as seções e acentuação; abre em leitor comum.
|
||||
- [ ] Falha de SMTP/WhatsApp não quebra o envio do briefing.
|
||||
- [ ] Nenhum CPF completo em PDF, e-mails ou logs.
|
||||
|
||||
Atualize `99-progresso.md` (10).
|
||||
@@ -0,0 +1,26 @@
|
||||
# 11 — LGPD e segurança
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapas 01–10 concluídas.
|
||||
|
||||
## Tarefa
|
||||
1. **Páginas legais:** `/privacidade` (Política de Privacidade) e `/termos`, com texto-base editável (marcar claramente como "revisar com assessoria jurídica"); links no rodapé e no cadastro.
|
||||
2. **Direitos do titular:** em "Minha conta", cliente pode ver e editar seus dados, baixar seus dados (JSON) e solicitar exclusão (cria `SolicitacaoExclusao`; admin processa — anonimiza o cadastro mantendo o briefing sem identificação pessoal, conforme decisão do Tiago).
|
||||
3. **Cabeçalhos de segurança** no `next.config`: CSP, `X-Frame-Options`, `Referrer-Policy`, `Permissions-Policy`, HSTS em produção.
|
||||
4. **Proteções:** rate limit nos endpoints de cadastro, login, recuperação e upload; proteção CSRF nas server actions (padrão Next) e checagem de origem nas route handlers; sanitização de saída (React já escapa; nunca usar `dangerouslySetInnerHTML` com dados do cliente).
|
||||
5. **Logs:** nunca registrar senha, token, CPF ou conteúdo de respostas; logar apenas ids e eventos.
|
||||
6. **Backups:** script `scripts/backup.sh` com `pg_dump` + cópia do volume de uploads, com rotação.
|
||||
7. Revisão final: tentar manualmente acessar recurso de outro cliente em cada rota (briefing, resposta, anexo, PDF) e confirmar bloqueio.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Cabeçalhos de segurança presentes (verificar com `curl -I`).
|
||||
- [ ] Teste manual de isolamento entre clientes passa em todas as rotas.
|
||||
- [ ] `grep` no código não encontra CPF/senha em logs.
|
||||
- [ ] Backup e restauração testados em ambiente limpo.
|
||||
|
||||
Atualize `99-progresso.md` (11).
|
||||
@@ -0,0 +1,24 @@
|
||||
# 12 — Deploy em produção
|
||||
|
||||
## Contexto do projeto (leia sempre)
|
||||
Sistema web "Briefing de Site" da SeConectai: o cliente se cadastra e depois preenche o briefing de criação do site, com um botão **Ajuda** em cada pergunta que abre um popup com o texto do guia auxiliar. O dono (Tiago) acompanha tudo por um painel admin.
|
||||
**Stack fixa:** Next.js 14+ (App Router) + TypeScript, PostgreSQL 16, Prisma, Tailwind + shadcn/ui, React Hook Form + Zod, Auth.js v5 (Credentials, estratégia JWT), Docker Compose. Idioma da interface: pt-BR.
|
||||
**Regras gerais:** leia `00-arquitetura-briefing-site.md` e `99-progresso.md` antes de começar; não avance se a etapa anterior estiver incompleta; ao terminar, devolva o `99-progresso.md` atualizado. Não invente dependências fora da stack. Nada de senhas de clientes em lugar nenhum.
|
||||
|
||||
## Pré-requisito
|
||||
Etapas 01–11 concluídas.
|
||||
|
||||
## Tarefa
|
||||
1. `docker-compose.prod.yml`: app (imagem standalone), Postgres 16 com volume, volume de uploads, restart `unless-stopped`, sem portas do banco expostas, variáveis só por `.env` do servidor.
|
||||
2. Proxy reverso com HTTPS (Caddy ou Nginx + Let's Encrypt) para o domínio escolhido; redirecionar HTTP → HTTPS.
|
||||
3. Comando de release: `prisma migrate deploy` + seed idempotente (que não sobrescreve nada do cliente).
|
||||
4. Healthcheck `/api/health` (app + banco) e política de reinício.
|
||||
5. Documentar em `README.md`: variáveis de ambiente, como subir, como rodar backup/restauração, como criar o admin, como atualizar.
|
||||
6. Conferir e-mail (SPF/DKIM do remetente) para os e-mails não caírem em spam.
|
||||
|
||||
## Critérios de aceite
|
||||
- [ ] Sistema acessível por HTTPS no domínio, cadastro → briefing → envio funcionando de ponta a ponta em produção.
|
||||
- [ ] Banco e uploads persistem após `docker compose down && up`.
|
||||
- [ ] Porta do Postgres não acessível externamente.
|
||||
|
||||
Atualize `99-progresso.md` (12) e marque o projeto como concluído.
|
||||
@@ -0,0 +1,29 @@
|
||||
# 99 — Progresso do projeto (guardrail obrigatório)
|
||||
|
||||
> **Instrução à IA executora:** leia este arquivo ANTES de iniciar cada etapa e devolva-o atualizado ao terminar. Nunca avance se a etapa anterior não estiver 100% concluída (todos os critérios de aceite marcados). Se algo falhar, registre em "Bloqueios" e pare.
|
||||
|
||||
| Etapa | Arquivo | Status | Observações |
|
||||
|---|---|---|---|
|
||||
| 01 | 01-setup-projeto-docker.md | 🟨 em andamento | Estrutura Next/Tailwind/Docker criada na raiz; falta validar `npm install`, `npm run lint`, `npm run build` e `docker compose up`. |
|
||||
| 02 | 02-banco-prisma-schema.md | 🟨 em andamento | `prisma/schema.prisma`, migrations `0001_init` e `0002_configuracao`, e `lib/db.ts` criados; falta aplicar/validar com Prisma e Postgres. |
|
||||
| 03 | 03-seed-briefing-do-docx.md | 🟨 em andamento | `prisma/briefing-seed.json`, `prisma/seed.ts` e `lib/briefing-queries.ts` criados; falta executar seed e conferir contagens. |
|
||||
| 04 | 04-autenticacao-e-cadastro.md | 🟨 em andamento | Cadastro, validadores, criptografia de CPF, Auth.js Credentials, middleware, login, logout, recuperação/redefinição de senha e rotas protegidas iniciais criados; falta validar em runtime com banco, SMTP e build. |
|
||||
| 05 | 05-motor-do-formulario-briefing.md | 🟨 em andamento | Motor inicial criado: lista de briefings, criação de RASCUNHO, abertura com orientações/configurações, cabeçalho editável local, progresso por seção, tela de seção renderizada pelo banco com TEXTAREA/RADIO/CHECKBOX/ANEXO e navegação. Falta validar em runtime e conectar persistência na etapa 07. |
|
||||
| 06 | 06-botao-ajuda-popup.md | 🟨 em andamento | `components/ajuda/AjudaButton.tsx` e `components/ui/dialog.tsx` criados; perguntas com `ajuda` agora exibem botão Ajuda com popup, textos do guia e atalhos para TEXTAREA. Falta validar foco/teclado/mobile e amostrar 1 pergunta por seção em runtime. |
|
||||
| 07 | 07-rascunho-autosave-e-envio.md | 🟨 em andamento | Autosave com debounce, salvar ao navegar, bloqueio server-side para briefing ENVIADO, revisão com respostas/brancos, confirmação e envio criados. Serviço `reabrirBriefing` criado. Falta validar persistência real, concorrência e navegação no runtime. |
|
||||
| 08 | 08-upload-anexos-checklist.md | 🟨 em andamento | Campo ANEXO criado com checkbox, links, upload, listagem, download e remoção. Route handlers privados para upload/download/delete criados, com validação de extensão, MIME, tamanho, magic bytes e bloqueio para briefing ENVIADO. Falta validar upload real, permissões e arquivos inválidos no runtime. |
|
||||
| 09 | 09-painel-admin.md | 🟨 em andamento | Painel admin criado: dashboard com contadores/últimos envios, clientes com busca/filtro, detalhe com CPF mascarado e revelação auditada, detalhe de briefing com respostas/anexos/status/reabertura/notas internas, edição de perguntas e ajudas. Migration `0003` criada. Falta validar permissões, auditoria e edição em runtime. |
|
||||
| 10 | 10-exportacao-pdf-e-notificacoes.md | 🟨 em andamento | PDF em `/api/briefings/[id]/pdf` criado com acesso dono/admin, dados do cliente sem CPF completo, respostas, opções ☒/☐, anexos e confirmação. Botões de download adicionados para cliente/admin. E-mails de cadastro e envio criados; falhas não bloqueiam cadastro/envio. Tabela `EnvioNotificacao` e migration `0004` criadas. WhatsApp/Evolution fica pendente de consulta da versão/payload da instância. Falta validar PDF, SMTP e registros em runtime. |
|
||||
| 11 | 11-lgpd-e-seguranca.md | 🟨 em andamento | Páginas legais marcadas como texto-base jurídico, Minha conta criada com edição de dados, exportação JSON e solicitação de exclusão (`SolicitacaoExclusao`, migration `0005`). Cabeçalhos de segurança adicionados no `next.config`, rate limits ampliados, checagem de origem em route handlers mutáveis, `/minha-conta` protegida no middleware e script `scripts/backup.sh` criado. Falta validar `curl -I`, isolamento manual entre clientes, backup/restauração e migrations em runtime. |
|
||||
| 12 | 12-deploy-producao.md | 🟨 em andamento | Deploy preparado: `docker-compose.prod.yml` com app standalone, Postgres sem porta externa, volumes persistentes, Caddy HTTPS, serviço release (`migrate deploy` + seed), `/api/health`, scripts release/restore e README de produção. Falta executar em servidor real, configurar domínio/SPF/DKIM, validar HTTPS e fluxo cadastro → briefing → envio. |
|
||||
|
||||
Legenda: ⬜ pendente · 🟨 em andamento · ✅ concluída
|
||||
|
||||
## Decisões tomadas durante a execução
|
||||
- O sistema está sendo criado na raiz do projeto, mantendo `Conhecimento/` e `Schema/` como referência.
|
||||
- `Configuracao` foi incluída no schema desde a preparação inicial para armazenar os textos do seed.
|
||||
- `Resposta.complemento` foi incluído para suportar o campo complementar previsto nas perguntas.
|
||||
|
||||
## Bloqueios
|
||||
- O shell atual não possui `node`, `npm` nem `docker`; por isso os critérios de aceite que exigem instalação, build, lint, Docker, Prisma migrate e seed ainda não puderam ser executados.
|
||||
- Etapa 12 depende de servidor com Docker, domínio apontado por DNS e credenciais SMTP reais para validar HTTPS, persistência, e-mail e fluxo ponta a ponta.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user