/* hd-commerce — Wiederverwendbarer Medien-Picker (Admin). API: window.HDCMedia.pick({ multiple, onPick(url|urls) }) öffnet ein Modal mit Bibliothek (/api/admin/media), Inline-Upload (WebP) und Auswahl. */ (function () { var overlay = null, listEl = null, state = { multiple: false, onPick: null, selected: [] }; function el(tag, cls, html) { var e = document.createElement(tag); if (cls) e.className = cls; if (html != null) e.innerHTML = html; return e; } function build() { overlay = el('div', 'mp-overlay'); overlay.innerHTML = ''; document.body.appendChild(overlay); listEl = overlay.querySelector('[data-grid]'); overlay.querySelector('.mp-close').addEventListener('click', close); overlay.querySelector('.mp-cancel').addEventListener('click', close); overlay.addEventListener('click', function (e) { if (e.target === overlay) close(); }); overlay.querySelector('.mp-confirm').addEventListener('click', confirmSel); var fileInput = overlay.querySelector('.mp-upbtn input'); fileInput.addEventListener('change', function () { upload(fileInput.files); fileInput.value = ''; }); var drop = overlay.querySelector('[data-drop]'); ['dragover', 'dragenter'].forEach(function (ev) { drop.addEventListener(ev, function (e) { e.preventDefault(); drop.classList.add('over'); }); }); ['dragleave', 'drop'].forEach(function (ev) { drop.addEventListener(ev, function (e) { e.preventDefault(); drop.classList.remove('over'); }); }); drop.addEventListener('drop', function (e) { if (e.dataTransfer && e.dataTransfer.files) upload(e.dataTransfer.files); }); document.addEventListener('keydown', function (e) { if (overlay && overlay.classList.contains('open') && e.key === 'Escape') close(); }); } function msg(text, kind) { var m = overlay.querySelector('[data-msg]'); m.textContent = text || ''; m.className = 'mp-msg' + (kind ? ' ' + kind : '') + (text ? ' show' : ''); } function load() { listEl.innerHTML = '
Lädt …
'; fetch('/api/admin/media', { headers: { 'Accept': 'application/json' } }) .then(function (r) { return r.json(); }) .then(function (d) { renderGrid((d && d.media) || []); }) .catch(function () { listEl.innerHTML = '
Konnte Medien nicht laden.
'; }); } function renderGrid(media) { if (!media.length) { listEl.innerHTML = '
Noch keine Medien. Lade oben welche hoch.
'; return; } listEl.innerHTML = ''; media.forEach(function (m) { var card = el('div', 'mp-card'); if (state.selected.indexOf(m.url) > -1) card.classList.add('sel'); card.innerHTML = '
' + '
' + (m.filename || '') + '' + '' + Math.round((m.size || 0) / 1024) + ' KB' + (m.width ? ' · ' + m.width + '×' + m.height : '') + '
' + '
' + '' + '' + '
'; card.querySelector('.mp-thumb').addEventListener('click', function () { toggle(m.url, card); }); card.querySelector('[data-copy]').addEventListener('click', function (e) { e.stopPropagation(); try { navigator.clipboard.writeText(location.origin + m.url); msg('URL kopiert.', 'ok'); } catch (x) {} }); card.querySelector('[data-del]').addEventListener('click', function (e) { e.stopPropagation(); if (!confirm('Dieses Medium löschen?')) return; fetch('/api/admin/media?id=' + m.id, { method: 'DELETE' }).then(function (r) { return r.json(); }) .then(function (d) { if (d.ok) { state.selected = state.selected.filter(function (u) { return u !== m.url; }); load(); } else msg(d.error || 'Löschen fehlgeschlagen.', 'err'); }); }); listEl.appendChild(card); }); updateSelCount(); } function toggle(url, card) { if (state.multiple) { var i = state.selected.indexOf(url); if (i > -1) { state.selected.splice(i, 1); card.classList.remove('sel'); } else { state.selected.push(url); card.classList.add('sel'); } } else { state.selected = [url]; Array.prototype.forEach.call(listEl.querySelectorAll('.mp-card'), function (c) { c.classList.remove('sel'); }); card.classList.add('sel'); } updateSelCount(); } function updateSelCount() { var s = overlay.querySelector('[data-sel]'); s.textContent = state.selected.length ? state.selected.length + ' ausgewählt' : ''; } function upload(files) { if (!files || !files.length) return; var fd = new FormData(); Array.prototype.forEach.call(files, function (f) { fd.append('files', f); }); msg('Lädt ' + files.length + ' Datei(en) hoch …'); fetch('/api/upload', { method: 'POST', body: fd }).then(function (r) { return r.json(); }) .then(function (d) { if (d && d.results) { var conv = d.results.filter(function (r) { return r.converted; }).length; msg('Hochgeladen' + (conv ? ' (' + conv + '× zu WebP konvertiert)' : '') + '.', 'ok'); // Neu hochgeladene direkt vorauswählen d.results.forEach(function (r) { if (r.ok && r.url && state.selected.indexOf(r.url) < 0) { if (state.multiple) state.selected.push(r.url); else state.selected = [r.url]; } }); load(); } else { msg((d && d.error) || 'Upload fehlgeschlagen.', 'err'); } }) .catch(function () { msg('Upload fehlgeschlagen.', 'err'); }); } function confirmSel() { if (!state.selected.length) { close(); return; } var cb = state.onPick; var sel = state.selected.slice(); close(); if (cb) cb(state.multiple ? sel : sel[0]); } function open() { if (!overlay) build(); overlay.classList.add('open'); msg(''); load(); } function close() { if (overlay) overlay.classList.remove('open'); } window.HDCMedia = { pick: function (opts) { opts = opts || {}; state.multiple = !!opts.multiple; state.onPick = opts.onPick || null; state.selected = []; open(); } }; })();