diff --git a/templates/admin/manual_ingest.html.twig b/templates/admin/manual_ingest.html.twig index 4e65b02..a4781f7 100644 --- a/templates/admin/manual_ingest.html.twig +++ b/templates/admin/manual_ingest.html.twig @@ -78,6 +78,7 @@ {# ── Search photo (mandatory) ─────────────────────────────── #} + {% set searchInputId = form.image.vars.id %}
@@ -87,34 +88,39 @@
Typenschild / Aufkleber mit Modell & Seriennummer
- {# Hidden actual file input #} - {{ form_widget(form.image, {'attr': {'class': 'd-none', 'id': 'search-photo-input'}}) }} + {# File input — opacity:0 so label-click still works in all browsers #} + {{ form_widget(form.image, {'attr': {'style': 'position:absolute;opacity:0;width:0;height:0;', 'tabindex': '-1', 'id': searchInputId}}) }} {{ form_errors(form.image) }} - {# Preview #} -
- {# Hidden input that holds extra files #} + {# Plain HTML input — label trigger works without JS tricks #} + accept="image/jpeg,image/png,image/webp" multiple + style="position:absolute;opacity:0;width:0;height:0;">
@@ -139,9 +146,9 @@ - +
@@ -243,7 +250,7 @@ errDiv.style.display = 'block'; // Mobile fallback: trigger native camera input if (cameraTarget === 'search') { - document.getElementById('search-photo-input').click(); + searchInput?.click(); } else { document.getElementById('extra-photos-input').click(); } @@ -285,14 +292,16 @@ }); /* ── Search photo ──────────────────────────────────────────── */ - const searchInput = document.getElementById('search-photo-input'); + const dropZone = document.getElementById('search-drop-zone'); + const searchInput = document.getElementById(dropZone.dataset.input); const searchPreview = document.getElementById('search-photo-preview'); - const searchImg = document.getElementById('search-photo-img'); - const searchHolder = document.getElementById('search-photo-placeholder'); + const searchImg = document.getElementById('search-photo-img'); + const searchHolder = document.getElementById('search-photo-placeholder'); document.getElementById('btn-search-camera').addEventListener('click', () => openCamera('search')); - document.getElementById('btn-search-file').addEventListener('click', () => searchInput.click()); - document.getElementById('search-photo-clear').addEventListener('click', () => { + + document.getElementById('search-photo-clear').addEventListener('click', e => { + e.stopPropagation(); searchInput.value = ''; searchImg.src = ''; searchPreview.style.display = 'none'; @@ -303,6 +312,24 @@ if (searchInput.files[0]) setSearchPhoto(searchInput.files[0]); }); + // Drag & drop on the drop zone + dropZone.addEventListener('dragover', e => { + e.preventDefault(); + dropZone.style.borderColor = '#0d6efd'; + dropZone.style.background = '#e8f0fe'; + }); + dropZone.addEventListener('dragleave', () => { + dropZone.style.borderColor = ''; + dropZone.style.background = ''; + }); + dropZone.addEventListener('drop', e => { + e.preventDefault(); + dropZone.style.borderColor = ''; + dropZone.style.background = ''; + const file = e.dataTransfer.files[0]; + if (file) setSearchPhoto(file); + }); + function setSearchPhoto(file) { const dt = new DataTransfer(); dt.items.add(file); @@ -310,6 +337,8 @@ searchImg.src = URL.createObjectURL(file); searchPreview.style.display = 'block'; searchHolder.style.display = 'none'; + dropZone.style.borderColor = ''; + dropZone.style.background = ''; } /* ── Extra photos ──────────────────────────────────────────── */