diff --git a/assets/js/map-utils.js b/assets/js/map-utils.js index 0172253..e69de29 100644 --- a/assets/js/map-utils.js +++ b/assets/js/map-utils.js @@ -1,161 +0,0 @@ -// Fonctions utilitaires pour la gestion des marqueurs et popups sur la carte - -function getCompletionColor(completion) { - if (completion === undefined || completion === null) { - return '#808080'; // Gris pour pas d'information - } - // Convertir le pourcentage en couleur verte (0% = blanc, 100% = vert foncé) - const intensity = Math.floor((completion / 100) * 255); - return `rgb(0, ${intensity}, 0)`; -} - -function calculateCompletion(element) { - let completionCount = 0; - let totalFields = 0; - let missingFields = []; - - const fieldsToCheck = [ - { name: 'name', label: 'Nom du commerce' }, - { name: 'contact:street', label: 'Rue' }, - { name: 'contact:housenumber', label: 'Numéro' }, - { name: 'opening_hours', label: 'Horaires d\'ouverture' }, - { name: 'contact:website', label: 'Site web' }, - { name: 'contact:phone', label: 'Téléphone' }, - { name: 'wheelchair', label: 'Accessibilité PMR' } - ]; - - fieldsToCheck.forEach(field => { - totalFields++; - if (element.tags && element.tags[field.name]) { - completionCount++; - } else { - missingFields.push(field.label); - } - }); - - return { - percentage: (completionCount / totalFields) * 100, - missingFields: missingFields - }; -} - -function createPopupContent(element) { - const completion = calculateCompletion(element); - let content = ` -
-
${element.tags?.name || 'Sans nom'}
-
- - Éditer - - - OSM - -
-
- `; - - if (completion.percentage < 100) { - content += ` -
-
Informations manquantes :
- -
- `; - } - - content += ''; - - // Ajouter tous les tags - if (element.tags) { - for (const tag in element.tags) { - content += ``; - } - } - - content += '
${tag}${element.tags[tag]}
'; - return content; -} - -function updateMarkers(features, map, currentMarkerType, dropMarkers, overpassData) { - // Supprimer tous les marqueurs existants - dropMarkers.forEach(marker => marker.remove()); - dropMarkers = []; - - features.forEach(feature => { - if (currentMarkerType === 'drop') { - const el = document.createElement('div'); - el.className = 'marker'; - el.style.backgroundColor = getCompletionColor(feature.properties.completion); - el.style.width = '15px'; - el.style.height = '15px'; - el.style.borderRadius = '50%'; - el.style.border = '2px solid white'; - el.style.cursor = 'pointer'; - - const marker = new maplibregl.Marker(el) - .setLngLat(feature.geometry.coordinates) - .addTo(map); - - // Ajouter l'événement de clic - el.addEventListener('click', () => { - const element = overpassData[feature.properties.id]; - if (element) { - const popup = new maplibregl.Popup() - .setLngLat(feature.geometry.coordinates) - .setHTML(createPopupContent(element)); - popup.addTo(map); - } - }); - - dropMarkers.push(marker); - } else { - // Créer un cercle pour chaque feature - const circle = turf.circle( - feature.geometry.coordinates, - 0.5, // rayon en kilomètres - { steps: 64, units: 'kilometers' } - ); - - // Ajouter la source et la couche pour le cercle - if (!map.getSource(feature.id)) { - map.addSource(feature.id, { - type: 'geojson', - data: circle - }); - - map.addLayer({ - id: feature.id, - type: 'fill', - source: feature.id, - paint: { - 'fill-color': getCompletionColor(feature.properties.completion), - 'fill-opacity': 0.6, - 'fill-outline-color': '#fff' - } - }); - - // Ajouter l'événement de clic sur le cercle - map.on('click', feature.id, () => { - const element = overpassData[feature.properties.id]; - if (element) { - const popup = new maplibregl.Popup() - .setLngLat(feature.geometry.coordinates) - .setHTML(createPopupContent(element)); - popup.addTo(map); - } - }); - } - } - }); - - return dropMarkers; -} - -// Exporter les fonctions -window.getCompletionColor = getCompletionColor; -window.calculateCompletion = calculateCompletion; -window.createPopupContent = createPopupContent; -window.updateMarkers = updateMarkers; \ No newline at end of file diff --git a/templates/admin/stats.html.twig b/templates/admin/stats.html.twig index 2cf0edf..0822950 100644 --- a/templates/admin/stats.html.twig +++ b/templates/admin/stats.html.twig @@ -400,6 +400,170 @@ let dropMarkers = []; // Tableau pour stocker les marqueurs en goutte let contextMenu = null; // Menu contextuel + +function calculateCompletion(element) { + let completionCount = 0; + let totalFields = 0; + let missingFields = []; + + const fieldsToCheck = [ + { name: 'name', label: 'Nom du commerce' }, + { name: 'contact:street', label: 'Rue' }, + { name: 'contact:housenumber', label: 'Numéro' }, + { name: 'opening_hours', label: 'Horaires d\'ouverture' }, + { name: 'contact:website', label: 'Site web' }, + { name: 'contact:phone', label: 'Téléphone' }, + { name: 'wheelchair', label: 'Accessibilité PMR' } + ]; + + fieldsToCheck.forEach(field => { + totalFields++; + if (element.tags && element.tags[field.name]) { + completionCount++; + } else { + missingFields.push(field.label); + } + }); + + return { + percentage: (completionCount / totalFields) * 100, + missingFields: missingFields + }; +} +// Fonctions utilitaires pour la gestion des marqueurs et popups sur la carte + +function getCompletionColor(completion) { + if (completion === undefined || completion === null) { + return '#808080'; // Gris pour pas d'information + } + // Convertir le pourcentage en couleur verte (0% = blanc, 100% = vert foncé) + const intensity = Math.floor((completion / 100) * 255); + return `rgb(0, ${intensity}, 0)`; +} + + +function createPopupContent(element) { + const completion = calculateCompletion(element); + let content = ` +
+
${element.tags?.name || 'Sans nom'}
+
+ + Éditer + + + OSM + +
+
+ `; + + if (completion.percentage < 100) { + content += ` +
+
Informations manquantes :
+ +
+ `; + } + + content += ''; + + // Ajouter tous les tags + if (element.tags) { + for (const tag in element.tags) { + content += ``; + } + } + + content += '
${tag}${element.tags[tag]}
'; + return content; +} + +function updateMarkers(features, map, currentMarkerType, dropMarkers, overpassData) { + // Supprimer tous les marqueurs existants + dropMarkers.forEach(marker => marker.remove()); + dropMarkers = []; + + features.forEach(feature => { + if (currentMarkerType === 'drop') { + const el = document.createElement('div'); + el.className = 'marker'; + el.style.backgroundColor = getCompletionColor(feature.properties.completion); + el.style.width = '15px'; + el.style.height = '15px'; + el.style.borderRadius = '50%'; + el.style.border = '2px solid white'; + el.style.cursor = 'pointer'; + + const marker = new maplibregl.Marker(el) + .setLngLat(feature.geometry.coordinates) + .addTo(map); + + // Ajouter l'événement de clic + el.addEventListener('click', () => { + const element = overpassData[feature.properties.id]; + if (element) { + const popup = new maplibregl.Popup() + .setLngLat(feature.geometry.coordinates) + .setHTML(createPopupContent(element)); + popup.addTo(map); + } + }); + + dropMarkers.push(marker); + } else { + // Créer un cercle pour chaque feature + const circle = turf.circle( + feature.geometry.coordinates, + 0.5, // rayon en kilomètres + { steps: 64, units: 'kilometers' } + ); + + // Ajouter la source et la couche pour le cercle + if (!map.getSource(feature.id)) { + map.addSource(feature.id, { + type: 'geojson', + data: circle + }); + + map.addLayer({ + id: feature.id, + type: 'fill', + source: feature.id, + paint: { + 'fill-color': getCompletionColor(feature.properties.completion), + 'fill-opacity': 0.6, + 'fill-outline-color': '#fff' + } + }); + + // Ajouter l'événement de clic sur le cercle + map.on('click', feature.id, () => { + const element = overpassData[feature.properties.id]; + if (element) { + const popup = new maplibregl.Popup() + .setLngLat(feature.geometry.coordinates) + .setHTML(createPopupContent(element)); + popup.addTo(map); + } + }); + } + } + }); + + return dropMarkers; +} + +// Exporter les fonctions +window.getCompletionColor = getCompletionColor; +window.calculateCompletion = calculateCompletion; +window.createPopupContent = createPopupContent; +window.updateMarkers = updateMarkers; + + function calculateCompletionDistribution(elements) { // Créer des buckets de 10% (0-10%, 10-20%, etc.) const buckets = Array(11).fill(0);