@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,190 @@
|
|
|
1
|
+
# Capabilities — Features Transversais do Frontend
|
|
2
|
+
|
|
3
|
+
> Sistema de funcionalidades reutilizaveis em apps/web/src/capabilities/
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Mapa das 11 Capabilities
|
|
8
|
+
|
|
9
|
+
| Capability | Pasta | Funcao |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Contacts | `contacts/` | Telefones e emails centralizados |
|
|
12
|
+
| Social | `social/` | Redes sociais (13 plataformas) |
|
|
13
|
+
| Code Snippets | `code-snippets/` | Scripts de marketing (GTM, GA, Facebook Pixel) |
|
|
14
|
+
| MetaTags | `metatags/` | SEO global (title, favicon, OG) |
|
|
15
|
+
| Navigations | `navigations/` | Menus dinamicos (ver NAVEGACAO_DINAMICA.md) |
|
|
16
|
+
| Redirects | `redirects/` | URLs antigas → novas |
|
|
17
|
+
| Sitemap | `sitemap/` | XML dinamico conectado com modulos |
|
|
18
|
+
| Translation | `translation/` | Multilingue (PT, EN, ES) |
|
|
19
|
+
| UTM Tracking | `utm-tracking/` | Captura parametros UTM |
|
|
20
|
+
| Forms | `forms/` | Envio de leads + LGPD |
|
|
21
|
+
| WhatsApp Float | `(em components/)` | Botao flutuante de atendimento |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## CONTACTS — Sistema de Contatos
|
|
26
|
+
|
|
27
|
+
**Pasta:** `capabilities/contacts/`
|
|
28
|
+
|
|
29
|
+
Centraliza TODOS os contatos do site (telefones, emails, WhatsApp).
|
|
30
|
+
|
|
31
|
+
**Interface:**
|
|
32
|
+
```typescript
|
|
33
|
+
interface Contact {
|
|
34
|
+
type: "phone" | "email";
|
|
35
|
+
tags: ContactTag[]; // "whatsapp", "telegram", "mobile", "land"
|
|
36
|
+
value: string; // numero ou email
|
|
37
|
+
label: string; // "WhatsApp Principal"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Registry:** `CONTACT_TAG_CONFIG` mapeia tags para icones e URLs:
|
|
42
|
+
- whatsapp → `https://wa.me/{numero}`
|
|
43
|
+
- telegram → `https://t.me/{username}`
|
|
44
|
+
- mobile → icone smartphone
|
|
45
|
+
- land → icone phone
|
|
46
|
+
|
|
47
|
+
**Dados:** `data/contacts.data.ts` — contatos base do cliente
|
|
48
|
+
**Converters:** `toNavigationItems(contacts)` → NavigationItem[]
|
|
49
|
+
|
|
50
|
+
**Ao criar site novo:** Editar `data/contacts.data.ts` com contatos do cliente.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## SOCIAL — Redes Sociais
|
|
55
|
+
|
|
56
|
+
**Pasta:** `capabilities/social/`
|
|
57
|
+
|
|
58
|
+
13 plataformas suportadas: Facebook, Instagram, LinkedIn, X, YouTube, TikTok, WhatsApp Business, Telegram, Pinterest, Discord, GitHub, Blog, Other.
|
|
59
|
+
|
|
60
|
+
**Registry:** `SOCIAL_PLATFORMS` com icone, URL pattern, cor, descricao para cada plataforma.
|
|
61
|
+
|
|
62
|
+
**Helpers:**
|
|
63
|
+
- `createSocialFromUsername(platform, username)` → Social
|
|
64
|
+
- `validateSocial(social)` → boolean
|
|
65
|
+
- `toNavigationItems(socials)` → NavigationItem[]
|
|
66
|
+
|
|
67
|
+
**Ao criar site novo:** Editar dados das redes sociais do cliente.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## CODE-SNIPPETS — Marketing Scripts
|
|
72
|
+
|
|
73
|
+
**Pasta:** `capabilities/code-snippets/`
|
|
74
|
+
|
|
75
|
+
Arquivo unico `scripts-marketing.tsx` com:
|
|
76
|
+
- Google Tag Manager (GTM)
|
|
77
|
+
- Google Analytics (GA4)
|
|
78
|
+
- Facebook Pixel
|
|
79
|
+
- Eventos de conversao (pagina /obrigado, cliques WhatsApp)
|
|
80
|
+
|
|
81
|
+
**Ao criar site novo:** Trocar IDs de GTM, GA e Facebook Pixel do cliente.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## METATAGS — SEO Global
|
|
86
|
+
|
|
87
|
+
**Pasta:** `capabilities/metatags/`
|
|
88
|
+
|
|
89
|
+
Configuracao centralizada em `seo.ts`:
|
|
90
|
+
- Title suffix (nome da imobiliaria)
|
|
91
|
+
- Favicon path
|
|
92
|
+
- OG Image (800x450)
|
|
93
|
+
|
|
94
|
+
**Ao criar site novo:** Trocar nome, favicon e OG image.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## REDIRECTS — URLs Antigas
|
|
99
|
+
|
|
100
|
+
**Pasta:** `capabilities/redirects/nextjs/`
|
|
101
|
+
|
|
102
|
+
Gera redirects permanentes para o next.config:
|
|
103
|
+
- Property: `/imovel/{slug}-ref-{id}` → `/imovel/{id}`
|
|
104
|
+
- Genericos: `/venda` → `/imoveis/venda`
|
|
105
|
+
- Search mappings: `/venda/apartamentos` → `/imoveis?filtros`
|
|
106
|
+
|
|
107
|
+
**Exporta:** `generateNextConfigRedirects()` para integrar no next.config.js
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## SITEMAP — XML Dinamico
|
|
112
|
+
|
|
113
|
+
**Pasta:** `capabilities/sitemap/`
|
|
114
|
+
|
|
115
|
+
Sistema modular: cada modulo implementa `SitemapProvider`.
|
|
116
|
+
- `router.ts` roteia slug para provider correto via MODULES_REGISTRY
|
|
117
|
+
- `config/static-pages.ts` lista paginas estaticas
|
|
118
|
+
- `generators/` gera XML valido + sitemap index
|
|
119
|
+
|
|
120
|
+
**Paginas estaticas incluidas:** /, /sobre, /contato, /localizacao, /termos-uso, /politica-privacidade
|
|
121
|
+
|
|
122
|
+
**Ao criar site novo:** Verificar se paginas estaticas correspondem as existentes.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## TRANSLATION — Multilingue
|
|
127
|
+
|
|
128
|
+
**Pasta:** `capabilities/translation/`
|
|
129
|
+
|
|
130
|
+
3 idiomas: Portugues (pt), Ingles (en), Espanhol (es).
|
|
131
|
+
Usa Google Translate com cookie `googtrans`.
|
|
132
|
+
|
|
133
|
+
**Componentes:** LanguageProvider, LanguageSelector, LanguageSuggestionBanner
|
|
134
|
+
**Hook:** `useForceTranslation`, `useLanguage`
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## UTM TRACKING — Parametros de Marketing
|
|
139
|
+
|
|
140
|
+
**Pasta:** `capabilities/utm-tracking/`
|
|
141
|
+
|
|
142
|
+
Captura parametros UTM da URL e persiste em localStorage.
|
|
143
|
+
- `extractUTMFromURL()` → UTMParams
|
|
144
|
+
- `saveUTMToStorage()` / `loadUTMFromStorage()`
|
|
145
|
+
- Hook: `useUTMTracking`, `useCurrentUTM`
|
|
146
|
+
|
|
147
|
+
**Tipo:** `UTMParams { source, medium, campaign, term, content }`
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## FORMS — Envio de Leads
|
|
152
|
+
|
|
153
|
+
**Pasta:** `capabilities/forms/`
|
|
154
|
+
|
|
155
|
+
Sistema centralizado para envio de leads:
|
|
156
|
+
- `sendLead(data)` → envia para AUTOMATIONS
|
|
157
|
+
- `consent.data.ts` → textos LGPD (completo e compacto)
|
|
158
|
+
- Captura meta: page_id, utm_source, utm_campaign
|
|
159
|
+
|
|
160
|
+
**Interface:** `LeadFormData` com campos tipados (text, email, phone, etc.)
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## WHATSAPP FLUTUANTE
|
|
165
|
+
|
|
166
|
+
**Pasta:** `components/whatsapp-float-button/`
|
|
167
|
+
|
|
168
|
+
Botao circular fixo no canto inferior direito com:
|
|
169
|
+
- Balao de mensagem animado (delay 7s)
|
|
170
|
+
- Avatar do atendente customizavel
|
|
171
|
+
- LocalStorage para lembrar fechamento
|
|
172
|
+
- Link direto: `https://api.whatsapp.com/send/?phone={num}&text={msg}`
|
|
173
|
+
|
|
174
|
+
**Config:** `WhatsAppConfig { phoneNumber, message, showBubble, bubbleMessage, attendantName, attendantAvatar }`
|
|
175
|
+
|
|
176
|
+
**Ao criar site novo:** Configurar numero, mensagem e avatar no WhatsAppProvider.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## CHECKLIST — O que trocar ao criar site novo
|
|
181
|
+
|
|
182
|
+
Ao usar template Horizon para novo cliente, trocar em capabilities:
|
|
183
|
+
1. `contacts/data/contacts.data.ts` — telefones e emails
|
|
184
|
+
2. `social/data/` — redes sociais
|
|
185
|
+
3. `code-snippets/scripts-marketing.tsx` — IDs GTM, GA, Facebook
|
|
186
|
+
4. `metatags/seo.ts` — nome, favicon, OG image
|
|
187
|
+
5. `redirects/` — URLs especificas do cliente
|
|
188
|
+
6. `sitemap/config/static-pages.ts` — paginas estaticas
|
|
189
|
+
7. `WhatsAppProvider` — numero, mensagem, avatar
|
|
190
|
+
8. `forms/` — verificar destino de leads
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
# Sistema de Componentes Globais
|
|
2
|
+
|
|
3
|
+
Sistema completo de componentes reutilizáveis e utilitários para a aplicação Nova Torres.
|
|
4
|
+
|
|
5
|
+
## Componentes Implementados
|
|
6
|
+
|
|
7
|
+
### **1. Sonner Toast** (Já Ativo)
|
|
8
|
+
Sistema de notificações elegante já integrado no layout.
|
|
9
|
+
|
|
10
|
+
**Uso:**
|
|
11
|
+
```tsx
|
|
12
|
+
import { toast } from "sonner";
|
|
13
|
+
|
|
14
|
+
// Sucesso
|
|
15
|
+
toast.success("Formulário enviado com sucesso!");
|
|
16
|
+
|
|
17
|
+
// Erro
|
|
18
|
+
toast.error("Erro ao processar dados");
|
|
19
|
+
|
|
20
|
+
// Personalizado
|
|
21
|
+
toast("Mensagem", {
|
|
22
|
+
description: "Descrição adicional",
|
|
23
|
+
duration: 5000
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### **2. Global Loading**
|
|
28
|
+
Loading global centralizado com overlay.
|
|
29
|
+
|
|
30
|
+
**Uso:**
|
|
31
|
+
```tsx
|
|
32
|
+
import { useGlobalLoading } from "@/components/providers/GlobalUIProvider";
|
|
33
|
+
|
|
34
|
+
function MeuComponente() {
|
|
35
|
+
const { showLoading, hideLoading } = useGlobalLoading();
|
|
36
|
+
|
|
37
|
+
const handleSubmit = async () => {
|
|
38
|
+
showLoading();
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
await minhaFuncaoAsincrona();
|
|
42
|
+
} finally {
|
|
43
|
+
hideLoading();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### **3. Form Alert Modal** (Sua Ideia Genial!)
|
|
50
|
+
Modal de feedback para formulários com timeout automático.
|
|
51
|
+
|
|
52
|
+
**Uso:**
|
|
53
|
+
```tsx
|
|
54
|
+
import { useFormAlert } from "@/components/providers/GlobalUIProvider";
|
|
55
|
+
|
|
56
|
+
function MeuFormulario() {
|
|
57
|
+
const { showAlert } = useFormAlert();
|
|
58
|
+
|
|
59
|
+
const handleSubmit = () => {
|
|
60
|
+
// Lógica do formulário...
|
|
61
|
+
|
|
62
|
+
showAlert({
|
|
63
|
+
type: "success", // "success" | "error" | "warning"
|
|
64
|
+
title: "Formulário Enviado!",
|
|
65
|
+
message: "Nossa equipe entrará em contato em breve.",
|
|
66
|
+
timeout: 5000 // auto-fechar em 5s
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### **4. Generic Modal**
|
|
73
|
+
Sistema de modais reutilizáveis com diferentes tipos.
|
|
74
|
+
|
|
75
|
+
**Uso:**
|
|
76
|
+
```tsx
|
|
77
|
+
import { useModal } from "@/components/providers/GlobalUIProvider";
|
|
78
|
+
|
|
79
|
+
function MeuComponente() {
|
|
80
|
+
const { showModal } = useModal();
|
|
81
|
+
|
|
82
|
+
// Modal customizado
|
|
83
|
+
const openCustomModal = () => {
|
|
84
|
+
showModal({
|
|
85
|
+
type: "dialog",
|
|
86
|
+
title: "Editar Perfil",
|
|
87
|
+
content: <MeuFormulario />,
|
|
88
|
+
size: "lg"
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Alert simples
|
|
93
|
+
const openAlert = () => {
|
|
94
|
+
showModal({
|
|
95
|
+
type: "alert",
|
|
96
|
+
title: "Sucesso!",
|
|
97
|
+
description: "Operação realizada com sucesso."
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Confirmação
|
|
102
|
+
const openConfirm = () => {
|
|
103
|
+
showModal({
|
|
104
|
+
type: "confirm",
|
|
105
|
+
title: "Confirmar exclusão?",
|
|
106
|
+
description: "Esta ação não pode ser desfeita.",
|
|
107
|
+
variant: "destructive",
|
|
108
|
+
onConfirm: () => console.log("Confirmado"),
|
|
109
|
+
onCancel: () => console.log("Cancelado")
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### **5. Generic Sheet**
|
|
116
|
+
Sidebars/drawers deslizantes para menus e painéis.
|
|
117
|
+
|
|
118
|
+
**Uso:**
|
|
119
|
+
```tsx
|
|
120
|
+
import { useSheet } from "@/components/providers/GlobalUIProvider";
|
|
121
|
+
|
|
122
|
+
function MeuComponente() {
|
|
123
|
+
const { showSheet } = useSheet();
|
|
124
|
+
|
|
125
|
+
const openMenu = () => {
|
|
126
|
+
showSheet({
|
|
127
|
+
title: "Menu de Navegação",
|
|
128
|
+
side: "left", // "left" | "right" | "top" | "bottom"
|
|
129
|
+
size: "sm", // "sm" | "md" | "lg" | "xl" | "full"
|
|
130
|
+
content: <MenuNavegacao />
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const openSettings = () => {
|
|
135
|
+
showSheet({
|
|
136
|
+
title: "Configurações",
|
|
137
|
+
side: "right",
|
|
138
|
+
size: "md",
|
|
139
|
+
content: <PainelConfiguracoes />
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### **6. Splash Screen**
|
|
146
|
+
Tela inicial do app com animações elegantes.
|
|
147
|
+
|
|
148
|
+
**Uso:**
|
|
149
|
+
```tsx
|
|
150
|
+
import { useSplashScreen } from "@/components/providers/GlobalUIProvider";
|
|
151
|
+
|
|
152
|
+
function MeuComponente() {
|
|
153
|
+
const { showSplash, hideSplash } = useSplashScreen();
|
|
154
|
+
|
|
155
|
+
// Mostrar por 3 segundos
|
|
156
|
+
const showWelcome = () => {
|
|
157
|
+
showSplash(3000);
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Mostrar até esconder manualmente
|
|
161
|
+
const showPersistent = () => {
|
|
162
|
+
showSplash(0);
|
|
163
|
+
// Depois chamar hideSplash() quando quiser fechar
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### **7. Prose Typography**
|
|
169
|
+
Componente para conteúdo rico em texto (markdown, artigos, docs).
|
|
170
|
+
|
|
171
|
+
**Uso:**
|
|
172
|
+
```tsx
|
|
173
|
+
import { ProseTypography, ArticleProse, DocsProse } from "@/components/providers/GlobalUIProvider";
|
|
174
|
+
|
|
175
|
+
// Básico
|
|
176
|
+
<ProseTypography size="base" variant="default">
|
|
177
|
+
<div dangerouslySetInnerHTML={{ __html: meuConteudoHTML }} />
|
|
178
|
+
</ProseTypography>
|
|
179
|
+
|
|
180
|
+
// Para artigos
|
|
181
|
+
<ArticleProse
|
|
182
|
+
title="Título do Artigo"
|
|
183
|
+
subtitle="Subtítulo opcional"
|
|
184
|
+
size="lg"
|
|
185
|
+
>
|
|
186
|
+
{meuConteudo}
|
|
187
|
+
</ArticleProse>
|
|
188
|
+
|
|
189
|
+
// Para documentação
|
|
190
|
+
<DocsProse>
|
|
191
|
+
{documentacaoTecnica}
|
|
192
|
+
</DocsProse>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### **8. Video Player Modal**
|
|
196
|
+
Modal para reprodução de vídeos do YouTube/Vimeo com suporte a navegação.
|
|
197
|
+
|
|
198
|
+
**Localização:** `@/components/ui/horizon-ui/video-player-modal`
|
|
199
|
+
|
|
200
|
+
**Uso Básico:**
|
|
201
|
+
```tsx
|
|
202
|
+
import { useState } from "react";
|
|
203
|
+
import { VideoPlayerModal } from "@/components/ui/horizon-ui/video-player-modal";
|
|
204
|
+
|
|
205
|
+
function MeuComponente() {
|
|
206
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<>
|
|
210
|
+
<button onClick={() => setIsOpen(true)}>Assistir Vídeo</button>
|
|
211
|
+
|
|
212
|
+
<VideoPlayerModal
|
|
213
|
+
open={isOpen}
|
|
214
|
+
onOpenChange={setIsOpen}
|
|
215
|
+
video={{
|
|
216
|
+
id: "video-1",
|
|
217
|
+
title: "Título do Vídeo",
|
|
218
|
+
url: "https://www.youtube.com/watch?v=VIDEO_ID",
|
|
219
|
+
subtitle: "Descrição opcional",
|
|
220
|
+
}}
|
|
221
|
+
externalLinkText="Assistir no YouTube"
|
|
222
|
+
/>
|
|
223
|
+
</>
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Com Navegação (lista de vídeos):**
|
|
229
|
+
```tsx
|
|
230
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
231
|
+
const videos = [...]; // Lista de vídeos
|
|
232
|
+
|
|
233
|
+
<VideoPlayerModal
|
|
234
|
+
open={isOpen}
|
|
235
|
+
onOpenChange={setIsOpen}
|
|
236
|
+
video={videos[currentIndex]}
|
|
237
|
+
onPrevious={() => setCurrentIndex((i) => (i === 0 ? videos.length - 1 : i - 1))}
|
|
238
|
+
onNext={() => setCurrentIndex((i) => (i + 1) % videos.length)}
|
|
239
|
+
externalLinkText="Assistir no YouTube"
|
|
240
|
+
externalLinkIcon={<Youtube className="size-5" />}
|
|
241
|
+
/>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Props:**
|
|
245
|
+
| Prop | Tipo | Descrição |
|
|
246
|
+
|------|------|-----------|
|
|
247
|
+
| `open` | `boolean` | Controla abertura do modal |
|
|
248
|
+
| `onOpenChange` | `(open: boolean) => void` | Callback de mudança de estado |
|
|
249
|
+
| `video` | `{ id, title, url, subtitle? }` | Dados do vídeo atual |
|
|
250
|
+
| `onPrevious?` | `() => void` | Callback para vídeo anterior |
|
|
251
|
+
| `onNext?` | `() => void` | Callback para próximo vídeo |
|
|
252
|
+
| `showNavigation?` | `boolean` | Mostrar botões prev/next (default: true) |
|
|
253
|
+
| `showExternalLink?` | `boolean` | Mostrar link externo (default: true) |
|
|
254
|
+
| `externalLinkText?` | `string` | Texto do link externo |
|
|
255
|
+
| `externalLinkIcon?` | `ReactNode` | Ícone do link externo |
|
|
256
|
+
|
|
257
|
+
**Suporte automático:**
|
|
258
|
+
- YouTube: `youtube.com/watch?v=`, `youtu.be/`, `youtube.com/shorts/`
|
|
259
|
+
- Vimeo: `vimeo.com/`
|
|
260
|
+
- URLs de embed diretas
|
|
261
|
+
|
|
262
|
+
## Como Está Configurado
|
|
263
|
+
|
|
264
|
+
O sistema está **100% integrado** no seu `AppProviders.tsx`:
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
<GlobalUIProvider
|
|
268
|
+
splashScreen={{
|
|
269
|
+
autoShow: false, // Não mostrar automaticamente
|
|
270
|
+
defaultDuration: 2000,
|
|
271
|
+
}}
|
|
272
|
+
>
|
|
273
|
+
{/* Sua aplicação */}
|
|
274
|
+
</GlobalUIProvider>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Exemplo Prático: Página de Contato
|
|
278
|
+
|
|
279
|
+
Sua página `/contato` **já está usando** o sistema:
|
|
280
|
+
|
|
281
|
+
1. **Toast** para feedback (sucesso/erro)
|
|
282
|
+
2. **Loading** no botão durante envio
|
|
283
|
+
3. 🆕 **Pode adicionar Form Alert Modal** para feedback mais elegante
|
|
284
|
+
|
|
285
|
+
**Exemplo de melhoria:**
|
|
286
|
+
```tsx
|
|
287
|
+
// Substitua o toast por Form Alert Modal
|
|
288
|
+
import { useFormAlert } from "@/components/providers/GlobalUIProvider";
|
|
289
|
+
|
|
290
|
+
const { showAlert } = useFormAlert();
|
|
291
|
+
|
|
292
|
+
// Em vez de:
|
|
293
|
+
toast.success("Mensagem enviada com sucesso!");
|
|
294
|
+
|
|
295
|
+
// Use:
|
|
296
|
+
showAlert({
|
|
297
|
+
type: "success",
|
|
298
|
+
title: "Mensagem Enviada!",
|
|
299
|
+
message: "Nossa equipe entrará em contato em breve.",
|
|
300
|
+
timeout: 5000
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Stories no Storybook
|
|
305
|
+
|
|
306
|
+
Todos os componentes têm stories completos disponíveis em:
|
|
307
|
+
|
|
308
|
+
- `Global/GlobalLoading`
|
|
309
|
+
- `Global/FormAlertModal`
|
|
310
|
+
- `Global/useModal`
|
|
311
|
+
- `Global/useSheet`
|
|
312
|
+
- `Global/SplashScreen`
|
|
313
|
+
- `Global/ProseTypography`
|
|
314
|
+
- `Global/GlobalUIProvider`
|
|
315
|
+
- `HorizonUI/VideoPlayerModal`
|
|
316
|
+
|
|
317
|
+
Execute `pnpm storybook` e navegue para ver exemplos interativos.
|
|
318
|
+
|
|
319
|
+
## Características Técnicas
|
|
320
|
+
|
|
321
|
+
- **TypeScript completo** - Tipagem forte em todos os hooks
|
|
322
|
+
- **Responsivo** - Funciona em mobile/desktop
|
|
323
|
+
- **Tema adaptativo** - Dark/light mode automático
|
|
324
|
+
- **Animações suaves** - Transições elegantes
|
|
325
|
+
- **Acessibilidade** - Suporte a screen readers
|
|
326
|
+
- **Performance** - Context otimizado, sem re-renders desnecessários
|
|
327
|
+
- **Modular** - Use só o que precisa
|
|
328
|
+
- **Consistente** - Visual uniforme em toda app
|
|
329
|
+
|
|
330
|
+
## Próximos Passos
|
|
331
|
+
|
|
332
|
+
1. **Testar** todos os hooks nas páginas existentes
|
|
333
|
+
2. **Migrar** toasts existentes para Form Alert Modal onde fizer sentido
|
|
334
|
+
3. **Implementar** splash screen se desejado (`autoShow: true`)
|
|
335
|
+
4. **Usar** modais e sheets para menus e formulários
|
|
336
|
+
5. **Aplicar** ProseTypography em conteúdo de blog/docs
|
|
337
|
+
|
|
338
|
+
## Dicas de Uso
|
|
339
|
+
|
|
340
|
+
### **Para Formulários:**
|
|
341
|
+
```tsx
|
|
342
|
+
// Loading + Form Alert = UX perfeito
|
|
343
|
+
const { showLoading, hideLoading } = useGlobalLoading();
|
|
344
|
+
const { showAlert } = useFormAlert();
|
|
345
|
+
|
|
346
|
+
const handleSubmit = async () => {
|
|
347
|
+
showLoading();
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
await submitForm();
|
|
351
|
+
hideLoading();
|
|
352
|
+
|
|
353
|
+
showAlert({
|
|
354
|
+
type: "success",
|
|
355
|
+
title: "Sucesso!",
|
|
356
|
+
message: "Formulário processado com sucesso."
|
|
357
|
+
});
|
|
358
|
+
} catch (error) {
|
|
359
|
+
hideLoading();
|
|
360
|
+
|
|
361
|
+
showAlert({
|
|
362
|
+
type: "error",
|
|
363
|
+
title: "Erro no Envio",
|
|
364
|
+
message: "Tente novamente em alguns minutos."
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### **Para Navegação:**
|
|
371
|
+
```tsx
|
|
372
|
+
// Sheet para menu mobile
|
|
373
|
+
const { showSheet } = useSheet();
|
|
374
|
+
|
|
375
|
+
<Button onClick={() => showSheet({
|
|
376
|
+
title: "Menu",
|
|
377
|
+
side: "left",
|
|
378
|
+
size: "sm",
|
|
379
|
+
content: <MobileMenu />
|
|
380
|
+
})}>
|
|
381
|
+
Menu
|
|
382
|
+
</Button>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### **Para Confirmações:**
|
|
386
|
+
```tsx
|
|
387
|
+
// Modal de confirmação elegante
|
|
388
|
+
const { showModal } = useModal();
|
|
389
|
+
|
|
390
|
+
const handleDelete = () => {
|
|
391
|
+
showModal({
|
|
392
|
+
type: "confirm",
|
|
393
|
+
title: "Excluir imóvel?",
|
|
394
|
+
description: "Esta ação não poderá ser desfeita.",
|
|
395
|
+
variant: "destructive",
|
|
396
|
+
confirmLabel: "Sim, excluir",
|
|
397
|
+
cancelLabel: "Cancelar",
|
|
398
|
+
onConfirm: () => {
|
|
399
|
+
// Lógica de exclusão
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
};
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
**Parabéns!** Seu app agora tem um sistema completo de componentes globais reutilizáveis, elegantes e performáticos. Tudo configurado e pronto para usar!
|