feat(S9): captura de novidades da campanha na home pública (form + CTA do hero) #104
Loading…
Reference in a new issue
No description provided.
Delete branch "S9-captura-de-novidades-da-campanha-na-home-publica-form-cta"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #93
Captura de novidades da campanha na home pública (S9): seção "Receba as novidades da campanha" logo acima do rodapé + CTA secundário do hero virando o atalho (
#novidades, scroll suave). Form: nome + WhatsApp obrigatórios; e-mail, estado, cidade e comentário opcionais; toggle pré-selecionado "Quero fazer parte do time" gravado comosubscription.campaignLevel(time|esporadico) — visível como coluna própria no admin.Dados/consent:
Contact+SubscriptionemwithPayloadTransactioncom consentimento NOVO fail-closed por chave estávelcampanha-novidades— sem o texto aprovado no admin (jurídico pendente), o form recusa a captura e nada é gravado. Anti-goals respeitados: nada desupporter, sem mescla com/mandato-no-whatsapp, bandeiras seguem acessíveis (rodapé + "Ver bandeiras" no estado de sucesso).Schema: migration
20260819_192605_add_campaign_newsletter_capture—contact.stateDROP NOT NULL (estado opcional no form; a ficha staff via zod segue exigindo) + colunasubscription.campaign_levelcom enum. Cadeia validada porpnpm migrate+ int tests.Testes: int
submitCampaignNewsletter.int.spec.ts(fail-closed com mensagem exata + nada gravado; gravação dos dois níveis; estado omitido → null) · e2ecampaignNewsletter.e2e.spec.ts(âncora do hero, submissão, sucesso in-place, verificação REST do registro) · e2efrontendatualizados (âncora#novidades; pins de geometria do hero preservados com "Receba/novidades" — 2 linhas, mesma contagem de caracteres).Plano:
docs/plans/captura-novidades-home-campanha-impl.md(aprovado em sessão; posição da seção ajustada a pedido — acima do rodapé; scroll suave) · changelog2026-08-19-s9.md. Débito pós-entrega registrado como #102 (blocked,depends: #93).Nota: o path de recusa (consent ausente) é coberto pelo int test — o e2e guard trata 5xx como falha e a action fail-closed responde 500 (precedente WebAuthn usa 4xx tratado).
Consentimento criado em produção (rascunho p/ revisão jurídica):
Consentid 7, chavecampanha-novidades, 4 parágrafos cobrindo os dois níveis (time: comunicações frequentes + grupos de WhatsApp + ações; esporádico: sem grupos/sem frequência) + tratamento LGPD (finalidade, não-compartilhamento, direito de correção/exclusão/revogação). Inserido direto noteqo_1313(2026-08-19) a pedido do produto; o jurídico revisa/edita o texto via admin (a chave permanece estável). Com o deploy do S9 a captura já nasce ativa — o fail-closed abriu porque o documento existe.