diff --git a/index.html b/index.html index b6d097d..b9a2766 100644 --- a/index.html +++ b/index.html @@ -63,7 +63,13 @@ - + + + + + + + diff --git a/js/config.js b/js/config.js new file mode 100644 index 0000000..2e4c51e --- /dev/null +++ b/js/config.js @@ -0,0 +1,12 @@ +// =============================== +// CONFIG & GLOBAL STATE +// =============================== + +const API_URL = 'https://prova.patachina.it/photos'; + +let photosData = []; +let currentPhoto = null; + +// Mappa globale +let globalMap = null; +let globalMarkers = null; diff --git a/js/data.js b/js/data.js new file mode 100644 index 0000000..14c0af2 --- /dev/null +++ b/js/data.js @@ -0,0 +1,26 @@ +// =============================== +// FETCH DELLE FOTO +// =============================== +async function loadPhotos() { + console.log("Inizio fetch:", API_URL); + + let res; + try { + res = await fetch(API_URL); + } catch (e) { + console.error("Errore fetch:", e); + return; + } + + const text = await res.text(); + + try { + photosData = JSON.parse(text); + console.log("JSON parse OK, numero foto:", photosData.length); + } catch (e) { + console.error("Errore nel parse JSON:", e); + return; + } + + renderGallery(photosData); +} diff --git a/js/gallery.js b/js/gallery.js new file mode 100644 index 0000000..298b585 --- /dev/null +++ b/js/gallery.js @@ -0,0 +1,40 @@ +// =============================== +// RENDER GALLERIA +// =============================== +function renderGallery(photos) { + const gallery = document.getElementById('gallery'); + gallery.innerHTML = ''; + + photos.forEach(photo => { + const thumbDiv = document.createElement('div'); + thumbDiv.className = 'thumb'; + + const img = document.createElement('img'); + img.src = `https://prova.patachina.it/${photo.thub1}`; + img.alt = photo.name || ''; + img.loading = "lazy"; + + thumbDiv.appendChild(img); + + if (photo.mime_type.startsWith("video/")) { + const play = document.createElement("div"); + play.className = "play-icon"; + play.textContent = "▶"; + thumbDiv.appendChild(play); + } + + const preview = photo.thub2 + ? `https://prova.patachina.it/${photo.thub2}` + : `https://prova.patachina.it/${photo.thub1}`; + + thumbDiv.addEventListener('click', () => { + openModal( + `https://prova.patachina.it/${photo.path}`, + preview, + photo + ); + }); + + gallery.appendChild(thumbDiv); + }); +} diff --git a/js/infoPanel.js b/js/infoPanel.js new file mode 100644 index 0000000..06b16e4 --- /dev/null +++ b/js/infoPanel.js @@ -0,0 +1,57 @@ +// =============================== +// PANNELLO INFO + MAPPA +// =============================== +const infoPanel = document.getElementById('infoPanel'); +const infoBtn = document.getElementById('modalInfoBtn'); + +infoBtn.addEventListener('click', () => { + if (!currentPhoto) return; + + const gps = currentPhoto.gps || { lat: '-', lng: '-', alt: '-' }; + const folder = currentPhoto.path.split('/').slice(2, -1).join('/'); + + infoPanel.innerHTML = ` +

Informazioni

+ +
Nome: ${currentPhoto.name}
+
Data: ${currentPhoto.taken_at}
+ +
Latitudine: ${gps.lat}
+
Longitudine: ${gps.lng}
+
Altitudine: ${gps.alt} m
+ +
Dimensioni: ${currentPhoto.width} × ${currentPhoto.height}
+
Peso: ${(currentPhoto.size_bytes / 1024 / 1024).toFixed(2)} MB
+
Tipo: ${currentPhoto.mime_type}
+ +
Cartella: ${folder}
+ + ${gps.lat !== '-' ? '
' : ''} + `; + + infoPanel.classList.add('open'); + + if (gps.lat !== '-' && gps.lng !== '-') { + setTimeout(() => { + const map = L.map('infoMap', { + zoomControl: false, + attributionControl: false + }).setView([gps.lat, gps.lng], 13); + + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19 + }).addTo(map); + + L.marker([gps.lat, gps.lng]).addTo(map); + }, 50); + } +}); + +document.addEventListener('click', (e) => { + if (!infoPanel.classList.contains('open')) return; + + const inside = infoPanel.contains(e.target); + const btn = infoBtn.contains(e.target); + + if (!inside && !btn) infoPanel.classList.remove('open'); +}); diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..1f5ae9b --- /dev/null +++ b/js/main.js @@ -0,0 +1,5 @@ +// =============================== +// AVVIO +// =============================== +console.log("main.js avviato"); +loadPhotos(); diff --git a/js/mapGlobal.js b/js/mapGlobal.js new file mode 100644 index 0000000..fd0e257 --- /dev/null +++ b/js/mapGlobal.js @@ -0,0 +1,51 @@ +// =============================== +// MAPPA GLOBALE +// =============================== +document.getElementById("openMapBtn").addEventListener("click", openGlobalMap); + +function openGlobalMap() { + const mapDiv = document.getElementById("globalMap"); + const gallery = document.getElementById("gallery"); + + const isOpen = mapDiv.classList.contains("open"); + + if (isOpen) { + mapDiv.classList.remove("open"); + gallery.classList.remove("hidden"); + return; + } + + mapDiv.classList.add("open"); + gallery.classList.add("hidden"); + + if (!globalMap) { + globalMap = L.map("globalMap").setView([42.5, 12.5], 6); + + L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { + maxZoom: 19 + }).addTo(globalMap); + + globalMarkers = L.markerClusterGroup(); + globalMap.addLayer(globalMarkers); + + photosData.forEach(photo => { + if (!photo.gps || !photo.gps.lat || !photo.gps.lng) return; + + const marker = L.marker([photo.gps.lat, photo.gps.lng]); + + marker.on("click", () => { + openModal( + `https://prova.patachina.it/${photo.path}`, + photo.thub2 + ? `https://prova.patachina.it/${photo.thub2}` + : `https://prova.patachina.it/${photo.thub1}`, + photo + ); + }); + + globalMarkers.addLayer(marker); + }); + } + + setTimeout(() => globalMap.invalidateSize(), 200); +} diff --git a/js/modal.js b/js/modal.js new file mode 100644 index 0000000..3353f78 --- /dev/null +++ b/js/modal.js @@ -0,0 +1,47 @@ +// =============================== +// MODALE (FOTO + VIDEO) +// =============================== +const modal = document.getElementById('modal'); +const modalClose = document.getElementById('modalClose'); + +function openModal(srcOriginal, srcPreview, photo) { + currentPhoto = photo; + + const container = document.getElementById("modalMediaContainer"); + container.innerHTML = ""; + + if (photo.mime_type.startsWith("video/")) { + const video = document.createElement("video"); + video.src = srcOriginal; + video.controls = true; + video.autoplay = true; + video.style.maxWidth = "100%"; + video.style.maxHeight = "100%"; + container.appendChild(video); + } else { + const img = document.createElement("img"); + img.src = srcPreview; + img.style.maxWidth = "100%"; + img.style.maxHeight = "100%"; + img.style.objectFit = "contain"; + container.appendChild(img); + + const full = new Image(); + full.src = srcOriginal; + full.onload = () => { + img.src = srcOriginal; + }; + } + + modal.classList.add('open'); +} + +function closeModal() { + modal.classList.remove('open'); + document.getElementById("modalMediaContainer").innerHTML = ""; +} + +modalClose.addEventListener('click', closeModal); +modal.addEventListener('click', (e) => { + if (e.target === modal) closeModal(); +});