mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 16:03:21 +00:00
feat: Configuration et gestion du planning [#2]
This commit is contained in:
@ -1,77 +1,151 @@
|
||||
import { usePlanning } from '@/context/PlanningContext';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import SelectChoice from '@/components/SelectChoice';
|
||||
import { format } from 'date-fns';
|
||||
import React, { useEffect } from 'react';
|
||||
import { Users, BookOpen } from 'lucide-react';
|
||||
import { useClasses } from '@/context/ClassesContext';
|
||||
import { useClasseForm } from '@/context/ClasseFormContext';
|
||||
import { BK_GESTIONENSEIGNANTS_PLANNING_URL } from '@/utils/Url';
|
||||
import { BookOpen, Users } from 'lucide-react';
|
||||
|
||||
export default function SpecialityEventModal({ isOpen, onClose, eventData, setEventData, selectedClass }) {
|
||||
const { addEvent, updateEvent, deleteEvent, schedules } = usePlanning();
|
||||
const SpecialityEventModal = ({ isOpen, onClose, selectedCell, existingEvent, handleUpdatePlanning, classe }) => {
|
||||
const { formData, setFormData } = useClasseForm();
|
||||
const { groupSpecialitiesBySubject } = useClasses();
|
||||
const [selectedSpeciality, setSelectedSpeciality] = useState('');
|
||||
const [selectedTeacher, setSelectedTeacher] = useState('');
|
||||
const [eventData, setEventData] = useState({
|
||||
specialiteId: '',
|
||||
teacherId: '',
|
||||
start: '',
|
||||
duration: '1h'
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
// Réinitialiser eventData lorsque la modale se ferme
|
||||
setEventData({
|
||||
scheduleId: '',
|
||||
specialiteId: '',
|
||||
specialities: [],
|
||||
// Réinitialiser d'autres champs si nécessaire
|
||||
teacherId: '',
|
||||
start: '',
|
||||
duration: '1h'
|
||||
});
|
||||
setSelectedSpeciality('');
|
||||
setSelectedTeacher('');
|
||||
}
|
||||
}, [isOpen, setEventData]);
|
||||
}, [isOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen && selectedClass) {
|
||||
|
||||
setEventData(prev => ({
|
||||
...prev,
|
||||
scheduleId: selectedClass.id,
|
||||
specialities: Array.from(new Map(
|
||||
selectedClass.enseignants.flatMap(teacher =>
|
||||
teacher.specialites.map(specialite => [specialite.id, {
|
||||
id: specialite.id,
|
||||
nom: specialite.nom,
|
||||
codeCouleur: specialite.codeCouleur
|
||||
}])
|
||||
)
|
||||
).values())
|
||||
}));
|
||||
if (isOpen) {
|
||||
console.log('debug : ', selectedCell);
|
||||
if (existingEvent) {
|
||||
// Mode édition
|
||||
setEventData(existingEvent);
|
||||
setSelectedSpeciality(existingEvent.specialiteId);
|
||||
setSelectedTeacher(existingEvent.teacherId);
|
||||
} else {
|
||||
// Mode création
|
||||
setEventData(prev => ({
|
||||
...prev,
|
||||
start: selectedCell.hour,
|
||||
duration: '1h'
|
||||
}));
|
||||
setSelectedSpeciality('');
|
||||
setSelectedTeacher('');
|
||||
}
|
||||
}
|
||||
}, [isOpen, selectedClass, setEventData]);
|
||||
}, [isOpen, existingEvent, selectedCell]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!eventData.scheduleId) {
|
||||
|
||||
if (!eventData.specialiteId) {
|
||||
alert('Veuillez sélectionner une spécialité');
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedSchedule = schedules.find(s => s.id === eventData.scheduleId);
|
||||
|
||||
if (eventData.id) {
|
||||
updateEvent(eventData.id, {
|
||||
...eventData,
|
||||
scheduleId: eventData.scheduleId,
|
||||
color: eventData.color || selectedSchedule?.color
|
||||
});
|
||||
} else {
|
||||
addEvent({
|
||||
...eventData,
|
||||
id: `event-${Date.now()}`,
|
||||
scheduleId: eventData.scheduleId,
|
||||
color: eventData.color || selectedSchedule?.color
|
||||
});
|
||||
|
||||
if (!eventData.teacherId) {
|
||||
alert('Veuillez sélectionner un enseignant');
|
||||
return;
|
||||
}
|
||||
|
||||
// Transformer eventData pour correspondre au format du planning
|
||||
const selectedTeacherData = formData.enseignants.find(teacher => teacher.id === parseInt(eventData.teacherId, 10));
|
||||
const newCourse = {
|
||||
color: '#FF0000', // Vous pouvez définir la couleur de manière dynamique si nécessaire
|
||||
teachers: selectedTeacherData ? [`${selectedTeacherData.nom} ${selectedTeacherData.prenom}`] : [],
|
||||
heure: `${eventData.start}:00`,
|
||||
duree: eventData.duration.replace('h', ''), // Supposons que '1h' signifie 1
|
||||
matiere: 'GROUPE'
|
||||
};
|
||||
|
||||
// Mettre à jour le planning
|
||||
const updatedPlannings = classe.plannings_read.map(planning => {
|
||||
if (planning.niveau === selectedCell.selectedLevel) {
|
||||
const newEmploiDuTemps = { ...planning.emploiDuTemps };
|
||||
|
||||
if (!newEmploiDuTemps[selectedCell.day]) {
|
||||
newEmploiDuTemps[selectedCell.day] = [];
|
||||
}
|
||||
|
||||
const courseTime = newCourse.heure;
|
||||
const existingCourseIndex = newEmploiDuTemps[selectedCell.day].findIndex(course => course.heure === courseTime);
|
||||
|
||||
if (existingCourseIndex !== -1) {
|
||||
newEmploiDuTemps[selectedCell.day][existingCourseIndex] = newCourse;
|
||||
} else {
|
||||
newEmploiDuTemps[selectedCell.day].push(newCourse);
|
||||
}
|
||||
|
||||
return {
|
||||
...planning,
|
||||
emploiDuTemps: newEmploiDuTemps
|
||||
};
|
||||
}
|
||||
return planning;
|
||||
});
|
||||
|
||||
const updatedPlanning = updatedPlannings.find(planning => planning.niveau === selectedCell.selectedLevel);
|
||||
|
||||
setFormData(prevFormData => ({
|
||||
...prevFormData,
|
||||
plannings: updatedPlannings
|
||||
}));
|
||||
|
||||
// Appeler handleUpdatePlanning avec les arguments appropriés
|
||||
const planningId = updatedPlanning ? updatedPlanning.planning.id : null;
|
||||
console.log("id : ", planningId)
|
||||
if (planningId) {
|
||||
handleUpdatePlanning(BK_GESTIONENSEIGNANTS_PLANNING_URL, planningId, updatedPlanning.emploiDuTemps);
|
||||
}
|
||||
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleDelete = () => {
|
||||
if (eventData.id && confirm('Êtes-vous sûr de vouloir supprimer cet événement ?')) {
|
||||
deleteEvent(eventData.id);
|
||||
onClose();
|
||||
}
|
||||
const filteredTeachers = selectedSpeciality
|
||||
? formData.enseignants.filter(teacher =>
|
||||
teacher.specialites_ids.includes(parseInt(selectedSpeciality, 10))
|
||||
)
|
||||
: formData.enseignants;
|
||||
|
||||
const handleSpecialityChange = (e) => {
|
||||
const specialityId = e.target.value;
|
||||
setSelectedSpeciality(specialityId);
|
||||
|
||||
// Mettre à jour eventData
|
||||
setEventData(prev => ({
|
||||
...prev,
|
||||
specialiteId: specialityId
|
||||
}));
|
||||
};
|
||||
|
||||
const handleTeacherChange = (e) => {
|
||||
const teacherId = e.target.value;
|
||||
setSelectedTeacher(teacherId);
|
||||
|
||||
// Mettre à jour eventData
|
||||
setEventData(prev => ({
|
||||
...prev,
|
||||
teacherId: teacherId
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
@ -84,103 +158,77 @@ export default function SpecialityEventModal({ isOpen, onClose, eventData, setEv
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{/* Sélection de la Spécialité */}
|
||||
<div>
|
||||
{eventData.scheduleId && eventData.specialities && eventData.specialities.length > 0 ? (
|
||||
<SelectChoice
|
||||
name={`spécialités-${eventData.scheduleId}`}
|
||||
label="Spécialités"
|
||||
selected={eventData.specialiteId ? eventData.specialiteId : ''}
|
||||
choices={eventData.specialities.map(specialite => ({
|
||||
value: specialite.id,
|
||||
label: specialite.nom
|
||||
}))}
|
||||
callback={(event) => {
|
||||
const selectedSpecialityId = event.target.value;
|
||||
const selectedSpeciality = eventData.specialities.find(specialite => specialite.id === parseInt(selectedSpecialityId, 10));
|
||||
setEventData({
|
||||
...eventData,
|
||||
specialiteId: selectedSpecialityId,
|
||||
color: selectedSpeciality?.codeCouleur || '#10b981'
|
||||
});
|
||||
}}
|
||||
IconItem={BookOpen}
|
||||
/>
|
||||
) : (
|
||||
<p>Aucune spécialité disponible pour cette classe.</p>
|
||||
)}
|
||||
<SelectChoice
|
||||
name="specialites"
|
||||
label="Spécialités"
|
||||
selected={selectedSpeciality}
|
||||
choices={[
|
||||
{ value: '', label: 'Sélectionner une spécialité' },
|
||||
...groupSpecialitiesBySubject(formData.enseignants).map((speciality) => ({
|
||||
value: speciality.id,
|
||||
label: speciality.nom
|
||||
}))
|
||||
]}
|
||||
callback={handleSpecialityChange}
|
||||
IconItem={BookOpen}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Dates */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{/* Sélection de l'enseignant */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Début
|
||||
</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={format(new Date(eventData.start), "yyyy-MM-dd'T'HH:mm")}
|
||||
onChange={(e) => setEventData({ ...eventData, start: new Date(e.target.value).toISOString() })}
|
||||
className="w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-emerald-500"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Fin
|
||||
</label>
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={format(new Date(eventData.end), "yyyy-MM-dd'T'HH:mm")}
|
||||
onChange={(e) => setEventData({ ...eventData, end: new Date(e.target.value).toISOString() })}
|
||||
className="w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-emerald-500"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<SelectChoice
|
||||
name="teachers"
|
||||
label="Enseignants"
|
||||
selected={selectedTeacher}
|
||||
choices={[
|
||||
{ value: '', label: 'Sélectionner un enseignant'},
|
||||
...filteredTeachers.map(teacher => ({
|
||||
value: teacher.id,
|
||||
label: `${teacher.nom} ${teacher.prenom}`
|
||||
}))
|
||||
]}
|
||||
callback={handleTeacherChange}
|
||||
IconItem={Users}
|
||||
disabled={!selectedSpeciality} // Désactive le sélecteur si aucune spécialité n'est sélectionnée
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Lieu */}
|
||||
{/* Durée */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Lieu
|
||||
Durée
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={eventData.location || ''}
|
||||
onChange={(e) => setEventData({ ...eventData, location: e.target.value })}
|
||||
value={eventData.duration}
|
||||
onChange={(e) => setEventData(prev => ({
|
||||
...prev,
|
||||
duration: e.target.value
|
||||
}))}
|
||||
className="w-full p-2 border rounded focus:outline-none focus:ring-2 focus:ring-emerald-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Boutons */}
|
||||
<div className="flex justify-between gap-2 mt-6">
|
||||
<div>
|
||||
{eventData.id && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleDelete}
|
||||
className="px-4 py-2 text-red-600 hover:bg-red-50 rounded"
|
||||
>
|
||||
Supprimer
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded"
|
||||
>
|
||||
Annuler
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-4 py-2 bg-emerald-600 text-white rounded hover:bg-emerald-700"
|
||||
>
|
||||
{eventData.id ? 'Modifier' : 'Créer'}
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded"
|
||||
>
|
||||
Annuler
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="px-4 py-2 bg-emerald-600 text-white rounded hover:bg-emerald-700"
|
||||
>
|
||||
{eventData.id ? 'Modifier' : 'Créer'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SpecialityEventModal;
|
||||
|
||||
Reference in New Issue
Block a user