let currentPage = 1; let currentSearch = ''; let searchTimeout = null; // Load on page ready document.addEventListener('DOMContentLoaded', loadMappings); function debounceSearch() { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { currentSearch = document.getElementById('searchInput').value; currentPage = 1; loadMappings(); }, 300); } async function loadMappings() { const params = new URLSearchParams({ search: currentSearch, page: currentPage, per_page: 50 }); try { const res = await fetch(`/api/mappings?${params}`); const data = await res.json(); renderTable(data.mappings); renderPagination(data); } catch (err) { document.getElementById('mappingsBody').innerHTML = `Eroare: ${err.message}`; } } function renderTable(mappings) { const tbody = document.getElementById('mappingsBody'); if (!mappings || mappings.length === 0) { tbody.innerHTML = 'Nu exista mapari'; return; } tbody.innerHTML = mappings.map(m => ` ${esc(m.sku)} ${esc(m.codmat)} ${esc(m.denumire || '-')} ${m.cantitate_roa} ${m.procent_pret}% ${m.activ ? 'Activ' : 'Inactiv'} `).join(''); } function renderPagination(data) { const info = document.getElementById('pageInfo'); info.textContent = `${data.total} mapari | Pagina ${data.page} din ${data.pages || 1}`; const ul = document.getElementById('pagination'); if (data.pages <= 1) { ul.innerHTML = ''; return; } let html = ''; // Previous html += `
  • «
  • `; // Pages (show max 7) let start = Math.max(1, data.page - 3); let end = Math.min(data.pages, start + 6); start = Math.max(1, end - 6); for (let i = start; i <= end; i++) { html += `
  • ${i}
  • `; } // Next html += `
  • »
  • `; ul.innerHTML = html; } function goPage(p) { currentPage = p; loadMappings(); } // Autocomplete for CODMAT let acTimeout = null; document.addEventListener('DOMContentLoaded', () => { const input = document.getElementById('inputCodmat'); if (!input) return; input.addEventListener('input', () => { clearTimeout(acTimeout); acTimeout = setTimeout(() => autocomplete(input.value), 250); }); input.addEventListener('blur', () => { setTimeout(() => document.getElementById('autocompleteDropdown').classList.add('d-none'), 200); }); }); async function autocomplete(q) { const dropdown = document.getElementById('autocompleteDropdown'); if (q.length < 2) { dropdown.classList.add('d-none'); return; } try { const res = await fetch(`/api/articles/search?q=${encodeURIComponent(q)}`); const data = await res.json(); if (!data.results || data.results.length === 0) { dropdown.classList.add('d-none'); return; } dropdown.innerHTML = data.results.map(r => `
    ${esc(r.codmat)}
    ${esc(r.denumire)}
    `).join(''); dropdown.classList.remove('d-none'); } catch (err) { dropdown.classList.add('d-none'); } } function selectArticle(codmat, denumire) { document.getElementById('inputCodmat').value = codmat; document.getElementById('selectedArticle').textContent = denumire; document.getElementById('autocompleteDropdown').classList.add('d-none'); } // Save mapping (create) async function saveMapping() { const sku = document.getElementById('inputSku').value.trim(); const codmat = document.getElementById('inputCodmat').value.trim(); const cantitate = parseFloat(document.getElementById('inputCantitate').value) || 1; const procent = parseFloat(document.getElementById('inputProcent').value) || 100; if (!sku || !codmat) { alert('SKU si CODMAT sunt obligatorii'); return; } try { const res = await fetch('/api/mappings', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ sku, codmat, cantitate_roa: cantitate, procent_pret: procent }) }); const data = await res.json(); if (data.success) { bootstrap.Modal.getInstance(document.getElementById('addModal')).hide(); clearForm(); loadMappings(); } else { alert('Eroare: ' + (data.error || 'Unknown')); } } catch (err) { alert('Eroare: ' + err.message); } } function clearForm() { document.getElementById('inputSku').value = ''; document.getElementById('inputCodmat').value = ''; document.getElementById('inputCantitate').value = '1'; document.getElementById('inputProcent').value = '100'; document.getElementById('selectedArticle').textContent = ''; } // Inline edit function editCell(td, sku, codmat, field, currentValue) { if (td.querySelector('input')) return; // Already editing const input = document.createElement('input'); input.type = 'number'; input.className = 'form-control form-control-sm'; input.value = currentValue; input.step = field === 'cantitate_roa' ? '0.001' : '0.01'; input.style.width = '80px'; const originalText = td.textContent; td.textContent = ''; td.appendChild(input); input.focus(); input.select(); const save = async () => { const newValue = parseFloat(input.value); if (isNaN(newValue) || newValue === currentValue) { td.textContent = originalText; return; } try { const body = {}; body[field] = newValue; const res = await fetch(`/api/mappings/${encodeURIComponent(sku)}/${encodeURIComponent(codmat)}`, { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(body) }); const data = await res.json(); if (data.success) { loadMappings(); } else { td.textContent = originalText; alert('Eroare: ' + (data.error || 'Update failed')); } } catch (err) { td.textContent = originalText; } }; input.addEventListener('blur', save); input.addEventListener('keydown', (e) => { if (e.key === 'Enter') save(); if (e.key === 'Escape') { td.textContent = originalText; } }); } // Toggle active async function toggleActive(sku, codmat, currentActive) { try { const res = await fetch(`/api/mappings/${encodeURIComponent(sku)}/${encodeURIComponent(codmat)}`, { method: 'PUT', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ activ: currentActive ? 0 : 1 }) }); const data = await res.json(); if (data.success) loadMappings(); } catch (err) { alert('Eroare: ' + err.message); } } // Delete (soft) function deleteMappingConfirm(sku, codmat) { if (confirm(`Dezactivezi maparea ${sku} -> ${codmat}?`)) { fetch(`/api/mappings/${encodeURIComponent(sku)}/${encodeURIComponent(codmat)}`, { method: 'DELETE' }).then(r => r.json()).then(d => { if (d.success) loadMappings(); else alert('Eroare: ' + (d.error || 'Delete failed')); }); } } // CSV import async function importCsv() { const fileInput = document.getElementById('csvFile'); if (!fileInput.files.length) { alert('Selecteaza un fisier CSV'); return; } const formData = new FormData(); formData.append('file', fileInput.files[0]); try { const res = await fetch('/api/mappings/import-csv', { method: 'POST', body: formData }); const data = await res.json(); let html = `
    Procesate: ${data.processed}
    `; if (data.errors && data.errors.length > 0) { html += `
    Erori:
    `; } document.getElementById('importResult').innerHTML = html; loadMappings(); } catch (err) { document.getElementById('importResult').innerHTML = `
    ${err.message}
    `; } } function exportCsv() { window.location.href = '/api/mappings/export-csv'; } function downloadTemplate() { window.location.href = '/api/mappings/csv-template'; } // Escape HTML function esc(s) { if (s == null) return ''; return String(s).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, '''); }