mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
fix: Application du formattage sur les fichiers modifiés
This commit is contained in:
@ -65,13 +65,13 @@ export default function InscriptionFormShared({
|
||||
const [uploadedFiles, setUploadedFiles] = useState([]);
|
||||
const [schoolFileTemplates, setSchoolFileTemplates] = useState([]);
|
||||
const [parentFileTemplates, setParentFileTemplates] = useState([]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [isSignatureComplete, setIsSignatureComplete] = useState(false);
|
||||
const [currentPage, setCurrentPage] = useState(5);
|
||||
|
||||
const [isPage1Valid, setIsPage1Valid] = useState(false);
|
||||
const [isPage2Valid, setIsPage2Valid] = useState(false);
|
||||
const [isPage3Valid, setIsPage3Valid] = useState(false);
|
||||
const [isPage4Valid, setIsPage4Valid] = useState(false);
|
||||
const [isPage5Valid, setIsPage5Valid] = useState(false);
|
||||
|
||||
const [hasInteracted, setHasInteracted] = useState(false);
|
||||
|
||||
@ -83,7 +83,7 @@ export default function InscriptionFormShared({
|
||||
const firstUnsignedIndex = schoolFileTemplates.findIndex(
|
||||
(template) => template.file === null
|
||||
);
|
||||
|
||||
|
||||
// Mettre à jour l'index du template actuel
|
||||
if (firstUnsignedIndex !== -1) {
|
||||
setCurrentTemplateIndex(firstUnsignedIndex);
|
||||
@ -95,8 +95,10 @@ export default function InscriptionFormShared({
|
||||
|
||||
useEffect(() => {
|
||||
// Vérifier si tous les templates ont leur champ "file" différent de null
|
||||
const allSigned = schoolFileTemplates.every((template) => template.file !== null);
|
||||
|
||||
const allSigned = schoolFileTemplates.every(
|
||||
(template) => template.file !== null
|
||||
);
|
||||
|
||||
// Mettre à jour isPage4Valid en fonction de cette condition
|
||||
setIsPage4Valid(allSigned);
|
||||
|
||||
@ -105,26 +107,34 @@ export default function InscriptionFormShared({
|
||||
}
|
||||
}, [schoolFileTemplates]);
|
||||
|
||||
useEffect(() => {
|
||||
// Vérifier si tous les parentFileTemplates ont leur champ "file" différent de null
|
||||
const allUploaded = parentFileTemplates.every(
|
||||
(template) => template.file !== null
|
||||
);
|
||||
|
||||
// Mettre à jour isPage5Valid en fonction de cette condition
|
||||
setIsPage5Valid(allUploaded);
|
||||
}, [parentFileTemplates]);
|
||||
|
||||
const handleTemplateSigned = (index) => {
|
||||
const template = schoolFileTemplates[index];
|
||||
|
||||
|
||||
if (!template) {
|
||||
logger.error('Template introuvable pour l\'index donné.');
|
||||
logger.error("Template introuvable pour l'index donné.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
downloadTemplate(template.slug)
|
||||
.then((data) => fetch(data))
|
||||
.then((response) => response.blob())
|
||||
.then((blob) => {
|
||||
const file = new File(
|
||||
[blob],
|
||||
`${template.name}.pdf`,
|
||||
{ type: blob.type }
|
||||
);
|
||||
const file = new File([blob], `${template.name}.pdf`, {
|
||||
type: blob.type,
|
||||
});
|
||||
const updateData = new FormData();
|
||||
updateData.append('file', file);
|
||||
|
||||
|
||||
return editRegistrationSchoolFileTemplates(
|
||||
template.id,
|
||||
updateData,
|
||||
@ -133,7 +143,7 @@ export default function InscriptionFormShared({
|
||||
})
|
||||
.then((data) => {
|
||||
logger.debug('Template mis à jour avec succès :', data);
|
||||
|
||||
|
||||
// Mettre à jour l'état local de schoolFileTemplates
|
||||
setSchoolFileTemplates((prevTemplates) =>
|
||||
prevTemplates.map((t, i) =>
|
||||
@ -236,6 +246,15 @@ export default function InscriptionFormShared({
|
||||
return updatedFiles;
|
||||
});
|
||||
|
||||
// Mettre à jour parentFileTemplates
|
||||
setParentFileTemplates((prevTemplates) =>
|
||||
prevTemplates.map((template) =>
|
||||
template.id === selectedFile.id
|
||||
? { ...template, file: response.data.file }
|
||||
: template
|
||||
)
|
||||
);
|
||||
|
||||
return response; // Retourner la réponse pour signaler le succès
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -265,6 +284,8 @@ export default function InscriptionFormShared({
|
||||
.then((response) => {
|
||||
logger.debug('Fichier supprimé avec succès dans la base :', response);
|
||||
|
||||
setIsPage5Valid(false);
|
||||
|
||||
// Mettre à jour l'état local pour refléter la suppression
|
||||
setUploadedFiles((prev) =>
|
||||
prev.map((uploadedFile) =>
|
||||
@ -273,6 +294,13 @@ export default function InscriptionFormShared({
|
||||
: uploadedFile
|
||||
)
|
||||
);
|
||||
|
||||
// Mettre à jour l'état local pour refléter la suppression dans parentFileTemplates
|
||||
setParentFileTemplates((prevTemplates) =>
|
||||
prevTemplates.map((template) =>
|
||||
template.id === templateId ? { ...template, file: null } : template
|
||||
)
|
||||
);
|
||||
return response;
|
||||
})
|
||||
.catch((error) => {
|
||||
@ -311,10 +339,9 @@ export default function InscriptionFormShared({
|
||||
const stepTitles = {
|
||||
1: 'Elève',
|
||||
2: 'Responsables légaux',
|
||||
3: "Modalités de paiement",
|
||||
4: "Formulaires à signer",
|
||||
5: "Pièces à fournir",
|
||||
6: "Validation"
|
||||
3: 'Modalités de paiement',
|
||||
4: 'Formulaires à signer',
|
||||
5: 'Pièces à fournir',
|
||||
};
|
||||
|
||||
const steps = [
|
||||
@ -323,7 +350,6 @@ export default function InscriptionFormShared({
|
||||
'Paiement',
|
||||
'Formulaires',
|
||||
'Documents parent',
|
||||
'Validation'
|
||||
];
|
||||
|
||||
const isStepValid = (stepNumber) => {
|
||||
@ -334,6 +360,10 @@ export default function InscriptionFormShared({
|
||||
return isPage2Valid;
|
||||
case 3:
|
||||
return isPage3Valid;
|
||||
case 4:
|
||||
return isPage4Valid;
|
||||
case 5:
|
||||
return isPage5Valid;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -350,7 +380,10 @@ export default function InscriptionFormShared({
|
||||
setStep={setCurrentPage}
|
||||
isStepValid={isStepValid}
|
||||
/>
|
||||
<div className="flex-1 overflow-y-auto mt-12 " style={{ maxHeight: 'calc(100vh - 400px)' }}>
|
||||
<div
|
||||
className="flex-1 overflow-y-auto mt-12 "
|
||||
style={{ maxHeight: 'calc(100vh - 400px)' }}
|
||||
>
|
||||
{/* Page 1 : Informations sur l'élève */}
|
||||
{currentPage === 1 && (
|
||||
<StudentInfoForm
|
||||
@ -393,78 +426,83 @@ export default function InscriptionFormShared({
|
||||
{/* Pages suivantes : Section Fichiers d'inscription */}
|
||||
{currentPage === 4 && (
|
||||
<div className="mt-8 mb-4 w-4/5 mx-auto flex gap-8">
|
||||
{/* Liste des états de signature */}
|
||||
<div className="w-1/4 bg-gray-50 p-4 rounded-lg shadow-sm border border-gray-200">
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-4">Documents</h3>
|
||||
<ul className="space-y-2">
|
||||
{schoolFileTemplates.map((template, index) => (
|
||||
<li
|
||||
key={template.id}
|
||||
className={`flex items-center cursor-pointer ${
|
||||
index === currentTemplateIndex
|
||||
? 'text-blue-600 font-bold'
|
||||
: template.file !== null
|
||||
? 'text-green-600'
|
||||
: 'text-gray-600'
|
||||
}`}
|
||||
onClick={() => setCurrentTemplateIndex(index)} // Mettre à jour l'index du template actuel
|
||||
>
|
||||
<span className="mr-2">
|
||||
{template.file !== null ? (
|
||||
<CheckCircle className="w-5 h-5 text-green-600" />
|
||||
) : (
|
||||
<Loader2 className="w-5 h-5 text-gray-600" />
|
||||
)}
|
||||
</span>
|
||||
{template.name || 'Document sans nom'}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{/* Liste des états de signature */}
|
||||
<div className="w-1/4 bg-gray-50 p-4 rounded-lg shadow-sm border border-gray-200">
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-4">
|
||||
Documents
|
||||
</h3>
|
||||
<ul className="space-y-2">
|
||||
{schoolFileTemplates.map((template, index) => (
|
||||
<li
|
||||
key={template.id}
|
||||
className={`flex items-center cursor-pointer ${
|
||||
index === currentTemplateIndex
|
||||
? 'text-blue-600 font-bold'
|
||||
: template.file !== null
|
||||
? 'text-green-600'
|
||||
: 'text-gray-600'
|
||||
}`}
|
||||
onClick={() => setCurrentTemplateIndex(index)} // Mettre à jour l'index du template actuel
|
||||
>
|
||||
<span className="mr-2">
|
||||
{template.file !== null ? (
|
||||
<CheckCircle className="w-5 h-5 text-green-600" />
|
||||
) : (
|
||||
<Loader2 className="w-5 h-5 text-gray-600" />
|
||||
)}
|
||||
</span>
|
||||
{template.name || 'Document sans nom'}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Affichage du fichier actuel */}
|
||||
<div className="w-3/4">
|
||||
{currentTemplateIndex < schoolFileTemplates.length && (
|
||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-4">
|
||||
{schoolFileTemplates[currentTemplateIndex].name ||
|
||||
'Document sans nom'}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-500 mb-4">
|
||||
{schoolFileTemplates[currentTemplateIndex].description ||
|
||||
'Aucune description disponible pour ce document.'}
|
||||
</p>
|
||||
|
||||
{schoolFileTemplates[currentTemplateIndex].file === null ? (
|
||||
<DocusealForm
|
||||
key={schoolFileTemplates[currentTemplateIndex].slug}
|
||||
id="docusealForm"
|
||||
src={`https://docuseal.com/s/${schoolFileTemplates[currentTemplateIndex].slug}`}
|
||||
withDownloadButton={false}
|
||||
withTitle={false}
|
||||
onComplete={() =>
|
||||
handleTemplateSigned(currentTemplateIndex)
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${BASE_URL}/${schoolFileTemplates[currentTemplateIndex].file}`}
|
||||
title="Document Viewer"
|
||||
className="w-full"
|
||||
style={{
|
||||
height: '75vh',
|
||||
border: 'none',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Message de fin */}
|
||||
{currentTemplateIndex >= schoolFileTemplates.length && (
|
||||
<div className="text-center text-green-600 font-semibold">
|
||||
Tous les formulaires ont été signés avec succès !
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Affichage du fichier actuel */}
|
||||
<div className="w-3/4">
|
||||
{currentTemplateIndex < schoolFileTemplates.length && (
|
||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
|
||||
<h3 className="text-lg font-semibold text-gray-800 mb-4">
|
||||
{schoolFileTemplates[currentTemplateIndex].name || 'Document sans nom'}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-500 mb-4">
|
||||
{schoolFileTemplates[currentTemplateIndex].description ||
|
||||
'Aucune description disponible pour ce document.'}
|
||||
</p>
|
||||
|
||||
{schoolFileTemplates[currentTemplateIndex].file === null ? (
|
||||
<DocusealForm
|
||||
key={schoolFileTemplates[currentTemplateIndex].slug}
|
||||
id="docusealForm"
|
||||
src={`https://docuseal.com/s/${schoolFileTemplates[currentTemplateIndex].slug}`}
|
||||
withDownloadButton={false}
|
||||
withTitle={false}
|
||||
onComplete={() => handleTemplateSigned(currentTemplateIndex)}
|
||||
/>
|
||||
) : (
|
||||
<iframe
|
||||
src={`${BASE_URL}/${schoolFileTemplates[currentTemplateIndex].file}`}
|
||||
title="Document Viewer"
|
||||
className="w-full"
|
||||
style={{
|
||||
height: '75vh',
|
||||
border: 'none',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Message de fin */}
|
||||
{currentTemplateIndex >= schoolFileTemplates.length && (
|
||||
<div className="text-center text-green-600 font-semibold">
|
||||
Tous les formulaires ont été signés avec succès !
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Dernière page : Section Fichiers parents */}
|
||||
@ -478,47 +516,57 @@ export default function InscriptionFormShared({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Boutons de contrôle */}
|
||||
<div className="flex justify-center space-x-4 mt-12">
|
||||
{currentPage > 1 && (
|
||||
<Button
|
||||
text="Précédent"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handlePreviousPage();
|
||||
}}
|
||||
primary
|
||||
/>
|
||||
)}
|
||||
{currentPage < steps.length && (
|
||||
<Button
|
||||
text="Suivant"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleNextPage();
|
||||
}}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid)
|
||||
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
|
||||
: 'bg-emerald-500 text-white hover:bg-emerald-600'
|
||||
}`}
|
||||
disabled={
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid)
|
||||
}
|
||||
primary
|
||||
name="Next"
|
||||
/>
|
||||
)}
|
||||
{currentPage === steps.length && (
|
||||
<Button onClick={handleSubmit} text="Valider" primary />
|
||||
)}
|
||||
</div>
|
||||
{/* Boutons de contrôle */}
|
||||
<div className="flex justify-center space-x-4 mt-12">
|
||||
{currentPage > 1 && (
|
||||
<Button
|
||||
text="Précédent"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handlePreviousPage();
|
||||
}}
|
||||
primary
|
||||
/>
|
||||
)}
|
||||
{currentPage < steps.length && (
|
||||
<Button
|
||||
text="Suivant"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleNextPage();
|
||||
}}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid)
|
||||
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
|
||||
: 'bg-emerald-500 text-white hover:bg-emerald-600'
|
||||
}`}
|
||||
disabled={
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid)
|
||||
}
|
||||
primary
|
||||
name="Next"
|
||||
/>
|
||||
)}
|
||||
{currentPage === steps.length && (
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
text="Valider"
|
||||
primary
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
currentPage === 5 && !isPage5Valid
|
||||
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
|
||||
: 'bg-emerald-500 text-white hover:bg-emerald-600'
|
||||
}`}
|
||||
disabled={currentPage === 5 && !isPage5Valid}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -7,12 +7,13 @@ export default function PaymentMethodSelector({
|
||||
registrationPaymentModes,
|
||||
tuitionPaymentModes,
|
||||
errors,
|
||||
setIsPageValid
|
||||
setIsPageValid,
|
||||
}) {
|
||||
|
||||
useEffect(() => {
|
||||
const isValid = !Object.keys(formData).some((field) => getLocalError(field) !== '');
|
||||
console.log(isValid)
|
||||
const isValid = !Object.keys(formData).some(
|
||||
(field) => getLocalError(field) !== ''
|
||||
);
|
||||
console.log(isValid);
|
||||
setIsPageValid(isValid);
|
||||
}, [formData, setIsPageValid]);
|
||||
|
||||
@ -30,8 +31,12 @@ export default function PaymentMethodSelector({
|
||||
const getLocalError = (field) => {
|
||||
if (
|
||||
// Student Form
|
||||
( field === 'registration_payment' && (!formData.registration_payment || String(formData.registration_payment).trim() === '') ) ||
|
||||
( field === 'tuition_payment' && (!formData.tuition_payment || String(formData.tuition_payment).trim() === '') )
|
||||
(field === 'registration_payment' &&
|
||||
(!formData.registration_payment ||
|
||||
String(formData.registration_payment).trim() === '')) ||
|
||||
(field === 'tuition_payment' &&
|
||||
(!formData.tuition_payment ||
|
||||
String(formData.tuition_payment).trim() === ''))
|
||||
) {
|
||||
return 'Champs requis';
|
||||
}
|
||||
@ -47,13 +52,14 @@ export default function PaymentMethodSelector({
|
||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
|
||||
{/* Titre */}
|
||||
<h2 className="text-2xl font-semibold mb-6 text-gray-800 border-b pb-2">
|
||||
Frais d'inscription
|
||||
Frais d'inscription
|
||||
</h2>
|
||||
|
||||
{/* Section d'information */}
|
||||
<div className="mb-6 bg-gray-50 p-4 rounded-lg border border-gray-100">
|
||||
<p className="text-gray-700 text-sm mb-2">
|
||||
<strong className="text-gray-900">Montant :</strong> {formData.totalRegistrationFees} €
|
||||
<strong className="text-gray-900">Montant :</strong>{' '}
|
||||
{formData.totalRegistrationFees} €
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -62,7 +68,7 @@ export default function PaymentMethodSelector({
|
||||
label="Mode de Paiement"
|
||||
placeHolder="Sélectionner un mode de paiement"
|
||||
selected={formData.registration_payment}
|
||||
callback={(e) => onChange("registration_payment", e.target.value)}
|
||||
callback={(e) => onChange('registration_payment', e.target.value)}
|
||||
choices={registrationPaymentModes.map((mode) => ({
|
||||
value: mode.mode,
|
||||
label:
|
||||
@ -70,20 +76,24 @@ export default function PaymentMethodSelector({
|
||||
?.name || 'Mode inconnu',
|
||||
}))}
|
||||
required
|
||||
errorMsg={getError("registration_payment") || getLocalError("registration_payment")}
|
||||
errorMsg={
|
||||
getError('registration_payment') ||
|
||||
getLocalError('registration_payment')
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200 mt-12">
|
||||
{/* Titre */}
|
||||
<h2 className="text-2xl font-semibold mb-6 text-gray-800 border-b pb-2">
|
||||
Frais de scolarité
|
||||
Frais de scolarité
|
||||
</h2>
|
||||
|
||||
{/* Section d'information */}
|
||||
<div className="mb-6 bg-gray-50 p-4 rounded-lg border border-gray-100">
|
||||
<p className="text-gray-700 text-sm mb-2">
|
||||
<strong className="text-gray-900">Montant :</strong> {formData.totalTuitionFees} €
|
||||
<strong className="text-gray-900">Montant :</strong>{' '}
|
||||
{formData.totalTuitionFees} €
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -92,7 +102,7 @@ export default function PaymentMethodSelector({
|
||||
label="Mode de Paiement"
|
||||
placeHolder="Sélectionner un mode de paiement"
|
||||
selected={formData.tuition_payment}
|
||||
callback={(e) => onChange("tuition_payment", e.target.value)}
|
||||
callback={(e) => onChange('tuition_payment', e.target.value)}
|
||||
choices={tuitionPaymentModes.map((mode) => ({
|
||||
value: mode.mode,
|
||||
label:
|
||||
@ -100,7 +110,9 @@ export default function PaymentMethodSelector({
|
||||
?.name || 'Mode inconnu',
|
||||
}))}
|
||||
required
|
||||
errorMsg={getError("tuition_payment") || getLocalError("tuition_payment")}
|
||||
errorMsg={
|
||||
getError('tuition_payment') || getLocalError('tuition_payment')
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -9,14 +9,18 @@ export default function ResponsableInputFields({
|
||||
guardians,
|
||||
setGuardians,
|
||||
errors,
|
||||
setIsPageValid
|
||||
setIsPageValid,
|
||||
}) {
|
||||
const t = useTranslations('ResponsableInputFields');
|
||||
|
||||
useEffect(() => {
|
||||
const isValid = guardians.length > 0 && guardians.every((guardian, index) => {
|
||||
return !Object.keys(guardian).some((field) => getLocalError(index, field) !== '');
|
||||
});
|
||||
const isValid =
|
||||
guardians.length > 0 &&
|
||||
guardians.every((guardian, index) => {
|
||||
return !Object.keys(guardian).some(
|
||||
(field) => getLocalError(index, field) !== ''
|
||||
);
|
||||
});
|
||||
|
||||
setIsPageValid(isValid);
|
||||
}, [guardians, setIsPageValid]);
|
||||
@ -28,18 +32,29 @@ export default function ResponsableInputFields({
|
||||
const getLocalError = (index, field) => {
|
||||
if (
|
||||
// Student Form
|
||||
( field === 'last_name' && (!guardians[index].last_name || guardians[index].last_name.trim() === '') ) ||
|
||||
( field === 'first_name' && (!guardians[index].first_name || guardians[index].first_name.trim() === '') ) ||
|
||||
( field === 'email' && (!guardians[index].associated_profile_email || guardians[index].associated_profile_email.trim() === '') ) ||
|
||||
( field === 'birth_date' && (!guardians[index].birth_date || guardians[index].birth_date.trim() === '') ) ||
|
||||
( field === 'profession' && (!guardians[index].profession || guardians[index].profession.trim() === '') ) ||
|
||||
( field === 'address' && (!guardians[index].address || guardians[index].address.trim() === '') )
|
||||
(field === 'last_name' &&
|
||||
(!guardians[index].last_name ||
|
||||
guardians[index].last_name.trim() === '')) ||
|
||||
(field === 'first_name' &&
|
||||
(!guardians[index].first_name ||
|
||||
guardians[index].first_name.trim() === '')) ||
|
||||
(field === 'email' &&
|
||||
(!guardians[index].associated_profile_email ||
|
||||
guardians[index].associated_profile_email.trim() === '')) ||
|
||||
(field === 'birth_date' &&
|
||||
(!guardians[index].birth_date ||
|
||||
guardians[index].birth_date.trim() === '')) ||
|
||||
(field === 'profession' &&
|
||||
(!guardians[index].profession ||
|
||||
guardians[index].profession.trim() === '')) ||
|
||||
(field === 'address' &&
|
||||
(!guardians[index].address || guardians[index].address.trim() === ''))
|
||||
) {
|
||||
return 'Champs requis';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
|
||||
const onGuardiansChange = (id, field, value) => {
|
||||
const updatedGuardians = guardians.map((guardian) =>
|
||||
guardian.id === id ? { ...guardian, [field]: value } : guardian
|
||||
@ -50,7 +65,7 @@ export default function ResponsableInputFields({
|
||||
const addGuardian = () => {
|
||||
setGuardians([...guardians, { id: Date.now(), name: '', email: '' }]);
|
||||
};
|
||||
|
||||
|
||||
const deleteGuardian = (index) => {
|
||||
const updatedGuardians = guardians.filter((_, i) => i !== index);
|
||||
setGuardians(updatedGuardians);
|
||||
@ -88,7 +103,10 @@ export default function ResponsableInputFields({
|
||||
onChange={(event) => {
|
||||
onGuardiansChange(item.id, 'last_name', event.target.value);
|
||||
}}
|
||||
errorMsg={getError(index, 'last_name') || getLocalError(index, 'last_name')}
|
||||
errorMsg={
|
||||
getError(index, 'last_name') ||
|
||||
getLocalError(index, 'last_name')
|
||||
}
|
||||
required
|
||||
/>
|
||||
<InputText
|
||||
@ -99,7 +117,10 @@ export default function ResponsableInputFields({
|
||||
onChange={(event) => {
|
||||
onGuardiansChange(item.id, 'first_name', event.target.value);
|
||||
}}
|
||||
errorMsg={getError(index, 'first_name') || getLocalError(index, 'first_name')}
|
||||
errorMsg={
|
||||
getError(index, 'first_name') ||
|
||||
getLocalError(index, 'first_name')
|
||||
}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
@ -118,11 +139,13 @@ export default function ResponsableInputFields({
|
||||
);
|
||||
}}
|
||||
required
|
||||
errorMsg={getError(index, 'email') || getLocalError(index, 'email')}
|
||||
errorMsg={
|
||||
getError(index, 'email') || getLocalError(index, 'email')
|
||||
}
|
||||
/>
|
||||
<InputPhone
|
||||
name="telephoneResponsable"
|
||||
label='phone'
|
||||
label="phone"
|
||||
value={item.phone}
|
||||
onChange={(event) => {
|
||||
onGuardiansChange(item.id, 'phone', event);
|
||||
@ -142,7 +165,10 @@ export default function ResponsableInputFields({
|
||||
onGuardiansChange(item.id, 'birth_date', event.target.value);
|
||||
}}
|
||||
required
|
||||
errorMsg={getError(index, 'birth_date') || getLocalError(index, 'birth_date')}
|
||||
errorMsg={
|
||||
getError(index, 'birth_date') ||
|
||||
getLocalError(index, 'birth_date')
|
||||
}
|
||||
/>
|
||||
<InputText
|
||||
name="professionResponsable"
|
||||
@ -153,7 +179,10 @@ export default function ResponsableInputFields({
|
||||
onGuardiansChange(item.id, 'profession', event.target.value);
|
||||
}}
|
||||
required
|
||||
errorMsg={getError(index, 'profession') || getLocalError(index, 'profession')}
|
||||
errorMsg={
|
||||
getError(index, 'profession') ||
|
||||
getLocalError(index, 'profession')
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -167,7 +196,9 @@ export default function ResponsableInputFields({
|
||||
onGuardiansChange(item.id, 'address', event.target.value);
|
||||
}}
|
||||
required
|
||||
errorMsg={getError(index, 'address') || getLocalError(index, 'address')}
|
||||
errorMsg={
|
||||
getError(index, 'address') || getLocalError(index, 'address')
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -2,9 +2,7 @@ import React, { useState, useEffect } from 'react';
|
||||
import InputText from '@/components/InputText';
|
||||
import SelectChoice from '@/components/SelectChoice';
|
||||
import Loader from '@/components/Loader';
|
||||
import {
|
||||
fetchRegisterForm
|
||||
} from '@/app/actions/subscriptionAction';
|
||||
import { fetchRegisterForm } from '@/app/actions/subscriptionAction';
|
||||
import logger from '@/utils/logger';
|
||||
import SectionHeader from '@/components/SectionHeader';
|
||||
import { User } from 'lucide-react';
|
||||
@ -29,9 +27,8 @@ export default function StudentInfoForm({
|
||||
errors,
|
||||
setIsPageValid,
|
||||
hasInteracted,
|
||||
setHasInteracted
|
||||
setHasInteracted,
|
||||
}) {
|
||||
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
@ -59,14 +56,15 @@ export default function StudentInfoForm({
|
||||
});
|
||||
|
||||
setIsLoading(false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [studentId, hasInteracted]);
|
||||
|
||||
useEffect(() => {
|
||||
const isValid = !Object.keys(formData).some((field) => getLocalError(field) !== '');
|
||||
const isValid = !Object.keys(formData).some(
|
||||
(field) => getLocalError(field) !== ''
|
||||
);
|
||||
setIsPageValid(isValid);
|
||||
}, [formData, hasInteracted, setIsPageValid]);
|
||||
|
||||
@ -77,15 +75,26 @@ export default function StudentInfoForm({
|
||||
const getLocalError = (field) => {
|
||||
if (
|
||||
// Student Form
|
||||
( field === 'last_name' && (!formData.last_name || formData.last_name.trim() === '') ) ||
|
||||
( field === 'first_name' && (!formData.first_name || formData.first_name.trim() === '') ) ||
|
||||
( field === 'nationality' && (!formData.nationality || formData.nationality.trim() === '') ) ||
|
||||
( field === 'birth_date' && (!formData.birth_date || formData.birth_date.trim() === '') ) ||
|
||||
( field === 'birth_place' && (!formData.birth_place || formData.birth_place.trim() === '') ) ||
|
||||
( field === 'birth_postal_code' && (!formData.birth_postal_code || String(formData.birth_postal_code).trim() === '') ) ||
|
||||
( field === 'address' && (!formData.address || formData.address.trim() === '') ) ||
|
||||
( field === 'attending_physician' && (!formData.attending_physician || formData.attending_physician.trim() === '') ) ||
|
||||
( field === 'level' && (!formData.level || String(formData.level).trim() === '') )
|
||||
(field === 'last_name' &&
|
||||
(!formData.last_name || formData.last_name.trim() === '')) ||
|
||||
(field === 'first_name' &&
|
||||
(!formData.first_name || formData.first_name.trim() === '')) ||
|
||||
(field === 'nationality' &&
|
||||
(!formData.nationality || formData.nationality.trim() === '')) ||
|
||||
(field === 'birth_date' &&
|
||||
(!formData.birth_date || formData.birth_date.trim() === '')) ||
|
||||
(field === 'birth_place' &&
|
||||
(!formData.birth_place || formData.birth_place.trim() === '')) ||
|
||||
(field === 'birth_postal_code' &&
|
||||
(!formData.birth_postal_code ||
|
||||
String(formData.birth_postal_code).trim() === '')) ||
|
||||
(field === 'address' &&
|
||||
(!formData.address || formData.address.trim() === '')) ||
|
||||
(field === 'attending_physician' &&
|
||||
(!formData.attending_physician ||
|
||||
formData.attending_physician.trim() === '')) ||
|
||||
(field === 'level' &&
|
||||
(!formData.level || String(formData.level).trim() === ''))
|
||||
) {
|
||||
return 'Champs requis';
|
||||
}
|
||||
@ -158,11 +167,12 @@ export default function StudentInfoForm({
|
||||
name="birth_postal_code"
|
||||
label="Code Postal de Naissance"
|
||||
value={formData.birth_postal_code}
|
||||
onChange={(e) =>
|
||||
onChange('birth_postal_code', e.target.value)
|
||||
}
|
||||
onChange={(e) => onChange('birth_postal_code', e.target.value)}
|
||||
required
|
||||
errorMsg={getError('birth_postal_code') || getLocalError('birth_postal_code')}
|
||||
errorMsg={
|
||||
getError('birth_postal_code') ||
|
||||
getLocalError('birth_postal_code')
|
||||
}
|
||||
/>
|
||||
<div className="md:col-span-2">
|
||||
<InputText
|
||||
@ -178,11 +188,12 @@ export default function StudentInfoForm({
|
||||
name="attending_physician"
|
||||
label="Médecin Traitant"
|
||||
value={formData.attending_physician}
|
||||
onChange={(e) =>
|
||||
onChange('attending_physician', e.target.value)
|
||||
}
|
||||
onChange={(e) => onChange('attending_physician', e.target.value)}
|
||||
required
|
||||
errorMsg={getError('attending_physician') || getLocalError('attending_physician')}
|
||||
errorMsg={
|
||||
getError('attending_physician') ||
|
||||
getLocalError('attending_physician')
|
||||
}
|
||||
/>
|
||||
<SelectChoice
|
||||
name="level"
|
||||
|
||||
@ -4,7 +4,10 @@ import Button from '@/components/Button';
|
||||
import ToggleSwitch from '@/components/ToggleSwitch'; // Import du composant ToggleSwitch
|
||||
import { BASE_URL } from '@/utils/Url';
|
||||
import { generateToken } from '@/app/actions/registerFileGroupAction';
|
||||
import { fetchSchoolFileTemplatesFromRegistrationFiles, fetchParentFileTemplatesFromRegistrationFiles } from '@/app/actions/subscriptionAction';
|
||||
import {
|
||||
fetchSchoolFileTemplatesFromRegistrationFiles,
|
||||
fetchParentFileTemplatesFromRegistrationFiles,
|
||||
} from '@/app/actions/subscriptionAction';
|
||||
import logger from '@/utils/logger';
|
||||
import { GraduationCap } from 'lucide-react';
|
||||
import FileUpload from '@/components/FileUpload';
|
||||
@ -47,7 +50,12 @@ export default function ValidateSubscription({
|
||||
setSchoolFileTemplates(data);
|
||||
logger.debug('Fichiers schoolFileTemplates récupérés:', data);
|
||||
})
|
||||
.catch((error) => logger.error('Erreur lors de la récupération des schoolFileTemplates:', error));
|
||||
.catch((error) =>
|
||||
logger.error(
|
||||
'Erreur lors de la récupération des schoolFileTemplates:',
|
||||
error
|
||||
)
|
||||
);
|
||||
|
||||
// Récupérer les fichiers parentFileTemplates pour l'étudiant
|
||||
fetchParentFileTemplatesFromRegistrationFiles(studentId)
|
||||
@ -55,7 +63,12 @@ export default function ValidateSubscription({
|
||||
setParentFileTemplates(data);
|
||||
logger.debug('Fichiers parentFileTemplates récupérés:', data);
|
||||
})
|
||||
.catch((error) => logger.error('Erreur lors de la récupération des parentFileTemplates:', error));
|
||||
.catch((error) =>
|
||||
logger.error(
|
||||
'Erreur lors de la récupération des parentFileTemplates:',
|
||||
error
|
||||
)
|
||||
);
|
||||
}, [studentId]);
|
||||
|
||||
const handleAccept = () => {
|
||||
@ -63,16 +76,16 @@ export default function ValidateSubscription({
|
||||
logger.error('Aucun fichier sélectionné pour le champ SEPA.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Ajouter le paramètre fusion dans l'URL
|
||||
const fusionParam = mergeDocuments ? 'true' : 'false';
|
||||
|
||||
|
||||
const data = {
|
||||
status: 7,
|
||||
sepa_file: selectedFile, // Utilise le fichier sélectionné depuis l'état
|
||||
fusionParam: fusionParam
|
||||
fusionParam: fusionParam,
|
||||
};
|
||||
|
||||
|
||||
// Appeler la fonction passée par le parent pour mettre à jour le RF
|
||||
onAccept(data);
|
||||
};
|
||||
@ -85,7 +98,11 @@ export default function ValidateSubscription({
|
||||
const isValidateButtonDisabled = isSepa && !uploadedFileName;
|
||||
|
||||
const goToNextPage = () => {
|
||||
const totalPages = 1 + schoolFileTemplates.length + parentFileTemplates.length + (isSepa ? 1 : 0);
|
||||
const totalPages =
|
||||
1 +
|
||||
schoolFileTemplates.length +
|
||||
parentFileTemplates.length +
|
||||
(isSepa ? 1 : 0);
|
||||
if (currentPage < totalPages) {
|
||||
setCurrentPage(currentPage + 1);
|
||||
}
|
||||
@ -97,7 +114,11 @@ export default function ValidateSubscription({
|
||||
}
|
||||
};
|
||||
|
||||
const totalPages = 1 + schoolFileTemplates.length + parentFileTemplates.length + (isSepa ? 1 : 0);
|
||||
const totalPages =
|
||||
1 +
|
||||
schoolFileTemplates.length +
|
||||
parentFileTemplates.length +
|
||||
(isSepa ? 1 : 0);
|
||||
|
||||
const renderContent = () => {
|
||||
if (currentPage === 1) {
|
||||
@ -114,7 +135,10 @@ export default function ValidateSubscription({
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (currentPage > 1 && currentPage <= 1 + schoolFileTemplates.length) {
|
||||
} else if (
|
||||
currentPage > 1 &&
|
||||
currentPage <= 1 + schoolFileTemplates.length
|
||||
) {
|
||||
// Pages des schoolFileTemplates
|
||||
const index = currentPage - 2; // Décalage pour correspondre à l'index du tableau
|
||||
return (
|
||||
@ -129,7 +153,10 @@ export default function ValidateSubscription({
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (currentPage > 1 + schoolFileTemplates.length && currentPage <= 1 + schoolFileTemplates.length + parentFileTemplates.length) {
|
||||
} else if (
|
||||
currentPage > 1 + schoolFileTemplates.length &&
|
||||
currentPage <= 1 + schoolFileTemplates.length + parentFileTemplates.length
|
||||
) {
|
||||
// Pages des parentFileTemplates
|
||||
const index = currentPage - 2 - schoolFileTemplates.length; // Décalage pour correspondre à l'index du tableau
|
||||
return (
|
||||
@ -175,7 +202,9 @@ export default function ValidateSubscription({
|
||||
{/* Option de fusion des documents (affichée uniquement sur la dernière page) */}
|
||||
{currentPage === totalPages && (
|
||||
<div className="flex items-center justify-between mt-6">
|
||||
<span className="text-gray-700">Fusionner les documents en un seul fichier PDF</span>
|
||||
<span className="text-gray-700">
|
||||
Fusionner les documents en un seul fichier PDF
|
||||
</span>
|
||||
<ToggleSwitch
|
||||
label="Fusionner"
|
||||
checked={mergeDocuments}
|
||||
|
||||
Reference in New Issue
Block a user