mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Suppression de l'ancienne POPUP de RF
This commit is contained in:
@ -21,7 +21,6 @@ import {
|
|||||||
Upload,
|
Upload,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import Modal from '@/components/Modal';
|
import Modal from '@/components/Modal';
|
||||||
import InscriptionForm from '@/components/Inscription/InscriptionForm';
|
|
||||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|||||||
@ -1,967 +0,0 @@
|
|||||||
import { useState, useEffect, useRef } from 'react';
|
|
||||||
import { User, Mail } from 'lucide-react';
|
|
||||||
import InputTextIcon from '@/components/InputTextIcon';
|
|
||||||
import ToggleSwitch from '@/components/ToggleSwitch';
|
|
||||||
import Button from '@/components/Button';
|
|
||||||
import Table from '@/components/Table';
|
|
||||||
import FeesSection from '@/components/Structure/Tarification/FeesSection';
|
|
||||||
import DiscountsSection from '@/components/Structure/Tarification/DiscountsSection';
|
|
||||||
import SectionTitle from '@/components/SectionTitle';
|
|
||||||
import ProgressStep from '@/components/ProgressStep';
|
|
||||||
import logger from '@/utils/logger';
|
|
||||||
import Popup from '@/components/Popup';
|
|
||||||
import InputPhone from '../InputPhone';
|
|
||||||
import { PhoneLabel } from '../PhoneLabel';
|
|
||||||
import CheckBox from '@/components/CheckBox';
|
|
||||||
import RadioList from '@/components/RadioList';
|
|
||||||
import SelectChoice from '@/components/SelectChoice';
|
|
||||||
import { getCurrentSchoolYear, getNextSchoolYear } from '@/utils/Date';
|
|
||||||
|
|
||||||
const InscriptionForm = ({
|
|
||||||
students,
|
|
||||||
registrationDiscounts,
|
|
||||||
tuitionDiscounts,
|
|
||||||
registrationFees,
|
|
||||||
tuitionFees,
|
|
||||||
profiles,
|
|
||||||
onSubmit,
|
|
||||||
groups,
|
|
||||||
showOnlyStep2 = false,
|
|
||||||
}) => {
|
|
||||||
const [formData, setFormData] = useState(() => {
|
|
||||||
if (showOnlyStep2) {
|
|
||||||
return {
|
|
||||||
guardianLastName: '',
|
|
||||||
guardianFirstName: '',
|
|
||||||
guardianEmail: '',
|
|
||||||
guardianPhone: '',
|
|
||||||
selectedGuardians: [],
|
|
||||||
responsableType: 'new',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
studentLastName: '',
|
|
||||||
studentFirstName: '',
|
|
||||||
guardianLastName: '',
|
|
||||||
guardianFirstName: '',
|
|
||||||
guardianEmail: '',
|
|
||||||
guardianPhone: '',
|
|
||||||
selectedGuardians: [],
|
|
||||||
responsableType: 'new',
|
|
||||||
autoMail: false,
|
|
||||||
selectedRegistrationDiscounts: [],
|
|
||||||
selectedRegistrationFees: registrationFees.map((fee) => fee.id),
|
|
||||||
selectedTuitionDiscounts: [],
|
|
||||||
selectedTuitionFees: [],
|
|
||||||
selectedFileGroup: null, // Ajout du groupe de fichiers sélectionné
|
|
||||||
schoolYear: getCurrentSchoolYear(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const [step, setStep] = useState(1);
|
|
||||||
const [selectedStudent, setSelectedEleve] = useState('');
|
|
||||||
const [existingGuardians, setExistingGuardians] = useState([]);
|
|
||||||
const [totalRegistrationAmount, setTotalRegistrationAmount] = useState(0);
|
|
||||||
const [totalTuitionAmount, setTotalTuitionAmount] = useState(0);
|
|
||||||
const [filteredStudents, setFilteredStudents] = useState(students);
|
|
||||||
|
|
||||||
const [popupVisible, setPopupVisible] = useState(false);
|
|
||||||
const [popupMessage, setPopupMessage] = useState('');
|
|
||||||
|
|
||||||
const formDataRef = useRef(formData);
|
|
||||||
|
|
||||||
const stepTitles = {
|
|
||||||
1: 'Nouvel élève',
|
|
||||||
2: 'Nouveau Responsable',
|
|
||||||
3: "Frais d'inscription",
|
|
||||||
4: 'Frais de scolarité',
|
|
||||||
5: 'Documents requis',
|
|
||||||
6: 'Récapitulatif',
|
|
||||||
};
|
|
||||||
|
|
||||||
const steps = [
|
|
||||||
'Élève',
|
|
||||||
'Responsable',
|
|
||||||
'Inscription',
|
|
||||||
'Scolarité',
|
|
||||||
'Documents',
|
|
||||||
'Récap',
|
|
||||||
];
|
|
||||||
|
|
||||||
const isStep1Valid = formData.studentLastName && formData.studentFirstName;
|
|
||||||
const isStep2Valid =
|
|
||||||
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 isStep5Valid = formData.selectedFileGroup !== null;
|
|
||||||
const isStep6Valid =
|
|
||||||
isStep1Valid &&
|
|
||||||
isStep2Valid &&
|
|
||||||
isStep3Valid &&
|
|
||||||
isStep4Valid &&
|
|
||||||
isStep5Valid;
|
|
||||||
|
|
||||||
const isStepValid = (stepNumber) => {
|
|
||||||
switch (stepNumber) {
|
|
||||||
case 1:
|
|
||||||
return isStep1Valid;
|
|
||||||
case 2:
|
|
||||||
return isStep2Valid;
|
|
||||||
case 3:
|
|
||||||
return isStep3Valid;
|
|
||||||
case 4:
|
|
||||||
return isStep4Valid;
|
|
||||||
case 5:
|
|
||||||
return isStep5Valid;
|
|
||||||
case 6:
|
|
||||||
return isStep6Valid;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
formDataRef.current = formData; // Mettre à jour la référence à chaque changement de formData
|
|
||||||
}, [formData]);
|
|
||||||
|
|
||||||
const handleToggleChange = () => {
|
|
||||||
setFormData({ ...formData, autoMail: !formData.autoMail });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = (e) => {
|
|
||||||
const { name, value } = e.target;
|
|
||||||
setFormData((prevState) => ({
|
|
||||||
...prevState,
|
|
||||||
[name]: value,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const validateAndSubmit = async () => {
|
|
||||||
const existingProfile = profiles.find(
|
|
||||||
(profile) => profile.email === formData.guardianEmail
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingProfile) {
|
|
||||||
console.log('existingProfile : ', existingProfile);
|
|
||||||
await setFormData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
guardianEmail: existingProfile.email, // Mettre à jour le champ guardianEmail avec l'email du profil
|
|
||||||
isExistingParentProfile: true, // Indiquer que le profil est un parent existant
|
|
||||||
existingProfileId: existingProfile.id,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Utiliser la dernière version de formData via formDataRef
|
|
||||||
logger.debug('Submitting form data:', formDataRef.current);
|
|
||||||
onSubmit(formDataRef.current);
|
|
||||||
};
|
|
||||||
|
|
||||||
const nextStep = async () => {
|
|
||||||
if (step === 2) {
|
|
||||||
const existingProfile = profiles.find(
|
|
||||||
(profile) => profile.email === formData.guardianEmail
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingProfile) {
|
|
||||||
console.log('existingProfile : ', existingProfile);
|
|
||||||
await setFormData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
guardianEmail: existingProfile.email, // Mettre à jour le champ guardianEmail avec l'email du profil
|
|
||||||
isExistingParentProfile: true, // Indiquer que le profil est un parent existant
|
|
||||||
existingProfileId: existingProfile.id,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!showOnlyStep2 && step < steps.length) {
|
|
||||||
setStep(step + 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const prevStep = () => {
|
|
||||||
if (!showOnlyStep2 && step > 1) {
|
|
||||||
setStep(step - 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEleveSelection = (student) => {
|
|
||||||
setSelectedEleve(student);
|
|
||||||
setFormData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
selectedGuardians: [],
|
|
||||||
}));
|
|
||||||
setExistingGuardians(student.guardians);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleResponsableSelection = (guardianId, guardianEmail) => {
|
|
||||||
setFormData((prevData) => {
|
|
||||||
const isSelected = prevData.selectedGuardians.includes(guardianId);
|
|
||||||
const selectedGuardians = isSelected
|
|
||||||
? prevData.selectedGuardians.filter((id) => id !== guardianId) // Retirer le guardian si déjà sélectionné
|
|
||||||
: [...prevData.selectedGuardians, guardianId]; // Ajouter le guardian s'il n'est pas sélectionné
|
|
||||||
|
|
||||||
// Mettre à jour l'email uniquement si un guardian est sélectionné
|
|
||||||
const updatedGuardianEmail = isSelected ? '' : guardianEmail;
|
|
||||||
|
|
||||||
// Si aucun guardian n'est sélectionné, réinitialiser le tableau des élèves
|
|
||||||
if (selectedGuardians.length === 0) {
|
|
||||||
setFilteredStudents(students); // Réafficher tous les élèves
|
|
||||||
setSelectedEleve(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...prevData,
|
|
||||||
selectedGuardians,
|
|
||||||
guardianEmail: updatedGuardianEmail,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const submit = () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
logger.debug('Submitting form data:', formData);
|
|
||||||
onSubmit(formData);
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRegistrationFeeSelection = (feeId) => {
|
|
||||||
setFormData((prevData) => {
|
|
||||||
const selectedRegistrationFees =
|
|
||||||
prevData.selectedRegistrationFees.includes(feeId)
|
|
||||||
? prevData.selectedRegistrationFees.filter((id) => id !== feeId)
|
|
||||||
: [...prevData.selectedRegistrationFees, feeId];
|
|
||||||
const finalAmount = calculateFinalRegistrationAmount(
|
|
||||||
selectedRegistrationFees,
|
|
||||||
prevData.selectedRegistrationDiscounts
|
|
||||||
);
|
|
||||||
setTotalRegistrationAmount(finalAmount);
|
|
||||||
return { ...prevData, selectedRegistrationFees };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTuitionFeeSelection = (feeId) => {
|
|
||||||
setFormData((prevData) => {
|
|
||||||
const selectedTuitionFees = prevData.selectedTuitionFees.includes(feeId)
|
|
||||||
? prevData.selectedTuitionFees.filter((id) => id !== feeId)
|
|
||||||
: [...prevData.selectedTuitionFees, feeId];
|
|
||||||
const finalAmount = calculateFinalTuitionAmount(
|
|
||||||
selectedTuitionFees,
|
|
||||||
prevData.selectedTuitionDiscounts
|
|
||||||
);
|
|
||||||
setTotalTuitionAmount(finalAmount);
|
|
||||||
return { ...prevData, selectedTuitionFees };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRegistrationDiscountSelection = (discountId) => {
|
|
||||||
setFormData((prevData) => {
|
|
||||||
const selectedRegistrationDiscounts =
|
|
||||||
prevData.selectedRegistrationDiscounts.includes(discountId)
|
|
||||||
? prevData.selectedRegistrationDiscounts.filter(
|
|
||||||
(id) => id !== discountId
|
|
||||||
)
|
|
||||||
: [...prevData.selectedRegistrationDiscounts, discountId];
|
|
||||||
const finalAmount = calculateFinalRegistrationAmount(
|
|
||||||
prevData.selectedRegistrationFees,
|
|
||||||
selectedRegistrationDiscounts
|
|
||||||
);
|
|
||||||
setTotalRegistrationAmount(finalAmount);
|
|
||||||
return { ...prevData, selectedRegistrationDiscounts };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTuitionDiscountSelection = (discountId) => {
|
|
||||||
setFormData((prevData) => {
|
|
||||||
const selectedTuitionDiscounts =
|
|
||||||
prevData.selectedTuitionDiscounts.includes(discountId)
|
|
||||||
? prevData.selectedTuitionDiscounts.filter((id) => id !== discountId)
|
|
||||||
: [...prevData.selectedTuitionDiscounts, discountId];
|
|
||||||
const finalAmount = calculateFinalTuitionAmount(
|
|
||||||
prevData.selectedTuitionFees,
|
|
||||||
selectedTuitionDiscounts
|
|
||||||
);
|
|
||||||
setTotalTuitionAmount(finalAmount);
|
|
||||||
return { ...prevData, selectedTuitionDiscounts };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const calculateFinalRegistrationAmount = (
|
|
||||||
selectedRegistrationFees,
|
|
||||||
selectedRegistrationDiscounts
|
|
||||||
) => {
|
|
||||||
const totalFees = selectedRegistrationFees.reduce((sum, feeId) => {
|
|
||||||
const fee = registrationFees.find((f) => f.id === feeId);
|
|
||||||
if (fee && !isNaN(parseFloat(fee.base_amount))) {
|
|
||||||
return sum + parseFloat(fee.base_amount);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
const totalDiscounts = selectedRegistrationDiscounts.reduce(
|
|
||||||
(sum, discountId) => {
|
|
||||||
const discount = registrationDiscounts.find((d) => d.id === discountId);
|
|
||||||
if (discount) {
|
|
||||||
if (
|
|
||||||
discount.discount_type === 0 &&
|
|
||||||
!isNaN(parseFloat(discount.amount))
|
|
||||||
) {
|
|
||||||
// Currency
|
|
||||||
return sum + parseFloat(discount.amount);
|
|
||||||
} else if (
|
|
||||||
discount.discount_type === 1 &&
|
|
||||||
!isNaN(parseFloat(discount.amount))
|
|
||||||
) {
|
|
||||||
// Percent
|
|
||||||
return sum + (totalFees * parseFloat(discount.amount)) / 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
},
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
const finalAmount = totalFees - totalDiscounts;
|
|
||||||
|
|
||||||
return finalAmount.toFixed(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
const calculateFinalTuitionAmount = (
|
|
||||||
selectedTuitionFees,
|
|
||||||
selectedTuitionDiscounts
|
|
||||||
) => {
|
|
||||||
const totalFees = selectedTuitionFees.reduce((sum, feeId) => {
|
|
||||||
const fee = tuitionFees.find((f) => f.id === feeId);
|
|
||||||
if (fee && !isNaN(parseFloat(fee.base_amount))) {
|
|
||||||
return sum + parseFloat(fee.base_amount);
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
const totalDiscounts = selectedTuitionDiscounts.reduce(
|
|
||||||
(sum, discountId) => {
|
|
||||||
const discount = tuitionDiscounts.find((d) => d.id === discountId);
|
|
||||||
if (discount) {
|
|
||||||
if (
|
|
||||||
discount.discount_type === 0 &&
|
|
||||||
!isNaN(parseFloat(discount.amount))
|
|
||||||
) {
|
|
||||||
// Currency
|
|
||||||
return sum + parseFloat(discount.amount);
|
|
||||||
} else if (
|
|
||||||
discount.discount_type === 1 &&
|
|
||||||
!isNaN(parseFloat(discount.amount))
|
|
||||||
) {
|
|
||||||
// Percent
|
|
||||||
return sum + (totalFees * parseFloat(discount.amount)) / 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
},
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
const finalAmount = totalFees - totalDiscounts;
|
|
||||||
|
|
||||||
return finalAmount.toFixed(2);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="space-y-4 mt-6">
|
|
||||||
{!showOnlyStep2 && (
|
|
||||||
<ProgressStep
|
|
||||||
steps={steps}
|
|
||||||
stepTitles={stepTitles}
|
|
||||||
currentStep={step}
|
|
||||||
setStep={setStep}
|
|
||||||
isStepValid={isStepValid}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 1 && (
|
|
||||||
<div className="mt-6">
|
|
||||||
{/* Sélection de l'année scolaire */}
|
|
||||||
<SelectChoice
|
|
||||||
name="schoolYear"
|
|
||||||
label="Année scolaire"
|
|
||||||
placeHolder="Sélectionnez une année scolaire"
|
|
||||||
choices={[
|
|
||||||
{ value: getCurrentSchoolYear(), label: getCurrentSchoolYear() },
|
|
||||||
{ value: getNextSchoolYear(), label: getNextSchoolYear() },
|
|
||||||
]}
|
|
||||||
selected={formData.schoolYear || getCurrentSchoolYear()}
|
|
||||||
callback={(e) =>
|
|
||||||
setFormData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
schoolYear: e.target.value,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
className="w-full mt-4"
|
|
||||||
/>
|
|
||||||
<InputTextIcon
|
|
||||||
name="studentLastName"
|
|
||||||
type="text"
|
|
||||||
IconItem={User}
|
|
||||||
placeholder="Nom de l'élève"
|
|
||||||
value={formData.studentLastName}
|
|
||||||
onChange={handleChange}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
<InputTextIcon
|
|
||||||
name="studentFirstName"
|
|
||||||
type="text"
|
|
||||||
IconItem={User}
|
|
||||||
placeholder="Prénom de l'élève"
|
|
||||||
value={formData.studentFirstName}
|
|
||||||
onChange={handleChange}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 2 && (
|
|
||||||
<div className="mt-6">
|
|
||||||
{/* Nom, Prénom et Téléphone */}
|
|
||||||
<InputTextIcon
|
|
||||||
name="guardianLastName"
|
|
||||||
type="text"
|
|
||||||
IconItem={User}
|
|
||||||
placeholder="Nom du responsable"
|
|
||||||
value={formData.guardianLastName}
|
|
||||||
onChange={handleChange}
|
|
||||||
className="w-full mt-4"
|
|
||||||
/>
|
|
||||||
<InputTextIcon
|
|
||||||
name="guardianFirstName"
|
|
||||||
type="text"
|
|
||||||
IconItem={User}
|
|
||||||
placeholder="Prénom du responsable"
|
|
||||||
value={formData.guardianFirstName}
|
|
||||||
onChange={handleChange}
|
|
||||||
className="w-full mt-4"
|
|
||||||
/>
|
|
||||||
<InputPhone
|
|
||||||
name="guardianPhone"
|
|
||||||
label="Numéro de téléphone (optionnel)"
|
|
||||||
value={formData.guardianPhone}
|
|
||||||
onChange={handleChange}
|
|
||||||
className="w-full mt-4"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Email du responsable */}
|
|
||||||
<InputTextIcon
|
|
||||||
name="guardianEmail"
|
|
||||||
type="email"
|
|
||||||
IconItem={Mail}
|
|
||||||
placeholder="Email du responsable"
|
|
||||||
value={formData.guardianEmail}
|
|
||||||
onChange={(e) => {
|
|
||||||
const email = e.target.value;
|
|
||||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
||||||
|
|
||||||
setFormData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
guardianEmail: email,
|
|
||||||
emailError:
|
|
||||||
email.length > 0 && // Le champ de mail est non null
|
|
||||||
!emailRegex.test(email) &&
|
|
||||||
filteredStudents.length === 0 // Format invalide ou aucun résultat
|
|
||||||
? "Format d'email invalide ou aucun élève trouvé"
|
|
||||||
: '',
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Filtrer les responsables affichés dans le tableau
|
|
||||||
const filteredGuardians = students
|
|
||||||
.flatMap((student) => student.guardians) // Récupérer tous les guardians
|
|
||||||
.filter((guardian) =>
|
|
||||||
guardian.associated_profile_email
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(email.toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filtrer les élèves en fonction des responsables
|
|
||||||
const filteredStudents = students.filter((student) =>
|
|
||||||
student.guardians.some((guardian) =>
|
|
||||||
filteredGuardians.some(
|
|
||||||
(filteredGuardian) => filteredGuardian.id === guardian.id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
setFilteredStudents(filteredStudents); // Mettre à jour l'état des élèves filtrés
|
|
||||||
|
|
||||||
// Réinitialiser existingGuardians et selectedStudent si l'élève sélectionné n'est plus dans le tableau
|
|
||||||
if (
|
|
||||||
!filteredStudents.some(
|
|
||||||
(student) => student.id === selectedStudent?.id
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
setSelectedEleve(null); // Réinitialiser l'élève sélectionné
|
|
||||||
setExistingGuardians([]); // Réinitialiser les responsables associés
|
|
||||||
setFormData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
selectedGuardians: [], // Réinitialiser les responsables sélectionnés
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
errorMsg={formData.emailError}
|
|
||||||
className="w-full mt-4"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Tableau des élèves */}
|
|
||||||
<div className="mt-4">
|
|
||||||
<div
|
|
||||||
className="mt-4"
|
|
||||||
style={{ maxHeight: '300px', overflowY: 'auto' }}
|
|
||||||
>
|
|
||||||
<table className="min-w-full bg-white border">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th className="px-4 py-2 border">Nom</th>
|
|
||||||
<th className="px-4 py-2 border">Prénom</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{filteredStudents.map(
|
|
||||||
(
|
|
||||||
student,
|
|
||||||
index // Utiliser les élèves filtrés
|
|
||||||
) => (
|
|
||||||
<tr
|
|
||||||
key={student.id}
|
|
||||||
className={`cursor-pointer ${
|
|
||||||
selectedStudent && selectedStudent.id === student.id
|
|
||||||
? 'bg-emerald-600 text-white'
|
|
||||||
: index % 2 === 0
|
|
||||||
? 'bg-emerald-100'
|
|
||||||
: ''
|
|
||||||
}`}
|
|
||||||
onClick={() => handleEleveSelection(student)}
|
|
||||||
>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{student.last_name}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{student.first_name}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{selectedStudent && (
|
|
||||||
<div className="mt-4">
|
|
||||||
<h3 className="font-bold">
|
|
||||||
Responsables associés à {selectedStudent.last_name}{' '}
|
|
||||||
{selectedStudent.first_name} :
|
|
||||||
</h3>
|
|
||||||
{existingGuardians.map((guardian) => (
|
|
||||||
<div key={guardian.id} className="mt-2">
|
|
||||||
<CheckBox
|
|
||||||
item={{ id: guardian.id }}
|
|
||||||
formData={{
|
|
||||||
selectedGuardians: formData.selectedGuardians,
|
|
||||||
}}
|
|
||||||
handleChange={() =>
|
|
||||||
setFormData((prevData) => {
|
|
||||||
const isSelected =
|
|
||||||
prevData.selectedGuardians.includes(guardian.id);
|
|
||||||
const updatedSelectedGuardians = isSelected
|
|
||||||
? prevData.selectedGuardians.filter(
|
|
||||||
(id) => id !== guardian.id
|
|
||||||
) // Retirer le guardian si décoché
|
|
||||||
: [...prevData.selectedGuardians, guardian.id]; // Ajouter le guardian si coché
|
|
||||||
|
|
||||||
return {
|
|
||||||
...prevData,
|
|
||||||
selectedGuardians: updatedSelectedGuardians,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fieldName="selectedGuardians"
|
|
||||||
itemLabelFunc={() =>
|
|
||||||
guardian.last_name && guardian.first_name
|
|
||||||
? `${guardian.last_name} ${guardian.first_name} - ${guardian.associated_profile_email}`
|
|
||||||
: `${guardian.associated_profile_email}`
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 3 && (
|
|
||||||
<div>
|
|
||||||
{registrationFees.length > 0 ? (
|
|
||||||
<>
|
|
||||||
<div className="mb-4">
|
|
||||||
<FeesSection
|
|
||||||
fees={registrationFees}
|
|
||||||
type={0}
|
|
||||||
subscriptionMode={true}
|
|
||||||
selectedFees={formData.selectedRegistrationFees}
|
|
||||||
handleFeeSelection={handleRegistrationFeeSelection}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<SectionTitle title="Réductions" />
|
|
||||||
<div className="mb-4">
|
|
||||||
{registrationDiscounts.length > 0 ? (
|
|
||||||
<DiscountsSection
|
|
||||||
discounts={registrationDiscounts}
|
|
||||||
type={0}
|
|
||||||
subscriptionMode={true}
|
|
||||||
selectedDiscounts={formData.selectedRegistrationDiscounts}
|
|
||||||
handleDiscountSelection={
|
|
||||||
handleRegistrationDiscountSelection
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<p
|
|
||||||
className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative"
|
|
||||||
role="alert"
|
|
||||||
>
|
|
||||||
<strong className="font-bold">Information</strong>
|
|
||||||
<span className="block sm:inline">
|
|
||||||
{' '}
|
|
||||||
Aucune réduction n'a été créée sur les frais
|
|
||||||
d'inscription.
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<SectionTitle title="Montant total" />
|
|
||||||
<Table
|
|
||||||
data={[{ id: 1 }]}
|
|
||||||
columns={[
|
|
||||||
{
|
|
||||||
name: 'LIBELLE',
|
|
||||||
transform: () => <span>MONTANT TOTAL</span>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'TOTAL',
|
|
||||||
transform: () => <b>{totalRegistrationAmount} €</b>,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
defaultTheme="bg-cyan-100"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<p
|
|
||||||
className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
|
|
||||||
role="alert"
|
|
||||||
>
|
|
||||||
<strong className="font-bold">Attention!</strong>
|
|
||||||
<span className="block sm:inline">
|
|
||||||
{' '}
|
|
||||||
Aucun frais d'inscription n'a été créé.
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 4 && (
|
|
||||||
<div>
|
|
||||||
{tuitionFees.length > 0 ? (
|
|
||||||
<>
|
|
||||||
<div className="mb-4">
|
|
||||||
<FeesSection
|
|
||||||
fees={tuitionFees}
|
|
||||||
type={1}
|
|
||||||
subscriptionMode={true}
|
|
||||||
selectedFees={formData.selectedTuitionFees}
|
|
||||||
handleFeeSelection={handleTuitionFeeSelection}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<SectionTitle title="Réductions" />
|
|
||||||
<div className="mb-4">
|
|
||||||
{tuitionDiscounts.length > 0 ? (
|
|
||||||
<DiscountsSection
|
|
||||||
discounts={tuitionDiscounts}
|
|
||||||
type={1}
|
|
||||||
subscriptionMode={true}
|
|
||||||
selectedDiscounts={formData.selectedTuitionDiscounts}
|
|
||||||
handleDiscountSelection={handleTuitionDiscountSelection}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<p
|
|
||||||
className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative"
|
|
||||||
role="alert"
|
|
||||||
>
|
|
||||||
<strong className="font-bold">Information</strong>
|
|
||||||
<span className="block sm:inline">
|
|
||||||
{' '}
|
|
||||||
Aucune réduction n'a été créée sur les frais de
|
|
||||||
scolarité.
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<SectionTitle title="Montant total" />
|
|
||||||
<Table
|
|
||||||
data={[{ id: 1 }]}
|
|
||||||
columns={[
|
|
||||||
{
|
|
||||||
name: 'LIBELLE',
|
|
||||||
transform: () => <span>MONTANT TOTAL</span>,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'TOTAL',
|
|
||||||
transform: () => <b>{totalTuitionAmount} €</b>,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
defaultTheme="bg-cyan-100"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<p
|
|
||||||
className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
|
|
||||||
role="alert"
|
|
||||||
>
|
|
||||||
<strong className="font-bold">Attention!</strong>
|
|
||||||
<span className="block sm:inline">
|
|
||||||
{' '}
|
|
||||||
Aucun frais de scolarité n'a été créé.
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === 5 && (
|
|
||||||
<div>
|
|
||||||
{groups.length > 0 ? (
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h3 className="font-bold">Sélectionnez un groupe de documents</h3>
|
|
||||||
<RadioList
|
|
||||||
sectionLabel=""
|
|
||||||
items={groups.map((group) => ({
|
|
||||||
id: group.id,
|
|
||||||
label: `${group.name}${
|
|
||||||
group.description ? ` (${group.description})` : ''
|
|
||||||
}`,
|
|
||||||
}))}
|
|
||||||
formData={{
|
|
||||||
...formData,
|
|
||||||
selectedFileGroup: parseInt(formData.selectedFileGroup, 10),
|
|
||||||
}}
|
|
||||||
handleChange={(e) => {
|
|
||||||
const value = parseInt(e.target.value, 10);
|
|
||||||
setFormData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
selectedFileGroup: value,
|
|
||||||
}));
|
|
||||||
}}
|
|
||||||
fieldName="selectedFileGroup"
|
|
||||||
className="mt-4"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p
|
|
||||||
className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
|
|
||||||
role="alert"
|
|
||||||
>
|
|
||||||
<strong className="font-bold">Attention!</strong>
|
|
||||||
<span className="block sm:inline">
|
|
||||||
Aucun groupe de documents n'a été créé.
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{step === steps.length && (
|
|
||||||
<div>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<section>
|
|
||||||
<h3 className="font-bold">Élève</h3>
|
|
||||||
<table className="min-w-full bg-white border">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th className="px-4 py-2 border">Nom</th>
|
|
||||||
<th className="px-4 py-2 border">Prénom</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{formData.studentLastName}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{formData.studentFirstName}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<h3 className="font-bold">Responsable(s)</h3>
|
|
||||||
{formData.responsableType === 'new' && (
|
|
||||||
<table className="min-w-full bg-white border">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th className="px-4 py-2 border">Email</th>
|
|
||||||
<th className="px-4 py-2 border">Téléphone</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{formData.guardianEmail}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
<PhoneLabel phoneNumber={formData.guardianPhone} />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
)}
|
|
||||||
{formData.responsableType === 'existing' && selectedStudent && (
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
Associé(s) à : {selectedStudent.nom}{' '}
|
|
||||||
{selectedStudent.prenom}
|
|
||||||
</p>
|
|
||||||
<table className="min-w-full bg-white border">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th className="px-4 py-2 border">Nom</th>
|
|
||||||
<th className="px-4 py-2 border">Prénom</th>
|
|
||||||
<th className="px-4 py-2 border">Email</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{existingGuardians
|
|
||||||
.filter((guardian) =>
|
|
||||||
formData.selectedGuardians.includes(guardian.id)
|
|
||||||
)
|
|
||||||
.map((guardian) => (
|
|
||||||
<tr key={guardian.id}>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{guardian.last_name}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{guardian.first_name}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-2 border">
|
|
||||||
{guardian.associated_profile_email}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
<div className="mt-4">
|
|
||||||
<ToggleSwitch
|
|
||||||
label="Envoi automatique"
|
|
||||||
checked={formData.autoMail}
|
|
||||||
onChange={handleToggleChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="flex justify-end mt-4 space-x-4">
|
|
||||||
{showOnlyStep2 ? (
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
text="Valider"
|
|
||||||
onClick={validateAndSubmit}
|
|
||||||
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"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{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>
|
|
||||||
|
|
||||||
<Popup
|
|
||||||
visible={popupVisible}
|
|
||||||
message={popupMessage}
|
|
||||||
onConfirm={() => setPopupVisible(false)}
|
|
||||||
onCancel={() => setPopupVisible(false)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default InscriptionForm;
|
|
||||||
Reference in New Issue
Block a user