feat: add full project - backend, frontend, docker, specs and configs
This commit is contained in:
parent
b77c7d5a01
commit
e6cb06255b
24489 changed files with 61341 additions and 36 deletions
36
specs/021-pagina-sobre/checklists/requirements.md
Normal file
36
specs/021-pagina-sobre/checklists/requirements.md
Normal 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`.
|
||||
150
specs/021-pagina-sobre/data-model.md
Normal file
150
specs/021-pagina-sobre/data-model.md
Normal 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 (2–3 parágrafos)
|
||||
│ ├── SectionDiferenciais
|
||||
│ │ └── grid de 3–4 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 |
|
||||
66
specs/021-pagina-sobre/plan.md
Normal file
66
specs/021-pagina-sobre/plan.md
Normal 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.*
|
||||
98
specs/021-pagina-sobre/quickstart.md
Normal file
98
specs/021-pagina-sobre/quickstart.md
Normal 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 320–1920 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` |
|
||||
102
specs/021-pagina-sobre/research.md
Normal file
102
specs/021-pagina-sobre/research.md
Normal 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 | 3–4 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.*
|
||||
101
specs/021-pagina-sobre/spec.md
Normal file
101
specs/021-pagina-sobre/spec.md
Normal 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.
|
||||
192
specs/021-pagina-sobre/tasks.md
Normal file
192
specs/021-pagina-sobre/tasks.md
Normal 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 + 2–3 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 (~30–45 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. T009–T011 (Polish): checklist e responsividade (~15 min)
|
||||
Loading…
Add table
Add a link
Reference in a new issue