/** * CSV Manager UI * User interface for CRUD operations on CSV files */ import { loadCSV, toCSV, downloadCSV, getAvailableCSVFiles, validateCSVData } from '../utils/csv-manager.js'; // Current state let currentCSVData = []; let currentFilename = ''; let currentFileId = ''; let editingIndex = -1; /** * Open CSV Manager Modal */ export function openCSVManager() { const modal = document.getElementById('csvManagerModal'); const select = document.getElementById('csvFileSelect'); // Populate file selector const files = getAvailableCSVFiles(); select.innerHTML = ''; files.forEach(file => { const option = document.createElement('option'); option.value = file.id; option.textContent = `${file.icon} ${file.name} - ${file.description}`; select.appendChild(option); }); modal.classList.add('active'); } /** * Close CSV Manager Modal */ export function closeCSVManager() { const modal = document.getElementById('csvManagerModal'); modal.classList.remove('active'); // Reset state currentCSVData = []; currentFilename = ''; currentFileId = ''; // Reset UI document.getElementById('csvFileSelect').value = ''; document.getElementById('csvContent').innerHTML = `
📁

Selecione um arquivo CSV para começar

Você poderá visualizar, editar, adicionar e remover registros

`; // Hide buttons document.getElementById('btnAddRecord').style.display = 'none'; document.getElementById('btnDownload').style.display = 'none'; } /** * Load selected CSV file */ export async function loadSelectedCSV() { const select = document.getElementById('csvFileSelect'); const fileId = select.value; if (!fileId) { closeCSVManager(); openCSVManager(); return; } const files = getAvailableCSVFiles(); const file = files.find(f => f.id === fileId); if (!file) return; // Show loading document.getElementById('csvContent').innerHTML = `

Carregando ${file.name}...

`; try { // Load CSV const data = await loadCSV(file.filename); // Update state currentCSVData = data; currentFilename = file.filename; currentFileId = fileId; // Render table renderCSVTable(data, file); // Show buttons document.getElementById('btnAddRecord').style.display = 'inline-block'; document.getElementById('btnDownload').style.display = 'inline-block'; } catch (error) { document.getElementById('csvContent').innerHTML = `

Erro ao carregar arquivo

${error.message}

`; } } /** * Render CSV data as table * @param {Array} data - CSV data * @param {object} file - File metadata */ function renderCSVTable(data, file) { if (data.length === 0) { document.getElementById('csvContent').innerHTML = `
📭

Arquivo vazio

Adicione o primeiro registro

`; return; } const headers = Object.keys(data[0]); let html = `
${file.icon}

${file.name}

${file.description}

📄 ${data.length} registros 📊 ${headers.length} colunas 💾 ${currentFilename}
${headers.map(h => ``).join('')} ${data.map((row, index) => ` ${headers.map(h => ``).join('')} `).join('')}
#${h}Ações
${index + 1}${row[h] || '-'}
`; document.getElementById('csvContent').innerHTML = html; } /** * Add new record */ export function addNewRecord() { if (currentCSVData.length === 0) { alert('⚠️ Não é possível adicionar registro em arquivo vazio. Faça upload de um arquivo com estrutura.'); return; } editingIndex = -1; const headers = Object.keys(currentCSVData[0]); showRecordModal('➕ Adicionar Novo Registro', headers, {}); } /** * Edit existing record * @param {number} index - Record index */ export function editRecord(index) { editingIndex = index; const record = currentCSVData[index]; const headers = Object.keys(record); showRecordModal(`✏️ Editar Registro #${index + 1}`, headers, record); } /** * Delete record * @param {number} index - Record index */ export function deleteRecord(index) { const record = currentCSVData[index]; const recordName = record.nome || record.id || `Registro #${index + 1}`; if (!confirm(`🗑️ Tem certeza que deseja deletar:\n\n"${recordName}"?\n\nEsta ação não pode ser desfeita.`)) { return; } // Remove from array currentCSVData.splice(index, 1); // Re-render table const files = getAvailableCSVFiles(); const file = files.find(f => f.id === currentFileId); renderCSVTable(currentCSVData, file); // Show success message showToast('✅ Registro deletado com sucesso!', 'success'); } /** * Show record editor modal * @param {string} title - Modal title * @param {Array} headers - Field names * @param {object} data - Current data */ function showRecordModal(title, headers, data) { document.getElementById('recordModalTitle').textContent = title; let html = '
'; headers.forEach(header => { const value = data[header] || ''; html += `
${header === 'id' ? 'Campo obrigatório e único' : ''}
`; }); html += '
'; document.getElementById('recordModalBody').innerHTML = html; document.getElementById('csvRecordModal').classList.add('active'); } /** * Close record editor modal */ export function closeRecordModal() { document.getElementById('csvRecordModal').classList.remove('active'); editingIndex = -1; } /** * Save record (add or edit) */ export function saveRecord() { const headers = Object.keys(currentCSVData[0] || {}); const newRecord = {}; // Collect form data headers.forEach(header => { const input = document.getElementById(`field_${header}`); if (input) { newRecord[header] = input.value.trim(); } }); // Validate required fields if (!newRecord.id) { alert('⚠️ O campo "id" é obrigatório!'); return; } // Check for duplicate ID (only when adding new) if (editingIndex === -1) { const duplicate = currentCSVData.find(r => r.id === newRecord.id); if (duplicate) { alert(`⚠️ Já existe um registro com o ID "${newRecord.id}"!\n\nEscolha um ID único.`); return; } } // Add or update if (editingIndex === -1) { // Add new currentCSVData.push(newRecord); showToast('✅ Registro adicionado com sucesso!', 'success'); } else { // Update existing currentCSVData[editingIndex] = newRecord; showToast('✅ Registro atualizado com sucesso!', 'success'); } // Re-render table const files = getAvailableCSVFiles(); const file = files.find(f => f.id === currentFileId); renderCSVTable(currentCSVData, file); // Close modal closeRecordModal(); } /** * Download current CSV */ export function downloadCurrentCSV() { if (currentCSVData.length === 0) { alert('⚠️ Não há dados para download!'); return; } // Validate data const validation = validateCSVData(currentCSVData); if (!validation.valid) { const proceed = confirm(`⚠️ Dados contêm erros:\n\n${validation.errors.join('\n')}\n\nDeseja fazer download mesmo assim?`); if (!proceed) return; } // Convert to CSV const csvText = toCSV(currentCSVData); // Download downloadCSV(currentFilename, csvText); showToast('💾 CSV baixado com sucesso!', 'success'); } /** * Show toast notification * @param {string} message - Message text * @param {string} type - Type (success, error, warning) */ function showToast(message, type = 'success') { const toast = document.createElement('div'); toast.className = `toast toast-${type}`; toast.textContent = message; toast.style.cssText = ` position: fixed; bottom: 24px; right: 24px; padding: 16px 24px; background: ${type === 'success' ? 'var(--color-success)' : 'var(--color-error)'}; color: white; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 10000; font-size: 14px; font-weight: 500; opacity: 0; transform: translateY(20px); transition: all 0.3s ease; `; document.body.appendChild(toast); setTimeout(() => { toast.style.opacity = '1'; toast.style.transform = 'translateY(0)'; }, 10); setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateY(20px)'; setTimeout(() => toast.remove(), 300); }, 3000); } // Export to global scope for onclick handlers if (typeof window !== 'undefined') { window.openCSVManager = openCSVManager; window.closeCSVManager = closeCSVManager; window.loadSelectedCSV = loadSelectedCSV; window.addNewRecord = addNewRecord; window.editRecord = editRecord; window.deleteRecord = deleteRecord; window.closeRecordModal = closeRecordModal; window.saveRecord = saveRecord; window.downloadCurrentCSV = downloadCurrentCSV; }