function pwaGoBack() { // Se esiste una pagina precedente nella cronologia della sessione if (window.history.length > 1) { window.history.back(); } else { // Fallback se l’app è stata aperta direttamente su questa pagina window.location.href = “/”; } }
#festival-map { width: 100%; height: calc(100vh – 120px); border-radius: 12px; z-index: 1; box-shadow: 0 4px 12px rgba(0,0,0,0.15); } .map-filter-bar { display: flex; gap: 8px; overflow-x: auto; padding: 10px 0; white-space: nowrap; -webkit-overflow-scrolling: touch; } .filter-btn { background: #f1f3f5; border: 1px solid #ced4da; border-radius: 20px; padding: 7px 15px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; } .filter-btn.active { background: #e52424; color: #fff; border-color: #e52424; } .stage-badge { background-color: #e63946; color: #ffffff; font-weight: 800; font-family: sans-serif; font-size: 12px; border: 1.5px solid #ffffff; box-shadow: 0 2px 5px rgba(0,0,0,0.4); display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 4px; } .food-badge { background-color: #ffb800; color: #ffffff; font-weight: 800; font-family: sans-serif; font-size: 12px; border: 1.5px solid #ffffff; box-shadow: 0 2px 5px rgba(0,0,0,0.4); display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 4px; } .service-badge { background: #ffffff; border: 1px solid #444; border-radius: 50%; font-size: 13px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 4px rgba(0,0,0,0.25); width: 24px; height: 24px; } .accessible-badge { background: #007aff; border: 1.5px solid #ffffff; border-radius: 50%; font-size: 13px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 5px rgba(0,0,0,0.35); width: 24px; height: 24px; } const map = L.map(‘festival-map’).setView([40.9190, 14.7345], 17); L.tileLayer(‘https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png’, { maxZoom: 19, attribution: ‘© OpenStreetMap’ }).addTo(map); const stageIcon = (num) => L.divIcon({ className: ‘custom-stage’, html: `
${num}
`, iconSize: [24, 24], iconAnchor: [12, 12], popupAnchor: [0, -12] }); const foodIcon = (num) => L.divIcon({ className: ‘custom-food’, html: `
${num}
`, iconSize: [24, 24], iconAnchor: [12, 12], popupAnchor: [0, -12] }); const serviceIcon = (emoji) => L.divIcon({ className: ‘custom-service’, html: `
${emoji}
`, iconSize: [24, 24], iconAnchor: [12, 12], popupAnchor: [0, -12] }); const accessibleIcon = () => L.divIcon({ className: ‘custom-accessible’, html: `
`, iconSize: [24, 24], iconAnchor: [12, 12], popupAnchor: [0, -12] }); const festivalRoute = [ [40.9190, 14.7346], [40.9190, 14.73475], [40.918775, 14.7348], [40.91861, 14.7346], [40.918595, 14.7344], [40.9186, 14.73395], [40.9189, 14.7330], [40.91903, 14.7328], [40.9190, 14.7327] ]; const routeLayer = L.polyline(festivalRoute, { color: ‘#e52424’, weight: 4, opacity: 0.8, dashArray: ‘2, 6’ }).addTo(map); // Array dei luoghi con l’aggiunta della proprietà ID const places = [ // — POSTAZIONI SPETTACOLO — { id: “palco-1”, name: “Postazione 1”, category: “palco”, coords: [40.9183, 14.7338], icon: stageIcon(“1”), desc: “Spettacolo” }, { id: “palco-2”, name: “Postazione 2”, category: “palco”, coords: [40.9183, 14.7334], icon: stageIcon(“2”), desc: “Spettacolo” }, { id: “palco-3”, name: “Postazione 3”, category: “palco”, coords: [40.9185, 14.7332], icon: stageIcon(“3”), desc: “Spettacolo” }, { id: “palco-4”, name: “Postazione 4”, category: “palco”, coords: [40.9187, 14.7329], icon: stageIcon(“4”), desc: “Spettacolo” }, { id: “palco-6”, name: “Postazione 6”, category: “palco”, coords: [40.9187, 14.7345], icon: stageIcon(“6”), desc: “Spettacolo” }, { id: “palco-8”, name: “Postazione 8”, category: “palco”, coords: [40.91905, 14.7340], icon: stageIcon(“8”), desc: “Spettacolo” }, { id: “palco-9”, name: “Postazione 9”, category: “palco”, coords: [40.919266, 14.733465], icon: stageIcon(“9”), desc: “Spettacolo” }, { id: “palco-10”, name: “Postazione 10”, category: “palco”, coords: [40.9195, 14.7332], icon: stageIcon(“10”), desc: “Spettacolo” }, // — FOOD & DRINK — { id: “ristoro-1”, name: “Punto Ristoro 1”, category: “food”, coords: [40.9183, 14.7337], icon: foodIcon(“A”), desc: “Stand Gastronomico” }, { id: “ristoro-mulino”, name: “Punto Ristoro Mulino”, category: “food”, coords: [40.9182, 14.7335], icon: foodIcon(“B”), desc: “Drink & Ristoro” }, { id: “ristoro-vagno”, name: “Punto Ristoro Vagno”, category: “food”, coords: [40.9190, 14.7328], icon: foodIcon(“C”), desc: “Stand Gastronomico” }, { id: “ristoro-concezione”, name: “Punto Ristoro Concezione”, category: “food”, coords: [40.91955, 14.7330], icon: foodIcon(“D”), desc: “Stand Gastronomico” }, // — INFO, SERVIZI & ACCESSIBILITÀ — { id: “disabili-inizio”, name: “Inizio accesso disabili”, category: “servizi”, coords: [40.9190, 14.7346], icon: accessibleIcon(), desc: “Percorso accessibile – Punto di partenza” }, { id: “disabili-fine”, name: “Fine accesso disabili”, category: “servizi”, coords: [40.9190, 14.7327], icon: accessibleIcon(), desc: “Percorso accessibile – Arrivo” }, { id: “info-principale”, name: “Info Point Principale”, category: “servizi”, coords: [40.9190, 14.7348], icon: serviceIcon(“ℹ️”), desc: “Informazioni e accoglienza” }, { id: “info-santi”, name: “Info Point Porta dei Santi”, category: “servizi”, coords: [40.9195, 14.7359], icon: serviceIcon(“ℹ️”), desc: “Informazioni e accoglienza” }, { id: “bagni-1”, name: “Bagni Pubblici 1”, category: “servizi”, coords: [40.9201, 14.7338], icon: serviceIcon(“🚻”), desc: “Bagni pubblici e WC disabili” }, { id: “bagni-2”, name: “Bagni Pubblici 2”, category: “servizi”, coords: [40.9206, 14.7329], icon: serviceIcon(“🚻”), desc: “Bagni pubblici” }, { id: “fermata-navetta”, name: “Fermata Navetta”, category: “servizi”, coords: [40.9190, 14.7347], icon: serviceIcon(“🚌”), desc: “Accesso facilitato e navetta” }, // — LUOGHI STORICI & MONUMENTI — { id: “chiesa-madre”, name: “Chiesa Madre S.S. Pietro e Paolo”, category: “monumento”, coords: [40.9187, 14.7346], icon: serviceIcon(“⛪”), desc: “Luogo d’interesse storico” }, { id: “chiesa-concezione”, name: “Chiesa S.S. Concezione”, category: “monumento”, coords: [40.9194, 14.7335], icon: serviceIcon(“⛪”), desc: “Luogo d’interesse storico” }, { id: “chiesa-salvatore”, name: “Chiesa S.S. Salvatore”, category: “monumento”, coords: [40.9180, 14.7356], icon: serviceIcon(“⛪”), desc: “Luogo d’interesse storico” }, { id: “chiesa-giovanni”, name: “Chiesa di San Giovanni”, category: “monumento”, coords: [40.9181, 14.7360], icon: serviceIcon(“⛪”), desc: “Luogo d’interesse storico” }, { id: “porta-santi”, name: “Porta dei Santi”, category: “monumento”, coords: [40.9195, 14.7360], icon: serviceIcon(“🏛️”), desc: “Accesso storico al borgo” }, { id: “chiesa-francesco”, name: “Chiesa di San Francesco”, category: “monumento”, coords: [40.9199, 14.7354], icon: serviceIcon(“⛪”), desc: “Complesso Monumentale” }, { id: “municipio”, name: “Palazzo Municipale”, category: “monumento”, coords: [40.92015, 14.7361], icon: serviceIcon(“🏛️”), desc: “Sede Comunale” } ]; let markers = []; // Creazione di tutti i marker places.forEach(p => { const m = L.marker(p.coords, { icon: p.icon }) .bindPopup(`${p.name}
${p.desc}`); m.category = p.category; m.id = p.id; m.coords = p.coords; markers.push(m); }); // 1. Controllo se l’utente proviene da un click su un ristorante (?poi=ID) const urlParams = new URLSearchParams(window.location.search); const targetPoi = urlParams.get(‘poi’); if (targetPoi) { // Rimuove l’active dai pulsanti document.querySelectorAll(‘.filter-btn’).forEach(b => b.classList.remove(‘active’)); map.removeLayer(routeLayer); markers.forEach(m => { if (m.id === targetPoi) { m.addTo(map); map.setView(m.coords, 18); m.openPopup(); } }); } else { // Se non c’è filtro, mostra tutti i marker markers.forEach(m => m.addTo(map)); } // Funzione filtro tramite i pulsanti della barra function filterMarkers(cat, btn) { document.querySelectorAll(‘.filter-btn’).forEach(b => b.classList.remove(‘active’)); btn.classList.add(‘active’); markers.forEach(m => { if (cat === ‘all’ || m.category === cat) { map.addLayer(m); } else { map.removeLayer(m); } }); if (cat === ‘all’ || cat === ‘servizi’) { map.addLayer(routeLayer); } else { map.removeLayer(routeLayer); } } // Geolocalizzazione Utente map.locate({ setView: false, maxZoom: 18, watch: true }); let userMarker = null; map.on(‘locationfound’, function(e) { if (!userMarker) { userMarker = L.circleMarker(e.latlng, { radius: 8, color: ‘#007aff’, fillColor: ‘#007aff’, fillOpacity: 0.9, weight: 3 }).addTo(map).bindPopup(“📍 Sei qui!”); } else { userMarker.setLatLng(e.latlng); } });

App created by Giuseppe Ragucci

____________________________________