Pular para o conteúdo principal

Página de Contato — Site Público Abracaf

A página de contato (abracaf/contato/page.tsx) é um RSC que compõe um hero, cards de canal de atendimento, formulário interativo e sidebar com mapa, horários e FAQ.

Estrutura da página

page.tsx (RSC)
├── <section> hero navy ← headline + descrição
└── <section> conteúdo
├── CHANNELS (3 cards) ← Associados, Imprensa, Geral
├── ContactForm ← formulário ('use client')
└── sidebar
├── AbracafMapWrapper ← mapa da sede
├── horário ← Seg-Sex, Sáb, Dom
└── FAQ ← accordion com <details>/<summary>

ContactForm

Arquivo: _components/abracaf-contact-form.tsx ('use client')

LibPapel
react-hook-formGerenciamento de estado e submit
zod + @hookform/resolversValidação via ContactSchema
next-safe-action (useAction)Chama a server action tipada

Campos e autoComplete

Todos os campos têm autoComplete declarado para melhorar a UX em mobile e reduzir o atrito de preenchimento:

CampoautoCompleteObrigatório
NomenameSim
Cargoorganization-titleNão
E-mailemailSim
TelefonetelNão
ConcessionáriaorganizationNão
Tipo de solicitaçãoSim
MensagemSim
LGPDSim

Máscara de telefone

O campo de telefone aplica máscara em tempo real via maskPhone() — uma função pura que formata para (XX) XXXX-XXXX (10 dígitos) ou (XX) XXXXX-XXXX (11 dígitos), sem dependências externas.

Estados do formulário

EstadoComportamento
idleFormulário disponível para preenchimento
successSubstitui o formulário por um Alert verde por 5 segundos, depois reseta
errorExibe Alert destrutivo no topo do formulário com link de fallback para e-mail

Server action

Arquivo: _lib/server/contact-abracaf-action.ts

Usa publicActionClient (sem autenticação requerida) do @kit/next/safe-action.

Fluxo de execução

  1. Recebe ContactData validado pelo ContactSchema
  2. Extrai o IP do header x-forwarded-for (primeiro da lista em caso de proxies)
  3. Verifica o rate limit — lança erro se excedido (ver Rate Limiting)
  4. Envia o e-mail via @kit/mailers

Destinatário e fallback de e-mail

const to = process.env.ABRACAF_CONTACT_EMAIL ?? 'secretaria@abracaf.com.br';

Se ABRACAF_CONTACT_EMAIL não estiver definida, os contatos chegam em secretaria@abracaf.com.br. O envio só ocorre se EMAIL_SENDER também estiver definido — em desenvolvimento sem configuração de e-mail, a action retorna sucesso silenciosamente sem tentar enviar.

Variáveis de ambiente

VariávelObrigatóriaDescrição
EMAIL_SENDERSim (prod)Remetente no formato "Nome <email>"
ABRACAF_CONTACT_EMAILNãoDestinatário; usa fallback se ausente

FAQ

O FAQ usa <details>/<summary> nativos do HTML sem JavaScript. A seta rotaciona via CSS com group-open:rotate-180 quando o <details> está aberto:

<details className="group py-3">
<summary className="...">
{question}
<span className="transition-transform group-open:rotate-180"></span>
</summary>
<p>{answer}</p>
</details>