add themes in main city page
This commit is contained in:
parent
952254b5d0
commit
03fede15aa
5 changed files with 91 additions and 18 deletions
|
|
@ -633,6 +633,31 @@ final class AdminController extends AbstractController
|
||||||
}
|
}
|
||||||
$progression7Days['places'] = \App\Service\FollowUpService::calculate7DayProgression($stats, 'places');
|
$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 ---
|
// --- Ajout : mesures CTC CityFollowUp pour le graphique d'évolution ---
|
||||||
$ctc_completion_series = [];
|
$ctc_completion_series = [];
|
||||||
foreach ($stats->getCityFollowUps() as $fu) {
|
foreach ($stats->getCityFollowUps() as $fu) {
|
||||||
|
|
@ -673,6 +698,7 @@ final class AdminController extends AbstractController
|
||||||
'ctc_completion_series' => $ctc_completion_series,
|
'ctc_completion_series' => $ctc_completion_series,
|
||||||
'averageUpdateDate' => $averageUpdateDate,
|
'averageUpdateDate' => $averageUpdateDate,
|
||||||
'daysSinceUpdate' => $daysSinceUpdate,
|
'daysSinceUpdate' => $daysSinceUpdate,
|
||||||
|
'theme_groups' => $theme_groups,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1122,7 +1122,12 @@ class PublicController extends AbstractController
|
||||||
$types[$type][] = $fu;
|
$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 = [];
|
$evolutions = [];
|
||||||
|
// D'abord, traiter les types qui ont des données
|
||||||
foreach ($types as $type => $fus) {
|
foreach ($types as $type => $fus) {
|
||||||
usort($fus, fn($a, $b) => $a->getDate() <=> $b->getDate());
|
usort($fus, fn($a, $b) => $a->getDate() <=> $b->getDate());
|
||||||
$latest = end($fus);
|
$latest = end($fus);
|
||||||
|
|
@ -1140,6 +1145,23 @@ class PublicController extends AbstractController
|
||||||
$evolutions[$type][$label] = $past !== null && $latest ? $latest->getMeasure() - $past : null;
|
$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
|
// Grouper les lieux par date de modification
|
||||||
$places = $stats->getPlaces();
|
$places = $stats->getPlaces();
|
||||||
$now = new \DateTime();
|
$now = new \DateTime();
|
||||||
|
|
@ -1170,6 +1192,8 @@ class PublicController extends AbstractController
|
||||||
'places_7j' => $places_7j,
|
'places_7j' => $places_7j,
|
||||||
'places_30j' => $places_30j,
|
'places_30j' => $places_30j,
|
||||||
'places_6mois' => $places_6mois,
|
'places_6mois' => $places_6mois,
|
||||||
|
'theme_labels' => $allThemes,
|
||||||
|
'theme_icons' => $allIcons,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -511,7 +511,7 @@ class FollowUpService
|
||||||
'tree' => ['species', 'leaf_type', 'leaf_cycle'],
|
'tree' => ['species', 'leaf_type', 'leaf_cycle'],
|
||||||
'power_pole' => ['ref', 'material'],
|
'power_pole' => ['ref', 'material'],
|
||||||
'places' => ['name', 'address', 'opening_hours', 'website', 'phone', 'wheelchair', 'ref:FR:SIRET', 'contact:phone', 'contact:email', 'contact:website'],
|
'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'],
|
'little_free_library' => ['amenity', 'operator'],
|
||||||
'playground' => ['playground', 'operator'],
|
'playground' => ['playground', 'operator'],
|
||||||
'restaurant' => ['contact:phone', 'phone', 'contact:email', 'email', 'contact:website', 'website', 'cuisine', 'ref:FR:SIRET'],
|
'restaurant' => ['contact:phone', 'phone', 'contact:email', 'email', 'contact:website', 'website', 'cuisine', 'ref:FR:SIRET'],
|
||||||
|
|
|
||||||
|
|
@ -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);'
|
'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 = {
|
{# theme_groups est maintenant passé depuis le contrôleur pour inclure tous les thèmes #}
|
||||||
'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']
|
|
||||||
} %}
|
|
||||||
|
|
||||||
<div class="row mb-4" id="themes">
|
<div class="row mb-4" id="themes">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
|
@ -346,14 +339,39 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-muted">
|
<td class="text-muted">
|
||||||
{% if loop.first %}
|
{% 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
|
{% if group_name == 'emergency' %}🚨 Urgence
|
||||||
{% elseif group_name == 'transport' %}🚌 Transport
|
{% elseif group_name == 'transport' %}🚌 Transport
|
||||||
{% elseif group_name == 'healthcare' %}🏥 Santé
|
{% elseif group_name == 'healthcare' %}🏥 Santé
|
||||||
{% elseif group_name == 'education' %}🎓 Éducation
|
{% elseif group_name == 'education' %}🎓 Éducation
|
||||||
{% elseif group_name == 'security' %}🛡️ Sécurité
|
{% elseif group_name == 'security' %}🛡️ Sécurité
|
||||||
{% elseif group_name == 'infrastructure' %}🏗️ Infrastructure
|
{% elseif group_name == 'infrastructure' %}🏗️ Infrastructure
|
||||||
{% else %}{{ group_name|capitalize }}
|
{% elseif group_name == 'mobilier_urbain' %}🪑 Mobilier urbain
|
||||||
{% endif %}
|
{% 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 %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,14 @@
|
||||||
title="Voir le graphe détaillé">
|
title="Voir le graphe détaillé">
|
||||||
<i class="bi bi-bar-chart"></i>
|
<i class="bi bi-bar-chart"></i>
|
||||||
</a>
|
</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>
|
||||||
<td class="text-end">{{ evo.now }}</td>
|
<td class="text-end">{{ evo.now ?? '-' }}</td>
|
||||||
{% for p in periods %}
|
{% 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 %}">
|
<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 %}
|
{% if evo[p] is not null %}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue