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: Política de Privacidade + Link no Footer
**Purpose**: Validar completude e qualidade da especificação antes de avançar para o planejamento
**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 passaram na validação inicial.
- Placeholders para nome/CNPJ/endereço da empresa e e-mail do DPO estão documentados nas Assumptions — devem ser preenchidos antes da implementação.
- Pronto para `/speckit.plan`.

View file

@ -0,0 +1,163 @@
# Data Model: Página de Política de Privacidade
**Feature**: 020-politica-de-privacidade
**Phase**: 1 — Design & Contracts
**Status**: Complete
---
## 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" aqui descreve a estrutura lógica do conteúdo estático e o contrato de componentes React.
---
## Entidades de Componente
### PrivacyPolicyPage
| Propriedade | Tipo | Descrição |
|---|---|---|
| — | — | Componente sem props (stateless, sem hooks) |
**Estrutura JSX**:
```
PrivacyPolicyPage
├── <Navbar />
├── <main id="main-content" className="min-h-screen bg-canvas">
│ └── <div className="max-w-[800px] mx-auto px-6 pt-16 pb-20">
│ ├── Header (label + título + data de atualização)
│ └── Seções (18)
│ └── <section> com <h2> numerado + <p>/<ul> de conteúdo
└── <Footer />
```
**Seções (hardcoded)**:
```typescript
type PolicySection = {
id: number // 18
title: string // "1. Instituição Responsável" etc.
content: ReactNode // JSX com paragrafos / listas
}
```
*Observação*: O tipo `PolicySection` NÃO precisa ser exportado nem criado como shared type — é usado somente internamente no componente. Principle VI: sem abstração prematura.
---
### Footer (atualizado)
Mudança pontual: adicionar `<Link to="/politica-de-privacidade">` no bloco `<nav>` existente.
**Estado atual do array `footerLinks`**:
```typescript
const footerLinks = [
{ label: 'Imóveis', href: '/imoveis' },
{ label: 'Sobre', href: '#sobre' },
{ label: 'Contato', href: '#contato' },
]
```
**Após a mudança** — o array `footerLinks` **não é alterado**. Um novo link `<Link>` do react-router-dom é adicionado manualmente no `<ul>` após os links existentes:
```tsx
import { Link } from 'react-router-dom'
// no <ul> dos footerLinks, após o map existente:
<li>
<Link
to="/politica-de-privacidade"
className="text-xs text-text-tertiary hover:text-text-secondary transition-colors duration-150"
>
Política de Privacidade
</Link>
</li>
```
**Rationale**: Adicionar ao array seria inconsistente (o array usa `href` para `<a>`, mas esse precisa de `<Link>`). Manter separado é mais claro e não requer refatorar o loop existente.
---
### Rota (App.tsx)
| Campo | Valor |
|---|---|
| `path` | `/politica-de-privacidade` |
| `element` | `<PrivacyPolicyPage />` |
| Posição no arquivo | Após a rota `/corretores`, antes da rota `/login` |
| Guards | Nenhum — rota pública |
---
## Conteúdo estático das seções
### Seção 1 — Instituição Responsável
Nome: `[NOME DA EMPRESA]`
CNPJ: `[CNPJ]`
Endereço: `[ENDEREÇO COMPLETO]`
*Esta empresa é a controladora dos dados pessoais tratados neste site.*
### Seção 2 — Coleta e Uso de Dados Pessoais
Dados coletados:
- Nome completo, e-mail e telefone ao preencher formulários de contato
- Dados de navegação (páginas visitadas, tempo de sessão) via cookies analíticos
- Dados fornecidos voluntariamente ao solicitar visitas a imóveis
Finalidades:
- Responder solicitações de contato e agendamento de visitas
- Melhorar a experiência de uso do site
- Enviar comunicações sobre imóveis compatíveis com o perfil do usuário (com consentimento)
### Seção 3 — Transferência de Dados Pessoais
Compartilhamento com:
- Corretores parceiros, apenas dados necessários para conduzir visitas
- Plataformas de análise de tráfego (ex.: Google Analytics) — dados anonimizados
- Não vendemos ou alugamos dados pessoais a terceiros
### Seção 4 — Uso de Cookies
Tipos de cookies utilizados:
- **Essenciais**: necessários para o funcionamento do site (autenticação, preferências)
- **Analíticos**: medem o uso do site para melhoria contínua
- O usuário pode desativar cookies analíticos nas configurações do navegador
### Seção 5 — Direitos do Usuário (LGPD)
Conforme a Lei 13.709/2018 (LGPD), o titular dos dados tem direito a:
- **Acesso**: confirmar a existência e solicitar cópia dos dados tratados
- **Correção**: atualizar dados incompletos, inexatos ou desatualizados
- **Exclusão**: solicitar a eliminação de dados desnecessários ou tratados com consentimento
- **Portabilidade**: receber seus dados em formato estruturado
- **Revogação de consentimento**: retirar o consentimento a qualquer momento
### Seção 6 — Segurança dos Dados
- Utilizamos conexões HTTPS em todo o site
- Dados sensíveis são armazenados com criptografia
- Acesso interno limitado ao pessoal autorizado
- Revisamos regularmente nossas práticas de segurança
### Seção 7 — Alterações nesta Política
Podemos atualizar esta Política periodicamente. A data de "última atualização" é exibida no topo da página. Recomendamos revisão periódica.
### Seção 8 — Contato / DPO
Para exercer seus direitos ou esclarecer dúvidas sobre o tratamento de seus dados:
E-mail do Encarregado (DPO): `[EMAIL DO DPO]`
Link exibido como `<a href="mailto:[EMAIL DO DPO]">` abrindo cliente de e-mail.
---
## Validações e regras de estado
| Regra | Implementação |
|---|---|
| Sem chamadas de API | Componente não usa `useEffect`, `useState`, nem imports de `services/` |
| Sem estado de loading | Nenhum skeleton, spinner ou estado condicional |
| Links externos abrem em nova aba | `target="_blank" rel="noopener noreferrer"` no link do e-mail DPO |

View file

@ -0,0 +1,95 @@
# Implementation Plan: Página de Política de Privacidade + Link no Footer
**Branch**: `master` | **Date**: 2026-04-17 | **Spec**: [specs/020-politica-de-privacidade/spec.md](spec.md)
**Input**: Feature specification from `specs/020-politica-de-privacidade/spec.md`
## Summary
Criar a página estática `/politica-de-privacidade` com 8 seções LGPD e adicioná-la ao sistema de roteamento SPA. Adicionar link client-side (`<Link>`) no Footer existente. Feature 100% frontend — sem backend, sem API, sem estado.
## 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 — componente puramente estático
**Testing**: `npm run build` (TypeScript type-check via tsc); verificação visual manual
**Target Platform**: Browser (SPA — Vite/React)
**Project Type**: Web application (frontend only)
**Performance Goals**: Navegação client-side < 500 ms (SC-003); sem requisições de rede na carga da página
**Constraints**: Layout max-width 800px; responsivo ≥ 320px sem overflow horizontal; conformidade total com tema dark do DESIGN.md
**Scale/Scope**: 1 componente novo (`PrivacyPolicyPage.tsx`), 2 arquivos modificados (`App.tsx`, `Footer.tsx`)
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
| Princípio | Status | Evidência |
|---|---|---|
| **I. Design-First** | ✅ PASS | Componente usa `bg-canvas`, `text-text-primary`, `text-text-secondary`, `border-white/[0.06]`, `fontFeatureSettings: '"cv01","ss03"'` — tokens idênticos às demais páginas. Max-width 800px, responsivo. Nenhum estilo inline que desvie do design system. |
| **II. Separation of Concerns** | ✅ PASS | Feature 100% frontend. Nenhuma rota Flask nova. Nenhum modelo de dados alterado. |
| **III. Spec-Driven Development** | ✅ PASS | `spec.md` aprovado com user stories e acceptance scenarios. Ordem: spec → plan → tasks → implement. |
| **IV. Data Integrity** | ✅ N/A | Sem entidades de banco. Sem Pydantic schemas. Sem migrations. |
| **V. Security** | ✅ PASS | Rota pública sem guards — correto (política de privacidade é pública). Nenhum token ou secret no frontend. |
| **VI. Simplicity First** | ✅ PASS | Componente stateless. Sem hooks. Sem services. Sem abstrações novas. 3 arquivos alterados/criados. Conteúdo inline no componente. |
**Resultado**: Nenhuma violação. Pode avançar para implementação.
---
## Project Structure
### Documentation (this feature)
```text
specs/020-politica-de-privacidade/
├── plan.md ← este arquivo
├── research.md ← gerado (Phase 0)
├── data-model.md ← gerado (Phase 1)
├── quickstart.md ← gerado (Phase 1)
└── tasks.md ← será gerado pelo /speckit.tasks
```
### Source Code (arquivos desta feature)
```text
frontend/
├── src/
│ ├── pages/
│ │ └── PrivacyPolicyPage.tsx ← CRIAR (novo)
│ ├── components/
│ │ └── Footer.tsx ← MODIFICAR (adicionar Link)
│ └── App.tsx ← MODIFICAR (adicionar rota)
```
**Sem backend envolvido.** Sem migrations, sem novos endpoints, sem schemas Pydantic.
---
## Implementation Approach
### Fase de implementação (executada via /speckit.tasks)
**Task 1 — Criar `PrivacyPolicyPage.tsx`**
Componente stateless com Navbar + main + Footer. Conteúdo estático das 8 seções LGPD inline. Design conforme tokens do DESIGN.md. Ver `data-model.md` para estrutura e conteúdo de cada seção.
**Task 2 — Adicionar rota em `App.tsx`**
Importar `PrivacyPolicyPage` e adicionar `<Route path="/politica-de-privacidade" element={<PrivacyPolicyPage />} />` após a rota `/corretores`.
**Task 3 — Atualizar `Footer.tsx`**
Importar `Link` do react-router-dom. Adicionar `<li><Link to="/politica-de-privacidade" ...>Política de Privacidade</Link></li>` no `<ul>` de navegação, após o map de `footerLinks`.
### Ordem de execução
Tasks 1, 2 e 3 são independentes em si, mas a verificação funcional requer todas completas. Ordem sugerida: 1 → 2 → 3 (criar página primeiro, depois rota, depois link no footer).
---
## Artefatos gerados
| Artefato | Caminho |
|---|---|
| Spec | [specs/020-politica-de-privacidade/spec.md](spec.md) |
| Research | [specs/020-politica-de-privacidade/research.md](research.md) |
| Data Model | [specs/020-politica-de-privacidade/data-model.md](data-model.md) |
| Quickstart | [specs/020-politica-de-privacidade/quickstart.md](quickstart.md) |
| Tasks | `specs/020-politica-de-privacidade/tasks.md` *(gerado por /speckit.tasks)* |

View file

@ -0,0 +1,150 @@
# Quickstart: Página de Política de Privacidade
**Feature**: 020-politica-de-privacidade
**Branch**: `master` (feature branch recomendada: `feat/020-politica-de-privacidade`)
---
## Pré-requisitos
- Node.js instalado
- Dependências do frontend instaladas: `cd frontend && npm install`
- Docker em execução (opcional — apenas se precisar do backend para outras páginas)
---
## Arquivos envolvidos
| Ação | Arquivo |
|---|---|
| **Criar** | `frontend/src/pages/PrivacyPolicyPage.tsx` |
| **Modificar** | `frontend/src/components/Footer.tsx` |
| **Modificar** | `frontend/src/App.tsx` |
---
## Como rodar o frontend em dev
```powershell
cd frontend
npm run dev
```
Acesse `http://localhost:5173/politica-de-privacidade` para verificar a nova página.
---
## Passo a passo de implementação
### 1. Criar `PrivacyPolicyPage.tsx`
```tsx
// frontend/src/pages/PrivacyPolicyPage.tsx
import Footer from '../components/Footer'
import Navbar from '../components/Navbar'
export default function PrivacyPolicyPage() {
return (
<>
<Navbar />
<main id="main-content" className="min-h-screen bg-canvas">
<div className="max-w-[800px] mx-auto px-6 pt-16 pb-20">
{/* Header */}
<p className="text-[#5e6ad2] text-sm font-medium tracking-widest uppercase mb-3">
Legal
</p>
<h1
className="text-3xl md:text-4xl font-semibold text-text-primary tracking-tight mb-2"
style={{ fontFeatureSettings: '"cv01","ss03"' }}
>
Política de Privacidade
</h1>
<p className="text-text-tertiary text-sm mb-12">
Última atualização: abril de 2026
</p>
{/* Seções */}
<div className="space-y-10">
{/* Seção 1 */}
<section>
<h2 className="text-lg font-semibold text-text-primary mb-3"
style={{ fontFeatureSettings: '"cv01","ss03"' }}>
1. Instituição Responsável
</h2>
<p className="text-text-secondary text-sm leading-relaxed">
[NOME DA EMPRESA], inscrita no CNPJ sob o nº [CNPJ], com sede em [ENDEREÇO COMPLETO],
é a controladora dos dados pessoais tratados por meio deste site.
</p>
</section>
{/* Seção 2 */}
<section>
<h2 ...>2. Coleta e Uso de Dados Pessoais</h2>
...
</section>
{/* ... demais seções ... */}
</div>
</div>
</main>
<Footer />
</>
)
}
```
> **Ver data-model.md para o conteúdo completo de cada seção.**
---
### 2. Adicionar rota em `App.tsx`
```tsx
// após import de AgentsPage
import PrivacyPolicyPage from './pages/PrivacyPolicyPage';
// dentro de <Routes>, após a rota /corretores:
<Route path="/politica-de-privacidade" element={<PrivacyPolicyPage />} />
```
---
### 3. Atualizar `Footer.tsx`
```tsx
// Adicionar import no topo:
import { Link } from 'react-router-dom'
// No <ul> dos footerLinks, adicionar após o map existente:
<li>
<Link
to="/politica-de-privacidade"
className="text-xs text-text-tertiary hover:text-text-secondary transition-colors duration-150"
>
Política de Privacidade
</Link>
</li>
```
---
## Verificação de conformidade
| Critério | Como verificar |
|---|---|
| 8 seções presentes | Contar visualmente em `http://localhost:5173/politica-de-privacidade` |
| Link no Footer funciona sem reload | Abrir DevTools > Network, clicar no link — nenhuma requisição de documento nova |
| Sem chamadas de API | DevTools > Network > XHR/Fetch — vazio ao carregar a página |
| Responsivo em 375px | DevTools > Device Toolbar → iPhone SE |
| Tema dark consistente | Comparar com `http://localhost:5173/corretores` — mesmas cores/fontes |
---
## Build de validação
```powershell
cd frontend
npm run build
```
Sem erros de TypeScript = pronto para PR.

View file

@ -0,0 +1,100 @@
# Research: Página de Política de Privacidade
**Feature**: 020-politica-de-privacidade
**Phase**: 0 — Outline & Research
**Status**: Complete — sem NEEDS CLARIFICATION
---
## 1. Padrão de página estática no projeto
**Decision**: Usar o mesmo padrão de `AgentsPage.tsx``<Navbar />` + `<main className="min-h-screen bg-canvas">` + `<Footer />`.
**Rationale**: Todas as páginas públicas do projeto seguem este padrão. `AgentsPage.tsx` é o exemplo mais recente e pode ser usado como referência direta.
**Alternatives considered**: Criar um componente `PublicLayout` com Navbar/Footer embutidos. Rejeitado por violar Principle VI (YAGNI — só 1 page nova, sem reutilização real).
---
## 2. Roteamento client-side
**Decision**: Adicionar `<Route path="/politica-de-privacidade" element={<PrivacyPolicyPage />} />` direto no arquivo `frontend/src/App.tsx`, na mesma camada das rotas públicas (`/`, `/imoveis`, `/corretores`).
**Rationale**: Padrão já usado por todas as rotas públicas. Sem guards de autenticação necessários.
**Alternatives considered**: Rota aninhada num layout público. Rejeitado — nenhuma outra rota pública usa layout aninhado; seria over-engineering.
---
## 3. Link no Footer — `<a>` vs `<Link>`
**Decision**: Usar `<Link to="/politica-de-privacidade">` do `react-router-dom` para o novo link no Footer. Os links existentes (`#sobre`, `#contato`) permanecem como `<a>` (são âncoras intra-página, não rotas SPA). O link `/imoveis` existente também fica como `<a>` para não alterar comportamento legado fora do escopo.
**Rationale**: FR-006 exige navegação sem recarregamento. O `<Link>` do React Router garante transição client-side sem `window.location` reload. O Footer está dentro do `<BrowserRouter>` (App.tsx), então `<Link>` funciona sem nenhuma mudança estrutural.
**Alternatives considered**:
1. Converter todos os links do footer para `<Link>` — fora de escopo, Principle VI proíbe mudanças além do especificado.
2. Usar `<a href="/politica-de-privacidade">` — causaria reload completo da página, violando FR-006 e SC-003.
---
## 4. Design tokens a utilizar
**Decision**: Seguir exatamente as classes Tailwind mapeadas para os tokens do DESIGN.md:
| Elemento | Classe Tailwind |
|---|---|
| Fundo da página | `bg-canvas` |
| Fundo de seção alternada (opcional) | N/A — fundo único para simplicidade |
| Texto principal (título, corpo) | `text-text-primary` |
| Texto secundário | `text-text-secondary` |
| Texto terciário (metadata) | `text-text-tertiary` |
| Separador entre seções | `border-white/[0.06]` |
| Largura máxima do conteúdo | `max-w-[800px] mx-auto px-6` |
| Títulos de seção | `font-semibold text-text-primary` + `fontFeatureSettings: '"cv01","ss03"'` |
| Label de categoria | `text-[#5e6ad2] text-sm font-medium tracking-widest uppercase` |
**Rationale**: Alinhamento com Principle I (Design-First). Tokens já existentes no `tailwind.config.ts`; sem novos tokens necessários.
---
## 5. Estrutura das 8 seções LGPD
**Decision**: Conteúdo estático inline no componente. Sem fonte de dados externa, sem CMS, sem JSON separado.
**Rationale**: Principle VI — a solução mais simples. A política muda raramente; extrair para arquivo JSON seria over-abstraction sem benefício concreto.
**Seções obrigatórias (FR-003)**:
| # | Título | Conteúdo-chave |
|---|---|---|
| 1 | Instituição Responsável | Nome, CNPJ, endereço (placeholders) |
| 2 | Coleta e Uso de Dados Pessoais | Quais dados, finalidade de uso |
| 3 | Transferência de Dados Pessoais | Compartilhamento com terceiros (parceiros, financeiras) |
| 4 | Uso de Cookies | Tipos de cookies, finalidade |
| 5 | Direitos do Usuário | Acesso, correção, exclusão, portabilidade, revogação de consentimento |
| 6 | Segurança dos Dados | Medidas técnicas adotadas |
| 7 | Alterações nesta Política | Versionamento e data de última atualização |
| 8 | Contato / DPO | E-mail do encarregado (placeholder `[EMAIL DO DPO]`) |
---
## 6. Responsividade
**Decision**: `max-w-[800px] mx-auto px-6` para o container do conteúdo. Em mobile, o padding `px-6` garante margens laterais. Sem media queries adicionais — Tailwind + text-base resolve legibilidade.
**Rationale**: SC-004 exige legibilidade a partir de 320px sem overflow horizontal. O container com `px-6` e `max-w-[800px]` atende naturalmente por ser menor que qualquer viewport padrão >375px.
---
## 7. Dependências novas
**Decision**: Nenhuma dependência nova.
**Rationale**: `react-router-dom` já está instalado. Tailwind já configurado. Principle VI — sem pacotes novos sem justificativa.
---
## Resolução de NEEDS CLARIFICATION
Não havia ambiguidades de natureza técnica que exigissem pesquisa externa. Todos os pontos foram resolvidos com base no código existente no projeto.

View file

@ -0,0 +1,120 @@
# Feature Specification: Página de Política de Privacidade + Link no Footer
**Feature Branch**: `020-politica-de-privacidade`
**Created**: 2026-04-17
**Status**: Draft
**Input**: Criar página estática /politica-de-privacidade com conteúdo LGPD adaptado para imobiliária e link no Footer existente.
---
## User Scenarios & Testing *(mandatory)*
### User Story 1 — Visitante lê a Política de Privacidade (Priority: P1)
Um visitante do site deseja conhecer como seus dados pessoais são tratados pela imobiliária. Ele navega até `/politica-de-privacidade` e encontra o documento completo, com todas as seções exigidas pela LGPD, organizado de forma legível.
**Why this priority**: Requisito de conformidade legal (LGPD). Toda empresa que coleta dados pessoais deve disponibilizar a política de privacidade de forma clara e acessível.
**Independent Test**: Pode ser testado acessando diretamente `/politica-de-privacidade` no navegador e verificando que o conteúdo é exibido com todas as 8 seções, Navbar e Footer presentes.
**Acceptance Scenarios**:
1. **Given** o visitante está em qualquer página do site, **When** digita `/politica-de-privacidade` na URL, **Then** a página carrega com título "Política de Privacidade", Navbar, Footer e as 8 seções numeradas.
2. **Given** o visitante está na página de política, **When** a página carrega, **Then** todo o conteúdo é exibido sem chamadas de API, sem estado de carregamento e sem erros.
3. **Given** o visitante lê a página em dispositivo móvel, **When** a página renderiza, **Then** o texto é legível, sem overflow horizontal e com espaçamento adequado.
---
### User Story 2 — Visitante encontra o link da Política no Footer (Priority: P2)
Um visitante está no rodapé do site (Footer) em qualquer página e deseja localizar o link para a Política de Privacidade.
**Why this priority**: O Footer é o local padrão e esperado pelos usuários para links legais. Garantir a descoberta do link é essencial para conformidade e UX.
**Independent Test**: Pode ser testado verificando o componente Footer em qualquer página — o link "Política de Privacidade" deve estar visível e clicar nele deve navegar para `/politica-de-privacidade` sem recarregar a página.
**Acceptance Scenarios**:
1. **Given** o visitante está em qualquer página com Footer, **When** rola até o rodapé, **Then** o link "Política de Privacidade" está visível.
2. **Given** o visitante clica no link "Política de Privacidade" no Footer, **When** o clique é registrado, **Then** o roteamento navega para `/politica-de-privacidade` sem recarregamento completo da página.
3. **Given** o visitante está na página de Política e clica no logo ou em um link de navegação, **When** o clique é registrado, **Then** ele retorna à página anterior normalmente.
---
### User Story 3 — Visitante identifica a empresa responsável e o canal de contato (Priority: P3)
Um visitante que lê a política deseja saber qual empresa é responsável pelo tratamento dos seus dados e como entrar em contato com o encarregado (DPO).
**Why this priority**: A LGPD exige identificação do controlador e disponibilização do canal de comunicação com o DPO. É requisito legal e melhora a confiança do usuário.
**Independent Test**: Pode ser testado verificando que a seção "Instituição Responsável" e a seção "Contato / DPO" contêm nome da empresa, informações de contato e canal para exercício de direitos LGPD.
**Acceptance Scenarios**:
1. **Given** o visitante está na página de Política, **When** lê a seção 1, **Then** encontra o nome, endereço e CNPJ da empresa responsável.
2. **Given** o visitante deseja exercer seus direitos (acesso, correção, exclusão), **When** lê a seção 8, **Then** encontra um endereço de e-mail ou formulário para contato com o DPO.
---
### Edge Cases
- O que acontece se o usuário acessa `/politica-de-privacidade` com JavaScript desabilitado? (SPA — página não renderiza; comportamento aceitável para PWA/SPA)
- O que acontece se o usuário acessar a rota diretamente após um refresh? (deve funcionar normalmente com o roteamento configurado)
- O conteúdo é longo — a rolagem da página deve funcionar normalmente sem quebras de layout.
- Links externos na seção de contato devem abrir em nova aba para não desviar o usuário do site.
---
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: O sistema DEVE exibir a página de Política de Privacidade na rota `/politica-de-privacidade`.
- **FR-002**: A página DEVE incluir o componente Navbar no topo e o componente Footer no rodapé, idênticos aos demais do site.
- **FR-003**: A página DEVE apresentar as seguintes 8 seções numeradas, nesta ordem:
1. Instituição Responsável
2. Coleta e Uso de Dados Pessoais
3. Transferência de Dados Pessoais
4. Uso de Cookies
5. Direitos do Usuário (acesso, correção, exclusão, portabilidade — conforme LGPD)
6. Segurança dos Dados
7. Alterações nesta Política
8. Contato / DPO
- **FR-004**: Cada seção DEVE ter um título com numeração visível (ex.: "1. Instituição Responsável") e conteúdo textual explicativo.
- **FR-005**: O conteúdo da página DEVE ser puramente estático — sem chamadas de API, sem fetchs de dados externos.
- **FR-006**: O Footer DEVE conter um link de texto "Política de Privacidade" que navega para `/politica-de-privacidade` usando roteamento client-side (sem reload da página).
- **FR-007**: O layout do conteúdo principal DEVE ter largura máxima de 800 px e ser centralizado horizontalmente na tela.
- **FR-008**: O design DEVE ser consistente com o tema escuro (dark) existente no site, utilizando as mesmas variáveis de cor e tipografia do restante das páginas.
- **FR-009**: A seção de Direitos do Usuário DEVE mencionar explicitamente: direito de acesso, correção, exclusão, portabilidade e revogação de consentimento, conforme a LGPD.
- **FR-010**: A seção de Contato / DPO DEVE incluir um canal de comunicação (e-mail) para que o usuário exerça seus direitos LGPD.
### Key Entities
- **PrivacyPolicyPage**: Componente de página React, sem estado próprio (stateless), responsável por renderizar o conteúdo da política. Localizado em `frontend/src/pages/PrivacyPolicyPage.tsx`.
- **Footer (atualizado)**: Componente existente que receberá o link adicional para a política de privacidade. Localizado em `frontend/src/components/Footer.tsx`.
- **Rota /politica-de-privacidade**: Entrada no sistema de roteamento client-side que mapeia a URL para `PrivacyPolicyPage`.
---
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: O link "Política de Privacidade" está presente e clicável no Footer em 100% das páginas que incluem o Footer.
- **SC-002**: A página `/politica-de-privacidade` exibe as 8 seções obrigatórias, cada uma com título numerado e conteúdo.
- **SC-003**: A navegação para a página a partir do Footer ocorre em menos de 500 ms (transição client-side, sem recarregamento).
- **SC-004**: O layout é responsivo — legível em telas a partir de 320 px de largura sem overflow horizontal.
- **SC-005**: A conformidade visual é total: as mesmas cores, fontes e espaçamentos do tema dark são aplicados, sem elementos que "quebrem" o padrão visual do site.
- **SC-006**: O conteúdo da seção 5 (Direitos do Usuário) abrange todos os 5 direitos previstos na LGPD mencionados nos requisitos.
---
## Assumptions
- O nome, CNPJ e endereço da empresa imobiliária serão fornecidos para preenchimento do conteúdo da seção 1 (Instituição Responsável); enquanto não fornecidos, placeholders serão utilizados como `[NOME DA EMPRESA]`, `[CNPJ]` e `[ENDEREÇO]`.
- O e-mail do DPO (encarregado de dados) será fornecido para a seção 8; enquanto não fornecido, será usado o placeholder `[EMAIL DO DPO]`.
- O componente Layout que envolve Navbar + Footer já existe e será reutilizado da mesma forma que nas demais páginas.
- Não há necessidade de versionamento do conteúdo da política — a data de "última atualização" será estática no código.
- A página não precisa suportar múltiplos idiomas (apenas português brasileiro).
- Acessibilidade básica (contraste adequado, semântica HTML) é esperada mas não requer certificação WCAG formal nesta versão.
- O conteúdo textual da política sera adequado para uma imobiliária genérica, baseado na LGPD; não é um documento jurídico revisado por advogado.

View file

@ -0,0 +1,132 @@
# Tasks: Página de Política de Privacidade + Link no Footer
**Input**: Design documents from `specs/020-politica-de-privacidade/`
**Prerequisites**: plan.md ✅, spec.md ✅, data-model.md ✅, quickstart.md ✅, research.md ✅
**Tests**: Não solicitados — verificação por `npm run build` e inspeção visual (conforme plan.md).
**Escopo**: 1 arquivo criado, 2 arquivos modificados — 100% frontend, sem backend, sem dependências novas.
## Format: `[ID] [P?] [Story] Description`
- **[P]**: Pode rodar em paralelo (arquivos diferentes, sem dependências entre si)
- **[Story]**: User story a que a task pertence (US1, US2, US3)
- Todos os caminhos são relativos à raiz do repositório
---
## Phase 1: Setup & Foundational
> **Não aplicável** — projeto já inicializado, sem novas dependências, sem infraestrutura nova.
> Pode avançar diretamente para as user stories.
---
## Phase 2: User Story 1 — Visitante lê a Política de Privacidade (Priority: P1) 🎯 MVP
**Goal**: Criar o componente `PrivacyPolicyPage` e registrá-lo no roteador para que a rota `/politica-de-privacidade` funcione.
**Independent Test**: Acessar `http://localhost:5173/politica-de-privacidade` no navegador após `npm run dev`. A página deve renderizar com Navbar, 8 seções numeradas e Footer, sem erros no console e sem chamadas de rede.
- [ ] T001 [P] [US1] Criar componente `PrivacyPolicyPage` stateless com Navbar, `<main>` centralizado (max-width 800 px), 8 seções LGPD numeradas e Footer, usando tokens `bg-canvas`, `text-text-primary`, `text-text-secondary`, `text-text-tertiary` e `fontFeatureSettings: '"cv01","ss03"'` em `frontend/src/pages/PrivacyPolicyPage.tsx`
- [ ] T002 [US1] Importar `PrivacyPolicyPage` e adicionar `<Route path="/politica-de-privacidade" element={<PrivacyPolicyPage />} />` após a rota `/corretores` em `frontend/src/App.tsx`
**Checkpoint**: Rota `/politica-de-privacidade` acessível no browser com as 8 seções visíveis. User Story 1 completa e testável de forma independente.
---
## Phase 3: User Story 2 — Visitante encontra o link da Política no Footer (Priority: P2)
**Goal**: Adicionar link "Política de Privacidade" no Footer usando roteamento client-side (sem reload da página).
**Independent Test**: Em qualquer página do site com Footer visível, verificar que o link "Política de Privacidade" está presente no rodapé e que clicar nele navega para `/politica-de-privacidade` sem recarregar a página (SPA navigation).
- [ ] T003 [P] [US2] Importar `Link` de `react-router-dom` e adicionar `<li><Link to="/politica-de-privacidade" ...>Política de Privacidade</Link></li>` no `<ul>` de navegação, após o `map` de `footerLinks` existente, com classes `text-xs text-text-tertiary hover:text-text-secondary transition-colors duration-150` em `frontend/src/components/Footer.tsx`
**Checkpoint**: Link visível no Footer de qualquer página; clique navega via SPA sem recarregamento. User Story 2 completa e testável de forma independente.
---
## Phase 4: User Story 3 — Visitante identifica empresa responsável e canal de contato (Priority: P3)
**Goal**: Substituir os placeholders `[NOME DA EMPRESA]`, `[CNPJ]`, `[ENDEREÇO COMPLETO]` e `[E-MAIL DO DPO]` nas seções 1 e 8 pelos dados reais da imobiliária.
**Independent Test**: Na página `/politica-de-privacidade`, seção 1 deve conter nome completo, CNPJ e endereço da empresa. Seção 8 deve conter endereço de e-mail válido para contato com o DPO.
- [ ] T004 [US3] Substituir placeholders na seção 1 (nome, CNPJ, endereço) e na seção 8 (e-mail do DPO) pelos dados reais da empresa em `frontend/src/pages/PrivacyPolicyPage.tsx`
**Checkpoint**: Seções 1 e 8 sem placeholders; conformidade LGPD com identificação do controlador e canal de comunicação com DPO. User Story 3 completa.
---
## Phase Final: Polish & Verificação
**Purpose**: Validação de tipos, build e verificação final de responsividade.
- [ ] T005 Executar `npm run build` no diretório `frontend/` e confirmar que não há erros de TypeScript nem de compilação
- [ ] T006 [P] Verificar responsividade da `PrivacyPolicyPage` em larguras ≥ 320 px (mobile) e ≥ 1280 px (desktop) — sem overflow horizontal, texto legível, espaçamento adequado
---
## Dependencies & Execution Order
### Dependências entre tasks
| Task | Depende de | Motivo |
|---|---|---|
| T002 | T001 | Importa `PrivacyPolicyPage` criado em T001 |
| T004 | T001 | Edita o arquivo criado em T001 |
| T005 | T001, T002, T003, T004 | Build final após todas as mudanças |
| T006 | T001, T002 | Requer a página funcional para testar responsividade |
### Tasks independentes (sem dependências entre si)
- **T001** e **T003** podem ser executadas em paralelo por devs diferentes — arquivos distintos, zero conflito.
### Ordem sugerida (desenvolvedor solo)
```
T001 → T002 → T003 → T004 → T005 → T006
```
### Ordem sugerida (dois devs em paralelo)
```
Dev A: T001 → T002 → T004 → T005
Dev B: T003 → T006
```
---
## Parallel Example: User Story 1 (MVP solo)
```bash
# 1. Criar o componente
# frontend/src/pages/PrivacyPolicyPage.tsx — novo arquivo
# 2. Adicionar rota
# frontend/src/App.tsx — adicionar Route após /corretores
# 3. Verificar
cd frontend && npm run dev
# Abrir http://localhost:5173/politica-de-privacidade
```
---
## Implementation Strategy
### MVP (apenas US1 — T001 + T002)
Entrega mínima: a página existe e é acessível via URL. Footer sem link ainda. Dados reais preenchidos depois.
### Incremental delivery
1. **Sprint 1** — T001 + T002: Página acessível (US1 ✅)
2. **Sprint 1** — T003: Link no Footer (US2 ✅)
3. **Sprint 2** — T004: Dados reais da empresa (US3 ✅)
4. **Sprint 2** — T005 + T006: Build limpo + verificação visual (Polish ✅)
### Sem testes automatizados
Conforme `plan.md` ("Testing: `npm run build` (TypeScript type-check via tsc); verificação visual manual"), não foram geradas tasks de teste automatizado para esta feature.