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