820 lines
28 KiB
JavaScript
820 lines
28 KiB
JavaScript
// 🎯 GERADORES V2.0 - CREATE-DOMAIN
|
|
// Arquivo complementar com as funções de geração para o create-domain-v2.js
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// ===== GERAÇÃO DO COMPONENT V2.0 =====
|
|
function generateComponentV2(domainConfig) {
|
|
const componentName = capitalize(domainConfig.name);
|
|
|
|
return `import { Component, ChangeDetectorRef } from "@angular/core";
|
|
import { CommonModule, DatePipe${domainConfig.hasFooter ? ', CurrencyPipe' : ''} } from "@angular/common";
|
|
|
|
import { TitleService } from "../../shared/services/theme/title.service";
|
|
import { HeaderActionsService } from "../../shared/services/header-actions.service";
|
|
import { ${componentName}Service } from "./${domainConfig.name}.service";
|
|
import { ${componentName} } from "./${domainConfig.name}.interface";
|
|
|
|
import { TabSystemComponent } from "../../shared/components/tab-system/tab-system.component";
|
|
import { BaseDomainComponent, DomainConfig } from "../../shared/components/base-domain/base-domain.component";
|
|
import { TabFormConfig } from "../../shared/interfaces/generic-tab-form.interface";
|
|
import { TabFormConfigService } from "../../shared/components/tab-system/services/tab-form-config.service";
|
|
${domainConfig.hasBulkActions ? `import { ConfirmationService } from "../../shared/services/confirmation/confirmation.service";` : ''}
|
|
${domainConfig.hasDateRangeUtils ? `import { DateRangeShortcuts } from "../../shared/utils/date-range.utils";` : ''}
|
|
|
|
// 🔧 SearchOptionsLibrary inline (V2.0)
|
|
const SearchOptionsLibrary = {
|
|
statusComplex: [
|
|
{ value: 'active', label: 'Ativo' },
|
|
{ value: 'inactive', label: 'Inativo' },
|
|
{ value: 'pending', label: 'Pendente' },
|
|
{ value: 'cancelled', label: 'Cancelado' },
|
|
{ value: 'suspended', label: 'Suspenso' },
|
|
{ value: 'archived', label: 'Arquivado' }
|
|
]
|
|
};
|
|
|
|
/**
|
|
* 🎯 ${componentName}Component - Gestão de ${domainConfig.displayName}
|
|
*
|
|
* ✨ Implementa BaseDomainComponent + Registry Pattern
|
|
* 🚀 Auto-registro de configurações para escalabilidade infinita!
|
|
*
|
|
* 🆕 V2.0 Features:
|
|
${domainConfig.hasFooter ? ` * - FooterConfig: Configuração avançada de rodapé` : ''}
|
|
${domainConfig.hasCheckboxGrouped ? ` * - CheckboxGrouped: ${domainConfig.checkboxGroupedConfig?.groups?.length || 'N/A'} grupos configurados` : ''}
|
|
${domainConfig.hasBulkActions ? ` * - BulkActions: Ações em lote configuradas` : ''}
|
|
${domainConfig.hasDateRangeUtils ? ` * - DateRangeUtils: Integração automática` : ''}
|
|
*/
|
|
@Component({
|
|
selector: 'app-${domainConfig.name}',
|
|
standalone: true,
|
|
imports: [CommonModule, TabSystemComponent],
|
|
providers: [DatePipe${domainConfig.hasFooter ? ', CurrencyPipe' : ''}],
|
|
templateUrl: './${domainConfig.name}.component.html',
|
|
styleUrl: './${domainConfig.name}.component.scss'
|
|
})
|
|
export class ${componentName}Component extends BaseDomainComponent<${componentName}> {
|
|
|
|
constructor(
|
|
private ${domainConfig.name}Service: ${componentName}Service,
|
|
titleService: TitleService,
|
|
headerActionsService: HeaderActionsService,
|
|
cdr: ChangeDetectorRef,
|
|
private datePipe: DatePipe,
|
|
${domainConfig.hasFooter ? `private currencyPipe: CurrencyPipe,` : ''}
|
|
private tabFormConfigService: TabFormConfigService${domainConfig.hasBulkActions ? `,
|
|
private confirmationService: ConfirmationService` : ''}
|
|
) {
|
|
super(titleService, headerActionsService, cdr, ${domainConfig.name}Service);
|
|
this.registerFormConfig();
|
|
}
|
|
|
|
private registerFormConfig(): void {
|
|
this.tabFormConfigService.registerFormConfig('${domainConfig.name}', () => this.getFormConfig());
|
|
}
|
|
|
|
// ========================================
|
|
// 🎯 CONFIGURAÇÃO DO DOMÍNIO ${domainConfig.name.toUpperCase()}
|
|
// ========================================
|
|
protected override getDomainConfig(): DomainConfig {
|
|
return {
|
|
domain: '${domainConfig.name}',
|
|
title: '${domainConfig.displayName}',
|
|
entityName: '${domainConfig.name}',
|
|
pageSize: 50,
|
|
subTabs: [${generateSubTabsList(domainConfig)}],
|
|
columns: [
|
|
{
|
|
field: "id",
|
|
header: "Id",
|
|
sortable: true,
|
|
filterable: true,
|
|
search: true,
|
|
searchType: "number"
|
|
},
|
|
{
|
|
field: "name",
|
|
header: "Nome",
|
|
sortable: true,
|
|
filterable: true,
|
|
search: true,
|
|
searchType: "text"${domainConfig.hasFooter && domainConfig.footerConfig?.columns?.find(c => c.field === 'name') ? `,
|
|
footer: ${JSON.stringify(domainConfig.footerConfig.columns.find(c => c.field === 'name'), null, 10).replace(/"/g, "'")}` : ''}
|
|
},
|
|
${generateStatusColumn(domainConfig)}
|
|
${generateFooterColumns(domainConfig)}
|
|
{
|
|
field: "createdAt",
|
|
header: "Criado em",
|
|
sortable: true,
|
|
filterable: true,
|
|
search: true,
|
|
searchType: "date",
|
|
label: (date: any) => this.datePipe.transform(date, "dd/MM/yyyy HH:mm") || "-"
|
|
}
|
|
]${domainConfig.hasBulkActions ? `,
|
|
bulkActions: ${generateBulkActionsConfig(domainConfig)}` : ''}${domainConfig.hasSideCard || domainConfig.hasAdvancedSideCard ? `,
|
|
sideCard: ${generateSideCardConfig(domainConfig)}` : ''}
|
|
};
|
|
}
|
|
|
|
// ========================================
|
|
// 📋 CONFIGURAÇÃO COMPLETA DO FORMULÁRIO
|
|
// ========================================
|
|
getFormConfig(): TabFormConfig {
|
|
return {
|
|
title: 'Dados do ${componentName}',
|
|
entityType: '${domainConfig.name}',
|
|
fields: [],
|
|
submitLabel: 'Salvar ${componentName}',
|
|
showCancelButton: true,
|
|
subTabs: [
|
|
{
|
|
id: 'dados',
|
|
label: 'Dados Básicos',
|
|
icon: 'fa-info-circle',
|
|
enabled: true,
|
|
order: 1,
|
|
templateType: 'fields',
|
|
requiredFields: ['name'],
|
|
fields: [
|
|
{
|
|
key: 'name',
|
|
label: 'Nome',
|
|
type: 'text',
|
|
required: true,
|
|
placeholder: 'Digite o nome'
|
|
}${generateFormFields(domainConfig)}
|
|
]
|
|
}${generateFormSubTabs(domainConfig)}
|
|
]
|
|
};
|
|
}
|
|
|
|
${generateBulkActionMethods(domainConfig)}
|
|
}`;
|
|
}
|
|
|
|
// ===== GERAÇÃO DO SERVICE V2.0 =====
|
|
function generateServiceV2(domainConfig) {
|
|
const componentName = capitalize(domainConfig.name);
|
|
|
|
return `import { Injectable } from '@angular/core';
|
|
import { Observable, of, map } from 'rxjs';
|
|
import { catchError } from 'rxjs/operators';
|
|
${domainConfig.hasDateRangeUtils ? `import { firstValueFrom } from 'rxjs';` : ''}
|
|
|
|
import { ${componentName} } from './${domainConfig.name}.interface';
|
|
import { ApiClientService } from '../../shared/services/api/api-client.service';
|
|
import { DomainService } from '../../shared/components/base-domain/base-domain.component';
|
|
import { PaginatedResponse } from '../../shared/interfaces/paginate.interface';
|
|
${domainConfig.hasDateRangeUtils ? `import { DateRangeShortcuts } from '../../shared/utils/date-range.utils';` : ''}
|
|
|
|
/**
|
|
* 🎯 ${componentName}Service - Serviço para gestão de ${domainConfig.displayName}
|
|
*
|
|
* ✨ Implementa DomainService<${componentName}>
|
|
* 🚀 Padrões de nomenclatura obrigatórios: create, update, delete, getById, get${componentName}s
|
|
*
|
|
* 🆕 V2.0 Features:
|
|
${domainConfig.hasDateRangeUtils ? ` * - DateRangeUtils: Filtros de data automáticos` : ''}
|
|
* - ApiClientService: NUNCA usar HttpClient diretamente
|
|
* - Fallback: Dados mock para desenvolvimento
|
|
*/
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class ${componentName}Service implements DomainService<${componentName}> {
|
|
|
|
constructor(
|
|
private apiClient: ApiClientService
|
|
) {}
|
|
|
|
// ========================================
|
|
// 🎯 IMPLEMENTAÇÃO DA INTERFACE DOMAINSERVICE
|
|
// ========================================
|
|
|
|
getEntities(page: number, pageSize: number, filters: any): Observable<{
|
|
data: ${componentName}[];
|
|
totalCount: number;
|
|
pageCount: number;
|
|
currentPage: number;
|
|
}> {
|
|
return this.get${componentName}s(page, pageSize, filters).pipe(
|
|
map(response => ({
|
|
data: response.data,
|
|
totalCount: response.totalCount,
|
|
pageCount: response.pageCount,
|
|
currentPage: response.currentPage
|
|
}))
|
|
);
|
|
}
|
|
|
|
create(data: any): Observable<${componentName}> {
|
|
return this.apiClient.post<${componentName}>('${domainConfig.name}s', data);
|
|
}
|
|
|
|
update(id: any, data: any): Observable<${componentName}> {
|
|
return this.apiClient.patch<${componentName}>(\`${domainConfig.name}s/\${id}\`, data);
|
|
}
|
|
|
|
// ========================================
|
|
// 🎯 MÉTODOS ESPECÍFICOS DO DOMÍNIO
|
|
// ========================================
|
|
|
|
get${componentName}s(
|
|
page = 1,
|
|
limit = 10,
|
|
filters?: any
|
|
): Observable<PaginatedResponse<${componentName}>> {
|
|
${domainConfig.hasDateRangeUtils ? `
|
|
// ✨ V2.0: DateRangeUtils automático
|
|
const dateFilters = filters?.dateRange ? DateRangeShortcuts.currentMonth() : {};
|
|
const allFilters = { ...filters, ...dateFilters };
|
|
` : 'const allFilters = filters || {};'}
|
|
|
|
let url = \`${domainConfig.name}s?page=\${page}&limit=\${limit}\`;
|
|
|
|
if (allFilters) {
|
|
const params = new URLSearchParams();
|
|
|
|
for (const [key, value] of Object.entries(allFilters)) {
|
|
if (value) {
|
|
params.append(key, value.toString());
|
|
}
|
|
}
|
|
|
|
if (params.toString()) {
|
|
url += \`&\${params.toString()}\`;
|
|
}
|
|
}
|
|
|
|
return this.apiClient.get<PaginatedResponse<${componentName}>>(url).pipe(
|
|
catchError(error => {
|
|
console.warn('⚠️ Backend indisponível, usando dados de fallback', error);
|
|
return of(this.getFallbackData(page, limit, allFilters));
|
|
})
|
|
);
|
|
}
|
|
|
|
getById(id: string): Observable<${componentName}> {
|
|
return this.apiClient.get<${componentName}>(\`${domainConfig.name}s/\${id}\`);
|
|
}
|
|
|
|
delete(id: string): Observable<void> {
|
|
return this.apiClient.delete<void>(\`${domainConfig.name}s/\${id}\`);
|
|
}
|
|
|
|
${generateBulkServiceMethods(domainConfig)}
|
|
|
|
private getFallbackData(page: number, limit: number, filters?: any): PaginatedResponse<${componentName}> {
|
|
const mockData: ${componentName}[] = ${generateMockData(domainConfig)};
|
|
|
|
const startIndex = (page - 1) * limit;
|
|
const endIndex = startIndex + limit;
|
|
const paginatedData = mockData.slice(startIndex, endIndex);
|
|
|
|
const totalPages = Math.ceil(mockData.length / limit);
|
|
|
|
return {
|
|
data: paginatedData,
|
|
totalCount: mockData.length,
|
|
pageCount: totalPages,
|
|
currentPage: page,
|
|
isFirstPage: page === 1,
|
|
isLastPage: page === totalPages,
|
|
nextPage: page < totalPages ? page + 1 : null,
|
|
previousPage: page > 1 ? page - 1 : null
|
|
};
|
|
}
|
|
}`;
|
|
}
|
|
|
|
// ===== GERAÇÃO DA INTERFACE V2.0 =====
|
|
async function generateInterfaceV2(domainConfig) {
|
|
const componentName = capitalize(domainConfig.name);
|
|
|
|
// 🚀 USAR API ANALYZER para geração automática de interface
|
|
try {
|
|
const { analyzeAPIForDomain } = require('./create-domain-v2-api-analyzer.js');
|
|
|
|
// 🔍 MODO FLEXÍVEL - Tenta API mas permite fallback
|
|
console.log(`🔍 Iniciando análise híbrida para domínio: ${domainConfig.name}`);
|
|
const apiAnalysis = await analyzeAPIForDomain(domainConfig.name, undefined, false);
|
|
|
|
if (apiAnalysis.success && apiAnalysis.interface) {
|
|
console.log(`✅ Interface gerada via API Analyzer - Estratégia: ${apiAnalysis.strategy}`);
|
|
console.log(`📊 Metadados:`, apiAnalysis.metadata);
|
|
|
|
// Adicionar campos específicos do V2.0 se não estiverem presentes
|
|
let interfaceCode = apiAnalysis.interface;
|
|
|
|
// 🔧 Adicionar campo de imagens PRIMEIRO (SideCard)
|
|
if (domainConfig.hasAdvancedSideCard && domainConfig.sideCardConfig?.imageField) {
|
|
const imageField = `${domainConfig.sideCardConfig.imageField}?: string[]; // Imagens do SideCard V2.0`;
|
|
|
|
if (!interfaceCode.includes(domainConfig.sideCardConfig.imageField)) {
|
|
// Adicionar antes do último }
|
|
const lastBraceIndex = interfaceCode.lastIndexOf('}');
|
|
interfaceCode = interfaceCode.slice(0, lastBraceIndex) + ` ${imageField}\n` + interfaceCode.slice(lastBraceIndex);
|
|
}
|
|
}
|
|
|
|
// 🔧 Adicionar checkbox grouped DEPOIS (para não interferir com o replace)
|
|
if (domainConfig.hasCheckboxGrouped) {
|
|
const checkboxField = `${domainConfig.checkboxGroupedConfig?.fieldName}?: {
|
|
[groupId: string]: {
|
|
[itemId: string]: boolean;
|
|
};
|
|
}; // Checkbox agrupado V2.0`;
|
|
|
|
if (!interfaceCode.includes(domainConfig.checkboxGroupedConfig?.fieldName)) {
|
|
// Adicionar antes do último }
|
|
const lastBraceIndex = interfaceCode.lastIndexOf('}');
|
|
interfaceCode = interfaceCode.slice(0, lastBraceIndex) + ` ${checkboxField}\n` + interfaceCode.slice(lastBraceIndex);
|
|
}
|
|
}
|
|
|
|
// Adicionar comentário sobre a estratégia usada
|
|
const strategyComment = `/**
|
|
* 🎯 ${componentName} Interface - V2.0 + API Analysis
|
|
*
|
|
* ✨ Auto-generated using API Analyzer - Strategy: ${apiAnalysis.strategy}
|
|
* 📊 Source: ${apiAnalysis.metadata.source || 'unknown'}
|
|
* 🔗 Fields detected: ${apiAnalysis.fields.length}
|
|
*
|
|
* 🆕 V2.0 Features Enhanced:
|
|
${domainConfig.hasCheckboxGrouped ? ` * - ${domainConfig.checkboxGroupedConfig?.fieldName}: Checkbox agrupado configurado` : ''}
|
|
${domainConfig.hasAdvancedSideCard ? ` * - ${domainConfig.sideCardConfig?.imageField}: Imagens para SideCard avançado` : ''}
|
|
*/`;
|
|
|
|
return interfaceCode.replace(/\/\*\*[\s\S]*?\*\//, strategyComment);
|
|
}
|
|
} catch (error) {
|
|
// 🚨 TRATAR ERROS CRÍTICOS DO MODO RIGOROSO
|
|
if (error.code === 'ENDPOINT_ACCESS_FAILED') {
|
|
console.error(`\n🚨 ERRO CRÍTICO: ${error.message}`);
|
|
console.error(`🔗 Endpoint: ${error.endpoint}`);
|
|
console.error(`\n📋 POSSÍVEIS SOLUÇÕES:`);
|
|
console.error(`1. 🔐 Verificar autenticação (Bearer token necessário?)`);
|
|
console.error(`2. 🌐 Verificar CORS (bloqueando requisições?)`);
|
|
console.error(`3. 📁 Verificar estrutura da resposta (tem campo 'data'?)`);
|
|
console.error(`4. 🔧 Verificar se endpoint está ativo no backend`);
|
|
console.error(`\n❌ INTERROMPENDO GERAÇÃO DE DOMÍNIO`);
|
|
throw error;
|
|
}
|
|
|
|
if (error.code === 'STRICT_MODE_FAILURE') {
|
|
console.error(`\n🚨 ERRO CRÍTICO: ${error.message}`);
|
|
console.error(`\n📋 AÇÕES NECESSÁRIAS:`);
|
|
console.error(`1. 🔍 Verificar se endpoint /${domainConfig.name}/ existe na API`);
|
|
console.error(`2. 🔐 Verificar configuração de autenticação`);
|
|
console.error(`3. 🌐 Verificar configuração de CORS`);
|
|
console.error(`4. 📊 Verificar estrutura da resposta da API`);
|
|
console.error(`\n❌ INTERROMPENDO GERAÇÃO DE DOMÍNIO`);
|
|
throw error;
|
|
}
|
|
|
|
// Outros erros - fallback com aviso
|
|
console.log(`⚠️ API Analyzer falhou: ${error.message}`);
|
|
console.log('🔄 Usando geração de interface padrão...');
|
|
}
|
|
|
|
// ✨ FALLBACK: Geração padrão V2.0 (se API Analyzer falhar)
|
|
return `/**
|
|
* 🎯 ${componentName} Interface - V2.0 Fallback
|
|
*
|
|
* Representa a estrutura de dados de ${domainConfig.displayName.toLowerCase()} no sistema.
|
|
*
|
|
* ⚠️ Generated using fallback template (API not available)
|
|
*
|
|
* 🆕 V2.0 Features:
|
|
${domainConfig.hasCheckboxGrouped ? ` * - ${domainConfig.checkboxGroupedConfig.fieldName}: Checkbox agrupado configurado` : ''}
|
|
${domainConfig.hasColor ? ` * - color: Configuração de cor com name e code` : ''}
|
|
*/
|
|
export interface ${componentName} {
|
|
id: number;
|
|
name: string;
|
|
${domainConfig.hasStatus ? `status: string;` : ''}
|
|
${domainConfig.hasColor ? `color?: {
|
|
name: string;
|
|
code: string;
|
|
};` : ''}
|
|
${domainConfig.hasKilometer ? `odometer?: number;` : ''}
|
|
${domainConfig.hasCheckboxGrouped ? `${domainConfig.checkboxGroupedConfig.fieldName}?: {
|
|
[groupId: string]: {
|
|
[itemId: string]: boolean;
|
|
};
|
|
};` : ''}
|
|
description?: string;
|
|
createdAt?: string;
|
|
updatedAt?: string;
|
|
${domainConfig.hasAdvancedSideCard && domainConfig.sideCardConfig.imageField ? `${domainConfig.sideCardConfig.imageField}?: string[];` : ''}
|
|
}`;
|
|
}
|
|
|
|
// ===== HELPERS =====
|
|
|
|
function generateSubTabsList(domainConfig) {
|
|
const tabs = ["'dados'"];
|
|
|
|
if (domainConfig.hasPhotos) tabs.push("'photos'");
|
|
if (domainConfig.hasCheckboxGrouped) tabs.push(`'${domainConfig.checkboxGroupedConfig.fieldName}'`);
|
|
|
|
return tabs.join(', ');
|
|
}
|
|
|
|
function generateStatusColumn(domainConfig) {
|
|
if (!domainConfig.hasStatus) return '';
|
|
|
|
const searchOptions = domainConfig.hasExtendedSearchOptions && domainConfig.searchOptionsConfig?.useStatusComplex
|
|
? 'SearchOptionsLibrary.statusComplex'
|
|
: `[
|
|
{ value: 'active', label: 'Ativo' },
|
|
{ value: 'inactive', label: 'Inativo' }
|
|
]`;
|
|
|
|
return `{
|
|
field: "status",
|
|
header: "Status",
|
|
sortable: true,
|
|
filterable: true,
|
|
allowHtml: true,
|
|
search: true,
|
|
searchType: "select",
|
|
searchOptions: ${searchOptions},
|
|
label: (value: any) => {
|
|
const statusConfig: { [key: string]: { label: string, class: string } } = {
|
|
'active': { label: 'Ativo', class: 'status-active' },
|
|
'inactive': { label: 'Inativo', class: 'status-inactive' }
|
|
};
|
|
const config = statusConfig[value?.toLowerCase()] || { label: value, class: 'status-unknown' };
|
|
return \`<span class="status-badge \${config.class}">\${config.label}</span>\`;
|
|
}
|
|
},`;
|
|
}
|
|
|
|
function generateFooterColumns(domainConfig) {
|
|
if (!domainConfig.hasFooter || !domainConfig.footerConfig?.columns?.length) return '';
|
|
|
|
return domainConfig.footerConfig.columns
|
|
.filter(col => col.field !== 'name') // Já incluído na coluna name
|
|
.map(col => `{
|
|
field: "${col.field}",
|
|
header: "${capitalize(col.field)}",
|
|
sortable: true,
|
|
filterable: true,
|
|
search: true,
|
|
searchType: "${col.type === 'count' ? 'number' : 'text'}",
|
|
${col.format === 'currency' ? `label: (value: any) => {
|
|
if (!value) return '-';
|
|
return this.currencyPipe.transform(value, 'BRL', 'symbol', '1.2-2', 'pt-BR') || '-';
|
|
},` : ''}
|
|
footer: ${JSON.stringify(col, null, 10).replace(/"/g, "'")}
|
|
}`)
|
|
.join(',\n ');
|
|
}
|
|
|
|
function generateBulkActionsConfig(domainConfig) {
|
|
if (!domainConfig.hasBulkActions) return '';
|
|
|
|
// 🔧 Ações padrão se não configuradas
|
|
const defaultActions = [
|
|
{
|
|
id: 'delete',
|
|
label: 'Excluir Selecionados',
|
|
icon: 'delete',
|
|
action: 'this.bulkDelete(selectedItems)'
|
|
}
|
|
];
|
|
|
|
const actions = (domainConfig.bulkActionsConfig?.actions || defaultActions)
|
|
.map(action => {
|
|
if (action.subActions) {
|
|
return `{
|
|
id: '${action.id}',
|
|
label: '${action.label}',
|
|
icon: '${action.icon}',
|
|
subActions: [
|
|
${action.subActions.map(sub => `{
|
|
id: '${sub.id}',
|
|
label: '${sub.label}',
|
|
icon: '${sub.icon}',
|
|
action: ${sub.action}
|
|
}`).join(',\n ')}
|
|
]
|
|
}`;
|
|
} else {
|
|
return `{
|
|
id: '${action.id}',
|
|
label: '${action.label}',
|
|
icon: '${action.icon}',
|
|
action: ${action.action}
|
|
}`;
|
|
}
|
|
})
|
|
.join(',\n ');
|
|
|
|
return `[
|
|
${actions}
|
|
]`;
|
|
}
|
|
|
|
function generateSideCardConfig(domainConfig) {
|
|
if (domainConfig.hasAdvancedSideCard) {
|
|
return `{
|
|
enabled: true,
|
|
title: "Resumo do ${capitalize(domainConfig.name)}",
|
|
position: "right",
|
|
width: "400px",
|
|
component: "summary",
|
|
data: {
|
|
${domainConfig.sideCardConfig.imageField ? `imageField: "${domainConfig.sideCardConfig.imageField}",` : ''}
|
|
displayFields: [
|
|
{
|
|
key: "name",
|
|
label: "Nome",
|
|
type: "text"
|
|
},
|
|
${domainConfig.hasStatus ? `{
|
|
key: "status",
|
|
label: "Status",
|
|
type: "status"
|
|
},` : ''}
|
|
{
|
|
key: "createdAt",
|
|
label: "Criado em",
|
|
type: "date"
|
|
}
|
|
],
|
|
${domainConfig.hasStatus ? `statusConfig: {
|
|
"active": { label: "Ativo", color: "#d4edda", icon: "fa-check-circle" },
|
|
"inactive": { label: "Inativo", color: "#f8d7da", icon: "fa-times-circle" }
|
|
}` : ''}
|
|
}
|
|
}`;
|
|
}
|
|
|
|
return `{
|
|
enabled: true,
|
|
title: "Resumo do ${capitalize(domainConfig.name)}",
|
|
position: "right",
|
|
width: "400px",
|
|
component: "summary",
|
|
data: {
|
|
displayFields: [
|
|
{
|
|
key: "name",
|
|
label: "Nome",
|
|
type: "text"
|
|
},
|
|
${domainConfig.hasStatus ? `{
|
|
key: "status",
|
|
label: "Status",
|
|
type: "status"
|
|
},` : ''}
|
|
{
|
|
key: "createdAt",
|
|
label: "Criado em",
|
|
type: "date"
|
|
}
|
|
],
|
|
statusField: "status"
|
|
}
|
|
}`;
|
|
}
|
|
|
|
function generateFormFields(domainConfig) {
|
|
let fields = [];
|
|
|
|
if (domainConfig.hasStatus) {
|
|
const statusOptions = domainConfig.hasExtendedSearchOptions && domainConfig.searchOptionsConfig.useStatusComplex
|
|
? `[
|
|
{ value: 'active', label: 'Ativo' },
|
|
{ value: 'inactive', label: 'Inativo' },
|
|
{ value: 'pending', label: 'Pendente' },
|
|
{ value: 'processing', label: 'Processando' },
|
|
{ value: 'completed', label: 'Concluído' },
|
|
{ value: 'cancelled', label: 'Cancelado' }
|
|
]`
|
|
: `[
|
|
{ value: 'active', label: 'Ativo' },
|
|
{ value: 'inactive', label: 'Inativo' }
|
|
]`;
|
|
|
|
fields.push(`{
|
|
key: 'status',
|
|
label: 'Status',
|
|
type: 'select',
|
|
required: true,
|
|
options: ${statusOptions}
|
|
}`);
|
|
}
|
|
|
|
if (domainConfig.hasKilometer) {
|
|
fields.push(`{
|
|
key: 'odometer',
|
|
label: 'Quilometragem',
|
|
type: 'kilometer-input',
|
|
placeholder: '0',
|
|
formatOptions: {
|
|
locale: 'pt-BR',
|
|
useGrouping: true,
|
|
suffix: ' km'
|
|
}
|
|
}`);
|
|
}
|
|
|
|
if (domainConfig.hasColor) {
|
|
fields.push(`{
|
|
key: 'color',
|
|
label: 'Cor',
|
|
type: 'color-input',
|
|
required: false,
|
|
options: [
|
|
{ value: { name: 'Branco', code: '#ffffff' }, label: 'Branco' },
|
|
{ value: { name: 'Preto', code: '#000000' }, label: 'Preto' },
|
|
{ value: { name: 'Azul', code: '#0000ff' }, label: 'Azul' },
|
|
{ value: { name: 'Vermelho', code: '#ff0000' }, label: 'Vermelho' }
|
|
]
|
|
}`);
|
|
}
|
|
|
|
return fields.length > 0 ? ',\n ' + fields.join(',\n ') : '';
|
|
}
|
|
|
|
function generateFormSubTabs(domainConfig) {
|
|
let subTabs = [];
|
|
|
|
if (domainConfig.hasPhotos) {
|
|
subTabs.push(`{
|
|
id: 'photos',
|
|
label: 'Fotos',
|
|
icon: 'fa-camera',
|
|
enabled: true,
|
|
order: 2,
|
|
templateType: 'component',
|
|
requiredFields: [],
|
|
dynamicComponent: {
|
|
selector: 'app-send-image',
|
|
inputs: {
|
|
entityType: '${domainConfig.name}',
|
|
maxFiles: 5,
|
|
acceptedTypes: ['image/jpeg', 'image/png']
|
|
}
|
|
}
|
|
}`);
|
|
}
|
|
|
|
if (domainConfig.hasCheckboxGrouped) {
|
|
subTabs.push(`{
|
|
id: '${domainConfig.checkboxGroupedConfig.fieldName}',
|
|
label: '${capitalize(domainConfig.checkboxGroupedConfig.fieldName)}',
|
|
icon: 'fa-cog',
|
|
enabled: true,
|
|
order: ${subTabs.length + 3},
|
|
templateType: 'fields',
|
|
requiredFields: ['${domainConfig.checkboxGroupedConfig.fieldName}'],
|
|
fields: [
|
|
{
|
|
key: '${domainConfig.checkboxGroupedConfig.fieldName}',
|
|
label: '${capitalize(domainConfig.checkboxGroupedConfig.fieldName)}',
|
|
type: 'checkbox-grouped',
|
|
hideLabel: true,
|
|
groups: ${JSON.stringify(domainConfig.checkboxGroupedConfig.groups, null, 14).replace(/"/g, "'")}
|
|
}
|
|
]
|
|
}`);
|
|
}
|
|
|
|
return subTabs.length > 0 ? ',\n ' + subTabs.join(',\n ') : '';
|
|
}
|
|
|
|
function generateBulkActionMethods(domainConfig) {
|
|
if (!domainConfig.hasBulkActions) return '';
|
|
|
|
const componentName = capitalize(domainConfig.name);
|
|
|
|
return `
|
|
// ========================================
|
|
// ⚡ BULK ACTIONS V2.0
|
|
// ========================================
|
|
|
|
async bulkDelete(selectedItems: ${componentName}[]) {
|
|
const confirmed = await this.confirmationService.confirm({
|
|
title: 'Confirmar exclusão',
|
|
message: \`Tem certeza que deseja excluir \${selectedItems.length} \${selectedItems.length === 1 ? 'item' : 'itens'}?\`,
|
|
confirmText: 'Excluir'
|
|
});
|
|
|
|
if (confirmed) {
|
|
// Implementar lógica de exclusão em lote
|
|
console.log('Excluindo itens:', selectedItems);
|
|
}
|
|
}
|
|
|
|
async bulkExport(selectedItems: ${componentName}[]) {
|
|
// Implementar lógica de exportação
|
|
console.log('Exportando itens:', selectedItems);
|
|
}
|
|
|
|
${domainConfig.bulkActionsConfig.type === 'advanced' ? `
|
|
async updateViaExternalAPI(selectedItems: ${componentName}[]) {
|
|
// Implementar atualização via API externa
|
|
console.log('Atualizando via API externa:', selectedItems);
|
|
}
|
|
|
|
async bulkEdit(selectedItems: ${componentName}[]) {
|
|
// Implementar edição em lote
|
|
console.log('Edição em lote:', selectedItems);
|
|
}
|
|
|
|
async bulkStatusChange(selectedItems: ${componentName}[]) {
|
|
// Implementar alteração de status em lote
|
|
console.log('Alterando status:', selectedItems);
|
|
}` : ''}`;
|
|
}
|
|
|
|
function generateBulkServiceMethods(domainConfig) {
|
|
if (!domainConfig.hasBulkActions) return '';
|
|
|
|
const componentName = capitalize(domainConfig.name);
|
|
|
|
return `
|
|
// ========================================
|
|
// ⚡ BULK OPERATIONS V2.0
|
|
// ========================================
|
|
|
|
bulkDelete(ids: string[]): Observable<void> {
|
|
return this.apiClient.post<void>(\`${domainConfig.name}s/bulk-delete\`, { ids });
|
|
}
|
|
|
|
bulkUpdate(updates: Array<{id: string, data: Partial<${componentName}>}>): Observable<${componentName}[]> {
|
|
return this.apiClient.patch<${componentName}[]>(\`${domainConfig.name}s/bulk\`, { updates });
|
|
}
|
|
|
|
${domainConfig.hasDateRangeUtils ? `
|
|
// ✨ V2.0: Exemplo de uso do DateRangeUtils
|
|
async getRecentItems(): Promise<${componentName}[]> {
|
|
const dateFilters = DateRangeShortcuts.last30Days();
|
|
const response = await firstValueFrom(this.get${componentName}s(1, 100, dateFilters));
|
|
return response.data;
|
|
}` : ''}`;
|
|
}
|
|
|
|
function generateMockData(domainConfig) {
|
|
const mockItems = [];
|
|
|
|
for (let i = 1; i <= 5; i++) {
|
|
const item = {
|
|
id: i,
|
|
name: `${domainConfig.displayName} ${i}`,
|
|
createdAt: new Date(Date.now() - i * 24 * 60 * 60 * 1000).toISOString(),
|
|
updatedAt: new Date(Date.now() - i * 24 * 60 * 60 * 1000).toISOString()
|
|
};
|
|
|
|
if (domainConfig.hasStatus) {
|
|
item.status = i % 2 === 0 ? 'active' : 'inactive';
|
|
}
|
|
|
|
if (domainConfig.hasKilometer) {
|
|
item.odometer = Math.floor(Math.random() * 100000);
|
|
}
|
|
|
|
if (domainConfig.hasColor) {
|
|
const colors = [
|
|
{ name: 'Branco', code: '#ffffff' },
|
|
{ name: 'Preto', code: '#000000' },
|
|
{ name: 'Azul', code: '#0000ff' }
|
|
];
|
|
item.color = colors[i % colors.length];
|
|
}
|
|
|
|
mockItems.push(item);
|
|
}
|
|
|
|
return JSON.stringify(mockItems, null, 4);
|
|
}
|
|
|
|
function capitalize(str) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
|
|
module.exports = {
|
|
generateComponentV2,
|
|
generateServiceV2,
|
|
generateInterfaceV2,
|
|
generateSubTabsList,
|
|
generateStatusColumn,
|
|
generateFooterColumns,
|
|
generateBulkActionsConfig,
|
|
generateSideCardConfig,
|
|
generateFormFields,
|
|
generateFormSubTabs,
|
|
generateBulkActionMethods,
|
|
generateBulkServiceMethods,
|
|
generateMockData,
|
|
capitalize
|
|
};
|