diff --git a/Back-End/Dockerfile b/Back-End/Dockerfile
index afa5421..0aa05ac 100644
--- a/Back-End/Dockerfile
+++ b/Back-End/Dockerfile
@@ -3,6 +3,7 @@
# The first instruction is what image we want to base our container on
# We Use an official Python runtime as a parent image
FROM python:3.12.7
+WORKDIR /Back-End
# Allows docker to cache installed dependencies between builds
COPY requirements.txt requirements.txt
@@ -11,7 +12,6 @@ RUN pip install pymupdf
# Mounts the application code to the image
COPY . .
-WORKDIR /Back-End
EXPOSE 8080
diff --git a/Back-End/School/serializers.py b/Back-End/School/serializers.py
index 39a69a6..44b3571 100644
--- a/Back-End/School/serializers.py
+++ b/Back-End/School/serializers.py
@@ -68,11 +68,7 @@ class TeacherSerializer(serializers.ModelSerializer):
def get_droit(self, obj):
if obj.associated_profile:
- droit_id = obj.associated_profile.droit
- return {
- "label": obj.associated_profile.get_droit_display(),
- "id": droit_id
- }
+ return obj.associated_profile.droit
return None
def get_specialities_details(self, obj):
@@ -163,7 +159,7 @@ class SchoolClassSerializer(serializers.ModelSerializer):
return instance
def get_teachers_details(self, obj):
- return [{'last_name': teacher.last_name, 'first_name': teacher.first_name} for teacher in obj.teachers.all()]
+ return [{'id': teacher.id, 'last_name': teacher.last_name, 'first_name': teacher.first_name} for teacher in obj.teachers.all()]
def get_updated_date_formatted(self, obj):
utc_time = timezone.localtime(obj.updated_date)
diff --git a/Front-End/src/components/MultiSelect.js b/Front-End/src/components/MultiSelect.js
new file mode 100644
index 0000000..3680d95
--- /dev/null
+++ b/Front-End/src/components/MultiSelect.js
@@ -0,0 +1,84 @@
+import React, { useState, useEffect, useRef } from 'react';
+import { Check, ChevronDown } from 'lucide-react';
+
+const MultiSelect = ({ name, label, options, selectedOptions, onChange, errorMsg }) => {
+ const [isOpen, setIsOpen] = useState(false);
+ const containerRef = useRef(null);
+
+ const handleSelect = (option) => {
+ const isSelected = selectedOptions.some(selected => selected.id === option.id);
+ let newSelectedOptions;
+ if (isSelected) {
+ newSelectedOptions = selectedOptions.filter(selected => selected.id !== option.id);
+ } else {
+ newSelectedOptions = [...selectedOptions, option];
+ }
+ onChange(newSelectedOptions);
+ };
+
+ const handleClickOutside = (event) => {
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
+ setIsOpen(false);
+ }
+ };
+
+ useEffect(() => {
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => {
+ document.removeEventListener('mousedown', handleClickOutside);
+ };
+ }, []);
+
+ return (
+
-
-
- {IconItem &&
-
- {}
-
- }
-
-
- {errorMsg &&
{errorMsg}
}
+
+
+ {IconItem &&
+
+ {}
+
+ }
+
+ {errorMsg &&
{errorMsg}
}
>
);
}
\ No newline at end of file
diff --git a/Front-End/src/components/Structure/Configuration/ClassForm.js b/Front-End/src/components/Structure/Configuration/ClassForm.js
deleted file mode 100644
index 01cf73e..0000000
--- a/Front-End/src/components/Structure/Configuration/ClassForm.js
+++ /dev/null
@@ -1,253 +0,0 @@
-import React, { useState } from 'react';
-import InputTextIcon from '@/components/InputTextIcon';
-import Button from '@/components/Button';
-import SelectChoice from '@/components/SelectChoice';
-import CheckBoxList from '@/components/CheckBoxList';
-import PlanningConfiguration from '@/components/Structure/Configuration/PlanningConfiguration';
-import TeachersSelectionConfiguration from '@/components/Structure/Configuration/TeachersSelectionConfiguration';
-import { Users, Maximize2, Calendar, UserPlus } from 'lucide-react';
-import { useClasseForm } from '@/context/ClasseFormContext';
-import { useClasses } from '@/context/ClassesContext';
-
-const ClassForm = ({ onSubmit, isNew, teachers }) => {
-
- const { formData, setFormData } = useClasseForm();
- const { getNiveauNameById, schoolYears, getNiveauxLabels, getNiveauxTabs, generateAgeToNiveaux, niveauxPremierCycle, niveauxSecondCycle, niveauxTroisiemeCycle, typeEmploiDuTemps, updatePlannings } = useClasses();
- const [selectedTeachers, setSelectedTeachers] = useState(formData.teachers);
-
- const handleTeacherSelection = (teacher) => {
- setSelectedTeachers(prevState =>
- prevState.includes(teacher.id)
- ? prevState.filter(id => id !== teacher.id)
- : [...prevState, teacher.id]
- );
- setFormData(prevState => ({
- ...prevState,
- teachers: prevState.teachers.includes(teacher.id)
- ? prevState.teachers.filter(id => id !== teacher.id)
- : [...prevState.teachers, teacher.id]
- }));
- };
-
- const handleTimeChange = (e, index) => {
- const { value } = e.target;
- setFormData(prevState => {
- const updatedTimes = [...prevState.time_range];
- updatedTimes[index] = value;
-
- const updatedFormData = {
- ...prevState,
- time_range: updatedTimes,
- };
-
- const existingPlannings = prevState.plannings || [];
- updatedFormData.plannings = updatePlannings(updatedFormData, existingPlannings);
-
- return updatedFormData;
- });
- };
-
- const handleJoursChange = (e) => {
- const { value, checked } = e.target;
- const dayId = parseInt(value, 10);
-
- setFormData((prevState) => {
- const updatedJoursOuverture = checked
- ? [...prevState.opening_days, dayId]
- : prevState.opening_days.filter((id) => id !== dayId);
-
- const updatedFormData = {
- ...prevState,
- opening_days: updatedJoursOuverture,
- };
-
- const existingPlannings = prevState.plannings || [];
- updatedFormData.plannings = updatePlannings(updatedFormData, existingPlannings);
-
- return updatedFormData;
- });
- };
-
- const handleChange = (e) => {
- e.preventDefault();
- const { name, value, type, checked } = e.target;
-
- setFormData(prevState => {
-
- // Copier l'état précédent
- let newState = { ...prevState };
-
- if (type === 'checkbox') {
- const newValues = checked
- ? [...(prevState[name] || []), parseInt(value)]
- : (prevState[name] || []).filter(v => v !== parseInt(value));
- newState[name] = newValues;
- } else if (name === 'age_range') {
- const [minAgeStr, maxAgeStr] = value.split('-');
- const minAge = minAgeStr ? parseInt(minAgeStr) : null;
- const maxAge = minAgeStr ? parseInt(maxAgeStr) : null;
- const selectedNiveaux = generateAgeToNiveaux(minAge, maxAge);
- const niveauxLabels = getNiveauxLabels(selectedNiveaux);
-
- newState = {
- ...prevState,
- [name]: value,
- levels: selectedNiveaux.length > 0 ? selectedNiveaux : [],
- };
- } else if (type === 'radio') {
- newState[name] = parseInt(value, 10);
- } else {
- newState[name] = value;
- }
-
- const existingPlannings = prevState.plannings || [];
- newState.plannings = updatePlannings(newState, existingPlannings);
-
- return newState;
- });
-};
-
- const handleSubmit = () => {
- onSubmit(formData);
- };
-
- const [minAge, maxAge] = formData.age_range.length === 2 ? formData.age_range : [null, null];
- const selectedAgeGroup = generateAgeToNiveaux(minAge, maxAge);
-
- return (
-
- );
-};
-
-export default ClassForm;
diff --git a/Front-End/src/components/Structure/Configuration/ClassesSection.js b/Front-End/src/components/Structure/Configuration/ClassesSection.js
index 31cd45d..f5ac6b2 100644
--- a/Front-End/src/components/Structure/Configuration/ClassesSection.js
+++ b/Front-End/src/components/Structure/Configuration/ClassesSection.js
@@ -1,165 +1,427 @@
-import { Trash2, MoreVertical, Edit3, Plus, ZoomIn } from 'lucide-react';
-import { useState } from 'react';
+import { Trash2, Edit3, Plus, ZoomIn, Users, Check, X, Hand } from 'lucide-react';
+import React, { useState, useEffect } from 'react';
import Table from '@/components/Table';
-import DropdownMenu from '@/components/DropdownMenu';
-import Modal from '@/components/Modal';
-import ClassForm from '@/components/Structure/Configuration/ClassForm';
-import ClasseDetails from '@/components/ClasseDetails';
+import Popup from '@/components/Popup';
+import InputText from '@/components/InputText';
+import SelectChoice from '@/components/SelectChoice';
+import TeacherItem from '@/components/Structure/Configuration/TeacherItem';
+import MultiSelect from '@/components/MultiSelect';
import LevelLabel from '@/components/CustomLabels/LevelLabel';
-import TeacherLabel from '@/components/CustomLabels/TeacherLabel';
-import { ClasseFormProvider } from '@/context/ClasseFormContext';
-import { useClasses } from '@/context/ClassesContext';
+import { DndProvider, HTML5Backend, useDrop } from 'react-dnd';
+const ItemTypes = {
+ TEACHER: 'teacher',
+};
-const ClassesSection = ({ classes, teachers, handleCreate, handleEdit, handleDelete }) => {
+const TeachersDropZone = ({ classe, handleTeachersChange, teachers, isEditing }) => {
+ const [localTeachers, setLocalTeachers] = useState(classe.teachers_details || []);
- const { getNiveauxLabels } = useClasses();
- const [isOpen, setIsOpen] = useState(false);
- const [isOpenDetails, setIsOpenDetails] = useState(false);
- const [editingClass, setEditingClass] = useState(null);
+ useEffect(() => {
+ }, [teachers]);
- const openEditModal = (classe) => {
- setIsOpen(true);
- setEditingClass(classe);
- }
+ useEffect(() => {
+ setLocalTeachers(classe.teachers_details || []);
+ }, [classe.teachers_details]);
- const openEditModalDetails = (classe) => {
- setIsOpenDetails(true);
- setEditingClass(classe);
- }
+ useEffect(() => {
+ handleTeachersChange(localTeachers.map(teacher => teacher.id));
+ }, [localTeachers]);
- const closeEditModal = () => {
- setIsOpen(false);
- setEditingClass(null);
- };
+ const [{ isOver, canDrop }, drop] = useDrop({
+ accept: ItemTypes.TEACHER,
+ drop: (item) => {
+ const teacherDetails = teachers.find(teacher => teacher.id === item.id);
+ const exists = localTeachers.some(teacher => teacher.id === item.id);
+ if (!exists) {
+ setLocalTeachers(prevTeachers => {
+ const updatedTeachers = [
+ ...prevTeachers,
+ { id: item.id, last_name: teacherDetails.last_name, first_name: teacherDetails.first_name }
+ ];
+ return updatedTeachers;
+ });
+ }
+ },
+ collect: (monitor) => ({
+ isOver: !!monitor.isOver(),
+ canDrop: !!monitor.canDrop(),
+ }),
+ canDrop: () => {
+ return isEditing;
+ },
+ });
- const closeEditModalDetails = () => {
- setIsOpenDetails(false);
- setEditingClass(null);
- };
-
- const handleModalSubmit = (updatedData) => {
- if (editingClass) {
- handleEdit(editingClass.id, updatedData);
- } else {
- handleCreate(updatedData);
- }
- closeEditModal();
+ const handleRemoveTeacher = (id) => {
+ setLocalTeachers(prevTeachers => {
+ const updatedTeachers = prevTeachers.filter(teacher => teacher.id !== id);
+ return updatedTeachers;
+ });
};
return (
-
-
-
Gestion des classes
-
-
-
-
{
- const ambiance = row.atmosphere_name ? row.atmosphere_name : '';
- const trancheAge = row.age_range ? `${row.age_range} ans` : '';
-
- if (ambiance && trancheAge) {
- return `${ambiance} (${trancheAge})`;
- } else if (ambiance) {
- return ambiance;
- } else if (trancheAge) {
- return trancheAge;
- } else {
- return 'Non spécifié';
- }
- }
- },
- {
- name: 'NIVEAUX',
- transform: (row) => {
- const levelLabels = Array.isArray(row.levels) ? getNiveauxLabels(row.levels) : [];
- return (
-
- {levelLabels.length > 0
- ? levelLabels.map((label, index) => (
-
- ))
- : 'Aucun niveau'}
-
- );
- }
- },
- { name: 'CAPACITÉ MAX', transform: (row) => row.number_of_students },
- { name: 'ANNÉE SCOLAIRE', transform: (row) => row.school_year },
- {
- name: 'ENSEIGNANTS',
- transform: (row) => (
-
- {row.teachers_details.map((teacher, index) => (
-
- ))}
-
- )
- },
- { name: 'DATE DE CREATION', transform: (row) => row.updated_date_formatted },
- {
- name: 'ACTIONS', transform: (row) => (
- }
- items={[
- { label: 'Inspecter', icon: ZoomIn, onClick: () => openEditModalDetails(row) },
- { label: 'Modifier', icon: Edit3, onClick: () => openEditModal(row) },
- { label: 'Supprimer', icon: Trash2, onClick: () => handleDelete(row.id) }
- ]
- }
- buttonClassName="text-gray-400 hover:text-gray-600"
- menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg z-10 flex flex-col items-center"
- />
- )
- }
- ]}
- data={classes}
- />
-
- {isOpen && (
-
- (
-
- )}
- />
-
- )}
-
- {isOpenDetails && (
-
-
- {editingClass ? (
- <>
- {editingClass.atmosphere_name} - {editingClass.age_range[0]} à {editingClass.age_range[1]} ans
- >
- ) : ''}
-
- )}
- ContentComponent={() => (
-
- )}
- />
+
+ {isEditing && (
+
+ {/* Ajoutez l'icône Hand */}
+ Déposez un enseignant ici
+
)}
+ {localTeachers.map((teacher, index) => (
+
+
+ {isEditing && (
+
+ )}
+
+ ))}
);
};
-export default ClassesSection;
+const ClassesSection = ({ classes, setClasses, teachers, handleCreate, handleEdit, handleDelete }) => {
+ const [formData, setFormData] = useState({});
+ const [editingClass, setEditingClass] = useState(null);
+ const [newClass, setNewClass] = useState(null);
+ const [localErrors, setLocalErrors] = useState({});
+ const [popupVisible, setPopupVisible] = useState(false);
+ const [popupMessage, setPopupMessage] = useState("");
+
+ const niveauxPremierCycle = [
+ { id: 1, name: 'TPS', age: 2 },
+ { id: 2, name: 'PS', age: 3 },
+ { id: 3, name: 'MS', age: 4 },
+ { id: 4, name: 'GS', age: 5 },
+ ];
+
+ const niveauxSecondCycle = [
+ { id: 5, name: 'CP', age: 6 },
+ { id: 6, name: 'CE1', age: 7 },
+ { id: 7, name: 'CE2', age: 8 },
+ ];
+
+ const niveauxTroisiemeCycle = [
+ { id: 8, name: 'CM1', age: 9 },
+ { id: 9, name: 'CM2', age: 10 },
+ ];
+
+ const allNiveaux = [...niveauxPremierCycle, ...niveauxSecondCycle, ...niveauxTroisiemeCycle];
+
+ const getNiveauxLabels = (levels) => {
+ return levels.map(niveauId => {
+ const niveau = allNiveaux.find(n => n.id === niveauId);
+ return niveau ? niveau.name : niveauId;
+ });
+ };
+
+ // Fonction pour générer les années scolaires
+ const getSchoolYearChoices = () => {
+ const currentDate = new Date();
+ const currentYear = currentDate.getFullYear();
+ const currentMonth = currentDate.getMonth() + 1; // Les mois sont indexés à partir de 0
+
+ // Si nous sommes avant septembre, l'année scolaire en cours a commencé l'année précédente
+ const startYear = currentMonth >= 9 ? currentYear : currentYear - 1;
+
+ const choices = [];
+ for (let i = 0; i < 3; i++) {
+ const year = startYear + i;
+ choices.push({ value: `${year}-${year + 1}`, label: `${year}-${year + 1}` });
+ }
+ return choices;
+ };
+
+ const handleAddClass = () => {
+ setNewClass({ id: Date.now(), atmosphere_name: '', age_range: '', levels: [], number_of_students: '', school_year: '', teachers: [] });
+ setFormData({ atmosphere_name: '', age_range: '', levels: [], number_of_students: '', school_year: '', teachers: [] });
+ };
+
+ const handleChange = (e) => {
+ const { name, value } = e.target;
+
+ if (editingClass) {
+ setFormData((prevData) => ({
+ ...prevData,
+ [name]: value,
+ }));
+ } else if (newClass) {
+ setNewClass((prevData) => ({
+ ...prevData,
+ [name]: value,
+ }));
+ }
+ };
+
+ const handleSaveNewClass = () => {
+ if (newClass.atmosphere_name) {
+ handleCreate(newClass)
+ .then((createdClass) => {
+ setClasses((prevClasses) => [createdClass, ...classes]);
+ setNewClass(null);
+ setLocalErrors({});
+ })
+ .catch((error) => {
+ console.error(error);
+ });
+ } else {
+ setPopupMessage("Tous les champs doivent être remplis et valides");
+ setPopupVisible(true);
+ }
+ };
+
+ const handleUpdateClass = (id, updatedData) => {
+ if (!updatedData.atmosphere_name) {
+ setLocalErrors({ atmosphere_name: 'Le nom d\'ambiance est requis.' });
+ return;
+ }
+
+ handleEdit(id, updatedData)
+ .then((updatedClass) => {
+ setClasses((prevClasses) => prevClasses.map((classe) => (classe.id === id ? updatedClass : classe)));
+ setEditingClass(null);
+ setFormData({});
+ setLocalErrors({});
+ })
+ .catch((error) => {
+ console.error(error);
+ });
+ };
+
+ const handleTeachersChange = (selectedTeachers) => {
+ if (editingClass) {
+ setFormData((prevData) => ({
+ ...prevData,
+ teachers: selectedTeachers,
+ }));
+ } else if (newClass) {
+ setNewClass((prevData) => ({
+ ...prevData,
+ teachers: selectedTeachers,
+ }));
+ setFormData((prevData) => ({
+ ...prevData,
+ teachers: selectedTeachers,
+ }));
+ }
+ };
+
+ const handleMultiSelectChange = (selectedOptions) => {
+ const levels = selectedOptions.map(option => option.id);
+
+ if (editingClass) {
+ setFormData((prevData) => ({
+ ...prevData,
+ levels,
+ }));
+ } else if (newClass) {
+ setNewClass((prevData) => ({
+ ...prevData,
+ levels,
+ }));
+ setFormData((prevData) => ({
+ ...prevData,
+ levels,
+ }));
+ }
+ };
+
+ const renderClassCell = (classe, column) => {
+ const isEditing = editingClass === classe.id;
+ const isCreating = newClass && newClass.id === classe.id;
+ const currentData = isEditing ? formData : newClass || {};
+
+ if (isEditing || isCreating) {
+ switch (column) {
+ case 'AMBIANCE':
+ return (
+
+ );
+ case 'TRANCHE D\'AGE':
+ return (
+
+ )
+ case 'NIVEAUX':
+ return (
+ allNiveaux.find(level => level.id === levelId)) : []}
+ onChange={handleMultiSelectChange}
+ errorMsg={localErrors && localErrors.levels && Array.isArray(localErrors.levels) ? localErrors.levels[0] : ''}
+ />
+ );
+ case 'CAPACITE':
+ return (
+
+ )
+ case 'ANNÉE SCOLAIRE' :
+ return (
+
+ )
+ case 'ENSEIGNANTS':
+ return (
+
+ );
+ case 'ACTIONS':
+ return (
+
+
+
+
+ );
+ default:
+ return null;
+ }
+ } else {
+ switch (column) {
+ case 'AMBIANCE':
+ return classe.atmosphere_name;
+ case 'TRANCHE D\'AGE':
+ return classe.age_range;
+ case 'NIVEAUX':
+ const levelLabels = Array.isArray(classe.levels) ? getNiveauxLabels(classe.levels) : [];
+ return (
+
+ {levelLabels.length > 0
+ ? levelLabels.map((label, index) => (
+
+ ))
+ : 'Aucun niveau'}
+
+ );
+ case 'CAPACITE':
+ return classe.number_of_students;
+ case 'ANNÉE SCOLAIRE' :
+ return classe.school_year;
+ case 'ENSEIGNANTS':
+ return (
+
+ {classe.teachers_details.map((teacher) => (
+
+ ))}
+
+ );
+ case 'MISE A JOUR':
+ return classe.updated_date_formatted;
+ case 'ACTIONS':
+ return (
+
+
+
+
+
+ );
+ default:
+ return null;
+ }
+ }
+ };
+
+ const columns = [
+ { name: 'AMBIANCE', label: 'Nom d\'ambiance' },
+ { name: 'TRANCHE D\'AGE', label: 'Tranche d\'âge' },
+ { name: 'NIVEAUX', label: 'Niveaux' },
+ { name: 'CAPACITE', label: 'Capacité max' },
+ { name: 'ANNÉE SCOLAIRE', label: 'Année scolaire' },
+ { name: 'ENSEIGNANTS', label: 'Enseignants' },
+ { name: 'MISE A JOUR', label: 'Date mise à jour' },
+ { name: 'ACTIONS', label: 'Actions' }
+ ];
+
+ return (
+
+
+
+
+
setPopupVisible(false)}
+ onCancel={() => setPopupVisible(false)}
+ uniqueConfirmButton={true}
+ />
+
+
+ );
+};
+
+export default ClassesSection;
\ No newline at end of file
diff --git a/Front-End/src/components/Structure/Configuration/SpecialityItem.js b/Front-End/src/components/Structure/Configuration/SpecialityItem.js
index 8f0b801..6975b5d 100644
--- a/Front-End/src/components/Structure/Configuration/SpecialityItem.js
+++ b/Front-End/src/components/Structure/Configuration/SpecialityItem.js
@@ -5,6 +5,24 @@ const ItemTypes = {
SPECIALITY: 'speciality',
};
+const lightenColor = (color, percent) => {
+ const num = parseInt(color.slice(1), 16),
+ amt = Math.round(2.55 * percent),
+ R = (num >> 16) + amt,
+ G = (num >> 8 & 0x00FF) + amt,
+ B = (num & 0x0000FF) + amt;
+ return `#${(0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 + (G < 255 ? G < 1 ? 0 : G : 255) * 0x100 + (B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1).toUpperCase()}`;
+};
+
+const darkenColor = (color, percent) => {
+ const num = parseInt(color.slice(1), 16),
+ amt = Math.round(2.55 * percent),
+ R = (num >> 16) - amt,
+ G = (num >> 8 & 0x00FF) - amt,
+ B = (num & 0x0000FF) - amt;
+ return `#${(0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 + (G < 255 ? G < 1 ? 0 : G : 255) * 0x100 + (B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1).toUpperCase()}`;
+};
+
const SpecialityItem = ({ speciality, isDraggable = true }) => {
const [{ isDragging }, drag] = useDrag(() => ({
type: ItemTypes.SPECIALITY,
@@ -18,10 +36,15 @@ const SpecialityItem = ({ speciality, isDraggable = true }) => {
return (
{speciality.name}
diff --git a/Front-End/src/components/Structure/Configuration/StructureManagement.js b/Front-End/src/components/Structure/Configuration/StructureManagement.js
index f343ff7..bde54ca 100644
--- a/Front-End/src/components/Structure/Configuration/StructureManagement.js
+++ b/Front-End/src/components/Structure/Configuration/StructureManagement.js
@@ -7,7 +7,7 @@ import { BE_SCHOOL_SPECIALITY_URL, BE_SCHOOL_TEACHER_URL, BE_SCHOOL_SCHOOLCLASS_
const StructureManagement = ({ specialities, setSpecialities, teachers, setTeachers, classes, setClasses, handleCreate, handleEdit, handleDelete }) => {
return (
-
+
handleDelete(`${BE_SCHOOL_TEACHER_URL}`, id, setTeachers)}
/>
-
+
handleCreate(`${BE_SCHOOL_SCHOOLCLASS_URL}`, newData, setClasses)}
handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_SCHOOLCLASS_URL}`, id, updatedData, setClasses)}
diff --git a/Front-End/src/components/Structure/Configuration/TeacherItem.js b/Front-End/src/components/Structure/Configuration/TeacherItem.js
new file mode 100644
index 0000000..a0d6287
--- /dev/null
+++ b/Front-End/src/components/Structure/Configuration/TeacherItem.js
@@ -0,0 +1,35 @@
+import { useDrag } from 'react-dnd';
+import React from 'react';
+
+const ItemTypes = {
+ TEACHER: 'teacher',
+};
+
+const TeacherItem = ({ teacher, isDraggable = true }) => {
+ const [{ isDragging }, drag] = useDrag(() => ({
+ type: ItemTypes.TEACHER,
+ item: { id: teacher.id, name: `${teacher.last_name} ${teacher.first_name}` },
+ collect: (monitor) => ({
+ isDragging: !!monitor.isDragging(),
+ }),
+ canDrag: () => isDraggable,
+ }), [isDraggable]);
+
+ return (
+
+ {teacher.last_name} {teacher.first_name}
+
+ );
+};
+
+export default TeacherItem;
\ No newline at end of file
diff --git a/Front-End/src/components/Structure/Configuration/TeachersSection.js b/Front-End/src/components/Structure/Configuration/TeachersSection.js
index d6d7d0a..0799e50 100644
--- a/Front-End/src/components/Structure/Configuration/TeachersSection.js
+++ b/Front-End/src/components/Structure/Configuration/TeachersSection.js
@@ -9,6 +9,7 @@ import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import InputText from '@/components/InputText';
import SpecialityItem from '@/components/Structure/Configuration/SpecialityItem';
+import TeacherItem from './TeacherItem';
const ItemTypes = {
SPECIALITY: 'speciality',
@@ -149,11 +150,11 @@ const TeachersSection = ({ teachers, setTeachers, specialities, handleCreate, ha
};
const handleUpdateTeacher = (id, updatedData) => {
- console.log('UpdatedData:', updatedData);
+ console.log(updatedData)
const data = {
email: updatedData.email,
username: updatedData.email,
- droit: updatedData.droit.id,
+ droit: updatedData.droit,
};
updateProfile(updatedData.associated_profile, data, csrfToken)
.then(response => {
@@ -171,9 +172,15 @@ const TeachersSection = ({ teachers, setTeachers, specialities, handleCreate, ha
};
const handleChange = (e) => {
- const { name, value } = e.target;
+ const { name, value, type, checked } = e.target;
let parsedValue = value;
+ if (type === 'checkbox') {
+ parsedValue = checked ? 1 : 0;
+ }
+
+ console.log(`handleChange - name: ${name}, parsedValue: ${parsedValue}, type: ${type}, checked: ${checked}`);
+
if (editingTeacher) {
setFormData((prevData) => ({
...prevData,
@@ -216,25 +223,26 @@ const TeachersSection = ({ teachers, setTeachers, specialities, handleCreate, ha
if (isEditing || isCreating) {
switch (column) {
- case 'NOM':
+ case 'NOM - PRENOM':
return (
-
- );
- case 'PRENOM':
- return (
-
+
+
+
+
);
case 'EMAIL':
return (
@@ -250,14 +258,16 @@ const TeachersSection = ({ teachers, setTeachers, specialities, handleCreate, ha
return (
);
- // case 'PROFIL':
- // return (
- //
- // );
+ case 'ADMINISTRATEUR':
+ return (
+
+
+
+ );
case 'ACTIONS':
return (
@@ -282,10 +292,10 @@ const TeachersSection = ({ teachers, setTeachers, specialities, handleCreate, ha
}
} else {
switch (column) {
- case 'NOM':
- return teacher.last_name;
- case 'PRENOM':
- return teacher.first_name;
+ case 'NOM - PRENOM':
+ return (
+
+ );
case 'EMAIL':
return teacher.email;
case 'SPECIALITES':
@@ -296,13 +306,14 @@ const TeachersSection = ({ teachers, setTeachers, specialities, handleCreate, ha
))}
);
- case 'PROFIL':
+ case 'ADMINISTRATEUR':
if (teacher.associated_profile) {
- const badgeClass = teacher.droit.label === 'ECOLE' ? 'bg-blue-100 text-blue-600' : 'bg-red-100 text-red-600';
+ const badgeClass = teacher.droit === 1 ? 'bg-red-100 text-red-600' : 'bg-blue-100 text-blue-600';
+ const label = teacher.droit === 1 ? 'OUI' : 'NON';
return (
- {teacher.droit.label}
+ {label}
);
@@ -337,11 +348,10 @@ const TeachersSection = ({ teachers, setTeachers, specialities, handleCreate, ha
};
const columns = [
- { name: 'NOM', label: 'Nom' },
- { name: 'PRENOM', label: 'Prénom' },
+ { name: 'NOM - PRENOM', label: 'Nom et prénom' },
{ name: 'EMAIL', label: 'Email' },
{ name: 'SPECIALITES', label: 'Spécialités' },
- { name: 'PROFIL', label: 'Profil' },
+ { name: 'ADMINISTRATEUR', label: 'Profil' },
{ name: 'MISE A JOUR', label: 'Mise à jour' },
{ name: 'ACTIONS', label: 'Actions' }
];
diff --git a/Front-End/src/components/ToggleSwitch.js b/Front-End/src/components/ToggleSwitch.js
index 29fbfaa..262bd65 100644
--- a/Front-End/src/components/ToggleSwitch.js
+++ b/Front-End/src/components/ToggleSwitch.js
@@ -1,6 +1,6 @@
import { useRef } from 'react';
-const ToggleSwitch = ({ label, checked, onChange }) => {
+const ToggleSwitch = ({ name, label, checked, onChange }) => {
const inputRef = useRef(null);
const handleChange = (e) => {
@@ -16,15 +16,15 @@ const ToggleSwitch = ({ label, checked, onChange }) => {