mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +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:
@ -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