osm-labo/templates/admin/followup_global_graph.html.twig
2025-07-05 12:37:01 +02:00

110 lines
No EOL
4 KiB
Twig

{% extends 'base.html.twig' %}
{% block title %}Suivi global de toutes les villes{% endblock %}
{% block body %}
<div class="container mt-4">
<div class="d-flex align-items-center mb-3">
<h1 class="me-3">Suivi global de toutes les villes</h1>
<a href="{{ path('admin_followup_global') }}" class="btn btn-warning">
<i class="bi bi-arrow-repeat"></i> Rafraîchir le suivi global
</a>
</div>
<div class="mb-4">
<h3>Nombre de villes et complétion moyenne</h3>
<canvas id="global-summary-chart" height="400"></canvas>
</div>
<hr>
<h3>Suivi par thématique</h3>
<div class="row">
{% for type, label in followup_labels %}
<div class="col-md-6 mb-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">
<i class="bi {{ followup_icons[type]|default('bi-question-circle') }}"></i>
{{ label }}
</h5>
<canvas id="chart-{{ type }}-count" height="400"></canvas>
<canvas id="chart-{{ type }}-completion" height="400"></canvas>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0"></script>
<script>
const series = {{ series|json_encode|raw }};
// Graphe global summary
const ctxSummary = document.getElementById('global-summary-chart').getContext('2d');
const cityCountData = (series['city_count'] || []).map(e => ({x: e.date, y: e.value}));
const completionAvgData = (series['global_completion_average'] || []).map(e => ({x: e.date, y: e.value}));
new Chart(ctxSummary, {
type: 'line',
data: {
datasets: [
{
label: 'Nombre de villes',
data: cityCountData,
borderColor: 'blue',
yAxisID: 'y1',
},
{
label: 'Complétion moyenne (%)',
data: completionAvgData,
borderColor: 'green',
yAxisID: 'y2',
}
]
},
options: {
responsive: true,
interaction: {mode: 'index', intersect: false},
stacked: false,
scales: {
x: {type: 'time', time: {unit: 'day'}},
y1: {type: 'linear', position: 'left', title: {display: true, text: 'Villes'}},
y2: {type: 'linear', position: 'right', title: {display: true, text: '%'}, min: 0, max: 100},
}
}
});
// Graphes par thème
const themes = {{ followup_labels|keys|json_encode|raw }};
themes.forEach(theme => {
// Count
const countData = (series[theme + '_count'] || []).map(e => ({x: e.date, y: e.value}));
const ctxCount = document.getElementById('chart-' + theme + '-count').getContext('2d');
new Chart(ctxCount, {
type: 'line',
data: {
datasets: [{
label: 'Nombre',
data: countData,
borderColor: 'orange',
}]
},
options: {
responsive: true,
scales: {x: {type: 'time', time: {unit: 'day'}}, y: {beginAtZero: true}}
}
});
// Completion
const completionData = (series[theme + '_completion'] || []).map(e => ({x: e.date, y: e.value}));
const ctxCompletion = document.getElementById('chart-' + theme + '-completion').getContext('2d');
new Chart(ctxCompletion, {
type: 'line',
data: {
datasets: [{
label: 'Complétion (%)',
data: completionData,
borderColor: 'green',
}]
},
options: {
responsive: true,
scales: {x: {type: 'time', time: {unit: 'day'}}, y: {beginAtZero: true, max: 100}}
}
});
});
</script>
{% endblock %}