mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Ajout de la possibilité de supprimer une association
guardian/student + ajout de la possibilité de créer un guardian pour un student + tri chrologique
This commit is contained in:
@ -10,6 +10,7 @@ import ProfileDirectory from '@/components/ProfileDirectory';
|
||||
|
||||
export default function Page() {
|
||||
const [profileRoles, setProfileRoles] = useState([]);
|
||||
const [reloadFetch, setReloadFetch] = useState(false);
|
||||
|
||||
const csrfToken = useCsrfToken();
|
||||
const { selectedEstablishmentId } = useEstablishment();
|
||||
@ -19,7 +20,7 @@ export default function Page() {
|
||||
// Fetch data for profileRoles
|
||||
handleProfiles();
|
||||
}
|
||||
}, [selectedEstablishmentId]);
|
||||
}, [selectedEstablishmentId, reloadFetch]);
|
||||
|
||||
const handleProfiles = () => {
|
||||
fetchProfileRoles(selectedEstablishmentId)
|
||||
@ -27,6 +28,7 @@ export default function Page() {
|
||||
setProfileRoles(data);
|
||||
})
|
||||
.catch(error => logger.error('Error fetching profileRoles:', error));
|
||||
setReloadFetch(false);
|
||||
};
|
||||
|
||||
const handleEdit = (profileRole) => {
|
||||
@ -56,8 +58,37 @@ export default function Page() {
|
||||
|
||||
const handleDissociate = (studentId, guardianId) => {
|
||||
return dissociateGuardian(studentId, guardianId)
|
||||
.then(() => {
|
||||
.then((response) => {
|
||||
logger.debug("Guardian dissociated successfully:", guardianId);
|
||||
|
||||
// Vérifier si le Guardian a été supprimé
|
||||
const isGuardianDeleted = response?.isGuardianDeleted;
|
||||
|
||||
// Mettre à jour le modèle profileRoles
|
||||
setProfileRoles(prevState =>
|
||||
prevState.map(profileRole => {
|
||||
if (profileRole.associated_person?.id === guardianId) {
|
||||
if (isGuardianDeleted) {
|
||||
// Si le Guardian est supprimé, retirer le profileRole
|
||||
return null;
|
||||
} else {
|
||||
// Si le Guardian n'est pas supprimé, mettre à jour les élèves associés
|
||||
const updatedStudents = profileRole.associated_person.students.filter(
|
||||
student => student.id !== studentId
|
||||
);
|
||||
return {
|
||||
...profileRole,
|
||||
associated_person: {
|
||||
...profileRole.associated_person,
|
||||
students: updatedStudents, // Mettre à jour les élèves associés
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
setReloadFetch(true);
|
||||
return profileRole; // Conserver les autres profileRoles
|
||||
}).filter(Boolean) // Supprimer les entrées nulles
|
||||
);
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Error dissociating guardian:', error);
|
||||
|
||||
@ -15,7 +15,6 @@ import { MoreVertical, Send, Edit, Trash2, FileText, CheckCircle, Plus } from '
|
||||
import Modal from '@/components/Modal';
|
||||
import InscriptionForm from '@/components/Inscription/InscriptionForm'
|
||||
import AffectationClasseForm from '@/components/AffectationClasseForm'
|
||||
import { getSession } from 'next-auth/react';
|
||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||
|
||||
import {
|
||||
@ -87,6 +86,7 @@ export default function Page({ params: { locale } }) {
|
||||
const [tuitionFees, setTuitionFees] = useState([]);
|
||||
const [groups, setGroups] = useState([]);
|
||||
const [profiles, setProfiles] = useState([]);
|
||||
const [isOpenAddGuardian, setIsOpenAddGuardian] = useState(false);
|
||||
|
||||
const csrfToken = useCsrfToken();
|
||||
const { selectedEstablishmentId } = useEstablishment();
|
||||
@ -100,6 +100,15 @@ export default function Page({ params: { locale } }) {
|
||||
|
||||
}
|
||||
|
||||
const handleOpenAddGuardian = (eleveSelected) => {
|
||||
setIsOpenAddGuardian(true);
|
||||
setStudent(eleveSelected);
|
||||
};
|
||||
|
||||
const handleCloseAddGuardian = () => {
|
||||
setIsOpenAddGuardian(false);
|
||||
};
|
||||
|
||||
const openModalAssociationEleve = (eleveSelected) => {
|
||||
setIsOpenAffectationClasse(true);
|
||||
setStudent(eleveSelected);
|
||||
@ -480,10 +489,94 @@ useEffect(()=>{
|
||||
});
|
||||
}
|
||||
|
||||
const updateRF = (updatedData) => {
|
||||
logger.debug('updateRF updatedData:', updatedData);
|
||||
|
||||
const data = {
|
||||
student: {
|
||||
guardians: updatedData.selectedGuardians.length !== 0
|
||||
? updatedData.selectedGuardians.map(guardianId => ({ id: guardianId }))
|
||||
: (() => {
|
||||
if (updatedData.isExistingParentProfile) {
|
||||
return [{
|
||||
profile_role_data: {
|
||||
establishment: selectedEstablishmentId,
|
||||
role_type: 2,
|
||||
is_active: false,
|
||||
profile: updatedData.existingProfileId, // Associer au profil existant
|
||||
},
|
||||
last_name: updatedData.guardianLastName,
|
||||
first_name: updatedData.guardianFirstName,
|
||||
birth_date: updatedData.guardianBirthDate,
|
||||
address: updatedData.guardianAddress,
|
||||
phone: updatedData.guardianPhone,
|
||||
profession: updatedData.guardianProfession
|
||||
}];
|
||||
}
|
||||
|
||||
// Si aucun profil existant n'est trouvé, créer un nouveau profil
|
||||
return [{
|
||||
profile_role_data: {
|
||||
establishment: selectedEstablishmentId,
|
||||
role_type: 2,
|
||||
is_active: false,
|
||||
profile_data: {
|
||||
email: updatedData.guardianEmail,
|
||||
password: 'Provisoire01!',
|
||||
username: updatedData.guardianEmail,
|
||||
}
|
||||
},
|
||||
last_name: updatedData.guardianLastName,
|
||||
first_name: updatedData.guardianFirstName,
|
||||
birth_date: updatedData.guardianBirthDate,
|
||||
address: updatedData.guardianAddress,
|
||||
phone: updatedData.guardianPhone,
|
||||
profession: updatedData.guardianProfession
|
||||
}];
|
||||
})(),
|
||||
},
|
||||
establishment: selectedEstablishmentId
|
||||
};
|
||||
|
||||
editRegisterForm(student.id, data, csrfToken)
|
||||
.then(data => {
|
||||
// Mise à jour immédiate des données
|
||||
setRegistrationFormsDataPending(prevState => [...(prevState || []), data]);
|
||||
setTotalPending(prev => prev + 1);
|
||||
if (updatedData.autoMail) {
|
||||
sendConfirmRegisterForm(data.student.id, updatedData.studentLastName, updatedData.studentFirstName);
|
||||
}
|
||||
handleCloseAddGuardian();
|
||||
// Forcer le rechargement complet des données
|
||||
setReloadFetch(true);
|
||||
})
|
||||
.catch(error => {
|
||||
logger.error('Error during updating registration form:', error);
|
||||
});
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{ name: t('studentName'), transform: (row) => row.student.last_name },
|
||||
{ name: t('studentFistName'), transform: (row) => row.student.first_name },
|
||||
{ name: t('mainContactMail'), transform: (row) => (row.student.guardians && row.student.guardians.length > 0) ? row.student.guardians[0].associated_profile_email : '' },
|
||||
{
|
||||
name: t('mainContactMail'),
|
||||
transform: (row) => (
|
||||
row.student.guardians && row.student.guardians.length > 0
|
||||
? row.student.guardians[0].associated_profile_email
|
||||
: (
|
||||
<div className="flex justify-center h-full">
|
||||
<button
|
||||
className="flex items-center gap-2 text-blue-600 font-semibold hover:text-blue-800 transition duration-200 underline decoration-blue-600 hover:decoration-blue-800"
|
||||
onClick={() => handleOpenAddGuardian(row.student)}
|
||||
>
|
||||
<span className="px-3 py-1 bg-blue-100 rounded-full hover:bg-blue-200 transition duration-200">
|
||||
Ajouter un responsable
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
},
|
||||
{ name: t('phone'), transform: (row) => formatPhoneNumber(row.student.guardians[0]?.phone) },
|
||||
{ name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update},
|
||||
{ name: t('registrationFileStatus'), transform: (row) => (
|
||||
@ -742,13 +835,29 @@ const columnsSubscribed = [
|
||||
title="Affectation à une classe"
|
||||
ContentComponent={() => (
|
||||
<AffectationClasseForm
|
||||
student={student}
|
||||
students={students}
|
||||
onSubmit={affectationClassFormSubmitHandler}
|
||||
classes={classes}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{isOpenAddGuardian && (
|
||||
<Modal
|
||||
isOpen={isOpenAddGuardian}
|
||||
setIsOpen={setIsOpenAddGuardian}
|
||||
title="Ajouter un responsable"
|
||||
ContentComponent={() => (
|
||||
<InscriptionForm
|
||||
students={students}
|
||||
profiles={profiles}
|
||||
onSubmit={updateRF}
|
||||
currentStep={2}
|
||||
showOnlyStep2={true}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -11,8 +11,19 @@ import ProgressStep from '@/components/ProgressStep';
|
||||
import logger from '@/utils/logger';
|
||||
import Popup from '@/components/Popup';
|
||||
|
||||
const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, profiles, onSubmit, currentStep, groups }) => {
|
||||
const [formData, setFormData] = useState({
|
||||
const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, profiles, onSubmit, currentStep, groups, showOnlyStep2 = false }) => {
|
||||
const [formData, setFormData] = useState(() => {
|
||||
if (showOnlyStep2) {
|
||||
return {
|
||||
guardianLastName: '',
|
||||
guardianFirstName: '',
|
||||
guardianEmail: '',
|
||||
guardianPhone: '',
|
||||
selectedGuardians: [],
|
||||
responsableType: 'new',
|
||||
};
|
||||
}
|
||||
return {
|
||||
studentLastName: '',
|
||||
studentFirstName: '',
|
||||
guardianLastName: '',
|
||||
@ -27,6 +38,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
selectedTuitionDiscounts: [],
|
||||
selectedTuitionFees: [],
|
||||
selectedFileGroup: null // Ajout du groupe de fichiers sélectionné
|
||||
};
|
||||
});
|
||||
|
||||
const [step, setStep] = useState(currentStep || 1);
|
||||
@ -55,8 +67,8 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
formData.selectedGuardians.length > 0 ||
|
||||
(!formData.emailError && formData.guardianEmail.length > 0 && filteredStudents.length === 0)
|
||||
);
|
||||
const isStep3Valid = formData.selectedRegistrationFees.length > 0;
|
||||
const isStep4Valid = formData.selectedTuitionFees.length > 0;
|
||||
const isStep3Valid = formData.selectedRegistrationFees?.length > 0;
|
||||
const isStep4Valid = formData.selectedTuitionFees?.length > 0;
|
||||
const isStep5Valid = formData.selectedFileGroup !== null;
|
||||
const isStep6Valid = isStep1Valid && isStep2Valid && isStep3Valid && isStep4Valid && isStep5Valid;
|
||||
|
||||
@ -80,12 +92,14 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!showOnlyStep2) {
|
||||
// Calcul du montant total des frais d'inscription lors de l'initialisation
|
||||
const initialTotalRegistrationAmount = calculateFinalRegistrationAmount(
|
||||
registrationFees.map(fee => fee.id),
|
||||
[]
|
||||
);
|
||||
setTotalRegistrationAmount(initialTotalRegistrationAmount);
|
||||
}
|
||||
|
||||
}, [registrationDiscounts, registrationFees]);
|
||||
|
||||
@ -123,15 +137,15 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
}
|
||||
}
|
||||
|
||||
if (step < steps.length) {
|
||||
setStep(step + 1);
|
||||
if (!showOnlyStep2 && step < steps.length) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const prevStep = () => {
|
||||
if (step > 1) {
|
||||
setStep(step - 1);
|
||||
}
|
||||
if (!showOnlyStep2 && step > 1) {
|
||||
setStep(step - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEleveSelection = (student) => {
|
||||
@ -270,6 +284,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
|
||||
return (
|
||||
<div className="space-y-4 mt-6">
|
||||
{!showOnlyStep2 && (
|
||||
<ProgressStep
|
||||
steps={steps}
|
||||
stepTitles={stepTitles}
|
||||
@ -277,6 +292,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
setStep={setStep}
|
||||
isStepValid={isStepValid}
|
||||
/>
|
||||
)}
|
||||
|
||||
{step === 1 && (
|
||||
<div className="mt-6">
|
||||
@ -308,7 +324,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
name="guardianLastName"
|
||||
type="text"
|
||||
IconItem={User}
|
||||
placeholder="Nom du responsable (optionnel)"
|
||||
placeholder="Nom du responsable"
|
||||
value={formData.guardianLastName}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
@ -317,7 +333,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
name="guardianFirstName"
|
||||
type="text"
|
||||
IconItem={User}
|
||||
placeholder="Prénom du responsable (optionnel)"
|
||||
placeholder="Prénom du responsable"
|
||||
value={formData.guardianFirstName}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
@ -663,44 +679,83 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
)}
|
||||
|
||||
<div className="flex justify-end mt-4 space-x-4">
|
||||
{step > 1 && (
|
||||
<Button text="Précédent"
|
||||
onClick={prevStep}
|
||||
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md shadow-sm hover:bg-gray-400 focus:outline-none"
|
||||
secondary
|
||||
name="Previous" />
|
||||
)}
|
||||
{step < steps.length ? (
|
||||
<Button text="Suivant"
|
||||
onClick={nextStep}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(
|
||||
(step === 1 && !isStep1Valid) ||
|
||||
(step === 2 && !isStep2Valid) ||
|
||||
(step === 3 && !isStep3Valid) ||
|
||||
(step === 4 && !isStep4Valid) ||
|
||||
(step === 5 && !isStep5Valid)
|
||||
)
|
||||
? "bg-gray-300 text-gray-700 cursor-not-allowed"
|
||||
: "bg-emerald-500 text-white hover:bg-emerald-600"
|
||||
}`}
|
||||
disabled={
|
||||
(
|
||||
(step === 1 && !isStep1Valid) ||
|
||||
(step === 2 && !isStep2Valid) ||
|
||||
(step === 3 && !isStep3Valid) ||
|
||||
(step === 4 && !isStep4Valid) ||
|
||||
(step === 5 && !isStep5Valid)
|
||||
)
|
||||
}
|
||||
primary
|
||||
name="Next" />
|
||||
{showOnlyStep2 ? (
|
||||
<>
|
||||
<Button
|
||||
text="Valider"
|
||||
onClick={submit}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(
|
||||
(step === 1 && !isStep1Valid) ||
|
||||
(step === 2 && !isStep2Valid) ||
|
||||
(step === 3 && !isStep3Valid) ||
|
||||
(step === 4 && !isStep4Valid) ||
|
||||
(step === 5 && !isStep5Valid)
|
||||
)
|
||||
? "bg-gray-300 text-gray-700 cursor-not-allowed"
|
||||
: "bg-emerald-500 text-white hover:bg-emerald-600"
|
||||
}`}
|
||||
disabled={
|
||||
(
|
||||
(step === 1 && !isStep1Valid) ||
|
||||
(step === 2 && !isStep2Valid) ||
|
||||
(step === 3 && !isStep3Valid) ||
|
||||
(step === 4 && !isStep4Valid) ||
|
||||
(step === 5 && !isStep5Valid)
|
||||
)
|
||||
}
|
||||
primary
|
||||
name="Validate"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<Button text="Valider"
|
||||
onClick={submit}
|
||||
className="px-4 py-2 bg-emerald-500 text-white rounded-md shadow-sm hover:bg-emerald-600 focus:outline-none"
|
||||
primary
|
||||
name="Create" />
|
||||
<>
|
||||
{step > 1 && (
|
||||
<Button
|
||||
text="Précédent"
|
||||
onClick={prevStep}
|
||||
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md shadow-sm hover:bg-gray-400 focus:outline-none"
|
||||
secondary
|
||||
name="Previous"
|
||||
/>
|
||||
)}
|
||||
{step < steps.length ? (
|
||||
<Button
|
||||
text="Suivant"
|
||||
onClick={nextStep}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(
|
||||
(step === 1 && !isStep1Valid) ||
|
||||
(step === 2 && !isStep2Valid) ||
|
||||
(step === 3 && !isStep3Valid) ||
|
||||
(step === 4 && !isStep4Valid) ||
|
||||
(step === 5 && !isStep5Valid)
|
||||
)
|
||||
? "bg-gray-300 text-gray-700 cursor-not-allowed"
|
||||
: "bg-emerald-500 text-white hover:bg-emerald-600"
|
||||
}`}
|
||||
disabled={
|
||||
(
|
||||
(step === 1 && !isStep1Valid) ||
|
||||
(step === 2 && !isStep2Valid) ||
|
||||
(step === 3 && !isStep3Valid) ||
|
||||
(step === 4 && !isStep4Valid) ||
|
||||
(step === 5 && !isStep5Valid)
|
||||
)
|
||||
}
|
||||
primary
|
||||
name="Next"
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
text="Valider"
|
||||
onClick={submit}
|
||||
className="px-4 py-2 bg-emerald-500 text-white rounded-md shadow-sm hover:bg-emerald-600 focus:outline-none"
|
||||
primary
|
||||
name="Create"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@ -107,6 +107,7 @@ const ProfileDirectory = ({ profileRoles, handleActivateProfile, handleDeletePro
|
||||
|
||||
const parentColumns = [
|
||||
{ name: 'Identifiant', transform: (row) => row.associated_profile_email },
|
||||
{ name: 'Mise à jour', transform: (row) => row.updated_date_formatted },
|
||||
{ name: 'Rôle', transform: (row) => (
|
||||
<span className={`px-2 py-1 rounded-full font-bold ${roleTypeToBadgeClass(row.role_type)}`}>
|
||||
{roleTypeToLabel(row.role_type)}
|
||||
@ -120,40 +121,44 @@ const ProfileDirectory = ({ profileRoles, handleActivateProfile, handleDeletePro
|
||||
<span>{row.associated_person?.guardian_name}</span>
|
||||
{row.associated_person && (
|
||||
<div
|
||||
className="relative group"
|
||||
onMouseEnter={() => handleTooltipVisibility(row.id)} // Afficher la tooltip pour cette ligne
|
||||
onMouseLeave={handleTooltipHide} // Cacher la tooltip
|
||||
>
|
||||
<button className="text-blue-500 hover:text-blue-700">
|
||||
<Info className="w-5 h-5" />
|
||||
</button>
|
||||
{visibleTooltipId === row.id && ( // Afficher uniquement si l'ID correspond
|
||||
<div className="absolute z-50 w-96 p-4 bg-white border border-gray-200 rounded shadow-lg left-0 -translate-x-1/2 top-full">
|
||||
<div className="mb-2">
|
||||
<strong>Elève(s) associé(s):</strong>
|
||||
<div className="flex flex-col justify-center space-y-2 mt-4">
|
||||
{row.associated_person?.students?.map(student => (
|
||||
<div key={student.student_name} className="flex justify-between items-center">
|
||||
<span className="px-2 py-1 rounded-full text-gray-800 whitespace-nowrap inline-block min-w-0 max-w-fit">
|
||||
{student.student_name}
|
||||
</span>
|
||||
<div className="flex items-center space-x-2">
|
||||
<StatusLabel status={student.registration_status} showDropdown={false} />
|
||||
<button
|
||||
className="text-red-500 hover:text-red-700 flex items-center space-x-1"
|
||||
onClick={() => handleConfirmDissociateGuardian(row, student)}
|
||||
>
|
||||
<XCircle className="w-5 h-5" />
|
||||
<span className="text-sm">Dissocier</span>
|
||||
</button>
|
||||
</div>
|
||||
className="relative group"
|
||||
onMouseEnter={() => handleTooltipVisibility(row.id)} // Afficher la tooltip pour cette ligne
|
||||
onMouseLeave={handleTooltipHide} // Cacher la tooltip
|
||||
>
|
||||
<button className="relative text-blue-500 hover:text-blue-700 flex items-center justify-center">
|
||||
<div className="w-6 h-6 bg-blue-100 text-blue-700 rounded-full flex items-center justify-center font-bold">
|
||||
{row.associated_person?.students?.length || 0}
|
||||
</div>
|
||||
</button>
|
||||
{visibleTooltipId === row.id && ( // Afficher uniquement si l'ID correspond
|
||||
<div
|
||||
className="fixed z-50 w-96 p-4 bg-white border border-gray-200 rounded shadow-lg -translate-x-1/2"
|
||||
>
|
||||
<div className="mb-2">
|
||||
<strong>Elève(s) associé(s):</strong>
|
||||
<div className="flex flex-col justify-center space-y-2 mt-4">
|
||||
{row.associated_person?.students?.map(student => (
|
||||
<div key={student.student_name} className="flex justify-between items-center">
|
||||
<span className="px-2 py-1 rounded-full text-gray-800 whitespace-nowrap inline-block min-w-0 max-w-fit">
|
||||
{student.student_name}
|
||||
</span>
|
||||
<div className="flex items-center space-x-2">
|
||||
<StatusLabel status={student.registration_status} showDropdown={false} />
|
||||
<button
|
||||
className="text-red-500 hover:text-red-700 flex items-center space-x-1"
|
||||
onClick={() => handleConfirmDissociateGuardian(row, student)}
|
||||
>
|
||||
<XCircle className="w-5 h-5" />
|
||||
<span className="text-sm">Dissocier</span>
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
@ -183,6 +188,7 @@ const ProfileDirectory = ({ profileRoles, handleActivateProfile, handleDeletePro
|
||||
|
||||
const schoolAdminColumns = [
|
||||
{ name: 'Identifiant', transform: (row) => row.associated_profile_email },
|
||||
{ name: 'Mise à jour', transform: (row) => row.updated_date_formatted },
|
||||
{ name: 'Rôle', transform: (row) => (
|
||||
<span className={`px-2 py-1 rounded-full font-bold ${roleTypeToBadgeClass(row.role_type)}`}>
|
||||
{roleTypeToLabel(row.role_type)}
|
||||
|
||||
Reference in New Issue
Block a user