Files
SteelBase/public/js/sections/perfis-auto-loader.js

350 lines
14 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* CARREGADOR AUTOMÁTICO PARA TODOS OS PERFIS
* Gera automaticamente as funções de carregamento para cada tipo de perfil
*/
/**
* Gera função de carregamento forçado para um tipo de perfil
*/
function gerarFuncaoCarregamento(tipo) {
const config = window.PERFIS_CONFIG[tipo];
if (!config) return null;
const tipoId = tipo.replace(/-/g, '_');
const funcName = `forcarCarregamento${capitalize(tipoId)}`;
window[funcName] = async function() {
console.log(`🚨 CARREGAMENTO FORÇADO INICIADO: ${config.nome}`);
const tbody = document.getElementById(`${tipoId}-tbody`);
if (!tbody) {
alert(`❌ Erro: Elemento da tabela não encontrado!`);
console.error(`❌ Elemento ${tipoId}-tbody não encontrado`);
return;
}
// Mostrar loading
tbody.innerHTML = `
<tr>
<td colspan="${config.colunasTabel.length + 1}" style="text-align: center; padding: 40px;">
<div style="font-size: 48px; margin-bottom: 16px;">⏳</div>
<div style="font-size: 18px; font-weight: bold;">Carregando dados...</div>
<div style="font-size: 14px; color: #666; margin-top: 8px;">Aguarde alguns segundos</div>
</td>
</tr>
`;
try {
// Carregar CSV
console.log(`📥 Carregando CSV: ${config.csv}`);
const response = await fetch(config.csv);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const csvText = await response.text();
const linhas = csvText.trim().split('\n');
console.log(`📊 CSV carregado: ${linhas.length} linhas`);
// Processar dados
const dados = [];
for (let i = 1; i < linhas.length; i++) {
const linha = linhas[i].trim();
if (!linha) continue;
const colunas = linha.split(',');
if (colunas.length >= config.colunas.length) {
const item = {};
config.colunas.forEach((col, index) => {
let value = colunas[index].trim();
// Converter números
if (col.includes('_mm') || col.includes('_kg') || col.includes('_cm') || col.includes('_m2')) {
value = parseFloat(value) || 0;
}
item[col] = value;
});
dados.push(item);
}
}
console.log(`✅ Processados: ${dados.length} itens`);
if (dados.length === 0) {
throw new Error('Nenhum dado encontrado no CSV');
}
// Exibir na tabela
tbody.innerHTML = dados.map(item => `
<tr>
${config.colunasTabel.map(col => {
let value = item[col.key];
if (col.decimals && typeof value === 'number') {
value = value.toFixed(col.decimals);
}
if (col.badge) {
return `<td><span class="badge badge-info">${value}</span></td>`;
}
return `<td>${col.key === 'nome' ? '<strong>' + value + '</strong>' : value}</td>`;
}).join('')}
<td><button class="btn btn-sm btn-primary">👁 Ver</button></td>
</tr>
`).join('');
// Atualizar contador
const totalEl = document.getElementById(`${tipoId}-total`);
if (totalEl) {
totalEl.textContent = dados.length;
}
// Armazenar globalmente
window[`${tipoId}Data`] = dados;
console.log(`🎉 CARREGAMENTO CONCLUÍDO: ${config.nome}`);
// Notificar usuário
alert(` ${dados.length} ${config.nome.toLowerCase()} carregados com sucesso!`);
} catch (error) {
console.error(` Erro no carregamento: ${error.message}`);
tbody.innerHTML = `
<tr>
<td colspan="${config.colunasTabel.length + 1}" style="text-align: center; padding: 40px;">
<div style="font-size: 48px; margin-bottom: 16px;"></div>
<div style="font-size: 18px; font-weight: bold; color: #ef4444;">Erro ao carregar dados</div>
<div style="font-size: 14px; color: #666; margin-top: 8px;">${error.message}</div>
<button class="btn btn-primary" onclick="${funcName}()" style="margin-top: 16px;">
🔄 Tentar Novamente
</button>
</td>
</tr>
`;
alert(` Erro ao carregar dados: ${error.message}`);
}
};
console.log(` Função criada: ${funcName}`);
}
/**
* Gera funções de filtro para um tipo de perfil
*/
function gerarFuncoesFiltro(tipo) {
const config = window.PERFIS_CONFIG[tipo];
if (!config) return;
const tipoId = tipo.replace(/-/g, '_');
// Função de filtrar
window[`filtrar${capitalize(tipoId)}`] = function() {
const dados = window[`${tipoId}Data`];
if (!dados) {
console.warn('⚠️ Dados não carregados ainda');
return;
}
// Implementar filtros básicos
console.log(`🔍 Filtrando ${config.nome}...`);
// TODO: Implementar lógica de filtro
};
// Função de limpar filtros
window[`limparFiltros${capitalize(tipoId)}`] = function() {
console.log(`🧹 Limpando filtros de ${config.nome}`);
// Limpar campos
config.filtros.forEach(filtro => {
const el = document.getElementById(`${tipoId}-${filtro.id}`);
if (el) el.value = '';
});
// Reexibir todos os dados
const dados = window[`${tipoId}Data`];
if (dados) {
const tbody = document.getElementById(`${tipoId}-tbody`);
if (tbody) {
tbody.innerHTML = dados.map(item => `
<tr>
${config.colunasTabel.map(col => {
let value = item[col.key];
if (col.decimals && typeof value === 'number') {
value = value.toFixed(col.decimals);
}
if (col.badge) {
return `<td><span class="badge badge-info">${value}</span></td>`;
}
return `<td>${col.key === 'nome' ? '<strong>' + value + '</strong>' : value}</td>`;
}).join('')}
<td><button class="btn btn-sm btn-primary">👁 Ver</button></td>
</tr>
`).join('');
}
}
};
}
/**
* Gera função de conteúdo para um tipo de perfil
*/
function gerarFuncaoConteudo(tipo) {
const config = window.PERFIS_CONFIG[tipo];
if (!config) return;
const funcName = `get${capitalize(tipo.replace(/-/g, '_'))}Content`;
window[funcName] = function() {
console.log(`🔧 ${funcName}() chamada`);
return gerarConteudoPerfil(tipo);
};
console.log(` Função criada: ${funcName}`);
}
/**
* Inicializa todas as funções para todos os perfis
*/
function inicializarTodosPerfis() {
console.log('🚀 Inicializando funções para todos os perfis...');
Object.keys(window.PERFIS_CONFIG).forEach(tipo => {
gerarFuncaoConteudo(tipo);
gerarFuncaoCarregamento(tipo);
gerarFuncoesFiltro(tipo);
gerarFuncaoAtualizarFonte(tipo);
});
console.log('✅ Todas as funções de perfis inicializadas!');
}
/**
* Capitaliza primeira letra
*/
function capitalize(str) {
return str.split('_').map(word =>
word.charAt(0).toUpperCase() + word.slice(1)
).join('');
}
// Inicializar quando o script carregar
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', inicializarTodosPerfis);
} else {
inicializarTodosPerfis();
}
console.log('✅ Auto-loader de perfis carregado');
// ========================================
// Atualização direta a partir da fonte (CSV)
// ========================================
/**
* Mapeia o ID do template (com hífen) para a chave do DataManager (com underscore)
*/
function mapToDataManagerKey(tipo) {
return tipo.replace(/-/g, '_');
}
/**
* Gera função de atualização de dados a partir da fonte oficial (DataManager)
* Cria window["atualizarFonte<Cap>"] para cada tipo. O botão existe apenas em Tubos RHS.
*/
function gerarFuncaoAtualizarFonte(tipo) {
const config = window.PERFIS_CONFIG[tipo];
if (!config) return;
const tipoId = tipo.replace(/-/g, '_');
const funcName = `atualizarFonte${capitalize(tipoId)}`;
const dmKey = mapToDataManagerKey(tipo);
window[funcName] = async function() {
try {
const tbody = document.getElementById(`${tipoId}-tbody`);
const tableContainer = document.getElementById(`${tipoId}-table-container`);
if (!tbody || !tableContainer) {
alert('❌ Elementos da tabela não encontrados.');
return;
}
// Loader visual
tbody.innerHTML = `
<tr>
<td colspan="${config.colunasTabel.length + 1}" style="text-align:center; padding:32px;">
<div style="font-size:42px;"></div>
<div style="margin-top:8px; color: var(--color-text-secondary);">Atualizando da fonte: ${config.csv}</div>
</td>
</tr>
`;
// Atualizar via DataManager para registrar metadados e cache
const result = await window.dataManager.updateTypeData(dmKey);
const dados = result.data || [];
if (!dados.length) {
throw new Error('Fonte retornou 0 itens');
}
// Preencher tabela com os novos dados
tbody.innerHTML = dados.map(item => `
<tr>
${config.colunasTabel.map(col => {
let value = item[col.key];
if (col.decimals && typeof value === 'number') {
value = value.toFixed(col.decimals);
}
if (col.badge) {
return `<td><span class="badge badge-info">${value}</span></td>`;
}
return `<td>${col.key === 'nome' ? '<strong>' + value + '</strong>' : value}</td>`;
}).join('')}
<td><button class="btn btn-sm btn-primary">👁 Ver</button></td>
</tr>
`).join('');
// Atualizar contadores e metadados visuais
const totalEl = document.getElementById(`${tipoId}-total`);
const fonteEl = document.getElementById(`${tipoId}-fonte`);
const lastEl = document.getElementById(`${tipoId}-last`);
if (totalEl) totalEl.textContent = dados.length;
if (fonteEl) fonteEl.textContent = result.source || config.csv;
if (lastEl) lastEl.textContent = new Date(result.lastUpdate || Date.now()).toLocaleString('pt-BR');
// Atualizar descrição do cabeçalho (quantidade)
const headerDesc = document.querySelector('.section-description');
if (headerDesc && headerDesc.textContent.includes(config.descricao)) {
headerDesc.textContent = `${config.descricao} - ${dados.length} modelos disponíveis`;
}
// Atualizar notas nas outras abas (preços, especificações, fabricantes, aplicações)
['perfil-tab-1', 'perfil-tab-2', 'perfil-tab-3', 'perfil-tab-4'].forEach(tabId => {
const tab = document.getElementById(tabId);
if (tab) {
const noteId = `${tipoId}-update-note-${tabId}`;
let note = document.getElementById(noteId);
if (!note) {
note = document.createElement('div');
note.id = noteId;
note.style.marginTop = '12px';
note.style.fontSize = '12px';
note.style.color = 'var(--color-text-secondary)';
tab.appendChild(note);
}
note.textContent = `Dados atualizados (${dados.length} itens) Fonte: ${result.source} ${new Date(result.lastUpdate).toLocaleString('pt-BR')}`;
}
});
// Disponibilizar globalmente
window[`${tipoId}Data`] = dados;
alert(` ${config.nome} atualizado da fonte com ${dados.length} itens.`);
} catch (error) {
console.error(` Erro ao atualizar da fonte (${tipo}):`, error);
alert('❌ Erro ao atualizar da fonte: ' + error.message);
}
};
console.log(` Função criada: ${funcName}`);
}