144 lines
5.2 KiB
JavaScript
144 lines
5.2 KiB
JavaScript
// Editor delle piantine (pagina /piantine, solo amministratore).
|
|
//
|
|
// Mappa Leaflet su tessere OpenStreetMap: mostra l'area del KML, i poligoni
|
|
// dei territori già salvati e permette di disegnarne di nuovi con
|
|
// leaflet-draw. Parla con il componente Livewire attraverso eventi:
|
|
// JS → Livewire: 'poligono-disegnato', 'territorio-selezionato-mappa'
|
|
// Livewire → JS: 'piantine-dati-aggiornati'
|
|
|
|
import L from 'leaflet';
|
|
import 'leaflet/dist/leaflet.css';
|
|
import 'leaflet-draw';
|
|
import 'leaflet-draw/dist/leaflet.draw.css';
|
|
|
|
const STILE_AREA = { color: '#2563eb', weight: 2, dashArray: '8 6', fill: false, interactive: false };
|
|
const STILE_SALVATO = { color: '#6b7280', weight: 2, fillColor: '#6b7280', fillOpacity: 0.12 };
|
|
const STILE_SELEZIONATO = { color: '#4f46e5', weight: 3, fillColor: '#6366f1', fillOpacity: 0.2 };
|
|
const STILE_IN_ATTESA = { color: '#d81b1b', weight: 3, fillColor: '#ef4444', fillOpacity: 0.15 };
|
|
|
|
function initPiantine() {
|
|
const contenitore = document.getElementById('piantine-map');
|
|
if (!contenitore || contenitore.dataset.inizializzato) {
|
|
return;
|
|
}
|
|
contenitore.dataset.inizializzato = '1';
|
|
|
|
let dati = { area: null, poligoni: [], selezionato: null };
|
|
try {
|
|
dati = JSON.parse(document.getElementById('piantine-dati').textContent);
|
|
} catch {
|
|
// si parte comunque con la mappa vuota
|
|
}
|
|
|
|
// Etichette in italiano per la barra di disegno.
|
|
L.drawLocal.draw.toolbar.buttons.polygon = 'Disegna il poligono di un territorio';
|
|
L.drawLocal.draw.toolbar.actions = { title: 'Annulla il disegno', text: 'Annulla' };
|
|
L.drawLocal.draw.toolbar.finish = { title: 'Concludi il disegno', text: 'Concludi' };
|
|
L.drawLocal.draw.toolbar.undo = { title: 'Rimuovi l\'ultimo punto', text: 'Ultimo punto' };
|
|
L.drawLocal.draw.handlers.polygon.tooltip = {
|
|
start: 'Clicca sulla mappa per iniziare il poligono.',
|
|
cont: 'Continua a cliccare lungo il confine.',
|
|
end: 'Clicca sul primo punto per chiudere il poligono.',
|
|
};
|
|
|
|
const mappa = L.map(contenitore, { zoomControl: true });
|
|
|
|
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
|
maxZoom: 19,
|
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
|
}).addTo(mappa);
|
|
|
|
let layerArea = null;
|
|
const layerSalvati = L.featureGroup().addTo(mappa);
|
|
let layerInAttesa = null;
|
|
|
|
mappa.addControl(new L.Control.Draw({
|
|
draw: {
|
|
polygon: { allowIntersection: false, showArea: false, shapeOptions: STILE_IN_ATTESA },
|
|
polyline: false,
|
|
rectangle: false,
|
|
circle: false,
|
|
circlemarker: false,
|
|
marker: false,
|
|
},
|
|
edit: false,
|
|
}));
|
|
|
|
function ridisegna(nuoviDati, adattaVista) {
|
|
dati = nuoviDati;
|
|
|
|
if (layerArea) {
|
|
mappa.removeLayer(layerArea);
|
|
layerArea = null;
|
|
}
|
|
if (dati.area) {
|
|
layerArea = L.geoJSON(dati.area, { style: STILE_AREA, interactive: false }).addTo(mappa);
|
|
}
|
|
|
|
layerSalvati.clearLayers();
|
|
for (const poligono of dati.poligoni) {
|
|
const selezionato = dati.selezionato === poligono.territorioId;
|
|
const layer = L.geoJSON(
|
|
{ type: 'Feature', properties: {}, geometry: poligono.geometry },
|
|
{ style: selezionato ? STILE_SELEZIONATO : STILE_SALVATO }
|
|
);
|
|
layer.bindTooltip(`Terr. ${poligono.numero}`, { sticky: true });
|
|
layer.on('click', () => {
|
|
window.Livewire.dispatch('territorio-selezionato-mappa', { territorioId: poligono.territorioId });
|
|
});
|
|
layerSalvati.addLayer(layer);
|
|
}
|
|
|
|
if (!adattaVista) {
|
|
return;
|
|
}
|
|
const riferimento = layerArea ?? (dati.poligoni.length ? layerSalvati : null);
|
|
if (riferimento) {
|
|
mappa.fitBounds(riferimento.getBounds().pad(0.08));
|
|
} else {
|
|
mappa.setView([41.9, 12.5], 6); // Italia: nessun dato ancora caricato
|
|
}
|
|
}
|
|
|
|
ridisegna(dati, true);
|
|
|
|
mappa.on(L.Draw.Event.CREATED, (evento) => {
|
|
if (layerInAttesa) {
|
|
mappa.removeLayer(layerInAttesa);
|
|
}
|
|
layerInAttesa = evento.layer;
|
|
layerInAttesa.setStyle(STILE_IN_ATTESA);
|
|
layerInAttesa.addTo(mappa);
|
|
|
|
window.Livewire.dispatch('poligono-disegnato', { geometry: evento.layer.toGeoJSON().geometry });
|
|
});
|
|
|
|
let registrato = false;
|
|
document.addEventListener('livewire:init', registraEventi);
|
|
if (window.Livewire) {
|
|
registraEventi();
|
|
}
|
|
|
|
function registraEventi() {
|
|
if (registrato) {
|
|
return;
|
|
}
|
|
registrato = true;
|
|
window.Livewire.on('piantine-dati-aggiornati', ({ dati: nuovi }) => {
|
|
// Dopo un salvataggio il poligono provvisorio è diventato
|
|
// definitivo (o è stato scartato): via il tracciato rosso.
|
|
if (layerInAttesa) {
|
|
mappa.removeLayer(layerInAttesa);
|
|
layerInAttesa = null;
|
|
}
|
|
ridisegna(nuovi, false);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initPiantine);
|
|
} else {
|
|
initPiantine();
|
|
}
|