# Implementation Plan: Área do Cliente **Branch**: `master` | **Date**: 2026-04-13 | **Spec**: [spec.md](.specify/features/006-client-area/spec.md) **Input**: Feature specification from `.specify/features/006-client-area/spec.md` **Depends On**: Feature 005 — `ClientUser` model, `require_auth` decorator, JWT middleware ## Summary Implementação da Área do Cliente: favoritos (persistidos no backend), comparação de imóveis (localStorage), histórico de visitas e boletos. O backend expõe dois blueprints novos (`/api/v1/me` e `/api/v1/admin`) com autenticação JWT. O frontend adiciona rotas protegidas sob `/area-do-cliente`, contextos React para favoritos e comparação, e componentes de interação (HeartButton, ComparisonBar). ## Technical Context **Language/Version**: Python 3.12 (backend) · TypeScript 5.5 (frontend) **Primary Dependencies**: Flask 3.x, SQLAlchemy 2.x, Pydantic v2, PyJWT (backend) · React 18, react-router-dom v6, Axios, Tailwind CSS 3.4 (frontend) **Storage**: PostgreSQL 16 — 3 novas tabelas: `saved_properties`, `visit_requests`, `boletos` **Testing**: pytest (backend) — testes de rotas com client fixture; Vite build check (frontend) **Target Platform**: Servidor Linux (Docker) + SPA na mesma origem via proxy Vite **Project Type**: Web service (Flask REST API) + SPA (React) **Performance Goals**: Favoritar/desfavoritar < 2 s; tabela de comparação renderizada < 1 s para 3 imóveis **Constraints**: Comparação não persiste no backend; admin sem UI no MVP; sem integração com gateway de pagamento **Scale/Scope**: MVP — funcionalidades essenciais da área logada; admin opera via API direta ## 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 novos componentes React usam tokens do DESIGN.md: fundo `#08090a`, painéis `#0f1011`, acento `#5e6ad2`/`#7170ff`. Nenhum estilo inline fora do sistema. | | II. Separation of Concerns | ✅ PASS | Flask retorna JSON puro; React é SPA. Contextos (`FavoritesContext`, `ComparisonContext`) são camada de estado frontend apenas. | | III. Spec-Driven | ✅ PASS | spec.md aprovado → plan.md (este arquivo) → tasks.md → implementação. | | IV. Data Integrity | ✅ PASS | Todas as entradas via Pydantic schemas. `amount` usa `Numeric(12, 2)`. Novas tabelas via migração Alembic. Foreign keys explicitamente anuláveis ou não-anuláveis conforme modelo. | | V. Security | ⚠️ PARTIAL | `/api/v1/me/*` protegido por `require_auth`. `/api/v1/admin/*` protegido por `require_auth` mas **sem verificação de role no MVP** — qualquer ClientUser autenticado pode acessar rotas admin. FR-018 exige 403 para token de ClientUser; esta verificação é **adiada** e documentada como dívida técnica (ver Complexity Tracking). | | VI. Simplicity First | ✅ PASS | Comparação em localStorage (sem backend). Sem gateway de pagamento. Admin sem UI. Nenhuma abstração nova sem 3+ usos concretos. | **POST-DESIGN RE-CHECK**: ✅ Após Phase 1, o modelo de dados não introduz complexidade adicional. Violação de Princípio V documentada como dívida técnica deliberada para MVP. ## Project Structure ### Documentation (this feature) ```text .specify/features/006-client-area/ ├── plan.md # Este arquivo ├── research.md # Fase 0 — decisões e alternativas ├── data-model.md # Fase 1 — entidades e relacionamentos ├── quickstart.md # Fase 1 — como rodar e testar localmente ├── contracts/ │ ├── me-favorites.md │ ├── me-visits.md │ ├── me-boletos.md │ └── admin.md └── tasks.md # Fase 2 (gerado por /speckit.tasks) ``` ### Source Code (repository root) ```text backend/ ├── app/ │ ├── models/ │ │ ├── saved_property.py # NOVO — SavedProperty │ │ ├── visit_request.py # NOVO — VisitRequest │ │ ├── boleto.py # NOVO — Boleto │ │ └── client_user.py # PRÉ-REQUISITO (Feature 005) │ ├── schemas/ │ │ └── client_area.py # NOVO — todos os schemas de entrada/saída │ ├── routes/ │ │ ├── client_area.py # NOVO — blueprint client_bp (/api/v1/me) │ │ └── admin.py # NOVO — blueprint admin_bp (/api/v1/admin) │ └── __init__.py # ATUALIZAR — registrar modelos e blueprints └── migrations/ └── versions/ └── xxxx_add_saved_properties_visit_requests_boletos.py # NOVO frontend/ └── src/ ├── types/ │ └── clientArea.ts # NOVO — VisitRequest, Boleto, ComparisonState ├── contexts/ │ ├── ComparisonContext.tsx # NOVO — estado de comparação (localStorage) │ └── FavoritesContext.tsx # NOVO — favoritos (backend, apenas logado) ├── components/ │ ├── ComparisonBar.tsx # NOVO — barra flutuante rodapé │ ├── HeartButton.tsx # NOVO — toggle favorito │ ├── PropertyCard.tsx # ATUALIZAR — HeartButton + botão Comparar │ └── PropertyDetail/ │ └── ContactSection.tsx # ATUALIZAR — criar VisitRequest se logado ├── layouts/ │ └── ClientLayout.tsx # NOVO — sidebar da área do cliente ├── pages/ │ └── client/ │ ├── ClientDashboardPage.tsx # NOVO │ ├── FavoritesPage.tsx # NOVO │ ├── ComparisonPage.tsx # NOVO │ ├── VisitsPage.tsx # NOVO │ └── BoletosPage.tsx # NOVO ├── services/ │ └── clientArea.ts # NOVO — getFavorites, addFavorite, removeFavorite, getVisits, getBoletos └── App.tsx # ATUALIZAR — rotas protegidas + providers de contexto backend/tests/ ├── test_client_area.py # NOVO — testes de rotas /me e /admin └── conftest.py # ATUALIZAR — fixture client_user + auth token ``` **Structure Decision**: Web application (Option 2). Backend Flask REST API + frontend React SPA. Estrutura de arquivos segue o padrão já estabelecido no projeto (um arquivo por model, um arquivo por blueprint, schemas agrupados por domínio). ## Complexity Tracking | Violação | Por que necessária | Alternativa mais simples rejeitada porque | |----------|-------------------|-------------------------------------------| | Princípio V: rotas `/api/v1/admin/*` sem verificação de role no MVP | Admin opera via API direta; implementar RBAC completo exige tabela de roles, seed e testes adicionais fora do escopo desta feature | Adicionar `require_admin_role` desde já acoplaria esta feature a Feature 005 e bloquearia o MVP sem benefício real — único usuário da API admin é o próprio dono da aplicação |