'use client'; import React, { useState } from 'react'; import { BookOpen, TrendingUp, TrendingDown, Minus, Pencil, Trash2, Save, X } from 'lucide-react'; export default function EvaluationStudentView({ evaluations, studentEvaluations, onUpdateGrade, onDeleteGrade, editable = false }) { const [editingId, setEditingId] = useState(null); const [editScore, setEditScore] = useState(''); const [editComment, setEditComment] = useState(''); const [editAbsent, setEditAbsent] = useState(false); if (!evaluations || evaluations.length === 0) { return (
Aucune évaluation pour cette période
); } const startEdit = (ev, studentEval) => { setEditingId(ev.id); setEditScore(studentEval?.score ?? ''); setEditComment(studentEval?.comment ?? ''); setEditAbsent(studentEval?.is_absent ?? false); }; const cancelEdit = () => { setEditingId(null); setEditScore(''); setEditComment(''); setEditAbsent(false); }; const handleSaveEdit = async (ev, studentEval) => { if (onUpdateGrade && studentEval) { await onUpdateGrade(studentEval.id, { score: editAbsent ? null : (editScore === '' ? null : parseFloat(editScore)), comment: editComment, is_absent: editAbsent, }); } cancelEdit(); }; const handleDelete = async (studentEval) => { if (onDeleteGrade && studentEval && confirm('Supprimer cette note ?')) { await onDeleteGrade(studentEval.id); } }; // Grouper les évaluations par matière const groupedBySpeciality = evaluations.reduce((acc, ev) => { const key = ev.speciality_name || 'Sans matière'; if (!acc[key]) { acc[key] = { name: key, color: ev.speciality_color || '#6B7280', evaluations: [], totalScore: 0, totalMaxScore: 0, totalCoef: 0, weightedSum: 0, }; } const studentEval = studentEvaluations.find( (se) => se.evaluation === ev.id ); const evalData = { ...ev, studentScore: studentEval?.score, studentComment: studentEval?.comment, isAbsent: studentEval?.is_absent, }; acc[key].evaluations.push(evalData); // Calcul de la moyenne pondérée if (studentEval?.score != null && !studentEval?.is_absent) { const normalizedScore = (studentEval.score / ev.max_score) * 20; acc[key].weightedSum += normalizedScore * ev.coefficient; acc[key].totalCoef += parseFloat(ev.coefficient); acc[key].totalScore += studentEval.score; acc[key].totalMaxScore += parseFloat(ev.max_score); } return acc; }, {}); // Calcul de la moyenne générale let totalWeightedSum = 0; let totalCoef = 0; Object.values(groupedBySpeciality).forEach((group) => { if (group.totalCoef > 0) { const groupAvg = group.weightedSum / group.totalCoef; totalWeightedSum += groupAvg * group.totalCoef; totalCoef += group.totalCoef; } }); const generalAverage = totalCoef > 0 ? totalWeightedSum / totalCoef : null; const getScoreColor = (score, maxScore) => { if (score == null) return 'text-gray-400'; const percentage = (score / maxScore) * 100; if (percentage >= 70) return 'text-green-600'; if (percentage >= 50) return 'text-yellow-600'; return 'text-red-600'; }; const getAverageIcon = (avg) => { if (avg >= 14) return ; if (avg >= 10) return ; return ; }; return (
{/* Moyenne générale */} {generalAverage !== null && (
Moyenne générale
{getAverageIcon(generalAverage)} {generalAverage.toFixed(2)}/20
)} {/* Évaluations par matière */} {Object.values(groupedBySpeciality).map((group) => { const groupAverage = group.totalCoef > 0 ? group.weightedSum / group.totalCoef : null; return (
{/* Header de la matière */}
{group.name}
{groupAverage !== null && (
{getAverageIcon(groupAverage)} {groupAverage.toFixed(2)}/20
)}
{/* Liste des évaluations */}
{group.evaluations.map((ev) => { const studentEval = studentEvaluations.find(se => se.evaluation === ev.id); const isEditing = editingId === ev.id; return (
{ev.name}
{ev.date && ( {new Date(ev.date).toLocaleDateString('fr-FR')} )} Coef: {ev.coefficient}
{!isEditing && ev.studentComment && (
"{ev.studentComment}"
)} {isEditing && ( setEditComment(e.target.value)} placeholder="Commentaire" className="mt-2 w-full text-sm px-2 py-1 border rounded" /> )}
{isEditing ? ( <> {!editAbsent && ( setEditScore(e.target.value)} min="0" max={ev.max_score} step="0.5" className="w-16 text-center px-2 py-1 border rounded" /> )} /{ev.max_score} ) : ( <> {ev.isAbsent ? ( Absent ) : ev.studentScore != null ? ( {ev.studentScore}/{ev.max_score} ) : ( Non noté )} {editable && studentEval && ( <> {onDeleteGrade && ( )} )} )}
);})}
); })}
); }