feat: add score histo

This commit is contained in:
2025-08-09 12:29:35 +02:00
parent 0e87a457af
commit 859e496152
8 changed files with 604 additions and 15 deletions

View File

@@ -38,6 +38,9 @@ class ClassDashboard {
// Éléments DOM cachés
this.elements = {};
// Charts instances
this.studentAveragesChart = null;
this.init();
}
@@ -544,9 +547,9 @@ class ClassDashboard {
}
});
// Mise à jour de l'histogramme si présent
if (resultsData.distribution) {
this.updateHistogram(resultsData.distribution);
// Mise à jour de l'histogramme des moyennes des élèves
if (resultsData.student_averages_distribution) {
this.updateStudentAveragesChart(resultsData.student_averages_distribution);
}
}
@@ -582,7 +585,122 @@ class ClassDashboard {
}
/**
* Mise à jour de l'histogramme
* Mise à jour de l'histogramme des moyennes des élèves avec Chart.js
*/
updateStudentAveragesChart(distribution) {
const canvas = document.getElementById('studentAveragesChart');
const noDataElement = document.querySelector('[data-chart-no-data]');
if (!canvas) return;
// Vérifier s'il y a des données
const hasData = distribution && distribution.length > 0 && distribution.some(item => item.count > 0);
if (!hasData) {
if (noDataElement) {
noDataElement.style.display = 'flex';
}
// Détruire le graphique existant
if (this.studentAveragesChart) {
this.studentAveragesChart.destroy();
this.studentAveragesChart = null;
}
return;
}
if (noDataElement) {
noDataElement.style.display = 'none';
}
// Détruire le graphique existant
if (this.studentAveragesChart) {
this.studentAveragesChart.destroy();
}
// Préparer les données
const labels = distribution.map(item => item.range);
const data = distribution.map(item => item.count);
const maxCount = Math.max(...data);
// Créer le graphique
this.studentAveragesChart = new Chart(canvas, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Nombre d\'élèves',
data: data,
backgroundColor: 'rgba(251, 146, 60, 0.8)',
borderColor: 'rgba(251, 146, 60, 1)',
borderWidth: 1,
borderRadius: 4,
borderSkipped: false
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: 'white',
bodyColor: 'white',
borderColor: 'rgba(251, 146, 60, 1)',
borderWidth: 1,
callbacks: {
title: function(tooltipItems) {
return `Moyenne: ${tooltipItems[0].label}`;
},
label: function(context) {
const count = context.parsed.y;
return `${count} élève${count > 1 ? 's' : ''}`;
}
}
}
},
scales: {
x: {
display: true,
grid: {
display: false
},
ticks: {
color: 'rgba(251, 146, 60, 0.8)',
font: {
size: 10
},
maxRotation: 0
}
},
y: {
display: true,
beginAtZero: true,
max: maxCount > 0 ? Math.ceil(maxCount * 1.1) : 1,
grid: {
color: 'rgba(251, 146, 60, 0.1)'
},
ticks: {
color: 'rgba(251, 146, 60, 0.8)',
font: {
size: 10
},
stepSize: 1
}
}
},
animation: {
duration: this.options.animationDuration || 800,
easing: 'easeInOutCubic'
}
}
});
}
/**
* Mise à jour de l'histogramme (legacy - gardé pour compatibilité)
*/
updateHistogram(distribution) {
const histogramContainer = document.querySelector('[data-histogram]');
@@ -1698,6 +1816,12 @@ class ClassDashboard {
this.state.intersectionObserver.disconnect();
}
// Nettoyer les charts
if (this.studentAveragesChart) {
this.studentAveragesChart.destroy();
this.studentAveragesChart = null;
}
// Vider le cache
this.state.cache.clear();