// modules/holidays/holidays.js document.addEventListener("DOMContentLoaded", () => { // --- Modale "Ajouter une idée" const addBtn = document.getElementById("hol-add-open"); const addModal = document.getElementById("hol-add-modal"); if (addBtn && addModal) { const backdrop = addModal.querySelector(".hol-backdrop"); const cancel = addModal.querySelector(".hol-cancel"); const open = () => addModal.classList.add("open"); const close = () => addModal.classList.remove("open"); addBtn.addEventListener("click", open); backdrop.addEventListener("click", close); cancel.addEventListener("click", close); document.addEventListener("keydown", (e) => { if (e.key === "Escape") close(); }); } // --- Helpers modale "Éditer" const editModal = document.getElementById("hol-edit-modal"); const openEditModal = () => { if (editModal) editModal.classList.add("open"); }; const closeEditModal = () => { if (editModal) editModal.classList.remove("open"); }; async function openEditForId(id) { try { const res = await fetch( `/modules/holidays/view.php?id=${encodeURIComponent(id)}`, { headers: { Accept: "application/json" }, }, ); if (!res.ok) throw new Error("HTTP " + res.status); const it = await res.json(); if (!editModal) { alert("Modale édition introuvable"); return; } // Scope les sélecteurs à la modale pour éviter les null const $ = (sel) => editModal.querySelector(sel); const setVal = (sel, val) => { const el = $(sel); if (el) el.value = val ?? ""; }; setVal("#edit-id", it.id); setVal("#edit-title", it.title || ""); setVal("#edit-country", it.country || ""); setVal("#edit-region", it.region || ""); setVal("#edit-city", it.city || ""); setVal("#edit-lat", it.lat ?? ""); setVal("#edit-lng", it.lng ?? ""); setVal("#edit-start", it.desired_start_date ?? ""); setVal("#edit-end", it.desired_end_date ?? ""); setVal("#edit-season", it.season_hint || ""); setVal("#edit-days", it.ideal_days ?? ""); setVal("#edit-status", it.status || "draft"); setVal("#edit-notes", it.notes || ""); openEditModal(); } catch { alert("Impossible de charger l’idée."); } } // --- Modale "Éditer" (liste + page détail) if (editModal) { const backdrop = editModal.querySelector(".hol-backdrop"); const cancel = editModal.querySelector(".hol-cancel"); if (backdrop) backdrop.addEventListener("click", closeEditModal); if (cancel) cancel.addEventListener("click", closeEditModal); document.addEventListener("keydown", (e) => { if (e.key === "Escape") closeEditModal(); }); // Boutons "Éditer" des cards (liste/planifiées/archivées) document.querySelectorAll(".btn-edit[data-edit-id]").forEach((btn) => { btn.addEventListener("click", () => { const id = btn.getAttribute("data-edit-id"); if (id) openEditForId(id); }); }); // Bouton "Éditer" sur la page détail (en-tête) const headerEditBtn = document.getElementById("hol-edit-open"); if (headerEditBtn) { headerEditBtn.addEventListener("click", () => { const id = headerEditBtn.getAttribute("data-edit-id"); if (id) openEditForId(id); }); } } // --- Suppression (liste + planifiées + page détail) document.querySelectorAll(".btn-delete[data-del-id]").forEach((btn) => { btn.addEventListener("click", () => { const id = btn.getAttribute("data-del-id"); if (!id) return; if (confirm("Supprimer cette idée ?")) { const form = document.createElement("form"); form.method = "post"; form.action = "/modules/holidays/save.php"; form.innerHTML = ` `; document.body.appendChild(form); form.submit(); } }); }); // --- Géocodage via Nominatim + UI multi-résultats document.querySelectorAll(".hol-geocode-btn").forEach((btn) => { btn.addEventListener("click", async () => { const scope = btn.getAttribute("data-scope"); // 'add' ou 'edit' let form, city, region, country, latInput, lngInput; if (scope === "edit") { form = btn.closest("form") || document; city = (document.getElementById("edit-city")?.value || "").trim(); region = (document.getElementById("edit-region")?.value || "").trim(); country = (document.getElementById("edit-country")?.value || "").trim(); latInput = document.getElementById("edit-lat"); lngInput = document.getElementById("edit-lng"); } else { form = btn.closest("form"); city = (form?.querySelector('input[name="city"]')?.value || "").trim(); region = ( form?.querySelector('input[name="region"]')?.value || "" ).trim(); country = ( form?.querySelector('input[name="country"]')?.value || "" ).trim(); latInput = form?.querySelector('input[name="lat"]'); lngInput = form?.querySelector('input[name="lng"]'); } const q = [city, region, country].filter(Boolean).join(", "); if (!q) { alert("Renseigne au moins Ville/Pays."); return; } removeNearbyPicker(btn); btn.disabled = true; const original = btn.textContent; btn.textContent = "Recherche..."; try { const res = await fetch( `/modules/holidays/geocode.php?q=${encodeURIComponent(q)}&limit=5`, { headers: { Accept: "application/json" }, }, ); const data = await res.json(); if (!res.ok) throw new Error(data?.error || "Erreur géocodage"); if ("lat" in data && "lng" in data) { if (latInput) latInput.value = data.lat; if (lngInput) lngInput.value = data.lng; return; } if (Array.isArray(data.results) && data.results.length > 0) { renderGeocodePicker(btn, data.results, (choice) => { if (latInput) latInput.value = choice.lat; if (lngInput) lngInput.value = choice.lng; removeNearbyPicker(btn); }); } else { alert("Aucun résultat."); } } catch { alert("Impossible de trouver les coordonnées pour: " + q); } finally { btn.disabled = false; btn.textContent = original; } }); }); function renderGeocodePicker(anchorBtn, results, onPick) { removeNearbyPicker(anchorBtn); const wrapper = document.createElement("div"); wrapper.className = "hol-geocode-picker"; const header = document.createElement("div"); header.className = "hol-geocode-picker__header"; header.textContent = "Plusieurs résultats trouvés"; const closeBtn = document.createElement("button"); closeBtn.type = "button"; closeBtn.className = "hol-geocode-picker__close"; closeBtn.textContent = "×"; closeBtn.addEventListener("click", () => removeNearbyPicker(anchorBtn)); header.appendChild(closeBtn); const list = document.createElement("ul"); list.className = "hol-geocode-picker__list"; results.forEach((r) => { const li = document.createElement("li"); li.className = "hol-geocode-picker__item"; const label = document.createElement("div"); label.className = "hol-geocode-picker__label"; label.textContent = r.display_name || `${r.lat}, ${r.lng}`; const coords = document.createElement("div"); coords.className = "hol-geocode-picker__coords"; coords.textContent = `(${r.lat}, ${r.lng})`; const pickBtn = document.createElement("button"); pickBtn.type = "button"; pickBtn.className = "hol-geocode-picker__pick"; pickBtn.textContent = "Choisir"; pickBtn.addEventListener("click", () => onPick(r)); li.appendChild(label); li.appendChild(coords); li.appendChild(pickBtn); list.appendChild(li); }); wrapper.appendChild(header); wrapper.appendChild(list); const container = anchorBtn.closest(".hol-inline") || anchorBtn.parentElement; container.insertAdjacentElement("afterend", wrapper); } function removeNearbyPicker(anchorBtn) { const container = anchorBtn.closest(".hol-inline") || anchorBtn.parentElement; const next = container?.nextElementSibling; if (next && next.classList.contains("hol-geocode-picker")) { next.remove(); } } // --- Carte (Leaflet) const mapBtn = document.getElementById("hol-map-open"); const mapModal = document.getElementById("hol-map-modal"); if (mapBtn && mapModal) { const backdrop = mapModal.querySelector(".hol-backdrop"); const cancel = mapModal.querySelector(".hol-cancel"); const open = () => mapModal.classList.add("open"); const close = () => mapModal.classList.remove("open"); let mapInitialized = false; let map; function initMap() { // Évite double initialisation if (mapInitialized) return; mapInitialized = true; // Données carte (safe fallback) const MAP_DATA = Array.isArray(window.HOL_MAP_DATA) ? window.HOL_MAP_DATA : []; console.log("HOL_MAP_DATA (safe):", MAP_DATA); // Leaflet dispo ? if (typeof L === "undefined") { console.error("Leaflet non chargé"); return; } // Init carte une seule fois (ne pas faire ça dans la boucle) map = L.map("hol-map", { scrollWheelZoom: true }); L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: "© OpenStreetMap", }).addTo(map); // Corrige la taille après affichage de la modale setTimeout(() => map.invalidateSize(), 0); // Ajout des marqueurs const markers = []; MAP_DATA.forEach((it) => { const lat = parseFloat(it.lat); const lng = parseFloat(it.lng); if (!Number.isFinite(lat) || !Number.isFinite(lng)) return; const color = it.status === "planned" ? "#16a34a" : it.status === "favorite" ? "#f59e0b" : it.status === "shortlist" ? "#3b82f6" : "#6b7280"; const m = L.circleMarker([lat, lng], { radius: 6, color, fillColor: color, fillOpacity: 0.85, }).addTo(map); const loc = [it.city, it.region, it.country].filter(Boolean).join(", "); const dates = it.desired_start_date ? `${it.desired_start_date}${it.desired_end_date ? " → " + it.desired_end_date : ""}` : ""; m.bindPopup(` ${esc(it.title || "")}
${esc(loc)}
${dates ? "Dates: " + esc(dates) + "
" : ""} Statut: ${esc(it.status || "")}
Ouvrir `); markers.push(m); }); // Vue par défaut selon nombre de points if (markers.length === 1) { map.setView(markers[0].getLatLng(), 7); } else if (markers.length > 1) { const group = L.featureGroup(markers); map.fitBounds(group.getBounds(), { padding: [20, 20] }); } else { console.warn( "HOL_MAP_DATA vide ou coordonnées non valides.", window.HOL_MAP_DATA, ); map.setView([20, 0], 2); } // Re-valider la taille après rendu complet setTimeout(() => map.invalidateSize(), 100); } function esc(s) { return String(s).replace( /[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'", })[c], ); } mapBtn.addEventListener("click", () => { open(); setTimeout(initMap, 0); }); if (backdrop) backdrop.addEventListener("click", close); if (cancel) cancel.addEventListener("click", close); document.addEventListener("keydown", (e) => { if (e.key === "Escape") close(); }); } });