(function () { const API_BASE = '/api'; const printerSelect = document.getElementById('printerSelect'); const printerCompare = document.getElementById('printerCompare'); const matBody = document.getElementById('matBody'); const tableHead = document.getElementById('tableHead'); const statusEl = document.getElementById('status'); const errorBox = document.getElementById('errorBox'); if (!printerSelect || !printerCompare || !matBody || !tableHead) { return; } function setStatus(text) { if (statusEl) { statusEl.textContent = text; } } function showError(msg) { if (!errorBox) return; errorBox.hidden = false; errorBox.textContent = msg; } function clearError() { if (!errorBox) return; errorBox.hidden = true; errorBox.textContent = ''; } function escapeHtml(value) { return String(value ?? '') .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } async function fetchJSON(path) { const res = await fetch(API_BASE + path, { headers: { 'Accept': 'application/json' } }); if (!res.ok) throw new Error('HTTP ' + res.status + ' for ' + path); return await res.json(); } async function loadPrinters() { try { setStatus('Lade Drucker ...'); const data = await fetchJSON('/printers'); printerSelect.innerHTML = ''; printerCompare.innerHTML = ''; if (!Array.isArray(data) || data.length === 0) { printerSelect.innerHTML = ''; setStatus('Keine Drucker gefunden'); return; } data.forEach(p => { printerSelect.appendChild(new Option(p.name, p.id)); printerCompare.appendChild(new Option(p.name, p.id)); }); loadSinglePrinter(data[0].id); setStatus('Drucker geladen'); } catch (err) { console.error(err); showError('Konnte Drucker nicht laden.'); setStatus('Fehler'); } } async function loadSinglePrinter(id) { if (!id) return; clearError(); setStatus('Lade Materialien ...'); try { const data = await fetchJSON('/printer-materials?id=' + encodeURIComponent(id)); renderTable([data]); setStatus('Fertig'); } catch (err) { console.error(err); showError('Konnte Materialien für den Drucker nicht laden.'); setStatus('Fehler'); } } async function loadMultiplePrinters(ids) { if (!ids.length) return; clearError(); setStatus('Lade Vergleich ...'); try { const datasets = await Promise.all( ids.map(id => fetchJSON('/printer-materials?id=' + encodeURIComponent(id))) ); renderTable(datasets); setStatus('Vergleich geladen'); } catch (err) { console.error(err); showError('Konnte einen der gewählten Drucker nicht laden.'); setStatus('Fehler'); } } function renderTable(datasets) { const baseHead = [ 'Material', 'Eigenschaften', 'Tg °C', 'Düse', 'Platte', 'Zusatz', 'Anwendung', 'Kinder ', 'Emission ' ].map(label => `${label}`).join(''); let printerCols = ''; datasets.forEach(ds => { if (ds && ds.printer) { printerCols += `${escapeHtml(ds.printer.name)}`; } }); tableHead.innerHTML = baseHead + printerCols; const materials = (datasets[0] && datasets[0].materials) ? datasets[0].materials : []; matBody.innerHTML = ''; if (!materials.length) { const empty = document.createElement('tr'); empty.innerHTML = 'Keine Materialien gefunden.'; matBody.appendChild(empty); return; } materials.forEach((m, idx) => { const tr = document.createElement('tr'); tr.className = idx % 2 === 0 ? '' : 'is-alt'; const kid = m.kid_safety === 'safe' ? { icon: '🌿', text: 'sicher' } : (m.kid_safety === 'limited' ? { icon: '🟡', text: 'eingeschränkt' } : { icon: '🔴', text: 'nicht geeignet' }); const em = m.emission === 'low' ? { icon: '✅', text: 'niedrig' } : (m.emission === 'medium' ? { icon: '⚠️', text: 'mittel' } : { icon: '⛔', text: 'hoch' }); let html = ''; html += `${escapeHtml(m.code)}
${escapeHtml(m.short_desc || '')}
`; html += `${escapeHtml(m.properties || '')}`; html += `${escapeHtml(m.tg_celsius || '–')}`; html += `${escapeHtml(m.nozzle_req || '')}`; html += `${escapeHtml(m.plate_req || '')}`; html += `${escapeHtml(m.extra_req || '')}`; html += `${escapeHtml(m.application || '')}`; html += `${kid.icon}`; html += `${em.icon}`; datasets.forEach(ds => { const printerId = ds && ds.printer ? ds.printer.id : ''; const match = ds.materials.find(x => x.id === m.id || x.code === m.code); if (!match || !match.support_level) { html += `unbekannt`; } else { let badge = ''; if (match.support_level === 'full') { badge = 'voll'; } else if (match.support_level === 'partial') { badge = 'teilw.'; } else if (match.support_level === 'with_addon') { badge = 'Zusatz'; } else { badge = 'nein'; } const note = match.partial_reason ? `
${escapeHtml(match.partial_reason)}
` : (match.extra_info ? `
${escapeHtml(match.extra_info)}
` : ''); html += `${badge}${note}`; } }); tr.innerHTML = html; matBody.appendChild(tr); }); } printerSelect.addEventListener('change', e => { const id = e.target.value; if (id) { loadSinglePrinter(id); printerCompare.selectedIndex = -1; } }); printerCompare.addEventListener('change', e => { const ids = Array.from(e.target.selectedOptions).map(o => o.value); if (ids.length) { loadMultiplePrinters(ids); } }); loadPrinters(); })();