// =============================== // AVVIO // =============================== console.log("main.js avviato"); // =============================== // PATCH: misura l'altezza reale dell'header e aggiorna --header-h // (serve per far partire la mappa subito sotto l’header, anche su mobile) // =============================== (function () { const root = document.documentElement; const header = document.querySelector('header'); function setHeaderHeight() { const h = header ? Math.round(header.getBoundingClientRect().height) : 60; root.style.setProperty('--header-h', h + 'px'); } setHeaderHeight(); if (window.ResizeObserver && header) { const ro = new ResizeObserver(setHeaderHeight); ro.observe(header); } else { window.addEventListener('resize', setHeaderHeight); window.addEventListener('orientationchange', setHeaderHeight); } window.addEventListener('load', setHeaderHeight); })(); // =============================== // PATCH: quando si apre la mappa (#globalMap.open) invalida le dimensioni Leaflet // (utile perché prima era display:none; invalidateSize evita “tagli” o tile sfasati) // =============================== (function () { const mapEl = document.getElementById('globalMap'); if (!mapEl) return; function invalidateWhenOpen() { if (!mapEl.classList.contains('open')) return; // Aspetta un tick così il layout è aggiornato setTimeout(() => { try { // Sostituisci con la tua variabile dell'istanza L.map, se diversa window.leafletMapInstance?.invalidateSize(); } catch (e) { console.warn('invalidateSize non eseguito:', e); } }, 0); } // 1) Osserva il cambio classe (quando aggiungi .open) const mo = new MutationObserver((mutations) => { if (mutations.some(m => m.attributeName === 'class')) { invalidateWhenOpen(); } }); mo.observe(mapEl, { attributes: true, attributeFilter: ['class'] }); // 2) Fallback: se usi il bottone #openMapBtn per aprire/chiudere document.getElementById('openMapBtn')?.addEventListener('click', () => { setTimeout(invalidateWhenOpen, 0); }); })(); // =============================== // LOGIN AUTOMATICO SU INDEX // =============================== document.addEventListener("DOMContentLoaded", async () => { try { // 1) Carica config const cfgRes = await fetch('/config'); const cfg = await cfgRes.json(); window.BASE_URL = cfg.baseUrl; // 2) Recupera token salvato const savedToken = localStorage.getItem("token"); // Se non c'è token → mostra login if (!savedToken) { document.getElementById("loginModal").style.display = "flex"; return; } // 3) Verifica token const ping = await fetch(`${window.BASE_URL}/photos`, { headers: { "Authorization": "Bearer " + savedToken } }); if (!ping.ok) { // Token invalido → cancella e mostra login localStorage.removeItem("token"); document.getElementById("loginModal").style.display = "flex"; return; } // 4) Token valido → salva e carica gallery window.token = savedToken; loadPhotos(); } catch (err) { console.error("Errore autenticazione:", err); document.getElementById("loginModal").style.display = "flex"; } }); // =============================== // VARIABILI GLOBALI // =============================== let currentSort = "desc"; let currentGroup = "auto"; let currentFilter = null; window.currentSort = currentSort; window.currentGroup = currentGroup; window.currentFilter = currentFilter; // =============================== // MENU ⋮ // =============================== const optionsBtn = document.getElementById("optionsBtn"); const optionsSheetEl = document.getElementById("optionsSheet"); optionsBtn?.addEventListener("click", () => { optionsSheetEl?.classList.add("open"); }); // =============================== // BOTTONI OPZIONI // =============================== document.querySelectorAll("#optionsSheet .sheet-btn").forEach(btn => { btn.addEventListener("click", () => { if (btn.dataset.sort) window.currentSort = currentSort = btn.dataset.sort; if (btn.dataset.group) window.currentGroup = currentGroup = btn.dataset.group; if (btn.dataset.filter) window.currentFilter = currentFilter = btn.dataset.filter; optionsSheetEl?.classList.remove("open"); refreshGallery(); }); }); // =============================== // REFRESH GALLERY // =============================== function refreshGallery() { console.log("Aggiornamento galleria..."); const data = Array.isArray(window.photosData) ? window.photosData : []; let photos = [...data]; if (typeof applyFilters === 'function') photos = applyFilters(photos); if (typeof sortByDate === 'function') photos = sortByDate(photos, currentSort); let sections = [{ label: 'Tutte', photos }]; if (typeof groupByDate === 'function') sections = groupByDate(photos, currentGroup); if (typeof renderGallery === 'function') { renderGallery(sections); } } window.refreshGallery = refreshGallery; // =============================== // SETTINGS (⚙️) — apre admin.html // =============================== const settingsBtn = document.getElementById('settingsBtn'); settingsBtn?.addEventListener('click', () => { window.location.href = "admin.html"; }); // =============================== // LOGIN SUBMIT // =============================== document.getElementById("loginSubmit").addEventListener("click", async () => { const email = document.getElementById("loginEmail").value; const password = document.getElementById("loginPassword").value; const errorEl = document.getElementById("loginError"); errorEl.textContent = ""; try { const res = await fetch(`${window.BASE_URL}/auth/login`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }) }); if (!res.ok) { errorEl.textContent = "Utente o password errati"; return; } const data = await res.json(); const token = data.token; // Salva token localStorage.setItem("token", token); window.token = token; // Chiudi login document.getElementById("loginModal").style.display = "none"; // Carica gallery loadPhotos(); } catch (err) { console.error("Errore login:", err); errorEl.textContent = "Errore di connessione al server"; } });