add themes in main city page

This commit is contained in:
Tykayn 2025-11-19 23:03:58 +01:00 committed by tykayn
parent 952254b5d0
commit 03fede15aa
5 changed files with 91 additions and 18 deletions

View file

@ -633,6 +633,31 @@ final class AdminController extends AbstractController
}
$progression7Days['places'] = \App\Service\FollowUpService::calculate7DayProgression($stats, 'places');
// Construire theme_groups pour inclure tous les thèmes
$allThemes = \App\Service\FollowUpService::getFollowUpThemes();
$theme_groups = [
'emergency' => ['fire_hydrant', 'defibrillator'],
'transport' => ['bus_stop', 'charging_station', 'bicycle_parking'],
'healthcare' => ['healthcare', 'laboratory', 'drinking_water'],
'education' => ['school'],
'security' => ['police', 'camera'],
'infrastructure' => ['toilets', 'recycling', 'substation', 'power_pole', 'street_lamp', 'manhole'],
'mobilier_urbain' => ['bench', 'waste_basket', 'tree', 'advertising_board'],
'loisirs' => ['playground', 'little_free_library'],
'commerces' => ['restaurant', 'places'],
'batiments' => ['building', 'rnb'],
'divers' => ['email'],
];
// Ajouter les thèmes manquants dans une catégorie "divers"
$allGroupedThemes = [];
foreach ($theme_groups as $group => $themes) {
$allGroupedThemes = array_merge($allGroupedThemes, $themes);
}
$missingThemes = array_diff(array_keys($allThemes), $allGroupedThemes);
if (!empty($missingThemes)) {
$theme_groups['divers'] = array_merge($theme_groups['divers'] ?? [], $missingThemes);
}
// --- Ajout : mesures CTC CityFollowUp pour le graphique d'évolution ---
$ctc_completion_series = [];
foreach ($stats->getCityFollowUps() as $fu) {
@ -673,6 +698,7 @@ final class AdminController extends AbstractController
'ctc_completion_series' => $ctc_completion_series,
'averageUpdateDate' => $averageUpdateDate,
'daysSinceUpdate' => $daysSinceUpdate,
'theme_groups' => $theme_groups,
]);
}

View file

@ -1122,7 +1122,12 @@ class PublicController extends AbstractController
$types[$type][] = $fu;
}
}
// Récupérer tous les thèmes connus pour afficher même ceux sans données
$allThemes = \App\Service\FollowUpService::getFollowUpThemes();
$allIcons = \App\Service\FollowUpService::getFollowUpIcons();
$evolutions = [];
// D'abord, traiter les types qui ont des données
foreach ($types as $type => $fus) {
usort($fus, fn($a, $b) => $a->getDate() <=> $b->getDate());
$latest = end($fus);
@ -1140,6 +1145,23 @@ class PublicController extends AbstractController
$evolutions[$type][$label] = $past !== null && $latest ? $latest->getMeasure() - $past : null;
}
}
// Ensuite, ajouter les thèmes qui n'ont pas encore de données
foreach ($allThemes as $theme => $themeLabel) {
if (!isset($evolutions[$theme])) {
$evolutions[$theme] = [
'now' => null
];
foreach ($periods as $periodLabel => $date) {
$evolutions[$theme][$periodLabel] = null;
}
}
}
// Trier les évolutions par ordre alphabétique des labels
uksort($evolutions, function($a, $b) use ($allThemes) {
$labelA = $allThemes[$a] ?? $a;
$labelB = $allThemes[$b] ?? $b;
return strcasecmp($labelA, $labelB);
});
// Grouper les lieux par date de modification
$places = $stats->getPlaces();
$now = new \DateTime();
@ -1170,6 +1192,8 @@ class PublicController extends AbstractController
'places_7j' => $places_7j,
'places_30j' => $places_30j,
'places_6mois' => $places_6mois,
'theme_labels' => $allThemes,
'theme_icons' => $allIcons,
]);
}

View file

@ -511,7 +511,7 @@ class FollowUpService
'tree' => ['species', 'leaf_type', 'leaf_cycle'],
'power_pole' => ['ref', 'material'],
'places' => ['name', 'address', 'opening_hours', 'website', 'phone', 'wheelchair', 'ref:FR:SIRET', 'contact:phone', 'contact:email', 'contact:website'],
'manhole' => ['manhole', 'location'],
'manhole' => ['manhole'],
'little_free_library' => ['amenity', 'operator'],
'playground' => ['playground', 'operator'],
'restaurant' => ['contact:phone', 'phone', 'contact:email', 'email', 'contact:website', 'website', 'cuisine', 'ref:FR:SIRET'],

View file

@ -282,14 +282,7 @@
'healthcare': 'nwr["healthcare"](area.searchArea);nwr["amenity"="doctors"](area.searchArea);nwr["amenity"="pharmacy"](area.searchArea);nwr["amenity"="hospital"](area.searchArea);nwr["amenity"="clinic"](area.searchArea);nwr["amenity"="social_facility"](area.searchArea);'
} %}
{% set theme_groups = {
'emergency': ['fire_hydrant', 'defibrillator'],
'transport': ['bus_stop', 'charging_station', 'bicycle_parking'],
'healthcare': ['healthcare', 'laboratory', 'drinking_water'],
'education': ['school'],
'security': ['police', 'camera'],
'infrastructure': ['toilets', 'recycling', 'substation']
} %}
{# theme_groups est maintenant passé depuis le contrôleur pour inclure tous les thèmes #}
<div class="row mb-4" id="themes">
<div class="col-12">
@ -346,14 +339,39 @@
<tr>
<td class="text-muted">
{% if loop.first %}
{% set group_display_names = {
'batiments': '🏢 Bâtiments',
'commerces': '🏪 Commerces',
'divers': '📦 Divers',
'education': '🎓 Éducation',
'emergency': '🚨 Urgence',
'healthcare': '🏥 Santé',
'infrastructure': '🏗️ Infrastructure',
'loisirs': '🎮 Loisirs',
'mobilier_urbain': '🪑 Mobilier urbain',
'security': '🛡️ Sécurité',
'transport': '🚌 Transport'
} %}
{% set sorted_group_names = group_display_names|keys|sort %}
{% set sorted_group_display_names = {} %}
{% for g in sorted_group_names %}
{% set sorted_group_display_names = sorted_group_display_names|merge({ (g): group_display_names[g] }) %}
{% endfor %}
{% if group_name == 'emergency' %}🚨 Urgence
{% elseif group_name == 'transport' %}🚌 Transport
{% elseif group_name == 'healthcare' %}🏥 Santé
{% elseif group_name == 'education' %}🎓 Éducation
{% elseif group_name == 'security' %}🛡️ Sécurité
{% elseif group_name == 'infrastructure' %}🏗️ Infrastructure
{% else %}{{ group_name|capitalize }}
{% endif %}
{% elseif group_name == 'transport' %}🚌 Transport
{% elseif group_name == 'healthcare' %}🏥 Santé
{% elseif group_name == 'education' %}🎓 Éducation
{% elseif group_name == 'security' %}🛡️ Sécurité
{% elseif group_name == 'infrastructure' %}🏗️ Infrastructure
{% elseif group_name == 'mobilier_urbain' %}🪑 Mobilier urbain
{% elseif group_name == 'loisirs' %}🎮 Loisirs
{% elseif group_name == 'commerces' %}🏪 Commerces
{% elseif group_name == 'batiments' %}🏢 Bâtiments
{% elseif group_name == 'divers' %}📦 Divers
{% else %}{{ group_name|capitalize }}
{% endif %}
{% endif %}
</td>
<td>

View file

@ -42,9 +42,14 @@
title="Voir le graphe détaillé">
<i class="bi bi-bar-chart"></i>
</a>
{{ tag_emoji(type) }} {{ type }}
{% if theme_icons[type] is defined %}
<i class="bi {{ theme_icons[type] }}"></i>
{% else %}
{{ tag_emoji(type) }}
{% endif %}
{{ theme_labels[type]|default(type) }}
</td>
<td class="text-end">{{ evo.now }}</td>
<td class="text-end">{{ evo.now ?? '-' }}</td>
{% for p in periods %}
<td class="text-end{% if evo[p] is not null and evo[p] != 0 %} bg-success-subtle{% if evo[p] < 0 %} bg-danger-subtle{% endif %}{% endif %}">
{% if evo[p] is not null %}