'use client'; import React, { useState, useRef, useEffect } 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 InputPhone from '@/components/InputPhone'; import CheckBox from '@/components/CheckBox'; import RadioList from '@/components/RadioList'; import SelectChoice from '@/components/SelectChoice'; import Loader from '@/components/Loader'; import { getCurrentSchoolYear, getNextSchoolYear } from '@/utils/Date'; import logger from '@/utils/logger'; import { levels, genders } from '@/utils/constants'; import { useEstablishment } from '@/context/EstablishmentContext'; import { useSearchParams, useRouter } from 'next/navigation'; import { fetchRegisterForm, fetchStudents, createRegisterForm, editRegisterForm, } from '@/app/actions/subscriptionAction'; import { fetchRegistrationDiscounts, fetchTuitionDiscounts, fetchRegistrationFees, fetchTuitionFees, } from '@/app/actions/schoolAction'; import { fetchRegistrationFileGroups, fetchRegistrationSchoolFileMasters, fetchRegistrationParentFileMasters, cloneTemplate, createRegistrationSchoolFileTemplate, createRegistrationParentFileTemplate, } from '@/app/actions/registerFileGroupAction'; import { fetchProfiles } from '@/app/actions/authAction'; import { useClasses } from '@/context/ClassesContext'; import { useCsrfToken } from '@/context/CsrfContext'; import { FE_ADMIN_SUBSCRIPTIONS_URL, BASE_URL } from '@/utils/Url'; import { useNotification } from '@/context/NotificationContext'; export default function CreateSubscriptionPage() { const [formData, setFormData] = useState({ studentLastName: '', studentFirstName: '', studentLevel: '', studentGender: '', guardianLastName: '', guardianFirstName: '', guardianEmail: '', guardianPhone: '', guardianProfileRole: '', selectedGuardians: [], associatedGuardians: [], autoMail: false, selectedRegistrationDiscounts: [], selectedRegistrationFees: [], selectedTuitionDiscounts: [], selectedTuitionFees: [], selectedFileGroup: null, schoolYear: getCurrentSchoolYear(), }); const searchParams = useSearchParams(); const { showNotification } = useNotification(); // Si l'ID est valorisé, alors on est en mode édition const registerFormID = searchParams.get('id'); const registerFormMoment = searchParams.get('school_year'); const [students, setStudents] = useState([]); const [registrationDiscounts, setRegistrationDiscounts] = useState([]); const [tuitionDiscounts, setTuitionDiscounts] = useState([]); const [registrationFees, setRegistrationFees] = useState([]); const [tuitionFees, setTuitionFees] = useState([]); const [groups, setGroups] = useState([]); const [schoolFileMasters, setSchoolFileMasters] = useState([]); const [parentFileMasters, setParentFileMasters] = useState([]); const [profiles, setProfiles] = useState([]); const [isLoading, setIsLoading] = useState(false); const [existingGuardians, setExistingGuardians] = useState([]); const [totalRegistrationAmount, setTotalRegistrationAmount] = useState(0); const [totalTuitionAmount, setTotalTuitionAmount] = useState(0); const [selectedStudent, setSelectedEleve] = useState(null); const [isNewResponsable, setIsNewResponsable] = useState(true); const [initialGuardianEmail, setInitialGuardianEmail] = useState(''); const { getNiveauLabel } = useClasses(); const formDataRef = useRef(formData); const { selectedEstablishmentId, apiDocuseal } = useEstablishment(); const csrfToken = useCsrfToken(); const router = useRouter(); const isSubmitDisabled = () => { // Vérifie si les champs requis sont remplis const requiredFields = [ 'schoolYear', 'studentLastName', 'studentFirstName', ]; const hasErrors = requiredFields.some( (field) => getLocalError(field) !== '' ); // Vérifie si un groupe de fichiers est sélectionné const isFileGroupSelected = formData.selectedFileGroup !== null; // Vérifie si au moins un frais de scolarité est sélectionné const hasSelectedTuitionFees = formData.selectedTuitionFees.length > 0; // Vérifie les conditions spécifiques pour le responsable const isGuardianValid = isNewResponsable ? getLocalError('guardianEmail') === '' : formData.selectedGuardians.length > 0; // Retourne true si une des conditions n'est pas remplie return ( hasErrors || !isFileGroupSelected || !hasSelectedTuitionFees || !isGuardianValid ); }; const getLocalError = (field) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (field === 'guardianEmail') { if (!formData.guardianEmail || formData.guardianEmail.trim() === '') { return 'Champs requis'; } if (!emailRegex.test(formData.guardianEmail)) { return 'Email invalide'; } // Vérifiez si l'email existe déjà, mais ne mettez pas à jour `formData` ici const existingGuardian = students .flatMap((student) => student.guardians) .find( (guardian) => guardian.associated_profile_email === formData.guardianEmail ); if (existingGuardian) { return ''; // Pas d'erreur, mais l'email existe déjà } } if ( // Student Form (field === 'studentLastName' && (!formData.studentLastName || formData.studentLastName.trim() === '')) || (field === 'studentFirstName' && (!formData.studentFirstName || formData.studentFirstName.trim() === '')) || (field === 'schoolYear' && (!formData.schoolYear || formData.schoolYear.trim() === '')) ) { return 'Champs requis'; } return ''; }; const requestErrorHandler = (err) => { logger.error('Error fetching data:', err); //setErrors(err); }; useEffect(() => { formDataRef.current = formData; }, [formData]); useEffect(() => { if (!formData.guardianEmail) { // Si l'email est vide, réinitialiser existingProfileId et existingProfileInSchool setFormData((prevData) => ({ ...prevData, isExistingParentProfile: false, existingProfileId: null, existingProfileInSchool: false, associatedGuardians: [], })); return; } // Vérifiez si le profil existe dans la liste des profils const existingProfile = profiles.find( (profile) => profile.email === formData.guardianEmail ); if (existingProfile) { // Vérifiez si le profil parent est associé à l'établissement sélectionné const isInSchool = existingProfile.roles.some( (role) => role.role_type === 2 && role.establishment === selectedEstablishmentId ); // Récupérer l'ID de l'id_associated_person si applicable const associatedPersonId = existingProfile.roles.find( (role) => role.role_type === 2 && role.establishment === selectedEstablishmentId )?.id_associated_person; // Mettre à jour les variables en fonction des résultats setFormData((prevData) => ({ ...prevData, isExistingParentProfile: true, existingProfileId: existingProfile.id, // Récupérer l'ID du profil associé existingProfileInSchool: isInSchool, // Vérifie si le profil est dans l'établissement guardianEmail: existingProfile.email || '', associatedGuardians: associatedPersonId ? [associatedPersonId] // Ajouter l'ID de l'id_associated_person si trouvé : [], })); } else { // Si aucun profil avec cet email n'existe, réinitialiser les champs setFormData((prevData) => ({ ...prevData, isExistingParentProfile: false, existingProfileId: null, existingProfileInSchool: false, associatedGuardians: [], })); } }, [formData.guardianEmail, profiles, selectedEstablishmentId]); useEffect(() => { fetchProfiles() .then((data) => { setProfiles(data); }) .catch(requestErrorHandler); if (selectedEstablishmentId) { if (registerFormID) { fetchRegisterForm(registerFormID) .then((data) => { setFormData((prevData) => ({ ...prevData, studentLastName: data?.student?.last_name || '', studentFirstName: data?.student?.first_name || '', studentLevel: data?.student?.level || '', studentGender: data?.student?.gender || '', guardianLastName: data?.student?.guardians[0]?.last_name || '', guardianFirstName: data?.student?.guardians[0]?.first_name || '', guardianEmail: data?.student?.guardians[0]?.associated_profile_email || '', guardianPhone: data?.student?.guardians[0]?.phone || '', selectedFileGroup: data?.fileGroup || '', schoolYear: data?.school_year || '', guardianProfileRole: data?.student?.guardians[0]?.profile_role || '', })); setIsNewResponsable( !Array.isArray(data?.student?.guardians) || data.student.guardians.length <= 1 ); // Définir l'email initial setInitialGuardianEmail( data?.student?.guardians[0]?.associated_profile_email || '' ); }) .catch(requestErrorHandler); } fetchStudents(selectedEstablishmentId) .then((studentsData) => { setStudents(studentsData); }) .catch(requestErrorHandler); fetchRegistrationDiscounts(selectedEstablishmentId) .then((data) => { setRegistrationDiscounts(data); }) .catch(requestErrorHandler); fetchTuitionDiscounts(selectedEstablishmentId) .then((data) => { setTuitionDiscounts(data); }) .catch(requestErrorHandler); fetchRegistrationFees(selectedEstablishmentId) .then((data) => { setRegistrationFees(data); // Sélectionner par défaut les frais d'inscription setFormData((prevData) => ({ ...prevData, selectedRegistrationFees: data.map((fee) => fee.id), })); }) .catch(requestErrorHandler); fetchTuitionFees(selectedEstablishmentId) .then((data) => { setTuitionFees(data); }) .catch(requestErrorHandler); fetchRegistrationFileGroups(selectedEstablishmentId) .then((data) => { setGroups(data); }) .catch(requestErrorHandler); fetchRegistrationSchoolFileMasters() .then((data) => { setSchoolFileMasters(data); }) .catch(requestErrorHandler); fetchRegistrationParentFileMasters() .then((data) => { setParentFileMasters(data); }) .catch(requestErrorHandler); } }, [selectedEstablishmentId]); useEffect(() => { if (registrationFees.length > 0) { const defaultSelectedFees = registrationFees.map((fee) => fee.id); const totalAmount = calculateFinalRegistrationAmount( defaultSelectedFees, formData.selectedRegistrationDiscounts ); setTotalRegistrationAmount(totalAmount); } }, [registrationFees]); const handleChange = (e) => { const { name, value } = e.target; setFormData((prevState) => ({ ...prevState, [name]: value, })); }; const resetGuardianFields = () => { setFormData((prevData) => ({ ...prevData, guardianLastName: '', guardianFirstName: '', guardianEmail: '', guardianPhone: '', selectedGuardians: [], })); }; // Gestion du changement du toggle const handleToggleChange = (e) => { const isChecked = e.target.checked; setIsNewResponsable(isChecked); if (isChecked) { // Réinitialiser les champs si on passe à "Nouveau responsable" resetGuardianFields(); } }; const submit = () => { logger.debug('formData:', formDataRef.current); const selectedRegistrationFeesIds = formDataRef.current.selectedRegistrationFees.map((feeId) => feeId); const selectedRegistrationDiscountsIds = formDataRef.current.selectedRegistrationDiscounts.map( (discountId) => discountId ); const selectedTuitionFeesIds = formDataRef.current.selectedTuitionFees.map( (feeId) => feeId ); const selectedTuitionDiscountsIds = formDataRef.current.selectedTuitionDiscounts.map( (discountId) => discountId ); const selectedFileGroup = formDataRef.current.selectedFileGroup; const allFeesIds = [ ...selectedRegistrationFeesIds, ...selectedTuitionFeesIds, ]; const allDiscountsIds = [ ...selectedRegistrationDiscountsIds, ...selectedTuitionDiscountsIds, ]; // Vérifiez si le profil existe dans la liste des profils const existingProfile = profiles.find( (profile) => profile.id === formDataRef.current.existingProfileId ); const guardians = (() => { if (formDataRef.current.selectedGuardians.length > 0) { // Cas 3 : Des guardians sont sélectionnés logger.debug('Cas 3 : Des guardians sont sélectionnés'); return formDataRef.current.selectedGuardians.map((guardianId) => ({ id: guardianId, })); } else if (formDataRef.current.isExistingParentProfile) { if (initialGuardianEmail !== existingProfile?.email) { // Cas 2 : Profil existant différent de l'ancien logger.debug( "Cas 2 : Profil existant différent de l'ancien, mise à jour du profil", { existingProfile, guardianEmail: formDataRef.current.guardianEmail, } ); return [ { profile_role_data: { establishment: selectedEstablishmentId, role_type: 2, is_active: true, profile: formDataRef.current.existingProfileId, }, last_name: formDataRef.current.guardianLastName, first_name: formDataRef.current.guardianFirstName, phone: formDataRef.current.guardianPhone, }, ]; } else { // Cas 4 : Profil existant avec le même email logger.debug('Cas 4 : Profil existant avec le même email', { existingProfile, }); return [ { profile_role_data: { establishment: selectedEstablishmentId, role_type: 2, is_active: true, profile: formDataRef.current.existingProfileId, }, last_name: formDataRef.current.guardianLastName, first_name: formDataRef.current.guardianFirstName, phone: formDataRef.current.guardianPhone, }, ]; } } else { // Cas 1 : Profil inexistant logger.debug("Cas 1 : Profil inexistant, création d'un nouveau profil"); return [ { profile_role_data: { establishment: selectedEstablishmentId, role_type: 2, is_active: false, profile_data: { email: formDataRef.current.guardianEmail, password: 'Provisoire01!', username: formDataRef.current.guardianEmail, }, }, last_name: formDataRef.current.guardianLastName, first_name: formDataRef.current.guardianFirstName, birth_date: formDataRef.current.guardianBirthDate, phone: formDataRef.current.guardianPhone, }, ]; } })(); const data = { student: { last_name: formDataRef.current.studentLastName, first_name: formDataRef.current.studentFirstName, ...(formDataRef.current.studentLevel && { level: formDataRef.current.studentLevel, }), ...(formDataRef.current.studentGender && { gender: formDataRef.current.studentGender, }), guardians, sibling: [], }, fees: allFeesIds, discounts: allDiscountsIds, fileGroup: selectedFileGroup, establishment: selectedEstablishmentId, school_year: formDataRef.current.schoolYear, }; setIsLoading(true); if (registerFormID) { const formData = new FormData(); // Ajouter les données JSON sous forme de chaîne formData.append('data', JSON.stringify(data)); // Mode édition editRegisterForm(registerFormID, formData, csrfToken) .then((response) => { logger.debug('Dossier mis à jour avec succès:', response); router.push(FE_ADMIN_SUBSCRIPTIONS_URL); }) .catch((error) => { setIsLoading(false); logger.error('Erreur lors de la mise à jour du dossier:', error); showNotification( "Erreur lors de la mise à jour du dossier d'inscription", 'error', 'Erreur', 'ERR_ADM_SUB_06' ); }); } else { // Création du dossier d'inscription createRegisterForm(data, csrfToken) .then((data) => { // Clonage des schoolFileTemplates const masters = schoolFileMasters.filter((file) => file.groups.includes(selectedFileGroup) ); const parentMasters = parentFileMasters.filter((file) => file.groups.includes(selectedFileGroup) ); const clonePromises = masters.map((templateMaster) => cloneTemplate( templateMaster.id, formDataRef.current.guardianEmail, templateMaster.is_required, selectedEstablishmentId, apiDocuseal ) .then((clonedDocument) => { const cloneData = { name: `${templateMaster.name}_${formDataRef.current.studentFirstName}_${formDataRef.current.studentLastName}`, slug: clonedDocument.slug, id: clonedDocument.id, master: templateMaster.id, registration_form: data.student.id, }; return createRegistrationSchoolFileTemplate( cloneData, csrfToken ) .then((response) => logger.debug('Template enregistré avec succès:', response) ) .catch((error) => { setIsLoading(false); logger.error( "Erreur lors de l'enregistrement du template:", error ); showNotification( "Erreur lors de la création du dossier d'inscription", 'error', 'Erreur', 'ERR_ADM_SUB_03' ); }); }) .catch((error) => { setIsLoading(false); logger.error('Error during cloning or sending:', error); showNotification( "Erreur lors de la création du dossier d'inscription", 'error', 'Erreur', 'ERR_ADM_SUB_05' ); }) ); // Clonage des parentFileTemplates const parentClonePromises = parentMasters.map((parentMaster) => { const parentTemplateData = { master: parentMaster.id, registration_form: data.student.id, }; return createRegistrationParentFileTemplate( parentTemplateData, csrfToken ) .then((response) => logger.debug( 'Parent template enregistré avec succès:', response ) ) .catch((error) => { setIsLoading(false); logger.error( "Erreur lors de l'enregistrement du parent template:", error ); showNotification( "Erreur lors de la création du dossier d'inscription", 'error', 'Erreur', 'ERR_ADM_SUB_02' ); }); }); // Attendre que tous les clones soient créés Promise.all([...clonePromises, ...parentClonePromises]) .then(() => { // Redirection après succès router.push(FE_ADMIN_SUBSCRIPTIONS_URL); }) .catch((error) => { setIsLoading(false); showNotification( "Erreur lors de la création du dossier d'inscription", 'error', 'Erreur', 'ERR_ADM_SUB_04' ); logger.error('Error during cloning or sending:', error); }); }) .catch((error) => { setIsLoading(false); showNotification( "Erreur lors de la création du dossier d'inscription", 'error', 'Erreur', 'ERR_ADM_SUB_01' ); logger.error('Error during register form creation:', error); }); } }; const handleEleveSelection = (student) => { setSelectedEleve(student); setExistingGuardians(student.guardians); }; // Gestion des changements dans la checkbox const handleGuardianCheckboxChange = (guardian) => { setFormData((prevData) => { const isSelected = prevData.selectedGuardians.includes(guardian.id); const updatedSelectedGuardians = isSelected ? prevData.selectedGuardians.filter((id) => id !== guardian.id) : [...prevData.selectedGuardians, guardian.id]; return { ...prevData, selectedGuardians: updatedSelectedGuardians, guardianEmail: guardian.associated_profile_email, }; }); }; // Gestion de la désélection d'un élève const handleEleveDeselection = () => { setSelectedEleve(null); setExistingGuardians([]); resetGuardianFields(); }; 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); }; if (isLoading === true) { return ; // Affichez le composant Loader } return (
{registerFormID ? (

Modifier un dossier d'inscription

) : (

Créer un dossier d'inscription

)} {/* Sélection de l'année scolaire */}
setFormData((prevData) => ({ ...prevData, schoolYear: e.target.value, })) } errorLocalMsg={getLocalError('schoolYear')} required />
{/* Informations sur l'élève */} {/* Nom et Prénom côte à côte */}
{/* Genre et Niveau côte à côte */}
setFormData((prevData) => ({ ...prevData, studentGender: e.target.value, })) } /> setFormData((prevData) => ({ ...prevData, studentLevel: e.target.value, })) } />
{/* Informations sur le responsable */} {/* Nom et Prénom côte à côte */}
{/* Email et Numéro de téléphone côte à côte */}
{/* Tableau des élèves pour responsable existant */} {!isNewResponsable && (
(
{row.photo ? ( {`${row.first_name} ) : (
{row.first_name[0]} {row.last_name[0]}
)}
), }, { name: 'Nom', transform: (row) => row.last_name, }, { name: 'Prénom', transform: (row) => row.first_name, }, { name: 'Niveau', transform: (row) => (
{getNiveauLabel(row.level)}
), }, ]} isSelectable={true} onRowClick={(event) => { if (event.deselected) { handleEleveDeselection(); } else { handleEleveSelection(event); } }} rowClassName={(row) => selectedStudent && selectedStudent.id === row.id ? 'bg-emerald-600 text-white' : '' } selectedRows={selectedStudent ? [selectedStudent.id] : []} // Assurez-vous que selectedRows est un tableau /> {selectedStudent && (

Responsables associés à {selectedStudent.last_name}{' '} {selectedStudent.first_name} :

{existingGuardians.map((guardian) => (
handleGuardianCheckboxChange(guardian)} fieldName="selectedGuardians" itemLabelFunc={() => guardian.last_name && guardian.first_name ? `${guardian.last_name} ${guardian.first_name} - ${guardian.associated_profile_email}` : `${guardian.associated_profile_email}` } />
))}
)} )} {/* Section des frais d'inscription */} {registrationFees.length > 0 || registrationDiscounts.length > 0 ? ( <>
{/* Tableau des frais */}
{/* Tableau des réductions */}
{registrationDiscounts.length > 0 ? ( ) : (

Information Aucune réduction n'a été créée sur les frais d'inscription.

)}
{/* Montant total */}
Montant total des frais d'inscription : {totalRegistrationAmount} €
) : (

Attention! Aucun frais d'inscription n'a été créé.

)}
{/* Section des frais de scolarité */} {tuitionFees.length > 0 || tuitionDiscounts.length > 0 ? ( <>
{/* Tableau des frais */}
{/* Tableau des réductions */}
{tuitionDiscounts.length > 0 ? ( ) : (

Information Aucune réduction n'a été créée sur les frais de scolarité.

)}
{/* Montant total */}
Montant total des frais de scolarité : {totalTuitionAmount} €
) : (

Attention! Aucun frais de scolarité n'a été créé.

)}
{/* Section des groupes de documents */} {groups.length > 0 ? (
({ 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" required className="mt-4" />
) : (

Attention! Aucun groupe de documents n'a été créé.

)}
{/* Bouton de soumission */}
); }