343 lines
14 KiB
JavaScript
343 lines
14 KiB
JavaScript
/**
|
||
* IMPORTADOR DE CSV - Ferramenta de Atualização do BD Interno
|
||
* Permite carregar CSVs externos e atualizar o banco de dados interno
|
||
*/
|
||
|
||
/**
|
||
* Abre modal de importação de CSV
|
||
*/
|
||
function abrirImportadorCSV() {
|
||
console.log('📥 Abrindo importador de CSV');
|
||
|
||
const modalHTML = `
|
||
<div class="modal active" id="modal-importador-csv" onclick="fecharImportadorCSV(event)">
|
||
<div class="modal-content" onclick="event.stopPropagation()" style="max-width: 900px;">
|
||
<div class="modal-header">
|
||
<div class="modal-title">📥 Importador de CSV - Atualizar BD Interno</div>
|
||
<button class="close-btn" onclick="fecharImportadorCSV()">×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
|
||
<!-- Instruções -->
|
||
<div class="card" style="background: var(--color-bg-1); margin-bottom: 20px;">
|
||
<h3 style="color: var(--color-primary); margin: 0 0 16px 0;">📋 Como Usar</h3>
|
||
<ol style="margin: 0; padding-left: 20px;">
|
||
<li>Selecione o tipo de perfil que deseja atualizar</li>
|
||
<li>Escolha o arquivo CSV com os novos dados</li>
|
||
<li>Clique em "Importar" para atualizar o BD interno</li>
|
||
<li>Os dados serão salvos no localStorage e usados imediatamente</li>
|
||
</ol>
|
||
</div>
|
||
|
||
<!-- Seleção de Tipo -->
|
||
<div class="card" style="background: var(--color-bg-1); margin-bottom: 20px;">
|
||
<h3 style="color: var(--color-primary); margin: 0 0 16px 0;">🎯 Selecionar Tipo de Perfil</h3>
|
||
<div class="form-group">
|
||
<label class="form-label">Tipo de Perfil:</label>
|
||
<select class="form-control" id="tipo-perfil-importar">
|
||
<option value="">Selecione um tipo...</option>
|
||
<option value="cantoneiras">Cantoneiras</option>
|
||
<option value="barras_redondas">Barras Redondas</option>
|
||
<option value="tubos_circulares">Tubos Circulares</option>
|
||
<option value="perfis_i">Perfis I (IPE)</option>
|
||
<option value="perfis_w">Perfis W</option>
|
||
<option value="tubos_rhs">Tubos RHS</option>
|
||
<option value="chapas">Chapas</option>
|
||
<option value="perfis_hp">Perfis HP</option>
|
||
<option value="barras_roscadas">Barras Roscadas</option>
|
||
<option value="barras_chatas">Barras Chatas</option>
|
||
</select>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Upload de Arquivo -->
|
||
<div class="card" style="background: var(--color-bg-1); margin-bottom: 20px;">
|
||
<h3 style="color: var(--color-primary); margin: 0 0 16px 0;">📁 Selecionar Arquivo CSV</h3>
|
||
<div class="form-group">
|
||
<label class="form-label">Arquivo CSV:</label>
|
||
<input type="file" class="form-control" id="arquivo-csv" accept=".csv" onchange="visualizarCSV()">
|
||
<small style="color: var(--color-text-secondary); margin-top: 8px; display: block;">
|
||
Selecione um arquivo CSV com os dados dos perfis
|
||
</small>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Preview do CSV -->
|
||
<div class="card" style="background: var(--color-bg-1); margin-bottom: 20px; display: none;" id="preview-csv">
|
||
<h3 style="color: var(--color-primary); margin: 0 0 16px 0;">👁️ Preview do Arquivo</h3>
|
||
<div id="preview-conteudo" style="max-height: 300px; overflow: auto;"></div>
|
||
<div id="preview-stats" style="margin-top: 12px; padding: 12px; background: var(--color-bg-2); border-radius: 6px;"></div>
|
||
</div>
|
||
|
||
<!-- Log de Importação -->
|
||
<div class="card" style="background: var(--color-bg-1); display: none;" id="log-importacao">
|
||
<h3 style="color: var(--color-primary); margin: 0 0 16px 0;">📝 Log de Importação</h3>
|
||
<div id="log-conteudo" style="background: #000; color: #0f0; padding: 16px; border-radius: 8px; font-family: monospace; font-size: 12px; max-height: 200px; overflow-y: auto;"></div>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button class="btn btn-secondary" onclick="fecharImportadorCSV()">Cancelar</button>
|
||
<button class="btn btn-primary" onclick="executarImportacao()" id="btn-importar" disabled>
|
||
📥 Importar Dados
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
|
||
// Remover modal existente
|
||
const existingModal = document.getElementById('modal-importador-csv');
|
||
if (existingModal) {
|
||
existingModal.remove();
|
||
}
|
||
|
||
// Adicionar novo modal
|
||
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
||
}
|
||
|
||
/**
|
||
* Fecha o importador de CSV
|
||
*/
|
||
function fecharImportadorCSV(event) {
|
||
if (event && event.target !== event.currentTarget) return;
|
||
|
||
const modal = document.getElementById('modal-importador-csv');
|
||
if (modal) {
|
||
modal.remove();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Visualiza o conteúdo do CSV selecionado
|
||
*/
|
||
function visualizarCSV() {
|
||
const arquivo = document.getElementById('arquivo-csv').files[0];
|
||
const tipoSelecionado = document.getElementById('tipo-perfil-importar').value;
|
||
|
||
if (!arquivo) {
|
||
document.getElementById('preview-csv').style.display = 'none';
|
||
document.getElementById('btn-importar').disabled = true;
|
||
return;
|
||
}
|
||
|
||
if (!tipoSelecionado) {
|
||
alert('⚠️ Selecione o tipo de perfil primeiro!');
|
||
return;
|
||
}
|
||
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const csvText = e.target.result;
|
||
const linhas = csvText.trim().split('\n');
|
||
|
||
// Mostrar preview
|
||
const previewDiv = document.getElementById('preview-conteudo');
|
||
const statsDiv = document.getElementById('preview-stats');
|
||
|
||
// Primeiras 5 linhas
|
||
const preview = linhas.slice(0, 6).map((linha, index) => {
|
||
const colunas = linha.split(',');
|
||
const isHeader = index === 0;
|
||
return `
|
||
<div style="padding: 8px; background: ${isHeader ? 'var(--color-primary)' : 'var(--color-bg-2)'};
|
||
color: ${isHeader ? 'white' : 'inherit'}; margin-bottom: 2px; border-radius: 4px;">
|
||
<strong>${isHeader ? 'CABEÇALHO:' : `Linha ${index}:`}</strong>
|
||
${colunas.join(' | ')}
|
||
</div>
|
||
`;
|
||
}).join('');
|
||
|
||
previewDiv.innerHTML = preview;
|
||
|
||
// Estatísticas
|
||
statsDiv.innerHTML = `
|
||
<strong>📊 Estatísticas:</strong><br>
|
||
• Total de linhas: ${linhas.length}<br>
|
||
• Linhas de dados: ${linhas.length - 1}<br>
|
||
• Colunas: ${linhas[0] ? linhas[0].split(',').length : 0}<br>
|
||
• Tamanho: ${(csvText.length / 1024).toFixed(2)} KB
|
||
`;
|
||
|
||
// Mostrar preview
|
||
document.getElementById('preview-csv').style.display = 'block';
|
||
document.getElementById('btn-importar').disabled = false;
|
||
};
|
||
|
||
reader.readAsText(arquivo);
|
||
}
|
||
|
||
/**
|
||
* Executa a importação do CSV
|
||
*/
|
||
function executarImportacao() {
|
||
const arquivo = document.getElementById('arquivo-csv').files[0];
|
||
const tipo = document.getElementById('tipo-perfil-importar').value;
|
||
|
||
if (!arquivo || !tipo) {
|
||
alert('⚠️ Selecione o tipo de perfil e o arquivo CSV!');
|
||
return;
|
||
}
|
||
|
||
// Mostrar log
|
||
document.getElementById('log-importacao').style.display = 'block';
|
||
const logDiv = document.getElementById('log-conteudo');
|
||
|
||
function log(msg) {
|
||
const time = new Date().toLocaleTimeString();
|
||
logDiv.innerHTML += `<div>[${time}] ${msg}</div>`;
|
||
logDiv.scrollTop = logDiv.scrollHeight;
|
||
}
|
||
|
||
log('🚀 Iniciando importação...');
|
||
log(`📊 Tipo: ${tipo}`);
|
||
log(`📁 Arquivo: ${arquivo.name}`);
|
||
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
try {
|
||
const csvText = e.target.result;
|
||
const linhas = csvText.trim().split('\n');
|
||
|
||
log(`📄 Arquivo lido: ${linhas.length} linhas`);
|
||
|
||
if (linhas.length < 2) {
|
||
throw new Error('Arquivo CSV deve ter pelo menos cabeçalho + 1 linha de dados');
|
||
}
|
||
|
||
// Processar dados
|
||
const cabecalho = linhas[0].split(',').map(h => h.trim().replace(/"/g, ''));
|
||
log(`📋 Cabeçalho: ${cabecalho.join(', ')}`);
|
||
|
||
const dados = [];
|
||
for (let i = 1; i < linhas.length; i++) {
|
||
const linha = linhas[i].trim();
|
||
if (!linha) continue;
|
||
|
||
const valores = linha.split(',').map(v => v.trim().replace(/"/g, ''));
|
||
if (valores.length < cabecalho.length) continue;
|
||
|
||
const item = {};
|
||
cabecalho.forEach((col, index) => {
|
||
let valor = valores[index] || '';
|
||
|
||
// Converter números
|
||
if (col.includes('_mm') || col.includes('_kg') || col.includes('_cm') || col.includes('_m2')) {
|
||
valor = parseFloat(valor) || 0;
|
||
}
|
||
|
||
item[col] = valor;
|
||
});
|
||
|
||
dados.push(item);
|
||
}
|
||
|
||
log(`✅ Processados: ${dados.length} itens`);
|
||
|
||
if (dados.length === 0) {
|
||
throw new Error('Nenhum dado válido encontrado no CSV');
|
||
}
|
||
|
||
// Atualizar banco de dados interno
|
||
if (!window.BANCO_DADOS_PERFIS) {
|
||
window.BANCO_DADOS_PERFIS = {};
|
||
}
|
||
|
||
window.BANCO_DADOS_PERFIS[tipo] = dados;
|
||
|
||
// Salvar no localStorage
|
||
const chaveCache = `acoCalcPro_dados_${tipo}`;
|
||
localStorage.setItem(chaveCache, JSON.stringify(dados));
|
||
|
||
log(`💾 Dados salvos no localStorage: ${chaveCache}`);
|
||
|
||
// Atualizar metadata
|
||
const metadata = {
|
||
tipo: tipo,
|
||
arquivo: arquivo.name,
|
||
dataImportacao: new Date().toISOString(),
|
||
totalItens: dados.length,
|
||
colunas: cabecalho
|
||
};
|
||
|
||
localStorage.setItem(`acoCalcPro_metadata_${tipo}`, JSON.stringify(metadata));
|
||
|
||
log(`📊 Metadata salvo`);
|
||
|
||
// Recarregar dados na tabela se estiver visível
|
||
if (typeof carregarPerfilUniversal === 'function') {
|
||
const sucesso = carregarPerfilUniversal(tipo);
|
||
if (sucesso) {
|
||
log(`🔄 Tabela atualizada automaticamente`);
|
||
}
|
||
}
|
||
|
||
log(`🎉 IMPORTAÇÃO CONCLUÍDA COM SUCESSO!`);
|
||
|
||
// Notificar usuário
|
||
setTimeout(() => {
|
||
alert(`✅ Importação concluída!\n\n📊 ${dados.length} itens de ${tipo} importados\n💾 Dados salvos no BD interno\n🔄 Tabela atualizada`);
|
||
}, 1000);
|
||
|
||
} catch (error) {
|
||
log(`❌ ERRO: ${error.message}`);
|
||
alert(`❌ Erro na importação: ${error.message}`);
|
||
}
|
||
};
|
||
|
||
reader.readAsText(arquivo);
|
||
}
|
||
|
||
/**
|
||
* Exporta dados atuais para CSV
|
||
*/
|
||
function exportarDadosCSV(tipo) {
|
||
if (!window.BANCO_DADOS_PERFIS || !window.BANCO_DADOS_PERFIS[tipo]) {
|
||
alert(`❌ Nenhum dado encontrado para ${tipo}`);
|
||
return;
|
||
}
|
||
|
||
const dados = window.BANCO_DADOS_PERFIS[tipo];
|
||
if (dados.length === 0) {
|
||
alert(`❌ Dados vazios para ${tipo}`);
|
||
return;
|
||
}
|
||
|
||
// Gerar CSV
|
||
const cabecalho = Object.keys(dados[0]);
|
||
const linhas = [cabecalho.join(',')];
|
||
|
||
dados.forEach(item => {
|
||
const linha = cabecalho.map(col => {
|
||
let valor = item[col];
|
||
if (typeof valor === 'string' && valor.includes(',')) {
|
||
valor = `"${valor}"`;
|
||
}
|
||
return valor;
|
||
}).join(',');
|
||
linhas.push(linha);
|
||
});
|
||
|
||
const csvContent = linhas.join('\n');
|
||
|
||
// Download
|
||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = `${tipo}_${new Date().toISOString().split('T')[0]}.csv`;
|
||
a.click();
|
||
URL.revokeObjectURL(url);
|
||
|
||
console.log(`✅ Dados de ${tipo} exportados para CSV`);
|
||
}
|
||
|
||
// Exportar funções
|
||
window.abrirImportadorCSV = abrirImportadorCSV;
|
||
window.fecharImportadorCSV = fecharImportadorCSV;
|
||
window.visualizarCSV = visualizarCSV;
|
||
window.executarImportacao = executarImportacao;
|
||
window.exportarDadosCSV = exportarDadosCSV;
|
||
|
||
console.log('✅ Importador de CSV carregado');
|