{"id":"repo/component-architecture","source":"repo","sourceLabel":"repository root","sourcePath":"COMPONENT_ARCHITECTURE.md","routePath":"/fastapp/public-docs/page/repo/component-architecture","rawPath":"/fastapp/public-docs/raw/repo/component-architecture","slug":["repo","component-architecture"],"slugPath":"repo/component-architecture","title":"🏗️ Arquitetura de Componentes — Padrão Dinâmico vs Concreto","description":"A estrutura de componentes do Fastapp segue a Escada de Abstração definida em ANTIGRAVITY GUIDELINES.md. A divisão de pastas reflete a intenção de separação entre o motor universal e as necessidades específicas:","headings":["🏗️ Arquitetura de Componentes — Padrão Dinâmico vs Concreto","📚 Princípio: Abstração Soberana","✅ Componentes Dinâmicos em core/","1. DynamicList.vue ✅","2. DynamicCRUD.vue ✅ [EVOLVED]","3. DynamicForm.vue ✅","4. RelationList.vue ✅","5. DynamicTable.vue ✅","6. BiWidget.vue ✅ [NEW]","7. DynamicFilter.vue ✅ [EVOLVED]","🎯 Componentes Concretos em Subpastas","components/fastapp/PropertyListEditor.vue ✅","components/crm/Kanban.vue ✅","components/crm/LeadCard.vue ✅","🏗️ Padrão de Decisão","📋 Estrutura Proposta (Pós Refactor)","🔄 Padrão de Integração","Fluxo Correto","❌ Anti Patterns","❌ Evitar","❌ Evitar Duplicação","❌ Evitar Lógica Específica em Core","✅ Boas Práticas","1️⃣ Componente Genérico em Core"],"wordCount":732,"markdown":"# 🏗️ Arquitetura de Componentes — Padrão Dinâmico vs Concreto\r\n\r\n## 📚 Princípio: Abstração Soberana\r\n\r\nA estrutura de componentes do Fastapp segue a **Escada de Abstração** definida em [ANTIGRAVITY_GUIDELINES.md](./ANTIGRAVITY_GUIDELINES.md). A divisão de pastas reflete a intenção de separação entre o motor universal e as necessidades específicas:\r\n\r\n```\r\ncomponents/\r\n├── core/           → DINÂMICOS (genéricos, reutilizáveis em qualquer contexto)\r\n│   ├── (Navigation)    BuilderHub.vue, AppMenu.vue\r\n│   └── (Data)          DynamicCRUD, DynamicForm, DynamicTable, DynamicList...\r\n├── fastapp/        → CONCRETOS (Ferramentas do Arquiteto)\r\n├── crm/            → CONCRETOS (específicos do CRM)\r\n├── sosplantao/     → CONCRETOS (específicos do SosPlantão)\r\n├── central-filtros/ → CONCRETOS (específicos do Central Filtros)\r\n└── lead/           → CONCRETOS (específicos do Lead)\r\n```\r\n\r\n## ✅ Componentes Dinâmicos em `core/`\r\n\r\n**Características**:\r\n- ✓ Genéricos e abstratos\r\n- ✓ Não dependem de domínio específico\r\n- ✓ Reutilizáveis em múltiplos contextos\r\n- ✓ Aceitam dados via props/slots\r\n- ✓ Emitem eventos genéricos\r\n\r\n**Exemplos Atuais**:\r\n\r\n### 1. **DynamicList.vue** ✅\r\n- **Propósito**: Renderizar listas de dados com opcional Drag & Drop e Seleção\r\n- **Props**: `schema`, `data`, `sortable`, `selectable`, `selectableMode` ('single' | 'multiple'), `layout` ('list' | 'grid')\r\n- **Slots**: `#item` (para renderização customizada por linha)\r\n- **Eventos**: `reorder`, `edit`, `delete`, `update`, `select`\r\n- **Uso**: Qualquer coleção que precise de visualização em lista/grid ou seleção\r\n- **Contextos**:\r\n  - Listas de CRUD\r\n  - Seletores de registros\r\n  - Dashboards\r\n  - Editors com slots customizados (\"DIY\" Pattern)\r\n\r\n**Padrão de Uso**:\r\n```vue\r\n<DynamicList\r\n  :schema=\"leadSchema\"\r\n  :data=\"leads\"\r\n  :sortable=\"true\"\r\n  :selectable=\"true\"\r\n  selectableMode=\"multiple\"\r\n  @select=\"handleSelection\"\r\n  @reorder=\"handleReorder\"\r\n/>\r\n```\r\n\r\n**Pattern Avançado (Slots)**:\r\n```vue\r\n<DynamicList :data=\"items\">\r\n  <template #item=\"{ item }\">\r\n    <MyCustomCard :data=\"item\" />\r\n  </template>\r\n</DynamicList>\r\n```\r\n\r\n### 2. **DynamicCRUD.vue** ✅ [EVOLVED]\r\n- **Propósito**: Orquestrador soberano de coleções de dados (List + Table + Form + Tabs).\r\n- **Orquestração de Interface**:\r\n  - **Wizard Mode**: Suporta renderização de formulários em passos (`group_render_mode: 'wizard'`) em modo full-page.\r\n  - **Nested CRUD**: Gerencia automaticamente abas de relações HasMany com suporte a:\r\n    - `initialViewMode`: Define se a aba abre como Tabela, Kanban, etc.\r\n    - `mode=\"modal\"`: Garante que o CRUD filho use modais para evitar conflitos de sidebar.\r\n- **Capacidades**:\r\n  - Auto-limpeza de propriedades (ex: oculta `location` em tabelas via `show_in_list`).\r\n  - Suporte a `crud_mode: 'split' | 'page' | 'modal'`.\r\n\r\n### 3. **DynamicForm.vue** ✅\r\n- **Propósito**: Renderizar formulários dinamicamente baseado em schema\r\n- **Props**: `properties`, `initialValues`, `compact`, `showActions`, `loading`\r\n- **Eventos**: `submit`, `change`, `cancel`\r\n- **Uso**: Standard Forms, Sidebars, Modais\r\n\r\n### 4. **RelationList.vue** ✅\r\n- **Propósito**: Gerenciar relacionamentos 1:N Embedded (JSONB)\r\n- **Pattern**: `storage: 'document_embed'`\r\n- **Props**: `schema`, `modelValue`, `disabled`\r\n- **Uso**: Listas de itens simples dentro de um objeto pai (ex: emails, telefones)\r\n\r\n### 5. **DynamicTable.vue** ✅\r\n- **Propósito**: Renderizar tabelas dinamicamente\r\n- **Props**: `schema`, `data`\r\n- **Eventos**: similares ao DynamicList\r\n\r\n### 6. **BiWidget.vue** ✅ [NEW]\r\n- **Propósito**: Componente \"Plug-and-Play\" para visualização de métricas BI.\r\n- **Capacidades**:\r\n  - Auto-inferência de tipo de gráfico (Donut, Line, KPI, Leaderboard).\r\n  - Suporte a séries temporais ponderadas (Financial Weighting).\r\n  - Seleção dinâmica de granularidade (Dia, Semana, Mês, Ano).\r\n  - Interatividade \"Click-to-Filter\" integrada.\r\n- **Props**: `metric` (blueprint gerado pela API), `total`.\r\n\r\n### 7. **DynamicFilter.vue** ✅ [EVOLVED]\r\n- **Propósito**: Painel de filtros reativo que governa a URL do sistema.\r\n- **Capacidades**:\r\n  - Geração dinâmica de campos baseado no Schema.\r\n  - Suporte a operadores complexos (between, in, like).\r\n  - Saída em formato **Flattened** (field[op]=val).\r\n  - Sincronização automática com `route.query`.\r\n\r\n---\r\n\r\n## 🎯 Componentes Concretos em Subpastas\r\n\r\n**Características**:\r\n- ✓ Específicos de um domínio/feature\r\n- ✓ Podem depender de stores, APIs do domínio\r\n- ✓ Implementam lógica customizada\r\n- ✓ Encapsulam regras de negócio\r\n- ✓ Podem usar componentes dinâmicos\r\n\r\n### **components/fastapp/PropertyListEditor.vue** ✅\r\n- **Propósito**: Editor especializado para reordenar propriedades de objetos do Schema\r\n- **Props**: `properties` (array de PropSchema)\r\n- **Eventos**: `update`, `reorder`\r\n- **Dependências**: draggable, PropSchema type\r\n- **Contexto**: Exclusivamente no Schema Manager\r\n- **Responsabilidades**:\r\n  - Gerir edição inline de propriedades\r\n  - Drag & Drop de propriedades\r\n  - Adição/remoção de propriedades\r\n  - Validação de metadados\r\n\r\n**Padrão de Uso**:\r\n```vue\r\n<!-- Apenas em schema.vue -->\r\n<PropertyListEditor\r\n  :properties=\"editingObject.properties\"\r\n  @update=\"onPropertyUpdate\"\r\n  @reorder=\"onPropertyReorder\"\r\n/>\r\n```\r\n\r\n### **components/crm/Kanban.vue** ✅\r\n- **Propósito**: Kanban board específico do CRM\r\n- **Dependências**: leadStore, LeadCard\r\n- **Contexto**: CRM leads pipeline\r\n\r\n### **components/crm/LeadCard.vue** ✅\r\n- **Propósito**: Card específico para exibir um lead no Kanban\r\n- **Contexto**: CRM\r\n\r\n---\r\n\r\n## 🏗️ Padrão de Decisão\r\n\r\n**Quando criar componente em `core/`?**\r\n```\r\n✓ Pode ser usado em 2+ contextos?\r\n✓ Não depende de domínio específico?\r\n✓ Funciona com dados genéricos via props?\r\n✓ Emite eventos genéricos?\r\n\r\nSE SIM → core/\r\n```\r\n\r\n**Quando criar componente em subfolder específica?**\r\n```\r\n✓ É específico de um feature/domínio?\r\n✓ Encapsula lógica de negócio?\r\n✓ Pode usar stores do domínio?\r\n✓ É interna daquele feature?\r\n\r\nSE SIM → fastapp/, crm/, lead/, etc.\r\n```\r\n\r\n---\r\n\r\n## 📋 Estrutura Proposta (Pós-Refactor)\r\n\r\n```\r\napp/\r\n├── components/\r\n│   ├── core/                          ← DINÂMICOS\r\n│   │   ├── BuilderHub.vue            ✅ Sovereign Navigation (top bar contextual)\r\n│   │   ├── AppMenu.vue               ✅ Sidebar colapsável (route-driven)\r\n│   │   ├── DynamicList.vue            ✅ genérico, reutilizável\r\n│   │   ├── DynamicForm.vue            ✅ genérico, reutilizável\r\n│   │   ├── DynamicTable.vue           ✅ genérico, reutilizável\r\n│   │   ├── DynamicFields.vue          ✅ genérico, Ontology v3\r\n│   │   ├── PrimitiveEditor.vue        ✅ genérico, reutilizável\r\n│   │   ├── RelationList.vue           ✅ Pattern: Embedded (JSONB)\r\n│   │   ├── DynamicIntegratedList.vue  ✅ Pattern: Physical (Relation tables)\r\n│   │   ├── RelationLookup.vue         ✅ Pattern: Physical (Foreign Key)\r\n│   │   ├── AssetUpload.vue            ✅ Pattern: semantic=asset\r\n│   │   ├── MapRenderer.vue            ✅ Pattern: spatial_type=point\r\n│   │   ├── BiWidget.vue               ✅ Engine de Visualização BI (Chart.js)\r\n│   │   └── DynamicFilter.vue          ✅ Filtro Universal Soberano (URL-driven)\r\n│   │\r\n│   ├── fastapp/                       ← ARCHITECT TOOLS\r\n│   │   ├── AgentChat.vue              ✅ Chat AI streaming com contexto\r\n│   │   ├── FastNode.vue               ✅ Node customizado Vue Flow\r\n│   │   ├── PropertyListEditor.vue     ✅ específico (Schema Manager)\r\n│   │   ├── SchemaPropertyManager.vue  ✅ específico (v3 Schema Editor)\r\n│   │   └── ...\r\n│   │\r\n│   ├── crm/                           ← CONCRETOS DO CRM\r\n│   │   ├── Kanban.vue                 ✅ específico (CRM)\r\n│   │   ├── LeadCard.vue               ✅ específico (CRM)\r\n│   │   └── ...\r\n│   │\r\n│   └── lead/                          ← CONCRETOS DO LEAD\r\n│       └── ...\r\n│\r\n└── pages/\r\n    └── fastapp/\r\n        └── example-dynamic-components.vue   ← KITCHEN SINK (Playground Oficial)\r\n```\r\n\r\n---\r\n\r\n## 🔄 Padrão de Integração\r\n\r\n### Fluxo Correto\r\n\r\n**Schema Manager**:\r\n```\r\nschema.vue (página)\r\n  ↓ usa\r\n[PropertyListEditor] (concreto em fastapp/)\r\n  ↓ que encapsula\r\nDynamicList (dinâmico em core/) → para futura reutilização\r\n```\r\n\r\n**CRM**:\r\n```\r\nleads.vue (página)\r\n  ↓ usa\r\n[Kanban] (concreto em crm/)\r\n  ↓ que contém\r\n[LeadCard] (concreto em crm/)\r\n  ↓ que poderia usar\r\nDynamicList (dinâmico em core/) com :sortable=\"true\"\r\n```\r\n\r\n**Forma Correta**:\r\n```vue\r\n<!-- Dentro de components/fastapp/PropertyListEditor.vue -->\r\n<script setup>\r\nimport draggable from 'vuedraggable';\r\n// Lógica especializada do Schema Manager aqui\r\n</script>\r\n\r\n<!-- Dentro de pages/fastapp/schema.vue -->\r\n<template>\r\n  <PropertyListEditor :properties=\"...\" @reorder=\"...\" />\r\n</template>\r\n```\r\n\r\n---\r\n\r\n## ❌ Anti-Patterns\r\n\r\n### ❌ Evitar\r\n```vue\r\n<!-- ❌ NÃO faça isso em components/core/ -->\r\n<PropertyListEditor />  <!-- muito concreto -->\r\n<SchemaObjectEditor />  <!-- muito concreto -->\r\n<CrmLeadForm />        <!-- muito concreto -->\r\n```\r\n\r\n### ❌ Evitar Duplicação\r\n```javascript\r\n// ❌ NÃO faça:\r\n// components/core/PropertyListEditor.vue (genérico)\r\n// components/fastapp/PropertyListEditor.vue (concreto)\r\n// → Conflita! Use apenas este: components/fastapp/\r\n```\r\n\r\n### ❌ Evitar Lógica Específica em Core\r\n```vue\r\n<!-- ❌ components/core/SomeComponent.vue -->\r\n<script setup>\r\nimport { useLeadStore } from '~/stores/lead';  // ❌ Específico!\r\nimport { useSystemStore } from '~/stores/system';  // ❌ Específico!\r\n</script>\r\n```\r\n\r\n---\r\n\r\n## ✅ Boas Práticas\r\n\r\n### 1️⃣ **Componente Genérico em Core**\r\n```vue\r\n<!-- components/core/DynamicList.vue -->\r\n<script setup>\r\nconst props = defineProps<{\r\n  schema: ObjectSchema;    // genérico\r\n  data: any[];            // genérico\r\n  sortable?: boolean;     // booleano simples\r\n}>();\r\n\r\nconst emit = defineEmits(['reorder', 'edit', 'delete']);\r\n// Sem dependências específicas!\r\n</script>\r\n```\r\n\r\n### 2️⃣ **Componente Concreto em Feature**\r\n```vue\r\n<!-- components/fastapp/PropertyListEditor.vue -->\r\n<script setup>\r\nimport type { PropSchema } from '~/types/schema';  // tipo compartilhado OK\r\n\r\nconst props = defineProps<{\r\n  properties: PropSchema[];  // específico da feature\r\n}>();\r\n\r\nconst emit = defineEmits(['update', 'reorder']);\r\n// Encapsula lógica especializada\r\n</script>\r\n```\r\n\r\n### 3️⃣ **Usar Concreto Dentro de Página**\r\n```vue\r\n<!-- pages/fastapp/schema.vue -->\r\n<template>\r\n  <PropertyListEditor \r\n    :properties=\"editingObject.properties\"\r\n    @reorder=\"onPropertyReorder\"\r\n  />\r\n</template>\r\n\r\n<script setup>\r\nimport PropertyListEditor from '~/components/fastapp/PropertyListEditor.vue';\r\n// Importar concreto em sua página\r\n</script>\r\n```\r\n\r\n---\r\n\r\n## 🚀 Próximo Passo\r\n\r\nSeguindo esse padrão, você pode:\r\n\r\n1. ✅ **Usar DynamicList** em múltiplos contextos com `sortable` prop\r\n2. ✅ **Criar specializations** (como PropertyListEditor) quando precisar\r\n3. ✅ **Manter core/** limpo e genérico\r\n4. ✅ **Reutilizar lógica** de reordenação via DynamicList\r\n5. ✅ **Encapsular domínio** em pastas específicas (fastapp/, crm/, lead/)\r\n\r\n---\r\n\r\n## 📚 Referência Rápida\r\n\r\n| Lugar | Tipo | Exemplo | Reutilizável |\r\n|-------|------|---------|--------------|\r\n| `components/core/` | Dinâmico | DynamicList, BuilderHub, AppMenu | ✅ Sim, em vários lugares |\r\n| `components/fastapp/` | Concreto | PropertyListEditor, AgentChat, FastNode | ❌ Apenas Ferramentas do Arquiteto |\r\n| `components/crm/` | Concreto | Kanban | ❌ Apenas CRM |\r\n| `pages/fastapp/` | Página | schema-v3.vue, diagram.vue, agent.vue | ❌ Apenas essas rotas |\r\n\r\n---\r\n\r\n> [!NOTE]\r\n> O `BuilderHub.vue` e `AppMenu.vue` vivem em `core/` porque são genéricos: não conhecem nenhum domínio específico. Eles consomem `systemStore` para navegação, não para lógica de negócio. O `AgentChat.vue` e `FastNode.vue` vivem em `fastapp/` porque são específicos das ferramentas do arquiteto.\r\n\r\n---\r\n\r\n**Data**: 22/02/2026  \r\n**Status**: ✅ Atualizado com Sovereign Navigation & Architect Tool Chain\r\n"}