import { Controller } from "@hotwired/stimulus"; import Sortable from "sortablejs"; export default class extends Controller { static targets = [ "input", "preview", "list", "card", "checkbox", "checkIcon", "overlay", "count", ]; sortable = null; connect() { this.restoreInitialSelection(); this.enableSortable(); this.updateCount(); } // --------------------------------------------------------------------- // 1) Restaurer auto la sélection existante (images déjà liées) // --------------------------------------------------------------------- restoreInitialSelection() { this.previewTarget.innerHTML = ""; const selectedIds = [ ...document.querySelectorAll('input[name="selectedImages[]"]'), ].map((input) => input.value); // coche les bonnes cases dans la modale this.checkboxTargets.forEach((checkbox) => { if (selectedIds.includes(checkbox.value)) { checkbox.checked = true; this.updateCard(checkbox.closest("label"), true); } }); // Ajoute dans le preview selectedIds.forEach((id) => { const card = this.cardTargets.find((c) => c.dataset.id === id); if (!card) return; const img = document.createElement("img"); img.src = card.dataset.url; img.dataset.id = id; img.className = "w-20 h-20 rounded object-cover cursor-move"; this.previewTarget.appendChild(img); }); } // --------------------------------------------------------------------- // 2) Sélection dans la modale // --------------------------------------------------------------------- cardClick(event) { const card = event.currentTarget; const checkbox = card.querySelector("input[type='checkbox']"); checkbox.checked = !checkbox.checked; this.updateCard(card, checkbox.checked); this.updateCount(); } toggleCheckbox(event) { const checkbox = event.currentTarget; const card = checkbox.closest("label"); this.updateCard(card, checkbox.checked); this.updateCount(); } updateCard(card, checked) { const icon = card.querySelector( "[data-news--edit-image-selector-target='checkIcon']", ); const overlay = card.querySelector( "[data-news--edit-image-selector-target='overlay']", ); if (icon) icon.classList.toggle("hidden", !checked); if (overlay) overlay.classList.toggle("hidden", !checked); card.classList.toggle("ring-4", checked); card.classList.toggle("ring-amber-500", checked); } updateCount() { const total = this.checkboxTargets.filter((c) => c.checked).length; if (this.hasCountTarget) { this.countTarget.textContent = `${total} sélectionnée(s)`; } } // --------------------------------------------------------------------- // 3) Validation depuis la modale → update preview + ordre // --------------------------------------------------------------------- validate() { const selected = this.checkboxTargets .filter((c) => c.checked) .map((c) => c.value); // 🔥 RESET COMPLET this.previewTarget.innerHTML = ""; // 🔁 RECONSTRUCTION PROPRE selected.forEach((id) => { const card = this.cardTargets.find((c) => c.dataset.id === id); if (!card) return; const img = document.createElement("img"); img.src = card.dataset.url; img.dataset.id = id; img.className = "w-20 h-20 rounded object-cover cursor-move"; this.previewTarget.appendChild(img); }); this.enableSortable(); this.updateOrder(); document .querySelector("[command='close'][commandfor='edit-news-image-dialog']") .click(); } // --------------------------------------------------------------------- // 4) Drag & drop // --------------------------------------------------------------------- enableSortable() { if (this.sortable) this.sortable.destroy(); this.sortable = Sortable.create(this.previewTarget, { animation: 150, ghostClass: "opacity-40", onSort: () => this.updateOrder(), }); } updateOrder() { const form = this.previewTarget.closest("form"); // supprime uniquement les inputs dynamiques form .querySelectorAll( 'input[name="selectedImages[]"]:not([data-permanent="true"])', ) .forEach((i) => i.remove()); // recréer les inputs cachés Array.from(this.previewTarget.children).forEach((img) => { const hidden = document.createElement("input"); hidden.type = "hidden"; hidden.name = "selectedImages[]"; hidden.value = img.dataset.id; form.appendChild(hidden); }); } }