feat: add full project - backend, frontend, docker, specs and configs

This commit is contained in:
MatheusAlves96 2026-04-20 23:59:45 -03:00
parent b77c7d5a01
commit e6cb06255b
24489 changed files with 61341 additions and 36 deletions

View file

@ -0,0 +1,36 @@
# Specification Quality Checklist: Página Sobre
**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-04-17
**Feature**: [spec.md](../spec.md)
## Content Quality
- [x] No implementation details (languages, frameworks, APIs)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed
## Requirement Completeness
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Success criteria are technology-agnostic (no implementation details)
- [x] All acceptance scenarios are defined
- [x] Edge cases are identified
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified
## Feature Readiness
- [x] All functional requirements have clear acceptance criteria
- [x] User scenarios cover primary flows
- [x] Feature meets measurable outcomes defined in Success Criteria
- [x] No implementation details leak into specification
## Notes
- Todos os itens aprovados na primeira iteração de validação.
- O conteúdo textual definitivo (história, diferenciais, métricas, número de WhatsApp) deverá ser fornecido pelo cliente antes da implementação — documentado nas Assumptions.
- Pronto para `/speckit.plan`.

View file

@ -0,0 +1,150 @@
# Data Model: Página Sobre
**Feature**: 021-pagina-sobre
**Phase**: 1 — Design & Contracts
**Status**: Completo
---
## Nota sobre "Data Model" para feature 100% frontend
Esta feature não envolve entidades de banco de dados nem estado gerenciado em store. O "modelo de dados" descreve a estrutura lógica do conteúdo estático e os contratos dos componentes React afetados.
---
## Componentes — contratos de props
### `AboutPage` (novo)
| Prop | Tipo | Descrição |
|------|------|-----------|
| — | — | Componente sem props (stateless, sem hooks) |
**Estrutura JSX de alto nível**:
```
AboutPage
├── <Navbar />
├── <main id="main-content" className="min-h-screen bg-canvas">
│ ├── SectionHero
│ │ └── título, subtítulo, parágrafo de missão
│ ├── SectionHistoria
│ │ └── texto narrativo (23 parágrafos)
│ ├── SectionDiferenciais
│ │ └── grid de 34 DiferencialCard
│ │ └── { icon, title, description }
│ ├── SectionNumeros
│ │ └── grid de 4 MetricCard
│ │ └── { value, label }
│ ├── SectionEquipe
│ │ └── texto introdutório + <Link to="/corretores">
│ └── SectionCTA
│ ├── <Link to="/imoveis"> "Ver imóveis disponíveis"
│ └── <a href="https://wa.me/5500000000000?text=..."> "Falar com corretor"
└── <Footer />
```
**Tipos locais (apenas internos ao arquivo, não exportados)**:
```typescript
// Apenas para as seções mapeadas com .map()
type DiferencialItem = {
icon: string // emoji ou símbolo UTF-8 (ex.: "🏠")
title: string
description: string
}
type MetricItem = {
value: string // ex.: "10+" | "2.500+" | "98%"
label: string // ex.: "Anos de mercado"
}
```
> **Nota**: Os tipos `DiferencialItem` e `MetricItem` NÃO são exportados. São usados somente internamente via arrays locais mapeados por `.map()`. Principle VI: sem abstração prematura.
---
### `Footer` (alterado)
Mudança pontual no array `footerLinks` e no JSX de renderização:
**Estado atual**:
```typescript
const footerLinks = [
{ label: 'Imóveis', href: '/imoveis' },
{ label: 'Sobre', href: '#sobre' }, // ← alterar
{ label: 'Contato', href: '#contato' },
{ label: 'Política de Privacidade', href: '/politica-de-privacidade' },
]
```
**Estado após a feature**:
```typescript
// O array footerLinks perde o href de '#sobre'
// O link "Sobre" passa a ser <Link to="/sobre"> em vez de <a href="#sobre">
```
**Estratégia de implementação no Footer**: O mesmo padrão introduzido pela feature 020 para `/politica-de-privacidade` — o link "Sobre" usa `<Link>` do react-router-dom enquanto os links com `#` permanecem como `<a>`.
---
### `App.tsx` (alterado)
Nova rota pública adicionada ao bloco existente:
```typescript
// Bloco atual (público)
<Route path="/" element={<HomePage />} />
<Route path="/imoveis" element={<PropertiesPage />} />
<Route path="/imoveis/:slug" element={<PropertyDetailPage />} />
<Route path="/corretores" element={<AgentsPage />} />
<Route path="/politica-de-privacidade" element={<PrivacyPolicyPage />} />
// Nova rota (esta feature)
<Route path="/sobre" element={<AboutPage />} />
```
---
## Conteúdo estático (dados hardcoded em `AboutPage.tsx`)
### Diferenciais (3 cards)
| Campo | Valor |
|-------|-------|
| [1] icon | `🏆` |
| [1] title | `Experiência comprovada` |
| [1] description | Mais de 10 anos conectando famílias aos melhores imóveis da região, com histórico de negociações bem-sucedidas. |
| [2] icon | `🤝` |
| [2] title | `Atendimento personalizado` |
| [2] description | Cada cliente é único. Nossa equipe ouve suas necessidades e apresenta opções alinhadas ao seu perfil e orçamento. |
| [3] icon | `🔑` |
| [3] title | `Processo transparente` |
| [3] description | Do primeiro contato à entrega das chaves, mantemos você informado em cada etapa da negociação. |
### Números em destaque (4 métricas)
| Campo | Valor |
|-------|-------|
| [1] value | `10+` |
| [1] label | Anos de mercado |
| [2] value | `2.500+` |
| [2] label | Imóveis negociados |
| [3] value | `98%` |
| [3] label | Clientes satisfeitos |
| [4] value | `30+` |
| [4] label | Corretores especializados |
> **Todos os valores são placeholders** a serem confirmados pelo cliente antes do go-live. Substituição é feita diretamente no array local de `AboutPage.tsx`.
---
## Contratos de navegação interna
| Origem | Destino | Mecanismo | Requisito |
|--------|---------|-----------|-----------|
| Footer — link "Sobre" | `/sobre` | `<Link to="/sobre">` | FR-009, FR-012 |
| CTA Final — "Ver imóveis" | `/imoveis` | `<Link to="/imoveis">` | FR-008, FR-012 |
| CTA Final — "Falar com corretor" | `https://wa.me/5500000000000?text=...` | `<a href target="_blank" rel="noopener noreferrer">` | FR-008 |
| Seção Equipe — "Conheça nosso time" | `/corretores` | `<Link to="/corretores">` | FR-007, FR-012 |

View file

@ -0,0 +1,66 @@
# Implementation Plan: Página Sobre
**Branch**: `021-pagina-sobre` | **Date**: 2026-04-17 | **Spec**: [spec.md](./spec.md)
**Input**: Criar página estática `/sobre` com hero, história, diferenciais, métricas, equipe e CTA final.
## Summary
Criar `AboutPage.tsx` — uma página 100% estática com seis seções institucionais — e integrá-la ao roteamento SPA via `App.tsx`. Adicionalmente, atualizar o link "Sobre" no `Footer.tsx` de `#sobre` para `/sobre` (navegação client-side via `<Link>`). Sem backend, sem chamadas a API, sem novo estado global.
## Technical Context
**Language/Version**: TypeScript 5.5 / React 18
**Primary Dependencies**: react-router-dom v6 (já instalado), Tailwind CSS 3.4 (já configurado)
**Storage**: N/A — página 100% estática
**Testing**: N/A — componente puramente estático
**Target Platform**: SPA browser (desktop + mobile, 320 px → 1920 px)
**Project Type**: Web application — frontend SPA
**Performance Goals**: Tempo de renderização equivalente ao das demais páginas estáticas do site
**Constraints**: Layout responsivo sem overflow horizontal; sem chamadas a APIs; WhatsApp placeholder `5500000000000`
**Scale/Scope**: 1 nova page, 2 arquivos editados
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
| Princípio | Status | Observação |
|-----------|--------|------------|
| I. Design-First | ✅ PASS | Todos os tokens do DESIGN.md são aplicados: `bg-canvas`, `bg-panel`, `text-text-primary/secondary/tertiary`, `border-white/[0.06]`, `rounded-2xl`, accent `#5e6ad2`. Nenhum inline style fora do sistema. |
| II. Separation of Concerns | ✅ PASS | Feature 100% frontend. Sem nenhuma chamada ao backend Flask. |
| III. Spec-Driven Development | ✅ PASS | `spec.md` aprovado; ciclo plan → tasks → implement respeitado. |
| IV. Data Integrity | ✅ N/A | Sem dados de API, sem banco de dados. Todo conteúdo é estático. |
| V. Security | ✅ PASS | Página pública, sem segredos, sem autenticação. Link WhatsApp usa `wa.me` com placeholder substituível. |
| VI. Simplicity First | ✅ PASS | 1 componente de page, sem abstração extra, sem helpers, sem contexto novo. |
**Resultado**: Sem violações. Pode prosseguir para Phase 0.
## Project Structure
### Documentation (this feature)
```text
specs/021-pagina-sobre/
├── plan.md # Este arquivo
├── research.md # Phase 0 output
├── data-model.md # Phase 1 output
├── quickstart.md # Phase 1 output
└── tasks.md # Phase 2 output (/speckit.tasks — NÃO gerado aqui)
```
### Source Code (repository root)
```text
frontend/
└── src/
├── pages/
│ └── AboutPage.tsx ← NOVO
├── App.tsx ← EDITADO (nova rota /sobre)
└── components/
└── Footer.tsx ← EDITADO (href #sobre → /sobre via <Link>)
```
**Structure Decision**: Web application — apenas camada frontend. Sem novos serviços, hooks, contextos ou tipos compartilhados. `AboutPage.tsx` segue exatamente o padrão de `PrivacyPolicyPage.tsx`.
## Complexity Tracking
*Nenhuma violação de Constitution detectada. Seção omitida conforme orientação do template.*

View file

@ -0,0 +1,98 @@
# Quickstart: Página Sobre
**Feature**: 021-pagina-sobre
**Branch**: `master` (branch recomendada para esta feature: `feat/021-pagina-sobre`)
---
## Pré-requisitos
- Node.js instalado
- Dependências do frontend instaladas: `cd frontend && npm install`
- Docker não é necessário — feature 100% estática, sem backend
---
## Arquivos envolvidos
| Ação | Arquivo |
|------|---------|
| **Criar** | `frontend/src/pages/AboutPage.tsx` |
| **Modificar** | `frontend/src/App.tsx` (1 import + 1 `<Route>`) |
| **Modificar** | `frontend/src/components/Footer.tsx` (link `#sobre``<Link to="/sobre">`) |
---
## Como rodar o frontend em dev
```powershell
cd frontend
npm run dev
```
Acesse `http://localhost:5173/sobre` para ver a nova página.
---
## Passo a passo de implementação
### Passo 1 — Criar `AboutPage.tsx`
Criar o arquivo `frontend/src/pages/AboutPage.tsx` seguindo o padrão de `PrivacyPolicyPage.tsx`:
- Sem props, sem estado, sem hooks
- Estrutura: `<Navbar />` + `<main>` com 6 seções + `<Footer />`
- Importar `Link` de `react-router-dom` para CTAs internos
- Usar tokens do DESIGN.md (ver `data-model.md` — seção "Design tokens")
Seções que usam `.map()` sobre array local:
- **Diferenciais**: array `diferenciais: DiferencialItem[]` com 3 itens
- **Números**: array `numeros: MetricItem[]` com 4 itens
Seções implementadas como JSX direto:
- Hero, Nossa História, Nossa Equipe, CTA Final
### Passo 2 — Registrar rota em `App.tsx`
```diff
import AgentsPage from './pages/AgentsPage';
import PrivacyPolicyPage from './pages/PrivacyPolicyPage';
+import AboutPage from './pages/AboutPage';
// ...
<Route path="/politica-de-privacidade" element={<PrivacyPolicyPage />} />
+<Route path="/sobre" element={<AboutPage />} />
```
### Passo 3 — Atualizar Footer
Em `Footer.tsx`, converter o link "Sobre" de `<a href="#sobre">` para `<Link to="/sobre">`.
Garantir que `Link` está importado de `react-router-dom` (provavelmente já está após feature 020).
---
## Checklist de validação manual
Após implementar, verificar:
- [ ] `http://localhost:5173/sobre` carrega sem erros de console
- [ ] As 6 seções são visíveis (Hero, História, Diferenciais, Números, Equipe, CTA)
- [ ] Navbar e Footer são exibidos corretamente
- [ ] Link "Sobre" no Footer navega para `/sobre` sem recarregar a página
- [ ] Botão "Ver imóveis disponíveis" navega para `/imoveis`
- [ ] Link "Conheça nosso time" navega para `/corretores`
- [ ] Link WhatsApp abre `wa.me` (verificar URL em inspeção de elemento)
- [ ] Layout responsivo funciona em 375 px (mobile) e 1280 px (desktop)
- [ ] Estilo visual consistente com `PrivacyPolicyPage` e demais páginas
---
## Critérios de aceite (mapeados da spec)
| Critério | Como verificar |
|----------|---------------|
| SC-001: `/sobre` acessível sem auth | Abrir em aba anônima |
| SC-002: Responsivo 3201920 px | DevTools → breakpoints 320, 375, 768, 1280, 1920 |
| SC-003: Footer "Sobre" → `/sobre` | Clicar no link e confirmar URL sem reload |
| SC-004: CTAs corretos | Clicar em cada um e verificar destino |
| SC-005: Sem erros de console | Console limpo após carregamento |
| SC-006: Performance equivalente | Primeira renderização comparável a `/politica-de-privacidade` |

View file

@ -0,0 +1,102 @@
# Research: Página Sobre
**Feature**: 021-pagina-sobre
**Phase**: 0 — Outline & Research
**Status**: Completo — sem NEEDS CLARIFICATION
---
## 1. Padrão de página estática no projeto
**Decision**: Seguir exatamente o padrão de `PrivacyPolicyPage.tsx``<Navbar />` + `<main id="main-content" className="min-h-screen bg-canvas">` + `<Footer />`, com conteúdo dentro de `max-w-[800px] mx-auto px-6`.
**Rationale**: `PrivacyPolicyPage.tsx` foi a página estática mais recente criada no projeto e já foi validada visualmente. É a referência canônica para páginas sem estado. A Página Sobre tem natureza idêntica: conteúdo textual organizado em seções, sem API calls.
**Alternatives considered**: Usar `AgentsPage.tsx` como template. Rejeitado — AgentsPage tem estado (`useState`, `useEffect`, skeleton loaders) que não se aplica a conteúdo estático. Usá-la como base adicionaria código morto desnecessário.
---
## 2. Roteamento — nova rota `/sobre`
**Decision**: Adicionar `<Route path="/sobre" element={<AboutPage />} />` diretamente em `frontend/src/App.tsx`, na mesma camada das rotas públicas existentes (`/`, `/imoveis`, `/corretores`, `/politica-de-privacidade`).
**Rationale**: Padrão já estabelecido para todas as rotas públicas. Sem guards de autenticação necessários — FR-001 exige acesso público irrestrito.
**Alternatives considered**: Rota aninhada num layout público compartilhado. Rejeitado — nenhuma outra rota pública usa layout aninhado; seria over-engineering (Principle VI).
---
## 3. Link "Sobre" no Footer — `<a>` vs `<Link>`
**Decision**: Converter `{ label: 'Sobre', href: '#sobre' }` para usar `<Link to="/sobre">` do `react-router-dom`, de forma análoga ao que foi feito com `/politica-de-privacidade` na feature 020.
**Rationale**: FR-009 e FR-012 exigem navegação SPA sem recarregar a aplicação. `<Link>` do React Router garante transição client-side. O Footer está dentro do `<BrowserRouter>` em App.tsx, portanto `<Link>` funciona sem mudança estrutural adicional. Os demais links `#contato` permanecem como `<a>` (âncoras intra-página, fora de escopo).
**Alternatives considered**: Usar `<a href="/sobre">` — causaria reload completo, violando FR-012 e SC-003.
> **Nota de implementação**: O Footer já usa uma mistura de `<a>` e `<Link>` (introduzida na feature 020 para `/politica-de-privacidade`). Basta adicionar o mesmo padrão para `/sobre`.
---
## 4. Estrutura de seções da AboutPage
**Decision**: Seis seções fixas, implementadas como JSX inline (sem array de seções mapeado, diferente do `PrivacyPolicyPage`):
| # | Nome | Conteúdo principal |
|---|------|--------------------|
| 1 | Hero | Título, subtítulo, parágrafo de missão/valores |
| 2 | Nossa História | Texto narrativo com origem e trajetória |
| 3 | Nossos Diferenciais | 34 cards `border border-white/[0.06] rounded-2xl` |
| 4 | Números em Destaque | 4 métricas em grid (anos, imóveis, satisfação, corretores) |
| 5 | Nossa Equipe | Texto introdutório + CTA `<Link to="/corretores">` |
| 6 | CTA Final | `<Link to="/imoveis">` + `<a href="https://wa.me/5500000000000?text=...">` |
**Rationale**: Seções simples, sem iteração sobre array, sem estado. Para as seções Hero/História/Equipe/CTA, JSX direto é mais legível. Para Diferenciais e Números, um array local mapeado por `.map()` reduz repetição sem criar abstração desnecessária.
**Alternatives considered**: Criar um array de seções tipadas para todas as 6 seções (padrão de PrivacyPolicyPage). Rejeitado — as seções têm layouts muito diferentes entre si; forçar um tipo `Section` genérico exigiria `ReactNode` em tudo, que é menos legível.
---
## 5. Design tokens para as seções
**Decision**: Seguir exatamente os tokens do DESIGN.md mapeados no Tailwind:
| Elemento | Classe Tailwind |
|---|---|
| Fundo da página | `bg-canvas` |
| Cards de diferenciais | `bg-panel border border-white/[0.06] rounded-2xl p-6` |
| Métricas em destaque | `bg-panel border border-white/[0.06] rounded-2xl` |
| Texto principal | `text-text-primary` |
| Texto secundário | `text-text-secondary` |
| Texto terciário | `text-text-tertiary` |
| Label de categoria ("Sobre nós", etc.) | `text-[#5e6ad2] text-sm font-medium tracking-widest uppercase` |
| Títulos de seção | `font-semibold text-text-primary tracking-tight` + `style={{ fontFeatureSettings: '"cv01","ss03"' }}` |
| CTA primário (Ver imóveis) | `bg-[#5e6ad2] hover:bg-[#6872e5] text-white rounded-lg px-5 py-2.5` |
| CTA secundário (WhatsApp) | `border border-white/[0.08] text-text-secondary hover:text-text-primary rounded-lg px-5 py-2.5` |
| Largura máxima | `max-w-[1200px] mx-auto px-6` |
**Rationale**: Alinhamento com Principle I (Design-First). Sem novos tokens; apenas os já existentes no `tailwind.config.ts`.
---
## 6. Link de WhatsApp
**Decision**: `https://wa.me/5500000000000?text=Ol%C3%A1%2C%20gostaria%20de%20falar%20com%20um%20corretor`
- Número placeholder: `5500000000000` (substituir antes do go-live)
- `wa.me` abre WhatsApp nativo no mobile e web no desktop, satisfazendo US-2 AC-3
- URL encoding da mensagem pré-preenchida
**Rationale**: Spec/Assumptions confirma uso de placeholder. Nenhum segredo ou token real envolvido.
---
## 7. Navegação interna (CTAs)
**Decision**: Usar `<Link to="...">` do `react-router-dom` para `/imoveis` e `/corretores`.
**Rationale**: FR-012 exige SPA navigation sem reload. Ambas as rotas já existem e estão funcionais (FR prevê `/corretores` como existente).
---
*Todos os NEEDS CLARIFICATION resolvidos. Sem dependências externas. Pode prosseguir para Phase 1.*

View file

@ -0,0 +1,101 @@
# Feature Specification: Página Sobre
**Feature Branch**: `021-pagina-sobre`
**Created**: 2026-04-17
**Status**: Draft
**Input**: Criar uma página estática /sobre com informações da empresa, incluindo hero, história, diferenciais, métricas, referência ao time e CTA final.
## User Scenarios & Testing *(mandatory)*
### User Story 1 — Visitante conhece a empresa na página Sobre (Priority: P1)
Um visitante do portal imobiliário deseja saber mais sobre a empresa antes de entrar em contato ou buscar imóveis. Ele acessa "/sobre" diretamente pela URL, pelo link no footer ou por qualquer chamada para ação do site, e navega pelas seções que descrevem a história, diferenciais e números da empresa.
**Why this priority**: É o fluxo principal da feature. Sem ele a página não entrega valor algum. Todo o restante depende de a página ser acessível e exibir seu conteúdo.
**Independent Test**: Pode ser testado acessando "/sobre" e verificando que as seis seções são renderizadas com conteúdo visível em dispositivos móveis e desktop.
**Acceptance Scenarios**:
1. **Given** o visitante está em qualquer página do site, **When** ele acessa a URL "/sobre", **Then** a página é exibida com navbar, todas as seis seções conteúdo e footer, sem erros visíveis.
2. **Given** o visitante está na página inicial ou em outra página qualquer, **When** ele clica no link "Sobre" no footer, **Then** é redirecionado para "/sobre" (navegação interna, sem recarregar a aplicação).
3. **Given** o visitante está na página "/sobre" em um dispositivo móvel, **When** ele rola a página, **Then** todas as seções são legíveis e os elementos se reorganizam adequadamente para telas pequenas.
---
### User Story 2 — Visitante usa o CTA final para iniciar contato ou buscar imóveis (Priority: P2)
Após ler sobre a empresa, o visitante quer dar o próximo passo: buscar imóveis disponíveis ou entrar em contato diretamente com a equipe via WhatsApp.
**Why this priority**: Os CTAs são o principal canal de conversão da página; sem eles a página seria informativa mas não geraria ação.
**Independent Test**: Pode ser testado clicando nos botões da seção CTA final e verificando que levam aos destinos corretos ("/imoveis" e WhatsApp).
**Acceptance Scenarios**:
1. **Given** o visitante leu o conteúdo e chegou ao CTA final, **When** ele clica em "Ver imóveis disponíveis" (ou equivalente), **Then** é redirecionado para "/imoveis".
2. **Given** o visitante prefere falar com um corretor, **When** ele clica no link de contato por WhatsApp no CTA final, **Then** o aplicativo ou web do WhatsApp é aberto com uma mensagem pré-preenchida direcionada à imobiliária.
3. **Given** o CTA de WhatsApp é exibido, **When** o visitante acessa pelo celular, **Then** o link abre o WhatsApp nativo (não o web).
---
### User Story 3 — Visitante descobre a equipe e navega para a listagem de corretores (Priority: P3)
O visitante quer conhecer a equipe da imobiliária. A seção "Nossa Equipe" na página Sobre apresenta uma chamada para ação que leva para "/corretores".
**Why this priority**: Complementa a apresentação institucional, mas o valor principal da feature já é entregue pelas histórias P1 e P2.
**Independent Test**: Pode ser testado clicando no CTA da seção "Nossa Equipe" e verificando que o visitante é levado para "/corretores".
**Acceptance Scenarios**:
1. **Given** o visitante está na seção "Nossa Equipe" da página "/sobre", **When** ele clica no botão/link "Conheça nosso time" (ou equivalente), **Then** é redirecionado para "/corretores".
2. **Given** a seção "Nossa Equipe" é exibida, **When** o visitante a visualiza, **Then** vê um texto introdutório sobre a equipe e o CTA claramente identificável.
---
### Edge Cases
- O que acontece se o visitante acessar "/sobre" sem conexão com a internet após o carregamento inicial? A página deve exibir o conteúdo estático já renderizado (sem dependência de chamadas externas).
- O que acontece se o número de WhatsApp configurado estiver incorreto? O link abrirá o WhatsApp, mas direcionará para um número inválido — isso é um problema de conteúdo, não de comportamento da feature.
- O que acontece se o visitante acessar a página em um navegador muito antigo sem suporte a CSS moderno? A página deve manter legibilidade mínima; estilos avançados podem degradar graciosamente.
- Como a página se comporta com zoom de acessibilidade acima de 200%? O layout responsivo deve garantir que o conteúdo não transborde horizontalmente.
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: A página "/sobre" DEVE ser acessível para todos os visitantes sem necessidade de autenticação.
- **FR-002**: A página DEVE exibir a barra de navegação (navbar) e o rodapé (footer) presentes nas demais páginas do site.
- **FR-003**: A página DEVE conter uma seção Hero com título da empresa, subtítulo e parágrafo de apresentação (missão, história breve e valores).
- **FR-004**: A página DEVE conter uma seção "Nossa História" com texto narrativo descrevendo a origem, trajetória e conquistas da empresa.
- **FR-005**: A página DEVE conter uma seção "Nossos Diferenciais" com 3 a 4 cards, cada um com título e descrição de um diferencial competitivo.
- **FR-006**: A página DEVE conter uma seção "Números em Destaque" com pelo menos 4 métricas estáticas representativas da empresa (ex.: anos de mercado, imóveis negociados, satisfação de clientes, número de corretores).
- **FR-007**: A página DEVE conter uma seção "Nossa Equipe" com texto introdutório sobre a equipe e um CTA que navega para "/corretores".
- **FR-008**: A página DEVE conter uma seção CTA Final com chamada para ação "Pronto para encontrar seu imóvel?" (ou equivalente), um botão que navega para "/imoveis" e um link que abre o WhatsApp para contato.
- **FR-009**: O link "Sobre" no footer DEVE navegar para "/sobre" (não mais para "#sobre").
- **FR-010**: Todo o conteúdo da página DEVE ser estático — sem chamadas a APIs ou serviços externos durante a renderização.
- **FR-011**: A página DEVE ser responsiva, adaptando layout e tipografia para dispositivos móveis (a partir de 320 px de largura) e desktop.
- **FR-012**: A navegação interna (links para "/imoveis" e "/corretores") DEVE funcionar como navegação de página única (SPA), sem recarregar a aplicação.
- **FR-013**: A página DEVE ser visualmente consistente com o tema e identidade visual das demais páginas do site.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: 100% dos visitantes conseguem acessar "/sobre" sem autenticação e visualizar todas as seis seções de conteúdo.
- **SC-002**: A página é exibida corretamente em dispositivos com largura de tela entre 320 px e 1920 px, sem transbordamento horizontal ou conteúdo cortado.
- **SC-003**: O link "Sobre" no footer navega para "/sobre" em 100% dos cenários testados (navegação interna sem recarga de página).
- **SC-004**: Todos os CTAs da página (botão para "/imoveis", link para "/corretores" e link de WhatsApp) levam ao destino correto em 100% dos cliques.
- **SC-005**: A página carrega sem erros de console relacionados à feature e sem conteúdo quebrado visível.
- **SC-006**: O tempo percebido pelo visitante para visualizar o conteúdo principal (acima da dobra) é equivalente ao das demais páginas estáticas do site.
## Assumptions
- O conteúdo textual (história da empresa, diferenciais, métricas e descrição da equipe) será preenchido com dados representativos de uma imobiliária; o conteúdo definitivo será definido pelo cliente.
- O número de telefone do WhatsApp será um placeholder (`5500000000000`) a ser substituído pelo número real antes do lançamento em produção.
- A página "/corretores" já existe e está funcional, portanto o CTA da seção "Nossa Equipe" pode referenciar essa rota sem risco de link quebrado.
- A navbar utilizada nas demais páginas já suporta a inclusão de novos itens ou a página "/sobre" será adicionada a ela conforme o padrão existente.
- Não há requisito de internacionalização; o idioma da página é exclusivamente português brasileiro.
- Não são necessários recursos de acessibilidade além do que já é padrão no restante do site (texto alternativo em imagens, contraste adequado).
- As métricas exibidas na seção "Números em Destaque" são valores de marketing estáticos e não refletem dados em tempo real do sistema.

View file

@ -0,0 +1,192 @@
# Tasks: Página Sobre
**Input**: Design documents from `/specs/021-pagina-sobre/`
**Prerequisites**: plan.md ✅, spec.md ✅, research.md ✅, data-model.md ✅, quickstart.md ✅
**Tests**: Não solicitados — feature 100% estática sem lógica testável via testes unitários.
**Organização**: Tarefas agrupadas por user story para permitir implementação e validação independente.
## Format: `[ID] [P?] [Story] Descrição`
- **[P]**: Pode rodar em paralelo (arquivos diferentes, sem dependências entre si)
- **[Story]**: User story correspondente (US1, US2, US3)
- Caminhos de arquivo relativos à raiz do repositório
---
## Phase 1: Setup
**Propósito**: Verificação do ambiente. Feature sem dependências novas — tudo já está instalado.
- [ ] T001 Confirmar que `react-router-dom` v6 está listado em `frontend/package.json` e que `tailwind.config.ts` define os tokens `bg-canvas`, `bg-panel`, `text-text-primary`, `text-text-secondary` e `text-text-tertiary`
**Checkpoint**: Ambiente pronto — nenhuma instalação necessária.
---
## Phase 2: Foundational (Pré-requisitos Bloqueantes)
**Propósito**: Garantir que os arquivos de referência foram lidos antes de qualquer implementação.
**⚠️ CRÍTICO**: Leia os arquivos de referência abaixo antes de iniciar qualquer tarefa das fases seguintes.
- [ ] T002 Ler `frontend/src/pages/PrivacyPolicyPage.tsx` para entender o padrão de página estática adotado no projeto (estrutura `<Navbar />` + `<main>` + `<Footer />`)
- [ ] T003 [P] Ler `frontend/src/App.tsx` para identificar onde inserir a nova rota `/sobre` e qual import seguir como padrão
- [ ] T003 [P] Ler `frontend/src/components/Footer.tsx` para entender como o link "Sobre" está implementado atualmente (`#sobre`) e confirmar que `Link` de `react-router-dom` já está importado (padrão introduzido na feature 020)
**Checkpoint**: Padrões de referência entendidos — implementação pode iniciar.
---
## Phase 3: User Story 1 — Visitante conhece a empresa na página Sobre (Priority: P1) 🎯 MVP
**Goal**: A rota `/sobre` é acessível publicamente, exibe as seis seções institucionais (Hero, História, Diferenciais, Números, Equipe, CTA Final) com Navbar e Footer, e o link "Sobre" no Footer navega para `/sobre` sem recarregar a aplicação.
**Independent Test**: Acessar `http://localhost:5173/sobre` e verificar que as seis seções são renderizadas com conteúdo visível em mobile (320 px) e desktop (1280 px), sem erros de console.
### Implementação da User Story 1
- [ ] T004 [US1] Criar `frontend/src/pages/AboutPage.tsx` — componente sem props e sem estado seguindo o padrão de `PrivacyPolicyPage.tsx`:
- Importar `Link` de `react-router-dom`, `Navbar` e `Footer`
- Estrutura raiz: `<Navbar />` + `<main id="main-content" className="min-h-screen bg-canvas">` + `<Footer />`
- Largura máxima do conteúdo: `max-w-[1200px] mx-auto px-6`
- Definir tipos locais (não exportados): `DiferencialItem { icon, title, description }` e `MetricItem { value, label }`
- **Seção Hero** (JSX direto): label `text-[#5e6ad2] text-sm font-medium tracking-widest uppercase` + título da empresa `font-semibold text-text-primary tracking-tight` + subtítulo `text-text-secondary` + parágrafo de missão/valores `text-text-tertiary`
- **Seção Nossa História** (JSX direto): título de seção + 23 parágrafos narrativos `text-text-secondary`
- **Seção Nossos Diferenciais** (`.map()` sobre array `diferenciais: DiferencialItem[]` com 3 itens): grid de cards `bg-panel border border-white/[0.06] rounded-2xl p-6`, cada card com ícone (emoji UTF-8), título `text-text-primary font-semibold` e descrição `text-text-secondary`
- **Seção Números em Destaque** (`.map()` sobre array `numeros: MetricItem[]` com 4 itens — anos de mercado, imóveis negociados, satisfação de clientes, número de corretores): grid de cards `bg-panel border border-white/[0.06] rounded-2xl`, cada card com valor `text-[#5e6ad2] font-bold text-3xl` e label `text-text-secondary text-sm`
- **Seção Nossa Equipe** (JSX direto): título de seção + texto introdutório + `<Link to="/corretores">` "Conheça nosso time"
- **Seção CTA Final** (JSX direto): título "Pronto para encontrar seu imóvel?" + `<Link to="/imoveis">` com classe `bg-[#5e6ad2] hover:bg-[#6872e5] text-white rounded-lg px-5 py-2.5` + `<a href="https://wa.me/5500000000000?text=Olá!%20Gostaria%20de%20saber%20mais%20sobre%20os%20imóveis%20disponíveis." target="_blank" rel="noopener noreferrer">` com classe `border border-white/[0.08] text-text-secondary hover:text-text-primary rounded-lg px-5 py-2.5`
- [ ] T005 [US1] Editar `frontend/src/App.tsx` — adicionar import e rota para `AboutPage`:
- Adicionar `import AboutPage from './pages/AboutPage';` junto aos demais imports de páginas (após `PrivacyPolicyPage` seguindo ordem alfabética/cronológica)
- Adicionar `<Route path="/sobre" element={<AboutPage />} />` na mesma camada das rotas públicas, após `<Route path="/politica-de-privacidade" element={<PrivacyPolicyPage />} />`
- [ ] T006 [US1] Editar `frontend/src/components/Footer.tsx` — converter link "Sobre" de âncora para navegação SPA:
- Localizar o item `{ label: 'Sobre', href: '#sobre' }` (ou equivalente)
- Substituir por `<Link to="/sobre">Sobre</Link>` seguindo o mesmo padrão do link `/politica-de-privacidade` introduzido na feature 020
- Garantir que `Link` de `react-router-dom` já está importado (não duplicar import)
**Checkpoint**: User Story 1 completa — `http://localhost:5173/sobre` exibe as seis seções, Navbar e Footer; link "Sobre" no Footer navega sem recarregar a página.
---
## Phase 4: User Story 2 — Visitante usa o CTA final para iniciar contato ou buscar imóveis (Priority: P2)
**Goal**: O botão "Ver imóveis disponíveis" navega para `/imoveis` e o link de WhatsApp abre o app com mensagem pré-preenchida.
**Independent Test**: Na página `/sobre`, clicar em "Ver imóveis disponíveis" e confirmar navegação para `/imoveis`; clicar no link de WhatsApp e confirmar abertura do app/web com mensagem pré-preenchida.
> **Nota**: Os CTAs de US2 são implementados dentro de `AboutPage.tsx` na tarefa T004 (Seção CTA Final). Esta fase consiste apenas em validar o comportamento.
### Validação da User Story 2
- [ ] T007 [US2] Validar na `AboutPage.tsx` (já criada em T004) se os dois CTAs da seção final estão corretos:
- `<Link to="/imoveis">` usa classe primária `bg-[#5e6ad2] hover:bg-[#6872e5] text-white rounded-lg px-5 py-2.5`
- `<a href="https://wa.me/5500000000000?text=...">` tem atributos `target="_blank"` e `rel="noopener noreferrer"` (requisito de segurança — evita `window.opener` exploit)
- Em mobile, confirmar que o link `wa.me` abre o WhatsApp nativo (comportamento padrão do protocolo)
**Checkpoint**: US1 e US2 funcionais — navegação e CTAs de conversão operantes.
---
## Phase 5: User Story 3 — Visitante descobre a equipe e navega para listagem de corretores (Priority: P3)
**Goal**: A seção "Nossa Equipe" exibe texto introdutório e um CTA `<Link to="/corretores">` funcional.
**Independent Test**: Na página `/sobre`, clicar em "Conheça nosso time" (ou equivalente) e confirmar navegação SPA para `/corretores`.
> **Nota**: O CTA de US3 é implementado dentro de `AboutPage.tsx` na tarefa T004 (Seção Nossa Equipe). Esta fase consiste apenas em validar o comportamento.
### Validação da User Story 3
- [ ] T008 [US3] Validar na `AboutPage.tsx` (já criada em T004) se a seção "Nossa Equipe" está correta:
- `<Link to="/corretores">` presente e com texto identificável (ex.: "Conheça nosso time")
- Texto introdutório sobre a equipe visível acima do CTA
**Checkpoint**: Todas as três user stories funcionais e independentemente testáveis.
---
## Phase 6: Polish & Validação Final
**Propósito**: Verificação de responsividade, consistência visual e ausência de erros.
- [ ] T009 [P] Executar checklist do `quickstart.md` em `http://localhost:5173/sobre`: verificar as seis seções visíveis, Navbar/Footer presentes, ausência de erros de console, link "Sobre" no Footer navegando sem reload
- [ ] T010 [P] Validar responsividade em viewport mobile (320 px e 375 px) e desktop (1280 px e 1920 px) — garantir que nenhum elemento transborda horizontalmente (`overflow-x` ausente)
- [ ] T011 Revisar se todos os tokens Tailwind usados (`bg-canvas`, `bg-panel`, `text-text-primary`, `text-text-secondary`, `text-text-tertiary`, `border-white/[0.06]`, `border-white/[0.08]`) estão definidos em `frontend/tailwind.config.ts` e não foram usados valores inline fora do sistema de design
---
## Dependencies & Execution Order
### Dependências entre Fases
- **Phase 1 (Setup)**: Sem dependências — iniciar imediatamente
- **Phase 2 (Foundational)**: Depende do Phase 1 — BLOQUEIA todas as user stories
- **Phase 3 (US1)**: Depende do Phase 2 — MVP entregável ao final desta fase
- **Phase 4 (US2)**: Depende do Phase 3 (T004 deve estar completo)
- **Phase 5 (US3)**: Depende do Phase 3 (T004 deve estar completo)
- **Phase 6 (Polish)**: Depende de todas as fases anteriores
### Dependências entre User Stories
- **US1 (P1)**: Independente — inicia após Phase 2
- **US2 (P2)**: Depende de US1 (T004 cria os CTAs validados em T007)
- **US3 (P3)**: Depende de US1 (T004 cria o CTA validado em T008)
### Dentro de cada User Story (Phase 3)
- T004 → T005 → T006 (sequencial: página criada → rota registrada → footer atualizado)
- T005 e T006 podem ser feitos em paralelo após T004
### Paralelo dentro da Phase 3
```
Após T004 (AboutPage.tsx criado):
[P] T005 — editar App.tsx (rota)
[P] T006 — editar Footer.tsx (link)
```
---
## Parallel Example: User Story 1
```
# T004 deve estar completo antes de T005 e T006
# T005 e T006 podem ser executados em paralelo:
Task T005: "Editar frontend/src/App.tsx — adicionar import e rota /sobre"
Task T006: "Editar frontend/src/components/Footer.tsx — converter link #sobre para /sobre"
```
---
## Implementation Strategy
### MVP First (User Story 1 Only)
1. Completar Phase 1: Setup (verificação rápida)
2. Completar Phase 2: Foundational (leitura dos arquivos de referência)
3. Completar Phase 3: User Story 1 (T004 → T005 + T006)
4. **PARAR E VALIDAR**: Acessar `http://localhost:5173/sobre` e confirmar as seis seções
5. Deploy se validado
### Entrega Incremental
1. Setup + Foundational → Referências entendidas
2. US1 completa → Página acessível, todas as seções visíveis, Footer atualizado → **MVP!**
3. US2 validada → CTAs de conversão verificados
4. US3 validada → CTA da equipe verificado
5. Polish → Responsividade e consistência visual confirmadas
### Estratégia para Desenvolvedor Único
Com um único desenvolvedor (cenário desta feature):
1. Phase 1 + Phase 2: leitura e setup (~10 min)
2. T004: criar `AboutPage.tsx` com todas as 6 seções (~3045 min)
3. T005 + T006 em paralelo: editar `App.tsx` e `Footer.tsx` (~5 min cada)
4. T007 + T008: validação dos CTAs (~10 min)
5. T009T011 (Polish): checklist e responsividade (~15 min)