@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.
@@ -0,0 +1,356 @@
1
+ # Módulo Imobiliário — Arquitetura Completa
2
+
3
+ > Tudo sobre o módulo de imóveis: backend (API), frontend, listas de atributos, cards, página.
4
+ > Genérico para qualquer CRM. Campos específicos vêm da FICHA_TECNICA de cada CRM.
5
+
6
+ ---
7
+
8
+ ## BACKEND (apps/api)
9
+
10
+ ### Estrutura do módulo
11
+ ```
12
+ apps/api/src/modules/property/
13
+ ├── controllers/ → search, sync, batch-search, schemas
14
+ ├── services/ → search.service, sync.service, batch-search.service
15
+ ├── schemas/
16
+ │ ├── source-schema.zod.ts → Validação Zod (import do pacote CRM)
17
+ │ └── entity-schema.ts → Schema SSOT com display overrides e relações
18
+ ├── mappers/
19
+ │ ├── dataModifier/rules.ts → Transformações Etapa 3 (subtipo, etc.)
20
+ │ └── computedFields/index.ts → Campos calculados (slug, thumbnails, endereço, flags)
21
+ └── database/
22
+ └── tables/property/
23
+ ├── create.sql → Schema do banco (seções: system, base, CRM extras, computed)
24
+ └── generated-columns.sql → FTS vector + geom
25
+ ```
26
+
27
+ ### Arquivos que MUDAM ao trocar de CRM
28
+ 1. `package.json` — trocar pacote `@horizon-integrations/[crm]`
29
+ 2. `create.sql` — remover colunas do CRM antigo, adicionar do novo
30
+ 3. `generated-columns.sql` — atualizar FTS com campos do novo CRM
31
+ 4. `source-schema.zod.ts` — trocar import do Zod
32
+ 5. `entity-schema.ts` — trocar import do schema, bump version
33
+ 6. `rules.ts` — limpar regras do CRM antigo
34
+ 7. `computedFields/index.ts` — limpar computed do cliente, manter base
35
+
36
+ ### Endpoints principais
37
+ - `POST /api/property/search` — Busca multipart (filters, facets, fts, geom, list, map)
38
+ - `POST /api/property/batch-search` — Múltiplas buscas em 1 request
39
+ - `PUT /api/property/sync` — Sincronização de dados (batches de 50 max)
40
+ - `GET /api/property/schemas/entity` — Schema SSOT
41
+
42
+ ---
43
+
44
+ ## FRONTEND (apps/web)
45
+
46
+ ### Estrutura do módulo
47
+ ```
48
+ apps/web/src/modules/property/
49
+ ├── core/ → Fundação reutilizável
50
+ │ ├── services/PropertyService.ts → Singleton com search, batchSearch, find, getDistinct
51
+ │ ├── item/
52
+ │ │ ├── page-config/ → ★ CONTRATOS + RESOLVERS (configuração central)
53
+ │ │ │ ├── types.ts → Todas as interfaces de contrato (16 sub-features)
54
+ │ │ │ ├── resolve-contracts.ts → Função master: resolvePageContracts()
55
+ │ │ │ └── resolvers/ → 1 resolver por sub-feature
56
+ │ │ ├── fields-lists.ts → TODAS as listas de campos (cards + página)
57
+ │ │ ├── select-fields.config.ts → Config de select por contexto (full, cardList, mapList)
58
+ │ │ ├── schemas/schema.generated.json → Schema gerado da API
59
+ │ │ └── computed-fields/ → Campos computados no frontend
60
+ │ └── libs/ → Engines (enricher, URL parser, facets generator)
61
+ ├── features/
62
+ │ ├── search-list/ → Buscador avançado + listagem
63
+ │ ├── item-display/ → ★ Cards + página do imóvel (Feature-Based Provider Composition)
64
+ │ │ ├── ui/ → Componentes de UI de field compartilhados
65
+ │ │ ├── cards/ → Cards de listagem
66
+ │ │ └── page-display/→ Página do imóvel com 16 sub-features
67
+ │ │ └── sub-features/ → Cada sub-feature com provider + componentes
68
+ │ ├── item-print/ → Página de impressão (reutiliza contratos sem providers)
69
+ │ ├── item-inspect/ → Ferramenta de debug
70
+ │ └── favorites/ → Favoritos
71
+ └── customs/ → Vitrines, search bar da home
72
+ ```
73
+
74
+ > **Arquitetura detalhada da página do imóvel:** ver [ITEM-DISPLAY-ARCHITECTURE.md](../../projects/ITEM-DISPLAY-ARCHITECTURE.md)
75
+
76
+ ---
77
+
78
+ ## 6 CATEGORIAS DE ATRIBUTOS ESPECIAIS
79
+
80
+ Cada CRM traz dados diferentes, mas todos os atributos de layout caem em 6 categorias:
81
+
82
+ | Cat. | Nome | Efeito | Onde aparece |
83
+ |---|---|---|---|
84
+ | **A** | Status do imóvel | Tarja diagonal, ticker banner, muda estado da página inteira | Card (tarja) + Página (banner) |
85
+ | **B** | Destaques de vitrine | Controla onde o imóvel aparece (home, seções especiais) | Vitrines, filtros |
86
+ | **C** | Badges flutuantes | Labels sobrepostos na imagem do card | Card (foto) |
87
+ | **D** | Atributos financeiros | Checkmarks na caixa de valores lateral | Página (bloco valores) |
88
+ | **E** | Atributos principais | Ícones com número (quartos, vagas, área) | Card + Página |
89
+ | **F** | Situações/qualificações | Informações de qualificação (averbado, escriturado, judicial) | Página (seção própria) |
90
+
91
+ **Cada CRM resolve essas categorias de forma diferente** — um usa array, outro usa booleans, outro usa tags. O agente consulta a FICHA_TECNICA pra saber como mapear.
92
+
93
+ ---
94
+
95
+ ## WIREFRAMES DE REFERÊNCIA
96
+
97
+ O agente pode (e deve) desenhar wireframes ASCII pra validar a organização dos campos ANTES de implementar. Abaixo os wireframes de referência do card e da página.
98
+
99
+ ### Wireframe do Card
100
+
101
+ ```
102
+ ┌─────────────────────────────────────────┐
103
+ │ ┌───────────────────────────────────┐ │
104
+ │ │ 📷 FOTO DO IMÓVEL │ │
105
+ │ │ │ │
106
+ │ │ ┌──────┐ ┌────────┐ BADGES │ │
107
+ │ │ │ MCMV │ │Permuta │ │ │
108
+ │ │ └──────┘ └────────┘ │ │
109
+ │ │ ┌───────┐ │ │
110
+ │ │ │ ❤️ │ │ │
111
+ │ │ └───────┘ │ │
112
+ │ │ ╱╱╱╱╱╱╱╱╱╱╱ │ │
113
+ │ │ ╱ Vendido ╱ TARJA │ │
114
+ │ │ ╱╱╱╱╱╱╱╱╱╱╱╱╱ │ │
115
+ │ └───────────────────────────────────┘ │
116
+ │ │
117
+ │ Casa à venda no Água Branca TÍTULO │
118
+ │ Água Branca, F. BELTRÃO | #79 END+REF │
119
+ │ R$ 650.000,00 PREÇO │
120
+ │ │
121
+ │ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
122
+ │ │ 🛏️ │ │ 🛏️ │ │ 🚿 │ │ 🚗 │ │
123
+ │ │ 3 │ │ 1 │ │ 2 │ │ 2 │ │
124
+ │ │quart.│ │suíte │ │banh. │ │vagas │ ATTRS│
125
+ │ └──────┘ └──────┘ └──────┘ └──────┘ │
126
+ │ ┌──────┐ ┌──────┐ │
127
+ │ │180m² │ │250m² │ │
128
+ │ │priv. │ │total │ │
129
+ │ └──────┘ └──────┘ │
130
+ │ │
131
+ │ 👤 Elvis Ghisi | CRECI 123 CORRETOR │
132
+ └─────────────────────────────────────────┘
133
+ ```
134
+
135
+ ### Wireframe da Página
136
+
137
+ ```
138
+ ╔═══════════════════════════════════╦═══════════════════════╗
139
+ ║ BLOCO CENTRAL ║ BLOCO LATERAL ║
140
+ ║ ║ ║
141
+ ║ ── Ficha do Imóvel ── ║ Valor venda: ║
142
+ ║ Descrição do imóvel... ║ R$ 650.000,00 ║
143
+ ║ ║ ☑ MCMV ║
144
+ ║ ── Principal ── ║ ☑ Aceita permuta ║
145
+ ║ 3 Dormitórios | 1 Suíte ║ ║
146
+ ║ 2 Banheiros | 2 Vagas ║ Valor locação: ║
147
+ ║ 1 Sala | 1 Cozinha ║ R$ 2.500,00 ║
148
+ ║ 250m² total | 180m² priv. ║ Condomínio: R$ 300 ║
149
+ ║ Tipo: Casa | Op: Venda ║ IPTU: R$ 85 ║
150
+ ║ ☑ MCMV | ☑ Permuta ║ Taxa lixo: R$ 25 ║
151
+ ║ ║ ║
152
+ ║ ── Características ── ║ 👤 Elvis Ghisi ║
153
+ ║ ☑ Churrasqueira | ☑ Elevador ║ [Enviar mensagem] ║
154
+ ║ ☑ Cozinha planejada ║ [WhatsApp] ║
155
+ ║ Piso: Porcelanato ║ ║
156
+ ║ Teto: Laje | Forro: Gesso ║ ║
157
+ ║ ║ ║
158
+ ║ ── Segurança ── ║ ║
159
+ ║ ☑ Interfone | ☑ Murado ║ ║
160
+ ║ ☑ Portão eletrônico ║ ║
161
+ ║ ║ ║
162
+ ║ ── Lazer ── ║ ║
163
+ ║ ☑ Piscina | ☑ Academia ║ ║
164
+ ║ Aquecimento: Gás ║ ║
165
+ ║ Posição solar: Norte ║ ║
166
+ ║ ║ ║
167
+ ║ ── Localização ── ║ ║
168
+ ║ Apto: 304 | Bloco: 1 ║ ║
169
+ ║ Andar: 3 ║ ║
170
+ ║ ║ ║
171
+ ║ ── Rural ── ║ ║
172
+ ║ ☑ Rio | ☑ Mina ║ ║
173
+ ║ Alqueires: 10 | Hectares: 24 ║ ║
174
+ ║ ║ ║
175
+ ║ ── Informações adicionais ── ║ ║
176
+ ║ Pintura: Acrílica ║ ║
177
+ ╚═══════════════════════════════════╩═══════════════════════╝
178
+ ```
179
+
180
+ Ao trocar de CRM, desenhar wireframes atualizados com os campos do novo CRM pra validar a organização antes de implementar.
181
+
182
+ ---
183
+
184
+ ## CARD DE IMÓVEL (Listagem)
185
+
186
+ O card tem áreas de dados configuráveis:
187
+
188
+ ### 1. Tarjas (stripes)
189
+ - **Visual:** Ribbon diagonal sobre a foto
190
+ - **Propósito:** Indicar INDISPONIBILIDADE (Vendido, Alugado, Reservado, etc.)
191
+ - **Fonte:** `getFieldsCardStripes()` → lê campo de situação do CRM
192
+ - **Regra:** Só exibir pra estados de indisponibilidade. Disponível = sem tarja.
193
+
194
+ ### 2. Badges (labels flutuantes na foto)
195
+ - **Visual:** Labels pequenos sobrepostos à foto
196
+ - **Propósito:** Indicar DESTAQUES POSITIVOS
197
+ - **Fonte:** `getFieldsDestaquesLabels()` → campos boolean/flag do CRM
198
+ - **Regra:** Pode ter até ~7 badges configurados, mas raramente mais de 2-3 aparecem ao mesmo tempo num imóvel.
199
+ - **Exemplos comuns:** MCMV, Permuta, Financiável, Lançamento, Exclusivo, Mobiliado, Baixou o preço
200
+
201
+ ### 3. Atributos com ícone (destaques da ficha)
202
+ - **Visual:** Ícones com valor (quartos, suítes, banheiros, vagas, área)
203
+ - **Fonte:** `getFieldsDestaquesComIcones()` → campos base Horizon
204
+ - **Campos fixos:** dormitorios, suites, banheiros, vagas_garagem, area_privativa, area_total
205
+ - **Regra:** Estes são campos BASE Horizon. Iguais em qualquer CRM.
206
+
207
+ ### 4. Campos padrão
208
+ - Título, endereço (bairro + cidade), referência, preço(s)
209
+ - Não vêm de listas — são direto do property
210
+
211
+ ### Select Fields
212
+ - `select-fields.config.ts` → `cardList`
213
+ - DEVE incluir TODOS os campos usados por tarjas, badges e atributos
214
+ - Se o campo não tiver no select, o card não recebe e não exibe
215
+
216
+ ---
217
+
218
+ ## DISPLAY CONFIG (flags de layout da página)
219
+
220
+ A página do imóvel usa flags tipadas por feature (`display-config/derive.ts`). Essas flags controlam quais blocos, botões e funcionalidades aparecem.
221
+
222
+ ### REGRA CRÍTICA: Preencher TODAS as flags
223
+
224
+ Se uma flag não for preenchida, a feature correspondente fica **DESATIVADA** na página. Isso é um problema sério — desativa street view, botões de solicitação, seção de financiamento, etc.
225
+
226
+ **Ao trocar de CRM, o agente DEVE:**
227
+ 1. Ler a FICHA_TECNICA do CRM pra saber quais campos nativos resolvem cada flag
228
+ 2. Se o CRM tem campo nativo (ex: `has_video`) → usar direto
229
+ 3. Se o CRM NÃO tem campo nativo → tentar resolver via:
230
+ - **Tags** (se o CRM suporta tags)
231
+ - **Campos customizados / fields[]** (campo sem valor = flag ativa)
232
+ - **Combinação de outros campos** (ex: `is_venda` derivado de `operacao.includes('venda')`)
233
+ 4. Se não tem como resolver de jeito nenhum → documentar como limitação do CRM
234
+
235
+ **O objetivo é PREENCHER o máximo possível de flags**, porque cada flag desativada = feature desativada na página.
236
+
237
+ ### Estrutura
238
+ ```
239
+ core/item/display-config/
240
+ ├── types.ts → Interfaces tipadas por feature (has_* pattern)
241
+ ├── derive.ts → ÚNICO arquivo que muda ao trocar de CRM
242
+ └── extensions/
243
+ └── index.ts → Customizações do cliente (Etapa 3)
244
+ ```
245
+
246
+ ---
247
+
248
+ ## PÁGINA DO IMÓVEL (Detalhe)
249
+
250
+ ### BLOCO CENTRAL — Ficha do Imóvel (`PropertyInfoBlock`)
251
+
252
+ Seções organizadas de forma concisa:
253
+
254
+ #### Princípios de organização
255
+ 1. **Sem seções com poucos campos** — Não criar título de seção pra 2-3 campos. Juntar com seção relacionada.
256
+ 2. **Enums junto com booleans** — Enums de uma categoria (ex: aquecimento, posição solar) vão na mesma seção dos booleans dessa categoria (ex: Lazer).
257
+ 3. **Acabamentos junto com características** — Piso, teto, forro são poucos campos, vão junto com as características.
258
+ 4. **Situação comercial na Principal** — MCMV, permuta, situação vão na ficha técnica principal.
259
+ 5. **Campos customizados** — Exibir os `fields[]` restantes como seção final.
260
+
261
+ #### Seções
262
+ 1. **Principal** — Contadores (quartos, suítes, banheiros, vagas, salas, cozinhas, closets, varandas, lavabos), áreas, tipo, operação, situação comercial (MCMV, permuta, etc.)
263
+ 2. **Características + Acabamentos** — Booleans do array de features + campos de acabamento (piso, teto, forro, etc.)
264
+ 3. **Segurança** — Booleans do array de segurança
265
+ 4. **Lazer** — Booleans do array de lazer + enums (aquecimento, posição solar, posição quadra)
266
+ 5. **Dimensões** — Todas as medidas do terreno e áreas adicionais
267
+ 6. **Localização complementar** — Apartamento, bloco, andar, quadra, lote
268
+ 7. **Rural** — Booleans do array rural + campos numéricos rurais
269
+ 8. **Campos extras** — `fields[]` JSONB restantes como key-value
270
+
271
+ ### BLOCO LATERAL — Caixa de Valores
272
+
273
+ Organizado por operação:
274
+
275
+ #### Venda (se operação inclui "venda")
276
+ ```
277
+ Valor de venda: R$ XXX.XXX,XX
278
+ ---
279
+ Atributos de venda:
280
+ ☑ MCMV (se disponível no CRM)
281
+ ☑ Aceita permuta
282
+ ☑ Aceita financiamento
283
+ ☑ Outros flags do CRM
284
+ ```
285
+
286
+ #### Locação (se operação inclui "locação")
287
+ ```
288
+ Valor de locação: R$ X.XXX,XX
289
+ ---
290
+ Valores monetários:
291
+ Condomínio: R$ XXX,XX
292
+ IPTU: R$ XX,XX
293
+ Taxa de lixo: R$ XX,XX
294
+ (outras taxas do CRM)
295
+ ---
296
+ Atributos de locação:
297
+ (tipos de garantia, caução, etc. — quando disponíveis)
298
+ ```
299
+
300
+ ---
301
+
302
+ ## COMO ADICIONAR UM CAMPO NA BUSCA
303
+
304
+ Para um campo aparecer como filtro na busca avançada, são necessários **3 arquivos**:
305
+
306
+ 1. **`features/search-list/schema.ts`** — Adicionar campo no Zod (ex: `meu_campo: z.boolean().optional()`)
307
+ 2. **`features/search-list/config/schema.ts`** — Adicionar config do facet (tipo, label, operator, options, facetConfig)
308
+ 3. **`features/search-list/components/fields/*.tsx`** — Adicionar num componente existente ou criar novo
309
+
310
+ **Sem o passo 1:** O campo é ignorado pela API. **Sem o 2:** Sem contagem. **Sem o 3:** Não aparece na UI.
311
+
312
+ **Booleans agrupados** (MCMV, Permuta, etc.) → adicionar em `SituacaoComercialField.tsx` no array `GROUPS[0].items[]`
313
+
314
+ ---
315
+
316
+ ## REGRA OBRIGATÓRIA AO TROCAR DE CRM
317
+
318
+ Ao configurar um novo CRM, SEMPRE:
319
+
320
+ 1. **Ler a FICHA_TECNICA** do CRM → saber quais campos existem
321
+ 2. **`fields-lists.ts`** → Configurar TODAS as funções getter pra cada seção (tarjas, badges, valores, ficha técnica, características, segurança, lazer, dimensões, localização, rural)
322
+ 3. **`select-fields.config.ts`** → Garantir que cardList tem todos os campos de tarjas + badges
323
+ 4. **`PropertyInfoBlock.tsx`** → Ajustar seções da ficha do imóvel
324
+ 5. **Caixa de Valores** → Ajustar valores monetários e flags por operação
325
+ 6. **`useLayoutManager.ts`** → Ajustar detecção de vendido/alugado, streetview, geo
326
+ 7. **Testar com imóvel completo** → Verificar que todas as seções renderizam
327
+
328
+ ---
329
+
330
+ ## NAVEGAÇÃO DINÂMICA
331
+
332
+ Os menus de Venda/Locação são dinâmicos — children vêm de facets da API:
333
+
334
+ - **Fetcher:** `capabilities/navigations/fetchers/property.ts`
335
+ - **Service:** `capabilities/navigations/navigation.service.ts` (com cache)
336
+ - **Provider:** `capabilities/navigations/NavigationProvider.tsx` → `useNavigation()`
337
+ - **Regra:** Ao trocar de CRM, menus se adaptam automaticamente (dados da API)
338
+ - **Counts:** Cada child do menu mostra contagem real
339
+
340
+ ---
341
+
342
+ ## VITRINE DA HOME
343
+
344
+ - **Componente:** `customs/property-showcase/PropertyShowcaseSectionSSR.tsx`
345
+ - **Filtro padrão:** `{ operacao: ["venda"], destaque: true }`
346
+ - **Campo `destaque`:** Existe pra alimentar esta vitrine. SEMPRE configurar.
347
+ - **Regra:** O SSR é a fonte de verdade dos filtros (não duplicar defaults no client)
348
+
349
+ ---
350
+
351
+ ## CATEGORIAS DA HOME
352
+
353
+ - **Arquivo:** `home/sections/categories-carousel/categories-data.ts` (ou guia-de-compra)
354
+ - **Cada card tem:** title, image, icon, link, filters (pra contagem dinâmica)
355
+ - **Contagem:** Via `batchSearch` usando os `filters` de cada categoria
356
+ - **Regra ao trocar CRM:** SEMPRE atualizar os tipos nos links e filters. Cada CRM tem tipos diferentes.
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@horizon-framework/website-dev-docs",
3
+ "version": "2.3.0",
4
+ "description": "Documentacao inteligente da plataforma Horizon para agentes de IA. Instale para tornar seu agente mais inteligente.",
5
+ "license": "UNLICENSED",
6
+ "private": false,
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "keywords": [
11
+ "horizon",
12
+ "docs",
13
+ "ai-agent",
14
+ "platform",
15
+ "real-estate"
16
+ ]
17
+ }