mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-04-05 12:41:27 +00:00
154 lines
5.2 KiB
JavaScript
154 lines
5.2 KiB
JavaScript
'use client';
|
|
import React, { useState } from 'react';
|
|
import { Trash2, Edit2, ClipboardList, ChevronDown, ChevronUp } from 'lucide-react';
|
|
import Button from '@/components/Form/Button';
|
|
import Popup from '@/components/Popup';
|
|
import { useNotification } from '@/context/NotificationContext';
|
|
|
|
export default function EvaluationList({
|
|
evaluations,
|
|
onDelete,
|
|
onEdit,
|
|
onGradeStudents,
|
|
}) {
|
|
const [expandedId, setExpandedId] = useState(null);
|
|
const [deletePopupVisible, setDeletePopupVisible] = useState(false);
|
|
const [evaluationToDelete, setEvaluationToDelete] = useState(null);
|
|
const { showNotification } = useNotification();
|
|
|
|
const handleDeleteClick = (evaluation) => {
|
|
setEvaluationToDelete(evaluation);
|
|
setDeletePopupVisible(true);
|
|
};
|
|
|
|
const handleConfirmDelete = () => {
|
|
if (evaluationToDelete && onDelete) {
|
|
onDelete(evaluationToDelete.id)
|
|
.then(() => {
|
|
showNotification('Évaluation supprimée avec succès', 'success', 'Succès');
|
|
setDeletePopupVisible(false);
|
|
setEvaluationToDelete(null);
|
|
})
|
|
.catch((error) => {
|
|
showNotification('Erreur lors de la suppression', 'error', 'Erreur');
|
|
});
|
|
}
|
|
};
|
|
|
|
// 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: [],
|
|
};
|
|
}
|
|
acc[key].evaluations.push(ev);
|
|
return acc;
|
|
}, {});
|
|
|
|
if (evaluations.length === 0) {
|
|
return (
|
|
<div className="text-center text-gray-500 py-8">
|
|
Aucune évaluation créée pour cette période
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
{Object.values(groupedBySpeciality).map((group) => (
|
|
<div
|
|
key={group.name}
|
|
className="border border-gray-200 rounded-lg overflow-hidden"
|
|
>
|
|
<div
|
|
className="flex items-center justify-between p-3 bg-gray-50 cursor-pointer"
|
|
onClick={() =>
|
|
setExpandedId(expandedId === group.name ? null : group.name)
|
|
}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<span
|
|
className="w-3 h-3 rounded-full"
|
|
style={{ backgroundColor: group.color }}
|
|
/>
|
|
<span className="font-medium text-gray-800">{group.name}</span>
|
|
<span className="text-sm text-gray-500">
|
|
({group.evaluations.length} évaluation
|
|
{group.evaluations.length > 1 ? 's' : ''})
|
|
</span>
|
|
</div>
|
|
{expandedId === group.name ? (
|
|
<ChevronUp size={20} className="text-gray-500" />
|
|
) : (
|
|
<ChevronDown size={20} className="text-gray-500" />
|
|
)}
|
|
</div>
|
|
|
|
{expandedId === group.name && (
|
|
<div className="divide-y divide-gray-100">
|
|
{group.evaluations.map((evaluation) => (
|
|
<div
|
|
key={evaluation.id}
|
|
className="p-3 flex items-center justify-between hover:bg-gray-50"
|
|
>
|
|
<div className="flex-1">
|
|
<div className="font-medium text-gray-700">
|
|
{evaluation.name}
|
|
</div>
|
|
<div className="text-sm text-gray-500 flex gap-3">
|
|
{evaluation.date && (
|
|
<span>
|
|
{new Date(evaluation.date).toLocaleDateString('fr-FR')}
|
|
</span>
|
|
)}
|
|
<span>Note max: {evaluation.max_score}</span>
|
|
<span>Coef: {evaluation.coefficient}</span>
|
|
</div>
|
|
</div>
|
|
<div className="flex gap-2">
|
|
<Button
|
|
primary
|
|
onClick={() => onGradeStudents(evaluation)}
|
|
icon={<ClipboardList size={16} />}
|
|
text="Noter"
|
|
title="Noter les élèves"
|
|
/>
|
|
<button
|
|
onClick={() => onEdit && onEdit(evaluation)}
|
|
className="p-2 text-gray-500 hover:text-blue-600 hover:bg-blue-50 rounded"
|
|
title="Modifier"
|
|
>
|
|
<Edit2 size={16} />
|
|
</button>
|
|
<button
|
|
onClick={() => handleDeleteClick(evaluation)}
|
|
className="p-2 text-gray-500 hover:text-red-600 hover:bg-red-50 rounded"
|
|
title="Supprimer"
|
|
>
|
|
<Trash2 size={16} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
|
|
<Popup
|
|
isOpen={deletePopupVisible}
|
|
message={`Êtes-vous sûr de vouloir supprimer l'évaluation "${evaluationToDelete?.name}" ?`}
|
|
onConfirm={handleConfirmDelete}
|
|
onCancel={() => {
|
|
setDeletePopupVisible(false);
|
|
setEvaluationToDelete(null);
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|