feat: features 025-032 - favoritos, contatos, trabalhe-conosco, area-cliente, navbar, hero-light-dark, performance-homepage
Some checks failed
CI/CD → Deploy via SSH / Build & Push Docker Images (push) Successful in 1m0s
CI/CD → Deploy via SSH / Deploy via SSH (push) Successful in 4m35s
CI/CD → Deploy via SSH / Validate HTTPS & Endpoints (push) Failing after 46s

- feat(025): favoritos locais com FavoritesContext, HeartButton, PublicFavoritesPage
- feat(026): central de contatos admin (leads/contatos unificados)
- feat(027): configuração da página de contato via admin
- feat(028): trabalhe conosco - candidaturas com upload e admin
- feat(029): UX área do cliente - visitas, comparação, perfil
- feat(030): navbar UX - menu mobile, ThemeToggle, useFavorites
- feat(031): hero light/dark - imagens separadas por tema, upload, preview, seed
- feat(032): performance homepage - Promise.all parallel fetches, sessionStorage cache,
  preload hero image, loading=lazy nos cards, useInView hook, will-change carrossel,
  keyframes em index.css, AgentsCarousel e HomeScrollScene via props
- fix: light mode HomeScrollScene - gradiente, cores de texto, scroll hint

migrations: g1h2i3j4k5l6 (source em leads), h1i2j3k4l5m6 (contact_config),
            i1j2k3l4m5n6 (job_applications), j2k3l4m5n6o7 (hero theme images)
This commit is contained in:
MatheusAlves96 2026-04-22 22:35:17 -03:00
parent 6ef5a7a17e
commit cf5603243c
106 changed files with 11927 additions and 1367 deletions

View file

@ -0,0 +1,165 @@
# Data Model — 030-navbar-topo-ux
> Esta feature não cria entidades de banco nem migrations. O modelo abaixo descreve dados de sessão já existentes e o estado de UI necessário para a navbar.
---
## 1. Entidades Existentes Consumidas
### `AuthSession`
Fonte: `frontend/src/contexts/AuthContext.tsx`
| Campo | Tipo | Origem | Uso na navbar |
|---|---|---|---|
| `user` | `User | null` | contexto de autenticação | Decide exibição de avatar, primeiro nome e papel do usuário |
| `token` | `string | null` | `localStorage` + contexto | Não renderiza UI diretamente; sustenta estado autenticado |
| `isAuthenticated` | `boolean` | derivado do contexto | Liga/desliga ações de visitante vs cliente/admin |
| `isLoading` | `boolean` | bootstrap da sessão | Evita flicker de ações incorretas durante hidratação |
| `logout()` | `() => void` | contexto | Encerra sessão e força retorno visual ao estado visitante |
### `UserProfile`
Fonte: tipo `User` retornado pelo fluxo de auth atual.
| Campo | Tipo | Regra | Uso na navbar |
|---|---|---|---|
| `name` | `string` | obrigatório quando `user != null` | Exibe inicial e primeiro nome truncado |
| `role` | `string` | valor relevante nesta feature: `admin` ou não-admin | Controla presença do menu Admin e do menu Minha Conta |
**Invariantes**:
- `user === null` implica navbar de visitante.
- `user.role === 'admin'` implica ausência do menu de cliente padrão.
- Nome longo nunca deve quebrar layout; deve ser truncado no gatilho.
---
## 2. Entidades de Navegação
### `NavItem`
Representa um item navegável exibido em um dos grupos da navbar.
```ts
interface NavItem {
label: string
to: string
end?: boolean
visibility: 'public' | 'client' | 'admin'
group: 'primary' | 'contextual' | 'cta'
}
```
**Regras**:
- Itens `public` aparecem para todos, salvo ajustes de prioridade visual.
- Itens `client` aparecem apenas quando `isAuthenticated === true` e `role !== 'admin'`.
- Itens `admin` aparecem apenas quando `role === 'admin'`.
- `group='cta'` não substitui o grupo público; ele complementa a hierarquia do topo.
### `ProfileSection`
Agrupa ações contextuais por perfil no mobile e no desktop.
```ts
interface ProfileSection {
id: 'admin' | 'client'
title: string
items: NavItem[]
includesLogout: boolean
}
```
**Regras**:
- No mobile, cada seção deve aparecer com cabeçalho próprio.
- Logout deve permanecer visualmente separado das ações de navegação.
---
## 3. Estado Transitório de UI
### `NavUIState`
Modelo recomendado para governar interações mutuamente exclusivas.
```ts
type ActiveOverlay = 'closed' | 'mobile' | 'admin' | 'client'
interface NavUIState {
activeOverlay: ActiveOverlay
isDesktop: boolean
}
```
**Regras de transição**:
| Evento | Estado atual | Próximo estado | Observação |
|---|---|---|---|
| Clique no hambúrguer | `closed` | `mobile` | Só em mobile |
| Clique no hambúrguer | `mobile` | `closed` | Toggle padrão |
| Clique no gatilho Admin | `closed` ou `client` | `admin` | Fecha qualquer outro overlay |
| Clique no gatilho Cliente | `closed` ou `admin` | `client` | Fecha qualquer outro overlay |
| Clique fora | `mobile` / `admin` / `client` | `closed` | Requisito FR-012 |
| Mudança de rota | qualquer | `closed` | Requisito FR-013 |
| Logout confirmado | qualquer | `closed` | Navbar volta ao estado visitante |
| Escape | `mobile` / `admin` / `client` | `closed` | Recomendado para previsibilidade |
**Invariantes**:
- Apenas um contexto pode permanecer aberto por vez.
- `mobile` não pode coexistir com `admin` ou `client`.
- `admin` e `client` são mutuamente exclusivos.
---
## 4. Estados Derivados de Exibição
### `NavbarVariant`
```ts
type NavbarVariant = 'visitor' | 'client' | 'admin'
```
Derivação:
- `visitor`: `!isLoading && !isAuthenticated`
- `client`: `isAuthenticated && user?.role !== 'admin'`
- `admin`: `isAuthenticated && user?.role === 'admin'`
### `ActiveLinkState`
Estado derivado de `NavLink`/rota atual.
**Regras**:
- Links públicos devem refletir estado ativo em desktop e mobile.
- Rotas com query string, como `/imoveis?listing_type=venda`, devem manter coerência visual com a intenção do link.
- Itens contextuais devem fechar o menu após navegação bem-sucedida.
---
## 5. Regras de Validação de UX/A11y
| Regra | Aplicação |
|---|---|
| `aria-expanded` coerente | gatilhos do menu mobile e dropdowns |
| `aria-controls` presente | menu hambúrguer e, se aplicável, painéis contextuais |
| foco visível | todos os links e botões interativos |
| alvo mínimo `44x44` | hambúrguer, CTA, itens tocáveis em mobile |
| truncamento elegante | nome do usuário e gatilhos de perfil |
---
## 6. Relações Entre Entidades
```text
AuthSession
└── UserProfile
├── role ──────────────┐
└── name ───────┐ │
│ │
NavbarVariant <─────────┘ │
NavItem.visibility ────────────┘
NavUIState.activeOverlay
├── controls mobile menu visibility
├── controls admin dropdown visibility
└── controls client dropdown visibility
```