| 
									
										
										
										
											2025-06-29 18:32:24 +02:00
										 |  |  | {% extends 'base.html.twig' %}
 | 
					
						
							|  |  |  | {% block title %}Suivi global de toutes les villes{% endblock %}
 | 
					
						
							|  |  |  | {% block body %}
 | 
					
						
							|  |  |  | <div class="container mt-4">
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:41:26 +02:00
										 |  |  |     <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>
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:32:24 +02:00
										 |  |  |     <div class="mb-4">
 | 
					
						
							|  |  |  |         <h3>Nombre de villes et complétion moyenne</h3>
 | 
					
						
							| 
									
										
										
										
											2025-07-05 12:37:01 +02:00
										 |  |  |         <canvas id="global-summary-chart" height="400"></canvas>
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:32:24 +02:00
										 |  |  |     </div>
 | 
					
						
							|  |  |  |     <hr>
 | 
					
						
							|  |  |  |     <h3>Suivi par thématique</h3>
 | 
					
						
							|  |  |  |     <div class="row">
 | 
					
						
							| 
									
										
										
										
											2025-06-29 19:24:00 +02:00
										 |  |  |         {% for type, label in followup_labels %}
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:32:24 +02:00
										 |  |  |             <div class="col-md-6 mb-4">
 | 
					
						
							|  |  |  |                 <div class="card">
 | 
					
						
							|  |  |  |                     <div class="card-body">
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:41:26 +02:00
										 |  |  |                         <h5 class="card-title">
 | 
					
						
							| 
									
										
										
										
											2025-06-29 19:24:00 +02:00
										 |  |  |                             <i class="bi {{ followup_icons[type]|default('bi-question-circle') }}"></i>
 | 
					
						
							|  |  |  |                             {{ label }}
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:41:26 +02:00
										 |  |  |                         </h5>
 | 
					
						
							| 
									
										
										
										
											2025-07-05 12:37:01 +02:00
										 |  |  |                         <canvas id="chart-{{ type }}-count" height="400"></canvas>
 | 
					
						
							|  |  |  |                         <canvas id="chart-{{ type }}-completion" height="400"></canvas>
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:32:24 +02:00
										 |  |  |                     </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'}},
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:41:26 +02:00
										 |  |  |             y2: {type: 'linear', position: 'right', title: {display: true, text: '%'}, min: 0, max: 100},
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:32:24 +02:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | });
 | 
					
						
							|  |  |  | // Graphes par thème
 | 
					
						
							| 
									
										
										
										
											2025-06-29 19:24:00 +02:00
										 |  |  | const themes = {{ followup_labels|keys|json_encode|raw }};
 | 
					
						
							| 
									
										
										
										
											2025-06-29 18:32:24 +02:00
										 |  |  | 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 %} 
 |