emoji pour le suivi de thème

This commit is contained in:
Tykayn 2025-07-12 13:32:08 +02:00 committed by tykayn
parent 7166eb646a
commit ed9e5b6b47
5 changed files with 101 additions and 21 deletions

View file

@ -246,9 +246,16 @@ export function setupCitySearch(inputId, suggestionListId, onSelect) {
suggestions.forEach(suggestion => {
const item = document.createElement('div');
item.classList.add('suggestion-item');
item.textContent = suggestion.display_name;
// Nouveau rendu : nom en gras, INSEE et CP en petit/gris
item.innerHTML = `
<span class="suggestion-name">${suggestion.name}</span>
<span class="suggestion-details">
<span>INSEE : <b>${suggestion.insee}</b></span>
<span style="margin-left:8px;">CP : <b>${Array.isArray(suggestion.postcodes) ? suggestion.postcodes.join(', ') : suggestion.postcode}</b></span>
</span>
`;
item.addEventListener('click', () => {
searchInput.value = suggestion.display_name;
searchInput.value = suggestion.name;
clearSuggestions();
if (onSelect) {
onSelect(suggestion);

View file

@ -1924,6 +1924,8 @@ final class AdminController extends AbstractController
public static function getTagEmoji(string $mainTag): string
{
// Si c'est un tag clé=valeur, on garde le match existant
if (str_contains($mainTag, '=')) {
return match ($mainTag) {
'amenity=restaurant', 'amenity=bar', 'amenity=cafe' => '🍽️',
'amenity=townhall', 'amenity=community_centre' => '🏛️',
@ -1939,6 +1941,34 @@ final class AdminController extends AbstractController
default => '🏷️',
};
}
// Sinon, on regarde si c'est un tag principal simple
return match ($mainTag) {
'bicycle_parking' => '🚲',
'building' => '🏢',
'email' => '📧',
'fire_hydrant' => '🚒',
'charging_station' => '⚡',
'toilets' => '🚻',
'bus_stop' => '🚌',
'defibrillator' => '❤️‍🩹',
'camera' => '📷',
'recycling' => '♻️',
'substation' => '🏭',
'laboratory' => '🧪',
'school' => '🏫',
'police' => '👮',
'healthcare' => '🏥',
'advertising_board' => '🪧',
'bench' => '🪑',
'waste_basket' => '🗑️',
'street_lamp' => '💡',
'drinking_water' => '🚰',
'tree' => '🌳',
'places' => '📍',
'power_pole' => '⚡',
default => '🏷️',
};
}
public function followupEmbedGraph(Request $request, string $insee_code, string $theme): Response
{

View file

@ -37,7 +37,7 @@
<tr>
<td>
<a href="{{ path('admin_followup_theme_graph', {'insee_code': stats.zone, 'theme': type}) }}" class="fw-bold text-decoration-none">
<i class="bi {{ followup_icons[type]|default('bi-question-circle') }}"></i> {{ diff.label }}
{{ tag_emoji(type) }} {{ diff.label }}
</a>
</td>
<td>

View file

@ -655,6 +655,36 @@
document.addEventListener('DOMContentLoaded', function() {
const geojsonData = {{ geojson|raw }};
const map_token = "{{ maptiler_token }}";
// Liste des tags attendus pour la complétion des lieux
const completionTags = {{ completion_tags['places']|json_encode|raw }};
// Calcul de la complétion et des tags manquants pour chaque lieu
geojsonData.features.forEach(f => {
let filled = 0;
let missing = [];
if (completionTags && completionTags.length > 0) {
completionTags.forEach(tag => {
if (f.properties && typeof f.properties[tag] !== 'undefined' && f.properties[tag] !== null && f.properties[tag] !== '') {
filled++;
} else {
missing.push(tag);
}
});
}
f.properties.completion = completionTags && completionTags.length > 0 ? Math.round(100 * filled / completionTags.length) : null;
// Correction : toujours un tableau
f.properties.missing_tags = Array.isArray(f.properties.missing_tags) ? f.properties.missing_tags : (f.properties.missing_tags ? [f.properties.missing_tags] : []);
});
// Fonction de couleur dégradée
function lerpColor(a, b, t) {
const ah = a.replace('#', '');
const bh = b.replace('#', '');
const ar = parseInt(ah.substring(0,2), 16), ag = parseInt(ah.substring(2,4), 16), ab = parseInt(ah.substring(4,6), 16);
const br = parseInt(bh.substring(0,2), 16), bg = parseInt(bh.substring(2,4), 16), bb = parseInt(bh.substring(4,6), 16);
const rr = Math.round(ar + (br-ar)*t);
const rg = Math.round(ag + (bg-ag)*t);
const rb = Math.round(ab + (bb-ab)*t);
return '#' + rr.toString(16).padStart(2,'0') + rg.toString(16).padStart(2,'0') + rb.toString(16).padStart(2,'0');
}
let map;
let map_is_loaded = false;
let currentMode = 'drop';
@ -682,10 +712,9 @@
'case',
['has', 'completion'],
[
'rgb',
0,
['*', ['get', 'completion'], 2.55],
0
'interpolate', ['linear'], ['get', 'completion'],
0, '#cccccc',
100, '#008000'
],
'#cccccc'
],
@ -701,7 +730,16 @@
source: 'places',
filter: ['!', ['has', 'point_count']],
paint: {
'circle-color': '#11b4da',
'circle-color': [
'case',
['has', 'completion'],
[
'interpolate', ['linear'], ['get', 'completion'],
0, '#cccccc',
100, '#008000'
],
'#cccccc'
],
'circle-radius': 8,
'circle-stroke-width': 2,
'circle-stroke-color': '#fff'
@ -795,7 +833,12 @@
if (properties.address) popupContent += `${properties.address}<br>`;
if (properties.main_tag) popupContent += `<em>${properties.main_tag}</em><br>`;
if (properties.note) popupContent += `<small>Note: ${properties.note}</small><br>`;
popupContent += `<a href="${properties.osm_url}" >Voir sur OSM</a>`;
popupContent += `<b>Complétion :</b> ${properties.completion !== null ? properties.completion + '%' : ''}`;
const missingTags = Array.isArray(properties.missing_tags) ? properties.missing_tags : [];
if (missingTags.length > 0) {
popupContent += `<div style='color:#b30000;font-size:0.95em;margin-top:4px;'><b>Manque :</b> ${missingTags.map(t => `<code>${t}</code>`).join(', ')}</div>`;
}
popupContent += `<br><a href="${properties.osm_url}" >Voir sur OSM</a>`;
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;

View file

@ -29,7 +29,7 @@
title="Voir le graphe détaillé">
<i class="bi bi-bar-chart"></i>
</a>
{{ type }}
{{ tag_emoji(type) }} {{ type }}
</td>
<td class="text-end">{{ evo.now }}</td>
{% for p in periods %}