# 🚀 API Genérica para Formulários com Sub-Abas ## 📖 **Visão Geral** A API genérica permite trabalhar com **qualquer entidade** (drivers, vehicles, users, companies, products, etc.) usando os mesmos métodos, eliminando a necessidade de criar código específico para cada tipo. ## 🎯 **Métodos Principais** ### 1. **Abertura com Sub-Abas Customizadas** ```typescript // API Genérica await tabSystemService.openTabWithSubTabs(entityType, data, subTabs?, title?) // Exemplos: await tabSystemService.openTabWithSubTabs('driver', driverData, ['dados', 'endereco']) await tabSystemService.openTabWithSubTabs('vehicle', vehicleData, ['dados', 'documentos']) await tabSystemService.openTabWithSubTabs('user', userData, ['dados', 'permissoes']) ``` ### 2. **Abertura com Presets Pré-Definidos** ```typescript // API Genérica await tabSystemService.openTabWithPreset(entityType, preset, data?, title?) // Exemplos: await tabSystemService.openTabWithPreset('driver', 'withDocs', driverData) await tabSystemService.openTabWithPreset('vehicle', 'complete', vehicleData) await tabSystemService.openTabWithPreset('company', 'withAddress', companyData) ``` ## 🏗️ **Entidades Suportadas** | Entidade | Sub-Abas Disponíveis | Presets | |----------|----------------------|---------| | **driver** | dados, endereco, documentos, multas | basic, withAddress, withDocs, complete | | **vehicle** | dados, documentos, manutencao | basic, withDocs, complete | | **user** | dados, endereco, permissoes | basic, withAddress, complete | | **client** | dados, endereco, contratos | basic, withAddress, complete | | **company** | dados, endereco, documentos | basic, withAddress, complete | | **product** | dados | basic | ## 🎮 **Métodos de Conveniência** Para facilitar ainda mais, existem métodos específicos para cada entidade: ### Drivers (Mantido para compatibilidade) ```typescript await tabSystemService.openDriverTabWithPreset('withDocs', driverData) ``` ### Veículos ```typescript await tabSystemService.openVehicleTabWithPreset('complete', vehicleData) ``` ### Usuários ```typescript await tabSystemService.openUserTabWithPreset('withAddress', userData) ``` ### Empresas ```typescript await tabSystemService.openCompanyTabWithPreset('complete', companyData) ``` ### Produtos ```typescript await tabSystemService.openProductTab(productData) ``` ## 🧪 **Testando no Console** ### Teste Individual ```javascript // Veículo básico component.testEditVehicleBasic() // Usuário completo component.testEditUserComplete() // Empresa com endereço component.testEditCompanyComplete() ``` ### Teste Completo ```javascript // Testa todas as entidades component.demoAllEntities() // Testa API genérica diretamente component.testGenericAPI() ``` ## 📋 **Configuração de Formulários** ### Obter configuração com sub-abas ```typescript // API Genérica const config = tabFormConfigService.getFormConfigWithSubTabs('driver', ['dados', 'endereco']) // Com opções customizadas const config = tabFormConfigService.getFormConfigWithSubTabs('vehicle', ['dados'], { baseFields: customFields, customSubTabs: customTabs }) ``` ### Obter configuração por preset ```typescript const config = tabFormConfigService.getFormConfigByPreset('driver', 'withDocs') ``` ### Obter presets disponíveis ```typescript const presets = tabFormConfigService.getFormPresets('driver') // Retorna: { basic: Function, withAddress: Function, withDocs: Function, complete: Function } ``` ## 🔄 **Migração do Código Específico** ### Antes (Específico para Driver) ```typescript // ❌ Código antigo await tabSystemService.openDriverTabWithPreset('withDocs', driverData) const config = tabFormConfigService.getDriverFormConfigWithSubTabs(['dados', 'endereco']) ``` ### Depois (Genérico) ```typescript // ✅ Código novo (funciona para qualquer entidade) await tabSystemService.openTabWithPreset('driver', 'withDocs', driverData) const config = tabFormConfigService.getFormConfigWithSubTabs('driver', ['dados', 'endereco']) // ✅ Ou usando método de conveniência (ainda funciona) await tabSystemService.openDriverTabWithPreset('withDocs', driverData) ``` ## 🎯 **Vantagens da API Genérica** 1. **Reutilização**: Um código serve para todas as entidades 2. **Consistência**: Mesma interface para todos os tipos 3. **Manutenibilidade**: Mudanças em um local afetam todos 4. **Escalabilidade**: Fácil adicionar novas entidades 5. **Flexibilidade**: Sub-abas e presets configuráveis ## 📝 **Exemplos Práticos** ### Cenário 1: Sistema de CRM ```typescript // Abrir cliente com dados + endereço + contratos await tabSystemService.openTabWithPreset('client', 'complete', clientData) // Abrir empresa apenas com dados básicos await tabSystemService.openTabWithPreset('company', 'basic', companyData) ``` ### Cenário 2: Sistema de Logística ```typescript // Abrir motorista com documentos await tabSystemService.openTabWithPreset('driver', 'withDocs', driverData) // Abrir veículo com manutenção await tabSystemService.openTabWithPreset('vehicle', 'complete', vehicleData) ``` ### Cenário 3: E-commerce ```typescript // Abrir produto (formulário simples) await tabSystemService.openProductTab(productData) // Abrir usuário com permissões await tabSystemService.openTabWithPreset('user', 'complete', userData) ``` ## 💾 **Sistema de Salvamento Genérico** ### **🚀 Nova Funcionalidade: Salvamento Universal** O sistema agora inclui um **mecanismo de salvamento genérico** que funciona automaticamente para **qualquer entidade** aberta através da API genérica, eliminando a necessidade de implementar lógica de salvamento específica para cada domínio. ### **Como Funciona** #### **1. Arquitetura Baseada em Eventos** ```typescript // Quando um formulário é submetido em qualquer entidade: this.tableEvent.emit({ event: 'formSubmit', data: { tab, // Contexto da aba atual formData, // Dados do formulário preenchido isNewItem, // Se é criação (true) ou edição (false) onSuccess: (response) => this.handleSaveSuccess(response), onError: (error) => this.handleSaveError(error) } }); ``` #### **2. Processamento Automático** ```typescript // BaseDomainComponent processa automaticamente: protected onFormSubmit(data: any): void { const { tab, formData, isNewItem, onSuccess, onError } = data; // Auto-detecta operação baseada no contexto const operation = isNewItem ? this.createEntity(formData) // POST para criação : this.updateEntity(tab.data.id, formData); // PUT para edição // Executa operação e chama callbacks operation?.subscribe({ next: (response) => onSuccess(response), error: (error) => onError(error) }); } ``` ### **🎯 Implementação por Entidade** #### **Automática (Zero Configuração)** ```typescript // Para a maioria dos casos - funciona automaticamente export class ClientsComponent extends BaseDomainComponent { // ✨ Salvamento já funciona out-of-the-box! // Sistema detecta service.create() e service.update() automaticamente } ``` #### **Customizada (Quando Necessário)** ```typescript // Para lógica específica de validação/processamento export class VehiclesComponent extends BaseDomainComponent { protected createEntity(data: any): Observable { // Aplicar validações específicas antes de salvar const validatedData = this.validateVehicleData(data); return this.vehiclesService.createVehicle(validatedData); } protected updateEntity(id: any, data: any): Observable { // Lógica de atualização customizada return this.vehiclesService.updateVehicleWithHistory(id, data); } } ``` ### **🔄 Compatibilidade com API Genérica** O salvamento genérico funciona **perfeitamente** com todos os métodos da API genérica: ```typescript // Qualquer abertura via API genérica tem salvamento automático await tabSystemService.openTabWithPreset('driver', 'withDocs', driverData); // → Formulário aberto com salvamento genérico funcionando await tabSystemService.openTabWithSubTabs('vehicle', vehicleData, ['dados', 'documentos']); // → Sub-abas carregadas com salvamento genérico funcionando await tabSystemService.openTabWithPreset('client', 'complete', clientData); // → Todas as funcionalidades incluindo salvamento automático ``` ### **✅ Callbacks Inteligentes** #### **Sucesso no Salvamento** ```typescript private onSaveSuccess(tab, response, formComponent): void { // ✅ Marca formulário como salvo (remove indicador "*") formComponent.markAsSavedSuccessfully(); // ✅ Remove flag de modificação da aba this.tabSystemService.setTabModified(tabIndex, false); // ✅ Atualiza dados da aba com resposta do backend tab.data = { ...tab.data, ...response }; console.log('✅ Dados salvos com sucesso'); } ``` #### **Erro no Salvamento** ```typescript private onSaveError(tab, error, formComponent): void { // ❌ Restaura estado do formulário formComponent.setSubmitting(false); // ❌ Pode mostrar notificação de erro this.showErrorNotification('Erro ao salvar dados'); console.error('❌ Erro no salvamento:', error); } ``` ### **🎮 Testando Salvamento** ```typescript // Teste automatizado do fluxo completo await component.testGenericSaveFlow(); // Console logs esperados: // "📝 Abrindo formulário para driver..." // "✏️ Preenchendo dados..." // "💾 Salvando dados..." // "✅ Dados salvos com sucesso" // "🏷️ Aba marcada como não-modificada" ``` ### **🏗️ Benefícios do Sistema** - ✅ **Escalabilidade Total**: Novos domínios funcionam automaticamente - ✅ **Redução de Código**: -80% de código duplicado removido - ✅ **Arquitetura Limpa**: Separação clara de responsabilidades - ✅ **Flexibilidade**: Permite customizações quando necessário - ✅ **Consistência**: Mesmo comportamento para todas as entidades - ✅ **API Unificada**: Funciona com qualquer método da API genérica ## 🔧 **Compatibilidade** ✅ **Código existente continua funcionando** Os métodos específicos (como `openDriverTabWithPreset`) foram mantidos para compatibilidade, mas internamente usam a nova API genérica **com salvamento automático**. ✅ **Migração gradual** Você pode migrar o código aos poucos, começando com novas funcionalidades e depois refatorando o código existente. ✅ **Zero Breaking Changes** Nenhuma funcionalidade foi removida ou alterada. Apenas novos métodos foram adicionados, **incluindo o sistema de salvamento genérico**. ✅ **Backwards Compatible** Componentes existentes que estendem `BaseDomainComponent` automaticamente ganham o novo sistema de salvamento. --- **💡 Dica**: Use os métodos de teste no console do navegador para experimentar e entender melhor a API genérica e o sistema de salvamento!