sass-imobiliaria/specs/028-trabalhe-conosco/spec.md
MatheusAlves96 cf5603243c
Some checks failed
CI/CD → Deploy via SSH / Build & Push Docker Images (push) Successful in 1m0s
CI/CD → Deploy via SSH / Deploy via SSH (push) Successful in 4m35s
CI/CD → Deploy via SSH / Validate HTTPS & Endpoints (push) Failing after 46s
feat: features 025-032 - favoritos, contatos, trabalhe-conosco, area-cliente, navbar, hero-light-dark, performance-homepage
- feat(025): favoritos locais com FavoritesContext, HeartButton, PublicFavoritesPage
- feat(026): central de contatos admin (leads/contatos unificados)
- feat(027): configuração da página de contato via admin
- feat(028): trabalhe conosco - candidaturas com upload e admin
- feat(029): UX área do cliente - visitas, comparação, perfil
- feat(030): navbar UX - menu mobile, ThemeToggle, useFavorites
- feat(031): hero light/dark - imagens separadas por tema, upload, preview, seed
- feat(032): performance homepage - Promise.all parallel fetches, sessionStorage cache,
  preload hero image, loading=lazy nos cards, useInView hook, will-change carrossel,
  keyframes em index.css, AgentsCarousel e HomeScrollScene via props
- fix: light mode HomeScrollScene - gradiente, cores de texto, scroll hint

migrations: g1h2i3j4k5l6 (source em leads), h1i2j3k4l5m6 (contact_config),
            i1j2k3l4m5n6 (job_applications), j2k3l4m5n6o7 (hero theme images)
2026-04-22 22:35:17 -03:00

13 KiB

Feature Specification: Página "Trabalhe Conosco"

Feature Branch: 028-trabalhe-conosco Created: 2026-04-21 Status: Draft


Contexto

O site imobiliário atualmente não oferece um canal formal para que candidatos manifestem interesse em trabalhar na empresa. Esse contato ocorre de maneira informal — por telefone, e-mail avulso ou presencialmente — sem rastreabilidade e sem uma experiência consistente para o candidato.

Esta spec cobre a criação de uma página pública "/trabalhe-conosco" com formulário de candidatura, armazenamento das submissões em banco de dados e listagem das candidaturas no painel administrativo. A página também deve ser acessível via links no footer e na página de equipe, tornando o recrutamento um ponto de contato organizado e profissional.


User Scenarios & Testing

User Story 1 — Candidato Envia Formulário de Candidatura (Priority: P1)

Um candidato interessado em trabalhar na imobiliária acessa a página "/trabalhe-conosco", preenche o formulário com seus dados e envia sua candidatura.

Why this priority: É o núcleo da feature. Toda a proposta de valor gira em torno dessa ação — sem ela, a página é apenas um conteúdo estático sem utilidade.

Independent Test: Acessar /trabalhe-conosco sem autenticação, preencher todos os campos obrigatórios (nome, e-mail, telefone, cargo de interesse, mensagem) e submeter. Verificar que uma mensagem de sucesso é exibida e que a candidatura aparece na listagem do painel admin em GET /api/v1/admin/jobs.

Acceptance Scenarios:

  1. Given um visitante não autenticado na página /trabalhe-conosco, When ele preenche todos os campos obrigatórios e clica em "Enviar Candidatura", Then a candidatura é registrada no sistema e uma mensagem de confirmação é exibida ao candidato.
  2. Given o formulário preenchido corretamente, When o campo de cargo de interesse é "Corretor(a)", Then o valor enviado e armazenado reflete exatamente a opção selecionada.
  3. Given o formulário preenchido corretamente com um arquivo PDF informado, When o candidato submete, Then o nome do arquivo é registrado junto com a candidatura, mesmo que o conteúdo do arquivo não seja armazenado nesta versão.
  4. Given o formulário submetido com sucesso, When o candidato tenta submeter novamente sem recarregar a página, Then o formulário é limpo/resetado após o sucesso, prevenindo envios duplicados acidentais.
  5. Given falha de rede durante o envio, When a requisição não é completada, Then uma mensagem de erro informativa é exibida e o candidato pode tentar novamente sem perder os dados preenchidos.

User Story 2 — Visitante Descobre a Oportunidade Pelo Site (Priority: P1)

Um visitante que navega pelo footer ou pela página de equipe (/corretores) encontra o link "Trabalhe Conosco" e acessa a página de candidatura.

Why this priority: Sem pontos de entrada adequados, a página não é encontrada organicamente dentro do site, tornando o canal de recrutamento inacessível na prática.

Independent Test: Acessar o footer do site e verificar a presença do link "Trabalhe Conosco" na coluna "A Imobiliária". Acessar /corretores e verificar a presença do link/botão "Trabalhe Conosco". Clicar em cada link e confirmar que navega para /trabalhe-conosco.

Acceptance Scenarios:

  1. Given um visitante em qualquer página do site, When ele visualiza o footer, Then o link "Trabalhe Conosco" está visível na coluna "A Imobiliária".
  2. Given um visitante na página /corretores, When ele visualiza a página de equipe, Then existe um elemento (link ou botão) com o texto "Trabalhe Conosco" que leva a /trabalhe-conosco.
  3. Given um visitante clicando no link "Trabalhe Conosco" a partir do footer, When a navegação ocorre, Then ele é direcionado para /trabalhe-conosco com a página completa carregada.
  4. Given um visitante em dispositivo móvel, When ele visualiza o footer ou a página /corretores, Then o link "Trabalhe Conosco" é igualmente acessível e funcional.

User Story 3 — Administrador Visualiza as Candidaturas Recebidas (Priority: P2)

O administrador da imobiliária acessa o painel admin e visualiza uma listagem paginada de todas as candidaturas enviadas pelos candidatos.

Why this priority: Sem visibilidade das candidaturas, o canal de recrutamento não entrega valor operacional. A listagem é o produto final que o administrador consume para iniciar o processo seletivo.

Independent Test: Com candidaturas já enviadas via formulário público, autenticar como administrador e consultar GET /api/v1/admin/jobs. Verificar que a resposta inclui os dados dos candidatos (nome, e-mail, cargo, data de envio) com paginação funcional.

Acceptance Scenarios:

  1. Given um administrador autenticado, When ele acessa o endpoint de listagem de candidaturas, Then a resposta inclui uma lista paginada com nome, e-mail, telefone, cargo de interesse, data de envio e nome do arquivo informado para cada candidatura.
  2. Given mais de 20 candidaturas no sistema, When o administrador consulta a segunda página, Then os resultados são diferentes da primeira página e o total de candidaturas é informado na resposta.
  3. Given um usuário não autenticado tentando acessar o endpoint de listagem, When a requisição é enviada, Then o sistema retorna erro de acesso não autorizado (HTTP 401).
  4. Given um token de usuário comum (não administrador), When ele tenta acessar o endpoint de listagem, Then o sistema retorna erro de permissão insuficiente (HTTP 403).
  5. Given nenhuma candidatura registrada, When o administrador consulta a listagem, Then o sistema retorna uma lista vazia com o total zerado, sem erro.

User Story 4 — Candidato Vê a Página com Conteúdo Institucional (Priority: P3)

Um candidato acessa /trabalhe-conosco e, além do formulário, encontra uma apresentação institucional da imobiliária como empregadora, com destaque para benefícios de trabalhar na empresa.

Why this priority: Enriquece a experiência do candidato e posiciona a imobiliária como empregadora, mas não bloqueia o funcionamento do recrutamento em si.

Independent Test: Acessar /trabalhe-conosco e verificar que a página contém: uma hero section com título e subtítulo, uma seção "Por que trabalhar conosco?" com exatamente 3 cards de benefícios, e o formulário de candidatura.

Acceptance Scenarios:

  1. Given qualquer visitante acessando /trabalhe-conosco, When a página carrega, Then uma hero section com título principal e subtítulo descritivo é exibida no topo.
  2. Given a página carregada, When o visitante rola a tela, Then uma seção "Por que trabalhar conosco?" com 3 cards de benefícios é visível antes do formulário.
  3. Given a página carregada, When o visitante acessa em dispositivo móvel, Then hero section, cards de benefícios e formulário se adaptam ao layout vertical sem perda de conteúdo ou sobreposição visual.

Edge Cases

  • O que acontece se o candidato enviar o formulário com um e-mail em formato inválido? A validação deve ocorrer no frontend antes do envio, e o backend deve rejeitar com HTTP 422 e mensagem descritiva.
  • O que acontece se o campo de mensagem ultrapassar o limite de caracteres? O sistema deve validar e informar o candidato antes de enviar.
  • O que acontece se o candidato tentar enviar o mesmo e-mail múltiplas vezes? Por padrão, múltiplas candidaturas do mesmo e-mail são permitidas (sem deduplicação nesta versão).
  • O que acontece se o candidato selecionar um arquivo que não seja PDF ou que exceda 2 MB? O frontend deve bloquear o envio e exibir mensagem de erro clara. Nesta versão, apenas o nome do arquivo é registrado — não há upload real de arquivo.
  • O que acontece se o backend retornar erro 500 durante o envio? O frontend deve exibir mensagem genérica de erro sem expor detalhes técnicos.
  • Como o endpoint público POST /api/v1/jobs/apply se comporta em caso de sobrecarga? Por padrão, o endpoint não possui rate limiting nesta versão — isso pode ser adicionado futuramente.

Requirements

Functional Requirements

  • FR-001: O sistema DEVE disponibilizar a rota pública /trabalhe-conosco no frontend, acessível sem autenticação.
  • FR-002: A página DEVE conter uma hero section com título e subtítulo configurados estaticamente.
  • FR-003: A página DEVE conter uma seção "Por que trabalhar conosco?" com 3 cards de benefícios (conteúdo estático).
  • FR-004: A página DEVE conter um formulário de candidatura com os campos: nome completo, e-mail, telefone, cargo de interesse (select), mensagem/apresentação e seleção de arquivo de currículo.
  • FR-005: O campo de cargo de interesse DEVE oferecer as opções: Corretor(a), Assistente Administrativo, Estagiário(a), Outro.
  • FR-006: O formulário DEVE validar campos obrigatórios (nome, e-mail, cargo, mensagem) antes do envio, exibindo mensagens de erro por campo.
  • FR-007: O campo de e-mail DEVE validar formato de e-mail válido no frontend antes do envio.
  • FR-008: O campo de arquivo DEVE aceitar apenas arquivos PDF e rejeitar arquivos acima de 2 MB, com mensagem de erro clara — a validação ocorre no frontend; nesta versão, apenas o nome do arquivo é enviado ao backend.
  • FR-009: Após envio bem-sucedido, o formulário DEVE exibir uma mensagem de confirmação ao candidato e limpar os campos.
  • FR-010: O sistema DEVE disponibilizar o endpoint público POST /api/v1/jobs/apply que receba e persista os dados textuais da candidatura (sem autenticação).
  • FR-011: O backend DEVE validar os dados recebidos no endpoint de candidatura e retornar HTTP 422 com detalhes para dados inválidos.
  • FR-012: O sistema DEVE armazenar as candidaturas em uma tabela job_applications com os campos: nome completo, e-mail, telefone, cargo de interesse, mensagem, nome do arquivo informado e data/hora do envio.
  • FR-013: O sistema DEVE disponibilizar o endpoint protegido GET /api/v1/admin/jobs que retorne uma listagem paginada das candidaturas, acessível apenas por administradores autenticados.
  • FR-014: O endpoint de listagem DEVE retornar para cada candidatura: nome, e-mail, telefone, cargo de interesse, mensagem, nome do arquivo e data de envio.
  • FR-015: O endpoint de listagem DEVE suportar paginação com parâmetros page e per_page, retornando o total de registros.
  • FR-016: O footer do site DEVE conter o link "Trabalhe Conosco" na coluna "A Imobiliária", navegando para /trabalhe-conosco.
  • FR-017: A página /corretores DEVE conter um link ou botão "Trabalhe Conosco" navegando para /trabalhe-conosco.
  • FR-018: O design da página DEVE seguir os design tokens existentes do projeto (cores, tipografia Inter, estilo de cards limpos).

Key Entities

  • JobApplication: Registro de candidatura enviada por um candidato. Atributos principais: identificador único, nome completo do candidato, e-mail, telefone, cargo de interesse selecionado, texto de apresentação/mensagem, nome do arquivo de currículo informado (opcional), data e hora do envio. Sem relacionamento com outras entidades nesta versão.

Success Criteria

Measurable Outcomes

  • SC-001: Um candidato consegue localizar e acessar a página "Trabalhe Conosco" a partir do footer ou da página de equipe em no máximo 2 cliques.
  • SC-002: Um candidato consegue preencher e enviar o formulário de candidatura completo em menos de 3 minutos.
  • SC-003: 100% das candidaturas enviadas com dados válidos são armazenadas e recuperáveis pelo administrador via painel admin.
  • SC-004: Tentativas de acesso não autorizado ao endpoint de listagem de candidaturas são bloqueadas em 100% dos casos.
  • SC-005: O formulário exibe mensagem de erro específica para cada campo inválido sem necessidade de recarregar a página.
  • SC-006: A página carrega e exibe todo o conteúdo estático (hero, benefícios, formulário) em menos de 2 segundos em conexões de banda larga padrão.

Assumptions

  • O upload real do arquivo de currículo (armazenamento binário no servidor ou serviço de storage) está fora do escopo desta versão; apenas o nome do arquivo informado pelo candidato é salvo como texto.
  • Não há deduplicação de candidaturas por e-mail nesta versão — múltiplas submissões do mesmo endereço são permitidas.
  • Os 3 benefícios exibidos na seção "Por que trabalhar conosco?" são conteúdo estático definido em tempo de desenvolvimento; não há interface de gerenciamento para esse conteúdo.
  • Não há envio de e-mail de confirmação ao candidato nem notificação por e-mail ao administrador nesta versão.
  • O endpoint público de candidatura não possui rate limiting nesta versão.
  • A listagem de candidaturas no painel admin é acessível via API; a interface visual no painel admin (página React de /admin/jobs) pode ser entregue em iteração futura, não sendo requisito desta spec.
  • O padrão de autenticação de administrador já implementado no projeto (require_admin) é suficiente e será reutilizado para proteger o endpoint de listagem.
  • O campo de telefone é opcional para o candidato, mas recomendado — a validação de formato não é obrigatória nesta versão.