import React, { useState, useEffect } from 'react'; import { Edit3, Trash2, GraduationCap, Check, X, Hand } from 'lucide-react'; import Table from '@/components/Table'; import Popup from '@/components/Popup'; import ToggleSwitch from '@/components/Form/ToggleSwitch'; import { useCsrfToken } from '@/context/CsrfContext'; import { DndProvider, useDrag, useDrop } from 'react-dnd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import InputText from '@/components/Form/InputText'; import SpecialityItem from '@/components/Structure/Configuration/SpecialityItem'; import TeacherItem from './TeacherItem'; import logger from '@/utils/logger'; import { useEstablishment } from '@/context/EstablishmentContext'; import SectionHeader from '@/components/SectionHeader'; import AlertMessage from '@/components/AlertMessage'; const ItemTypes = { SPECIALITY: 'speciality', }; const SpecialitiesDropZone = ({ teacher, handleSpecialitiesChange, specialities, isEditing, }) => { const [localSpecialities, setLocalSpecialities] = useState( teacher.specialities_details || [] ); useEffect(() => {}, [specialities]); useEffect(() => { setLocalSpecialities(teacher.specialities_details || []); }, [teacher.specialities_details]); useEffect(() => { handleSpecialitiesChange( localSpecialities.map((speciality) => speciality.id) ); }, [localSpecialities]); const [{ isOver, canDrop }, drop] = useDrop({ accept: ItemTypes.SPECIALITY, drop: (item) => { const specialityDetails = specialities.find( (speciality) => speciality.id === item.id ); const exists = localSpecialities.some( (speciality) => speciality.id === item.id ); if (!exists) { setLocalSpecialities((prevSpecialities) => { const updatedSpecialities = [ ...prevSpecialities, { id: item.id, name: specialityDetails.name, color_code: specialityDetails.color_code, }, ]; return updatedSpecialities; }); } }, collect: (monitor) => ({ isOver: !!monitor.isOver(), canDrop: !!monitor.canDrop(), }), canDrop: () => { return isEditing; }, }); const handleRemoveSpeciality = (id) => { setLocalSpecialities((prevSpecialities) => { const updatedSpecialities = prevSpecialities.filter( (speciality) => speciality.id !== id ); return updatedSpecialities; }); }; return (
{isEditing && (
{/* Ajoutez l'icône Hand */} Déposez une spécialité ici
)} {localSpecialities.map((speciality, index) => (
{isEditing && ( )}
))}
); }; const TeachersSection = ({ teachers, setTeachers, specialities, profiles, handleCreate, handleEdit, handleDelete, }) => { const csrfToken = useCsrfToken(); const [editingTeacher, setEditingTeacher] = useState(null); const [newTeacher, setNewTeacher] = useState(null); const [formData, setFormData] = useState({}); const [localErrors, setLocalErrors] = useState({}); const [popupVisible, setPopupVisible] = useState(false); const [popupMessage, setPopupMessage] = useState(''); const [removePopupVisible, setRemovePopupVisible] = useState(false); const [removePopupMessage, setRemovePopupMessage] = useState(''); const [removePopupOnConfirm, setRemovePopupOnConfirm] = useState(() => {}); const { selectedEstablishmentId } = useEstablishment(); // --- UTILS --- // Retourne le profil existant pour un email const getUsedProfileForEmail = (email) => { // On cherche tous les profils dont l'email correspond const matchingProfiles = profiles.filter(p => p.email === email); // On retourne le premier profil correspondant (ou undefined) const result = matchingProfiles.length > 0 ? matchingProfiles[0] : undefined; return result; }; // Met à jour le formData et newTeacher si besoin const updateFormData = (data) => { setFormData(prev => ({ ...prev, ...data })); if (newTeacher) setNewTeacher(prev => ({ ...prev, ...data })); }; // Récupération des messages d'erreur pour un champ donné const getError = (field) => { return localErrors?.[field]?.[0]; }; // --- HANDLERS --- const handleEmailChange = (e) => { const email = e.target.value; const existingProfile = getUsedProfileForEmail(email); if (existingProfile) { logger.info(`Adresse email déjà utilisée pour le profil ${existingProfile.id}`); } updateFormData({ associated_profile_email: email, existingProfileId: existingProfile ? existingProfile.id : null, }); }; const handleAddTeacher = () => { setNewTeacher({ id: Date.now(), last_name: '', first_name: '', associated_profile_email: '', specialities: [], role_type: 0, }); setFormData({ last_name: '', first_name: '', associated_profile_email: '', specialities: [], role_type: 0, }); }; const handleRemoveTeacher = (id) => { logger.debug('[DELETE] Suppression teacher id:', id); return handleDelete(id) .then(() => { setTeachers(prevTeachers => prevTeachers.filter(teacher => teacher.id !== id) ); logger.debug('[DELETE] Teacher supprimé:', id); }) .catch(logger.error); }; const handleSaveNewTeacher = () => { if ( formData.last_name && formData.first_name && formData.associated_profile_email ) { const data = { last_name: formData.last_name, first_name: formData.first_name, profile_role_data: { establishment: selectedEstablishmentId, role_type: formData.role_type || 0, is_active: true, ...(formData.existingProfileId ? { profile: formData.existingProfileId } : { profile_data: { email: formData.associated_profile_email, username: formData.associated_profile_email, password: 'Provisoire01!', }, }), }, specialities: formData.specialities || [], }; handleCreate(data) .then((createdTeacher) => { // Recherche du profile associé dans profiles let newProfileId = undefined; let foundProfile = undefined; if ( createdTeacher && createdTeacher.profile_role && createdTeacher.profile ) { newProfileId = createdTeacher.profile; foundProfile = profiles.find(p => p.id === newProfileId); } setTeachers([createdTeacher, ...teachers]); setNewTeacher(null); setLocalErrors({}); setFormData(prev => ({ ...prev, existingProfileId: newProfileId, })); }) .catch((error) => { logger.error('Error:', error.message); if (error.details) setLocalErrors(error.details); }); } else { setPopupMessage('Tous les champs doivent être remplis et valides'); setPopupVisible(true); } }; const handleUpdateTeacher = (id, updatedData) => { if ( updatedData.last_name && updatedData.first_name && updatedData.associated_profile_email ) { const profileRoleData = { id: updatedData.profile_role, establishment: selectedEstablishmentId, role_type: updatedData.role_type || 0, profile: updatedData.existingProfileId, }; handleEdit(id, { last_name: updatedData.last_name, first_name: updatedData.first_name, profile_role_data: profileRoleData, specialities: updatedData.specialities || [], }) .then((updatedTeacher) => { setTeachers((prevTeachers) => prevTeachers.map((teacher) => teacher.id === id ? { ...teacher, ...updatedTeacher } : teacher ) ); setEditingTeacher(null); setFormData({}); }) .catch((error) => { logger.error('Error:', error.message); if (error.details) setLocalErrors(error.details); }); } else { setPopupMessage('Tous les champs doivent être remplis et valides'); setPopupVisible(true); } }; const handleChange = (e) => { const { name, value, type, checked } = e.target; let parsedValue = type === 'checkbox' ? (checked ? 1 : 0) : value; updateFormData({ [name]: parsedValue }); }; const handleSpecialitiesChange = (selectedSpecialities) => { updateFormData({ specialities: selectedSpecialities }); }; const handleEditTeacher = (teacher) => { setEditingTeacher(teacher.id); setFormData({ ...teacher, associated_profile_email: teacher.associated_profile_email, role_type: teacher.role_type, }); }; const renderTeacherCell = (teacher, column) => { const isEditing = editingTeacher === teacher.id; const isCreating = newTeacher && newTeacher.id === teacher.id; const currentData = isEditing ? formData : newTeacher; if (isEditing || isCreating) { switch (column) { case 'NOM - PRENOM': return (
); case 'EMAIL': return ( ); case 'SPECIALITES': return ( ); case 'ADMINISTRATEUR': return (
); case 'ACTIONS': return (
); default: return null; } } else { switch (column) { case 'NOM - PRENOM': return ; case 'EMAIL': return teacher.associated_profile_email; case 'SPECIALITES': return (
{teacher.specialities_details.map((speciality) => ( ))}
); case 'ADMINISTRATEUR': if (teacher.associated_profile_email) { const badgeClass = teacher.role_type === 1 ? 'bg-red-100 text-red-600' : 'bg-blue-100 text-blue-600'; const label = teacher.role_type === 1 ? 'OUI' : 'NON'; return (
{label}
); } else { return Non définie; } case 'MISE A JOUR': return teacher.updated_date_formatted; case 'ACTIONS': return (
); default: return null; } } }; const columns = [ { name: 'NOM - PRENOM', label: 'Nom et prénom' }, { name: 'EMAIL', label: 'Email' }, { name: 'SPECIALITES', label: 'Spécialités' }, { name: 'ADMINISTRATEUR', label: 'Profil' }, { name: 'MISE A JOUR', label: 'Mise à jour' }, { name: 'ACTIONS', label: 'Actions' }, ]; return (
} /> setPopupVisible(false)} onCancel={() => setPopupVisible(false)} uniqueConfirmButton={true} /> setRemovePopupVisible(false)} /> ); }; export default TeachersSection;