COMPONENT_ARCHITECTURE.md

đŸ—ïž Arquitetura de Componentes — PadrĂŁo DinĂąmico vs Concreto

Public Markdown Document

đŸ—ïž Arquitetura de Componentes — PadrĂŁo DinĂąmico vs Concreto

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:

732 palavras24 headingsrepository root

đŸ—ïž 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. 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:

<DynamicList
  :schema="leadSchema"
  :data="leads"
  :sortable="true"
  :selectable="true"
  selectableMode="multiple"
  @select="handleSelection"
  @reorder="handleReorder"
/>

Pattern Avançado (Slots):

<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:

<!-- 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:

<!-- 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

<!-- ❌ NÃO faça isso em components/core/ -->
<PropertyListEditor />  <!-- muito concreto -->
<SchemaObjectEditor />  <!-- muito concreto -->
<CrmLeadForm />        <!-- muito concreto -->

❌ Evitar Duplicação

// ❌ 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

<!-- ❌ 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

<!-- 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

<!-- 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

<!-- 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