sass-imobiliaria/specs/009-contact-button/spec.md

13 KiB

Feature Specification: Contact Button

Feature Branch: [009-contact-button] Created: 2026-04-17 Status: Draft Input: Adicionar um botão destacado 'Entre em Contato' em cada card de imóvel (PropertyRowCard e PropertyCard). Ao clicar, o cliente pode escolher entre preencher um formulário de contato (gera lead no painel admin) ou entrar em contato via WhatsApp com mensagem pré-preenchida com o código do imóvel. O número de WhatsApp do corretor deve vir de uma configuração (variável de ambiente ou admin).


User Scenarios & Testing (mandatory)

User Story 1 - Acessar o Botão de Contato no Card do Imóvel (Priority: P1)

O visitante, ao visualizar qualquer card de imóvel (na listagem ou na seção de destaques), vê um botão destacado "Entre em Contato" e consegue acioná-lo com facilidade.

Why this priority: O botão é o ponto de entrada de toda a feature; sem ele, nenhum outro cenário é alcançável.

Independent Test: Verificar se o botão "Entre em Contato" está visível e clicável em todos os cards de imóvel (PropertyRowCard e PropertyCard).

Acceptance Scenarios:

  1. Given um visitante na página de listagem de imóveis, When visualiza um PropertyRowCard, Then vê o botão "Entre em Contato" em destaque no card.
  2. Given um visitante na página inicial (seção de destaques), When visualiza um PropertyCard, Then vê o botão "Entre em Contato" em destaque no card.
  3. Given um visitante em dispositivo móvel, When visualiza qualquer card de imóvel, Then o botão "Entre em Contato" é visível, acessível e clicável sem necessitar de rolagem horizontal.

User Story 2 - Escolher Canal de Contato (Priority: P1)

Ao clicar no botão "Entre em Contato", o visitante vê um modal/painel com duas opções claras: formulário de contato ou WhatsApp.

Why this priority: A escolha de canal é o fluxo central da feature; define qual caminho o usuário toma.

Independent Test: Verificar se o modal exibe as duas opções para cada imóvel diferente e que clicar fora do modal o fecha sem efeitos colaterais.

Acceptance Scenarios:

  1. Given o visitante clica em "Entre em Contato" em um card, When o modal abre, Then vê duas opções claramente apresentadas: "Formulário de Contato" e "WhatsApp".
  2. Given o modal está aberto, When o visitante clica fora da área do modal ou em um botão de fechar, Then o modal é fechado sem enviar nenhum dado.
  3. Given o modal está aberto para o imóvel X, When o visitante fecha e abre o modal de um imóvel Y diferente, Then o modal exibe o código do imóvel Y corretamente.

User Story 3 - Enviar Formulário de Contato (Priority: P1)

O visitante preenche e envia um formulário de contato com seu nome, e-mail, telefone (opcional) e uma mensagem pré-preenchida com o código do imóvel. O lead é registrado no sistema e visível no painel administrativo.

Why this priority: Captação de leads é um dos objetivos de negócio principais do sistema.

Independent Test: Verificar se um lead é criado no banco de dados com o property_id correto após o envio do formulário, e se o registro aparece no painel admin.

Acceptance Scenarios:

  1. Given o visitante escolhe "Formulário de Contato", When o formulário é exibido, Then o campo de mensagem já contém o código do imóvel (ex.: "Tenho interesse no imóvel de código 2880602111.").
  2. Given o formulário está aberto, When o visitante preenche nome, e-mail e mensagem e clica em "Enviar", Then os dados são enviados, o lead é salvo no sistema e o visitante vê uma mensagem de sucesso.
  3. Given o visitante tenta enviar o formulário com campos obrigatórios vazios (nome ou e-mail), When clica em "Enviar", Then vê mensagens de erro claras nos campos inválidos e o envio é bloqueado.
  4. Given o visitante preenche um e-mail em formato inválido, When clica em "Enviar", Then vê mensagem de erro específica sobre o e-mail.
  5. Given o visitante clica "Enviar" e ocorre falha de rede ou erro do servidor, When a resposta retorna erro, Then vê mensagem de erro amigável e pode tentar novamente sem perder os dados preenchidos.
  6. Given o formulário foi enviado com sucesso, When o admin acessa o painel de leads, Then vê o novo lead com o código/ID do imóvel associado, nome, e-mail, telefone e mensagem do visitante.

User Story 4 - Contato via WhatsApp (Priority: P1)

O visitante escolhe a opção WhatsApp e é redirecionado para o WhatsApp com uma mensagem pré-preenchida contendo o código do imóvel. O número de destino pertence ao corretor responsável.

Why this priority: WhatsApp é o canal de comunicação predominante no mercado imobiliário brasileiro; é esperado como opção principal.

Independent Test: Verificar se o link gerado aponta para o número correto (configurado no sistema) e se a mensagem contém o código do imóvel.

Acceptance Scenarios:

  1. Given o visitante escolhe a opção "WhatsApp" no modal, When confirma a ação, Then é redirecionado para o WhatsApp (web ou app) com a mensagem "Olá! Tenho interesse no imóvel de código [CÓDIGO]. Poderia me dar mais informações?" pré-preenchida.
  2. Given o número de WhatsApp do corretor está configurado no sistema, When o visitante aciona a opção WhatsApp, Then o link aponta para esse número configurado.
  3. Given o número de WhatsApp não está configurado, When o visitante tenta usar a opção WhatsApp, Then a opção é desabilitada ou exibe uma mensagem informando que o canal não está disponível no momento.
  4. Given o visitante está em desktop, When clica em WhatsApp, Then o link abre o WhatsApp Web em nova aba; em dispositivos móveis, abre o aplicativo nativo do WhatsApp.

User Story 5 - Configuração do Número de WhatsApp (Priority: P2)

O administrador pode configurar o número de WhatsApp do corretor que será usado nos links gerados nos cards de imóvel.

Why this priority: Sem configuração do número, a opção WhatsApp não funciona; mas a configuração em si pode ser feita antes do deploy via variável de ambiente.

Independent Test: Verificar se alternar o número de WhatsApp na configuração reflete imediatamente nos links gerados nos cards de imóvel.

Acceptance Scenarios:

  1. Given o admin acessa as configurações do sistema, When define ou altera o número de WhatsApp, Then os novos links gerados nos cards de imóvel usam o número atualizado.
  2. Given o número é definido via variável de ambiente WHATSAPP_NUMBER, When o sistema é iniciado, Then esse número é utilizado como padrão se não houver configuração salva no banco.

User Story 6 - Visualizar Leads no Painel Admin (Priority: P2)

O administrador pode visualizar, filtrar e exportar a lista de leads gerados pelos formulários de contato, com informação do imóvel associado.

Why this priority: Sem visibilidade dos leads, o objetivo de negócio de captação não se completa.

Independent Test: Verificar se leads aparecem no painel admin com os dados corretos e se os filtros por imóvel e por data funcionam.

Acceptance Scenarios:

  1. Given o admin acessa a seção de leads no painel, When visualiza a lista, Then vê todos os leads com: nome, e-mail, telefone, mensagem, código do imóvel associado e data de criação.
  2. Given o admin deseja encontrar leads de um imóvel específico, When filtra pelo código ou ID do imóvel, Then apenas os leads daquele imóvel são exibidos.
  3. Given o admin visualiza um lead, When clica para ver detalhes, Then vê todas as informações do lead e um link para o imóvel correspondente.

Functional Requirements

  1. O botão "Entre em Contato" deve ser exibido nos componentes PropertyRowCard e PropertyCard, com destaque visual adequado ao design existente (Linear dark theme).
  2. Ao clicar no botão, um modal deve ser aberto apresentando duas opções: "Formulário de Contato" e "WhatsApp".
  3. O formulário de contato deve conter os campos: nome (obrigatório), e-mail (obrigatório), telefone (opcional) e mensagem (obrigatório, pré-preenchida com o código do imóvel).
  4. O envio do formulário deve criar um ContactLead no banco de dados com o property_id do imóvel correspondente, via endpoint existente POST /api/v1/properties/<slug>/contact.
  5. O campo de mensagem deve ser pré-preenchido com o texto: "Tenho interesse no imóvel de código {CÓDIGO}. Poderia me dar mais informações?".
  6. A opção WhatsApp deve gerar um link wa.me/{NUMERO}?text={MENSAGEM_CODIFICADA} que seja aberto em nova aba.
  7. A mensagem pré-preenchida para o WhatsApp deve conter: "Olá! Tenho interesse no imóvel de código {CÓDIGO}. Poderia me dar mais informações?".
  8. O número de WhatsApp deve ser lido prioritariamente de uma configuração no banco de dados; como fallback, da variável de ambiente WHATSAPP_NUMBER.
  9. Quando o número de WhatsApp não estiver configurado, a opção WhatsApp deve ser desabilitada visualmente com mensagem informativa.
  10. O backend deve expor um endpoint GET /api/v1/config/whatsapp (sem autenticação) que retorna o número de WhatsApp configurado (ou null), para que o frontend possa exibir ou desabilitar a opção.
  11. O modal deve ser fechável clicando fora dele ou em um botão "X".
  12. O formulário deve exibir mensagens de erro inline para campos inválidos, sem recarregar a página.
  13. Após envio bem-sucedido, o formulário deve exibir mensagem de confirmação e fechar automaticamente após breve intervalo.
  14. Em caso de erro no envio, o formulário deve exibir mensagem de erro amigável e manter os dados preenchidos.
  15. O painel admin deve listar os leads captados com: nome, e-mail, telefone, mensagem, imóvel associado (código e link) e data de criação.
  16. A listagem de leads no admin deve suportar paginação e filtro pelo imóvel associado.

Non-Functional Requirements

  • O modal deve abrir em até 200 ms após o clique no botão (experiência percebida como instantânea).
  • O envio do formulário deve completar em até 3 segundos em condições normais de rede.
  • O link do WhatsApp deve ser gerado no lado do cliente, sem round-trip ao servidor.
  • O botão "Entre em Contato" deve ser acessível via teclado (foco visível, acionável com Enter/Space) e compatível com leitores de tela (atributo aria-label adequado).
  • O modal deve ser responsivo em todos os breakpoints (mobile, tablet, desktop).
  • Nenhum dado pessoal do visitante deve ser carregado ou exibido antes do visitante interagir com o formulário.
  • O endpoint GET /api/v1/config/whatsapp deve retornar resposta em até 500 ms e pode ser cacheado no cliente por até 5 minutos.

Out of Scope

  • Envio de e-mail de confirmação ao visitante após submissão do formulário (pode ser feature futura).
  • Integração com CRM externo para sincronização de leads.
  • Notificação em tempo real (push ou e-mail) ao admin quando um novo lead é criado.
  • Edição ou exclusão de leads pelo admin (somente leitura no escopo desta feature).
  • Rastreamento analítico de cliques no botão ou escolha de canal (pode ser feature futura).
  • Suporte a múltiplos números de WhatsApp por imóvel ou por corretor.
  • Formulário de contato na página de detalhe do imóvel (já implementado separadamente).

Key Entities

  • ContactLead: id, property_id (FK → properties.id), name, email, phone, message, created_at — tabela contact_leads já existe.
  • Property: id, code, slug, title — campo code usado como identificador legível na mensagem pré-preenchida.
  • WhatsApp Config: número de telefone do corretor no formato internacional (ex.: 5516999998888), armazenado em variável de ambiente WHATSAPP_NUMBER e/ou configuração no banco.
  • Modal de Contato: componente React com estado local controlando qual canal está selecionado e o ciclo de vida do formulário (idle → submitting → success/error).

Assumptions

  • O endpoint POST /api/v1/properties/<slug>/contact já está implementado e funcional; esta feature apenas o consome no frontend.
  • O code do imóvel (campo numérico) está disponível no objeto Property retornado pela API de listagem e já está presente nos props dos componentes de card.
  • O design do botão e do modal seguirá o tema Linear dark já adotado no projeto.
  • O número de WhatsApp será armazenado sem formatação, somente dígitos, no formato internacional sem + (ex.: 5516999998888).
  • A validação do formulário no frontend espelha as regras do schema Pydantic ContactLeadIn já existente (nome ≥ 2 chars, e-mail válido, mensagem ≥ 10 chars, etc.).
  • A configuração do número de WhatsApp via admin (painel) será implementada como parte da feature 007 (Admin Panel) ou como extensão futura; neste escopo, o número é definido via variável de ambiente WHATSAPP_NUMBER.