# Implementation Plan: Navegação Unificada no Header (Remoção do Sidebar)
**Branch**: `013-header-only-nav` | **Date**: 2026-04-14 | **Spec**: [spec.md](spec.md)
**Depends On**: Nenhuma dependência de feature anterior — alterações puramente de layout/componente frontend.
## Summary
Remoção dos sidebars de `AdminLayout` e `ClientLayout`, consolidando todos os itens de navegação no `Navbar` (header fixo) via dropdowns contextuais. O dropdown "Admin ▾" aparece apenas para `isAdmin`; o dropdown "Minha Conta ▾" aparece apenas para usuários autenticados não-admin. Nenhuma rota nova, nenhuma alteração de backend. Alterações em 3 arquivos frontend: `Navbar.tsx`, `AdminLayout.tsx` e `ClientLayout.tsx`.
**Observação sobre ClientLayout + Navbar**: `ClientLayout.tsx` atualmente **não** importa nem renderiza `` (ao contrário de `AdminLayout`). O `App.tsx` também não possui um `` global. Para que o dropdown "Minha Conta ▾" seja exibido nas rotas `/area-do-cliente/*`, **`ClientLayout` deve passar a renderizar ``** como parte desta feature.
## Technical Context
**Language/Version**: TypeScript 5.5 (frontend)
**Primary Dependencies**: React 18, react-router-dom v6, Tailwind CSS 3.4 (já utilizados — sem novas dependências)
**Storage**: Nenhuma alteração de banco de dados
**Testing**: Vite build check (frontend) — sem testes unitários para componentes de layout no projeto atual
**Target Platform**: SPA (React) servida via Vite proxy
**Project Type**: Web SPA (React)
**Performance Goals**: Sem re-renders desnecessários no toggle de dropdown; fechamento por clique externo via `useRef + useEffect`
**Constraints**: Sem bibliotecas externas novas; dropdowns implementados com React + Tailwind puro; mobile: itens expandidos inline no menu hamburger (sem toggle aninhado)
**Scale/Scope**: Refactor de layout puro — 3 arquivos frontend, sem impacto em rotas ou dados
## Constitution Check
| Princípio | Status | Observação |
|-----------|--------|------------|
| I. Design-First | ✅ PASS | Tokens `bg-[#0f1011]`, `border-white/[0.06]`, `bg-white/[0.06]`, `shadow-xl`, `rounded-xl` são idênticos aos já utilizados no projeto conforme `DESIGN.md`. |
| II. Separation of Concerns | ✅ PASS | Navbar contém lógica de navegação; layouts são thin wrappers sem lógica própria. |
| III. Spec-Driven | ✅ PASS | spec.md aprovado → plan.md (este) → implementação. |
| IV. Data Integrity | ✅ PASS | Nenhuma alteração de dados — feature puramente de UI. |
| V. Security | ✅ PASS | Visibilidade dos dropdowns controlada pelos mesmos guards já existentes (`isAdmin`, `isAuthenticated`). Nenhuma rota protegida exposta. |
| VI. Simplicity First | ✅ PASS | Remoção de código (sidebars) > adição. Sem abstração nova, sem nova lib. Alterações cirúrgicas em 3 arquivos. |
**POST-DESIGN RE-CHECK**: ✅ Adicionar `useRef + useEffect` ao Navbar e `` ao ClientLayout são as únicas adições de infraestrutura — totalmente justificadas pelo requisito de UX.
## Architecture Overview
```
App.tsx (inalterado)
├── /area-do-cliente → ProtectedRoute → ClientLayout →
│ ClientLayout: <> >
│ ↑ adicionado nesta feature
│
└── /admin → AdminRoute → AdminLayout →
AdminLayout: <> >
(sidebar removido; flex wrapper removido)
Navbar.tsx (ampliado)
├── adminNavItems[] — 7 itens /admin/*
├── clientNavItems[] — 5 itens /area-do-cliente/*
├── adminDropdownOpen (useState)
├── clientDropdownOpen (useState)
├── adminDropdownRef (useRef) + useEffect para fechar no outside click
├── clientDropdownRef (useRef) + useEffect para fechar no outside click
├── Desktop: dropdown "Admin ▾" (isAdmin) / "Minha Conta ▾" (isAuthenticated não-admin)
└── Mobile: itens admin ou cliente expandidos inline no menu hamburger
```
## Frontend Changes
### 1. `Navbar.tsx` — `frontend/src/components/Navbar.tsx`
#### 1.1 Imports adicionais
```tsx
import { useState, useRef, useEffect } from 'react'
import { Link, NavLink } from 'react-router-dom'
import { useAuth } from '../contexts/AuthContext'
import { ThemeToggle } from './ThemeToggle'
```
> `NavLink` substitui `Link` nos itens de dropdown para suporte a `isActive`.
#### 1.2 Arrays de navegação
```tsx
const adminNavItems = [
{ to: '/admin/properties', label: 'Imóveis' },
{ to: '/admin/clientes', label: 'Clientes' },
{ to: '/admin/boletos', label: 'Boletos' },
{ to: '/admin/visitas', label: 'Visitas' },
{ to: '/admin/favoritos', label: 'Favoritos' },
{ to: '/admin/cidades', label: 'Cidades' },
{ to: '/admin/amenidades', label: 'Amenidades' },
]
const clientNavItems = [
{ to: '/area-do-cliente', label: 'Painel', end: true },
{ to: '/area-do-cliente/favoritos',label: 'Favoritos',end: false },
{ to: '/area-do-cliente/comparar', label: 'Comparar', end: false },
{ to: '/area-do-cliente/visitas', label: 'Visitas', end: false },
{ to: '/area-do-cliente/boletos', label: 'Boletos', end: false },
]
```
#### 1.3 Estado e refs no componente
```tsx
const [menuOpen, setMenuOpen] = useState(false)
const [adminDropdownOpen, setAdminDropdownOpen] = useState(false)
const [clientDropdownOpen, setClientDropdownOpen] = useState(false)
const adminDropdownRef = useRef(null)
const clientDropdownRef = useRef(null)
// Fechar dropdown ao clicar fora
useEffect(() => {
function handleClickOutside(e: MouseEvent) {
if (adminDropdownRef.current && !adminDropdownRef.current.contains(e.target as Node)) {
setAdminDropdownOpen(false)
}
if (clientDropdownRef.current && !clientDropdownRef.current.contains(e.target as Node)) {
setClientDropdownOpen(false)
}
}
document.addEventListener('mousedown', handleClickOutside)
return () => document.removeEventListener('mousedown', handleClickOutside)
}, [])
```
#### 1.4 Desktop — Dropdown "Admin ▾"
Substituir o `
` do link "Painel Admin" no `navLinks` map por:
```tsx
{isAdmin && (
)}
>
) : (
Entrar
)}
```
> **Nota**: O link "Admin" (botão amarelo) e o link "Painel Admin" em `navLinks` são removidos. O dropdown no botão admin já contém todos os itens.
#### 1.6 Mobile — Itens admin/cliente inline
No mobile menu, substituir o bloco auth existente por:
```tsx
{!isLoading && (
isAuthenticated && user ? (
<>
{isAdmin
? adminNavItems.map(item => (