@horizon-framework/website-dev-docs 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/AGENTE_FULLSTACK.md +209 -0
- package/agents/AGENTE_LAYOUT_DESIGNER.md +930 -0
- package/checklists/ADICIONAR_CAMPO.md +95 -0
- package/checklists/CRIAR_SITE_NOVO.md +163 -0
- package/checklists/PUBLICAR_SITE.md +75 -0
- package/checklists/TROCAR_CRM.md +96 -0
- package/commercial/PACOTES_PAGINAS.md +86 -0
- package/commercial/POSSIBILIDADES_VENDA.md +52 -0
- package/index.md +54 -0
- package/knowledge/API_PROPERTY.md +566 -0
- package/knowledge/ARQUITETURA_GERAL.md +169 -0
- package/knowledge/ARQUITETURA_MODULOS_WEB.md +241 -0
- package/knowledge/BATCH_TOTALS_API.md +200 -0
- package/knowledge/CAPABILITIES.md +190 -0
- package/knowledge/COMPONENTES_GLOBAIS_UI.md +407 -0
- package/knowledge/CRMS_INTEGRACOES.md +151 -0
- package/knowledge/DESIGN_AVANCADO.md +403 -0
- package/knowledge/DESIGN_SYSTEM_CATALOG.md +349 -0
- package/knowledge/DESIGN_TEMPLATES_CATALOG.md +61 -0
- package/knowledge/DOMINIO_ENTIDADES.md +328 -0
- package/knowledge/HOOKS_REGISTRY.md +127 -0
- package/knowledge/MODULE_CREATION_PATTERN.md +624 -0
- package/knowledge/NAVEGACAO_DINAMICA.md +233 -0
- package/knowledge/PAGINAS_BASICAS.md +63 -0
- package/knowledge/SEARCH_ENGINE_API.md +1038 -0
- package/knowledge/SISTEMA_MODULAR.md +109 -0
- package/knowledge/SISTEMA_SCHEMAS.md +126 -0
- package/knowledge/SSOT_SPECIFICATION_V2.md +333 -0
- package/knowledge/UI_KIT_COMPLETO.md +125 -0
- package/modules/property/MODULO_IMOBILIARIO.md +356 -0
- package/package.json +17 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Navegacao Dinamica -- Sistema de Menus do Horizon
|
|
2
|
+
|
|
3
|
+
> Arquitetura do sistema de navegacao: dados estaticos, fetchers dinamicos, composicao em camadas, provider pattern.
|
|
4
|
+
|
|
5
|
+
**Localizacao:** `apps/web/src/capabilities/navigations/`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Conceito
|
|
10
|
+
|
|
11
|
+
O sistema de navegacao do Horizon usa **composicao em camadas**:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Building Blocks (Imoveis, QuemSomos, Anuncie...)
|
|
15
|
+
| composicao simples
|
|
16
|
+
Menus Compostos (Institucional = [QuemSomos, Localizacao, ...])
|
|
17
|
+
| reutilizacao de blocos
|
|
18
|
+
Menus Dinamicos (Venda, Locacao com children da API + contagem)
|
|
19
|
+
| spread operator
|
|
20
|
+
Menus Finais (headerMenu, footerMenu, drawerMenu)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Dados sao "burros" (so dados), componentes sao "inteligentes" (resolvem icones, estado ativo, etc.).
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Arquivos
|
|
28
|
+
|
|
29
|
+
| Arquivo | Funcao |
|
|
30
|
+
|---|---|
|
|
31
|
+
| `types.ts` | Interface NavigationItem (title, href, icon, children, count, badge, etc.) |
|
|
32
|
+
| `data/navigations.tsx` | Blocos basicos + menus compostos + `getMenus()` async |
|
|
33
|
+
| `fetchers/property.ts` | Busca facets da API e gera children dinamicos (Venda/Locacao por tipo) |
|
|
34
|
+
| `navigation.service.ts` | Cache server-side (`unstable_cache`, revalidate 1800s) |
|
|
35
|
+
| `NavigationProvider.tsx` | Context client-side (`useNavigation()` hook) |
|
|
36
|
+
| `helpers/` | `linkAttrs()`, `isActive()`, `slugify()`, `pluralize()` |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Fluxo Completo
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
1. Server-side: layout.tsx chama await getNavigation()
|
|
44
|
+
2. navigation.service.ts:
|
|
45
|
+
- DEV: chama getMenus() direto (sem cache)
|
|
46
|
+
- PROD: unstable_cache com revalidate: 1800s (30 min)
|
|
47
|
+
3. getMenus() chama fetchers em paralelo (Promise.all)
|
|
48
|
+
- getVendaMenu() -> facet tipo_gen filtrado por operacao=venda
|
|
49
|
+
- getLocacaoMenu() -> facet tipo_gen filtrado por operacao=locacao
|
|
50
|
+
4. Fetchers usam propertyService.search() com facets.includeCount=true
|
|
51
|
+
5. API retorna facets com value + count por tipo de imovel
|
|
52
|
+
6. Children montados com titulo, href (slug), count
|
|
53
|
+
7. Resultado passa pelo NavigationProvider
|
|
54
|
+
8. Client-side: useNavigation() retorna { headerMenu, footerMenu, drawerMenu }
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Interface NavigationItem
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
interface NavigationItem {
|
|
63
|
+
// Obrigatorios
|
|
64
|
+
title: string; // "Venda", "Apartamentos"
|
|
65
|
+
href: string; // "/imoveis?operacao=venda"
|
|
66
|
+
|
|
67
|
+
// Estrutura
|
|
68
|
+
children?: NavigationItem[]; // Submenu recursivo
|
|
69
|
+
separator?: boolean; // Divisor visual
|
|
70
|
+
|
|
71
|
+
// Apresentacao
|
|
72
|
+
icon?: string; // Nome do icone (string, nao import)
|
|
73
|
+
thumbnail?: string; // URL de imagem (para cards)
|
|
74
|
+
overline?: string; // Texto acima
|
|
75
|
+
description?: string; // Descricao/tooltip
|
|
76
|
+
badge?: string; // Text badge ("Novo", "3")
|
|
77
|
+
|
|
78
|
+
// Funcionalidade
|
|
79
|
+
count?: number; // Contagem dinamica (ex: 42 imoveis)
|
|
80
|
+
disabled?: boolean;
|
|
81
|
+
target?: "_self" | "_blank";
|
|
82
|
+
rel?: string; // Auto "noopener noreferrer" se _blank
|
|
83
|
+
match?: "exact" | "startsWith" | RegExp | ((pathname: string) => boolean);
|
|
84
|
+
|
|
85
|
+
// Avancado
|
|
86
|
+
id?: string;
|
|
87
|
+
audience?: ("guest" | "user" | "admin")[];
|
|
88
|
+
dropdownLayout?: 'default' | 'cards'; // Layout do dropdown (cards=4 cols com imagens)
|
|
89
|
+
meta?: Record<string, any>;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Dinamico vs Estatico
|
|
96
|
+
|
|
97
|
+
### Estaticos (em `data/navigations.tsx`)
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// Building blocks reutilizaveis
|
|
101
|
+
export const Imoveis = { title: "Venda", href: "/imoveis?operacao=venda", icon: "property" };
|
|
102
|
+
export const Especiais = { title: "Servicos", href: "#", dropdownLayout: "cards", children: [...] };
|
|
103
|
+
|
|
104
|
+
// Fallback
|
|
105
|
+
export const headerMainMenu: NavigationItem[] = [Imoveis, Locacao, Especiais, Institucional];
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Dinamicos (via `fetchers/property.ts`)
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// getVendaMenu() busca facets da API:
|
|
112
|
+
{
|
|
113
|
+
title: "Venda",
|
|
114
|
+
href: "/imoveis?operacao=venda",
|
|
115
|
+
icon: "house",
|
|
116
|
+
children: [
|
|
117
|
+
{ title: "Apartamentos", href: "/imoveis/venda/apartamentos?...", count: 1240 },
|
|
118
|
+
{ title: "Casas", href: "/imoveis/venda/casas?...", count: 892 },
|
|
119
|
+
// ... gerado automaticamente pelos facets
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Contagem Dinamica (count)
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
propertyService.search({
|
|
130
|
+
filters: { operacao: "venda" },
|
|
131
|
+
list: { limit: 1 },
|
|
132
|
+
facets: { includeCount: true, fields: [{ type: "terms", field: "tipo_gen" }] }
|
|
133
|
+
})
|
|
134
|
+
-> API retorna: { facets: { data: { tipo_gen: [{ value: "Apartamento", count: 1240 }, ...] } } }
|
|
135
|
+
-> Mapped para NavigationItem com count
|
|
136
|
+
-> Renderizado: <span>{child.count}</span>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Os menus dinamicos se adaptam automaticamente ao trocar de CRM (dados vem da API via facets).
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Menus Finais
|
|
144
|
+
|
|
145
|
+
| Menu | Composicao |
|
|
146
|
+
|---|---|
|
|
147
|
+
| `headerMenu` | [Venda(dinamico), Locacao(dinamico), Especiais(estatico), Institucional(estatico)] |
|
|
148
|
+
| `footerMenu` | [Venda, Locacao, ...Especiais.children, ...Institucional.children] (flat) |
|
|
149
|
+
| `drawerMenu` | [Venda, Locacao, ...Institucional.children, Especiais] (mobile) |
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Converters: Social e Contact -> NavigationItem
|
|
154
|
+
|
|
155
|
+
O sistema converte dados de contato e redes sociais para NavigationItem, reutilizando a mesma interface:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// Social -> NavigationItem
|
|
159
|
+
toNavigationItem(social): { title: social.label, href: social.url, icon: getIconForSocial(social), target: "_blank" }
|
|
160
|
+
|
|
161
|
+
// Contact -> NavigationItem
|
|
162
|
+
toNavigationItem(contact): { title: contact.label, href: getContactUrl(contact), icon: getIconForContact(contact) }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Registries:**
|
|
166
|
+
- `capabilities/social/registry.ts` -- plataformas (instagram, facebook, whatsapp, etc.)
|
|
167
|
+
- `capabilities/contacts/registry.ts` -- tipos de contato (whatsapp, telegram, mobile, email)
|
|
168
|
+
|
|
169
|
+
**Dados:**
|
|
170
|
+
- `capabilities/social/data/examples.ts` -- redes sociais do cliente
|
|
171
|
+
- `capabilities/contacts/data/contacts.data.ts` -- contatos do cliente
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Helpers
|
|
176
|
+
|
|
177
|
+
| Helper | Funcao |
|
|
178
|
+
|---|---|
|
|
179
|
+
| `isActive(pathname, item)` | Determina se item esta ativo (exact, startsWith, RegExp, funcao) |
|
|
180
|
+
| `linkAttrs(item)` | Gera target/rel seguro (auto noopener noreferrer se _blank) |
|
|
181
|
+
| `slugify(text)` | Gera URL amigavel ("Ponto Comercial" -> "ponto-comercial") |
|
|
182
|
+
| `pluralize(word)` | Pluraliza em portugues ("Casa" -> "Casas", "Rural" -> "Rurais") |
|
|
183
|
+
| `filterByAudience(items, role)` | Filtra por tipo de usuario |
|
|
184
|
+
| `countBadges(items)` | Soma badges numericas recursivamente |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Cache e Revalidacao
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
// navigation.service.ts
|
|
192
|
+
const getCachedNavigation = unstable_cache(
|
|
193
|
+
async () => getMenus(),
|
|
194
|
+
["dynamic-navigation"],
|
|
195
|
+
{ revalidate: 1800 } // 30 minutos
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
// DEV: sem cache (reflete mudancas instantaneamente)
|
|
199
|
+
// PROD: cache de 30min (economia de requests a API)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Componentes que Usam
|
|
205
|
+
|
|
206
|
+
| Componente | Menu | Contexto |
|
|
207
|
+
|---|---|---|
|
|
208
|
+
| `NavigationDesktop.tsx` | headerMenu | Desktop dropdown com hover |
|
|
209
|
+
| `NavigationDesktopDropdown.tsx` | headerMenu | Alternativa com HoverCard 3 colunas |
|
|
210
|
+
| `FooterNavigation.tsx` | footerMenu | Links simples no rodape |
|
|
211
|
+
| `MobileMenu.tsx` | drawerMenu | Menu recursivo em drawer |
|
|
212
|
+
| `ContactBox.tsx` | contacts->nav | Contatos via converter |
|
|
213
|
+
| `SocialLinks.tsx` | socials->nav | Redes sociais via converter |
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Como Trocar/Adicionar Menus
|
|
218
|
+
|
|
219
|
+
1. **Bloco basico novo:** adicionar export const em `data/navigations.tsx`
|
|
220
|
+
2. **Novo fetcher dinamico:** criar funcao em `fetchers/` usando fetchFacetMenu pattern
|
|
221
|
+
3. **Menu composto:** compor com children usando blocos existentes
|
|
222
|
+
4. **Menu final:** incluir nos arrays de headerMenu/footerMenu/drawerMenu em getMenus()
|
|
223
|
+
5. **Cache:** revalida a cada 30min em prod; sem cache em dev
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Regras
|
|
228
|
+
|
|
229
|
+
1. Icones sao STRINGS (ex: "house"), nunca imports diretos de Lucide
|
|
230
|
+
2. NavigationItem e a interface unica para TODOS os contextos (header, footer, drawer, contatos, sociais)
|
|
231
|
+
3. Menus dinamicos se adaptam automaticamente ao trocar de CRM (dados vem da API)
|
|
232
|
+
4. Sempre usar `linkAttrs()` para gerar target/rel seguro
|
|
233
|
+
5. Ao adicionar menu dinamico, seguir o pattern de `getVendaMenu()` como referencia
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Paginas Basicas — Pacote Padrao Horizon
|
|
2
|
+
|
|
3
|
+
> Todo site Horizon vem com ~14 paginas basicas incluidas no pacote.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Lista Completa das Paginas Basicas
|
|
8
|
+
|
|
9
|
+
| # | Rota | Pagina | Tipo |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| 1 | `/` ou `/home` | Home Page | Marketing |
|
|
12
|
+
| 2 | `/imoveis/[[...slug]]` | Busca/Lista de Imoveis | SSR Dinamica |
|
|
13
|
+
| 3 | `/imovel/[...slug]` | Detalhe do Imovel | SSR Dinamica |
|
|
14
|
+
| 4 | `/corretor/[...slug]` | Perfil do Corretor | SSR Dinamica |
|
|
15
|
+
| 5 | `/favoritos` | Favoritos | SSR |
|
|
16
|
+
| 6 | `/imoveis-compartilhados/[[...slug]]` | Imoveis Compartilhados | SSR Dinamica |
|
|
17
|
+
| 7 | `/quem-somos` | Quem Somos | Estatica |
|
|
18
|
+
| 8 | `/localizacao` | Localizacao/Unidades | Estatica |
|
|
19
|
+
| 9 | `/contato` | Formulario de Contato | Estatica |
|
|
20
|
+
| 10 | `/financiamento` | Financiamento | Estatica |
|
|
21
|
+
| 11 | `/anuncie-seu-imovel` | Anuncie | Estatica |
|
|
22
|
+
| 12 | `/encomende-seu-imovel` | Encomende | Estatica |
|
|
23
|
+
| 13 | `/obrigado` | Pagina de Agradecimento | Estatica |
|
|
24
|
+
| 14 | `/termos-uso` | Termos de Uso | Legal |
|
|
25
|
+
| 15 | `/politica-privacidade` | Politica de Privacidade | Legal |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Paginas Auxiliares (incluso)
|
|
30
|
+
|
|
31
|
+
| Rota | Pagina | Tipo |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `/guia-de-compra` | Guia de Compra | Marketing |
|
|
34
|
+
| `/guia-de-locacao` | Guia de Locacao | Marketing |
|
|
35
|
+
| `/avaliacao-imovel` | Avaliacao de Imovel | Marketing |
|
|
36
|
+
| `/login` | Login Admin | Minimal layout |
|
|
37
|
+
| `/print-imovel/[reference]` | Impressao de Imovel | Print layout |
|
|
38
|
+
| `/imovel/inspect/[...slug]` | Inspect Mode (admin) | Debug |
|
|
39
|
+
| `/sitemap.xml` | Sitemap XML | SEO |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Layouts
|
|
44
|
+
|
|
45
|
+
As paginas sao organizadas em grupos de layout:
|
|
46
|
+
|
|
47
|
+
- **(marketing)** — Layout completo com header, footer, navegacao
|
|
48
|
+
- **(print)** — Layout minimo para impressao
|
|
49
|
+
- **(minimal)** — Layout minimo (login)
|
|
50
|
+
- **(design)** — Layout para paginas avancadas/demo
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Ao Criar Site Novo
|
|
55
|
+
|
|
56
|
+
Todas as paginas basicas vem do template Horizon. O que trocar:
|
|
57
|
+
1. **Home** — Trocar conteudo, imagens, textos
|
|
58
|
+
2. **Quem Somos** — Trocar historia, fotos, missao/visao
|
|
59
|
+
3. **Localizacao** — Trocar enderecos e mapa
|
|
60
|
+
4. **Contato** — Trocar destino de leads
|
|
61
|
+
5. **Financiamento** — Verificar bancos disponiveis
|
|
62
|
+
6. **Termos/Privacidade** — Trocar nome da empresa
|
|
63
|
+
7. **SEO** — Trocar meta tags em cada pagina
|