mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
286 lines
9.7 KiB
JavaScript
286 lines
9.7 KiB
JavaScript
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 logger from '@/utils/logger';
|
|
import SectionHeader from '@/components/SectionHeader';
|
|
import { User } from 'lucide-react';
|
|
import FileUpload from '@/components/FileUpload';
|
|
import { BASE_URL } from '@/utils/Url';
|
|
import { levels, genders } from '@/utils/constants';
|
|
|
|
export default function StudentInfoForm({
|
|
studentId,
|
|
formData,
|
|
setFormData,
|
|
setGuardians,
|
|
setSiblings,
|
|
errors,
|
|
setIsPageValid,
|
|
hasInteracted,
|
|
setHasInteracted,
|
|
enable = true,
|
|
}) {
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
if (studentId && !hasInteracted) {
|
|
fetchRegisterForm(studentId).then((data) => {
|
|
logger.debug(data);
|
|
|
|
const photoPath = data?.student?.photo || null;
|
|
|
|
setFormData({
|
|
id: data?.student?.id || '',
|
|
photo: photoPath,
|
|
last_name: data?.student?.last_name || '',
|
|
first_name: data?.student?.first_name || '',
|
|
gender: data?.student?.gender || '',
|
|
address: data?.student?.address || '',
|
|
birth_date: data?.student?.birth_date || '',
|
|
birth_place: data?.student?.birth_place || '',
|
|
birth_postal_code: data?.student?.birth_postal_code || '',
|
|
nationality: data?.student?.nationality || '',
|
|
attending_physician: data?.student?.attending_physician || '',
|
|
level: data?.student?.level || '',
|
|
registration_payment: data?.registration_payment || '',
|
|
tuition_payment: data?.tuition_payment || '',
|
|
registration_payment_plan: data?.registration_payment_plan || '',
|
|
tuition_payment_plan: data?.tuition_payment_plan || '',
|
|
totalRegistrationFees: data?.totalRegistrationFees,
|
|
totalTuitionFees: data?.totalTuitionFees,
|
|
});
|
|
|
|
setGuardians(data?.student?.guardians || []);
|
|
setSiblings(data?.student?.siblings || []);
|
|
|
|
// Convertir la photo en fichier binaire si elle est un chemin ou une URL
|
|
if (photoPath && typeof photoPath === 'string') {
|
|
fetch(`${BASE_URL}${photoPath}`)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error('Erreur lors de la récupération de la photo.');
|
|
}
|
|
return response.blob();
|
|
})
|
|
.then((blob) => {
|
|
const file = new File([blob], photoPath.split('/').pop(), {
|
|
type: blob.type,
|
|
});
|
|
handlePhotoUpload(file); // Utiliser handlePhotoUpload pour valoriser la photo
|
|
})
|
|
.catch((error) => {
|
|
logger.error('Erreur lors de la conversion de la photo :', error);
|
|
});
|
|
}
|
|
});
|
|
|
|
setIsLoading(false);
|
|
} else {
|
|
setIsLoading(false);
|
|
}
|
|
}, [studentId, hasInteracted]);
|
|
|
|
useEffect(() => {
|
|
const isValid = !Object.keys(formData).some(
|
|
(field) => getLocalError(field) !== ''
|
|
);
|
|
setIsPageValid(isValid);
|
|
}, [formData, hasInteracted, setIsPageValid]);
|
|
|
|
const getError = (field) => {
|
|
return errors?.student?.[field]?.[0];
|
|
};
|
|
|
|
const getLocalError = (field) => {
|
|
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
if (
|
|
// Student Form
|
|
(field === 'last_name' &&
|
|
(!formData.last_name || formData.last_name.trim() === '')) ||
|
|
(field === 'first_name' &&
|
|
(!formData.first_name || formData.first_name.trim() === '')) ||
|
|
(field === 'gender' &&
|
|
(!formData.gender || String(formData.gender).trim() === '')) ||
|
|
(field === 'nationality' &&
|
|
(!formData.nationality || formData.nationality.trim() === '')) ||
|
|
(field === 'birth_date' &&
|
|
(!formData.birth_date ||
|
|
formData.birth_date.trim() === '' ||
|
|
!dateRegex.test(formData.birth_date))) ||
|
|
(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';
|
|
}
|
|
return '';
|
|
};
|
|
|
|
const onChange = (field, value) => {
|
|
setFormData((prev) => ({ ...prev, [field]: value }));
|
|
|
|
// Marquer que l'utilisateur a interagi avec le formulaire
|
|
if (!hasInteracted) {
|
|
setHasInteracted(true);
|
|
}
|
|
};
|
|
|
|
const handlePhotoUpload = (file) => {
|
|
if (file) {
|
|
setFormData((prev) => ({
|
|
...prev,
|
|
photo: file,
|
|
}));
|
|
logger.debug('Photo sélectionnée :', file.name);
|
|
}
|
|
};
|
|
|
|
// Affichage du loader pendant le chargement
|
|
if (isLoading) return <Loader />;
|
|
|
|
return (
|
|
<>
|
|
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200 space-y-8">
|
|
<SectionHeader
|
|
icon={User}
|
|
title={"Informations de l'élève"}
|
|
description={'Remplissez les champs requis'}
|
|
/>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
<InputText
|
|
name="last_name"
|
|
label="Nom"
|
|
value={formData.last_name}
|
|
onChange={(e) => onChange('last_name', e.target.value)}
|
|
required
|
|
errorMsg={getError('last_name')}
|
|
errorLocalMsg={getLocalError('last_name')}
|
|
enable={enable}
|
|
/>
|
|
<InputText
|
|
name="first_name"
|
|
label="Prénom"
|
|
value={formData.first_name}
|
|
onChange={(e) => onChange('first_name', e.target.value)}
|
|
errorMsg={getError('first_name')}
|
|
errorLocalMsg={getLocalError('first_name')}
|
|
required
|
|
enable={enable}
|
|
/>
|
|
<SelectChoice
|
|
name="gender"
|
|
label="Genre"
|
|
placeHolder="Sélectionner un genre"
|
|
selected={formData.gender}
|
|
callback={(e) => onChange('gender', e.target.value)}
|
|
choices={genders}
|
|
required
|
|
errorMsg={getError('gender')}
|
|
errorLocalMsg={getLocalError('gender')}
|
|
disabled={!enable}
|
|
/>
|
|
</div>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
<InputText
|
|
name="birth_date"
|
|
type="date"
|
|
label="Date de Naissance"
|
|
value={formData.birth_date}
|
|
onChange={(e) => onChange('birth_date', e.target.value)}
|
|
required
|
|
errorMsg={getError('birth_date')}
|
|
errorLocalMsg={getLocalError('birth_date')}
|
|
enable={enable}
|
|
/>
|
|
<InputText
|
|
name="birth_place"
|
|
label="Lieu de Naissance"
|
|
value={formData.birth_place}
|
|
onChange={(e) => onChange('birth_place', e.target.value)}
|
|
required
|
|
errorMsg={getError('birth_place')}
|
|
errorLocalMsg={getLocalError('birth_place')}
|
|
enable={enable}
|
|
/>
|
|
<InputText
|
|
name="birth_postal_code"
|
|
label="Code Postal de Naissance"
|
|
value={formData.birth_postal_code}
|
|
onChange={(e) => onChange('birth_postal_code', e.target.value)}
|
|
required
|
|
errorMsg={getError('birth_postal_code')}
|
|
errorLocalMsg={getLocalError('birth_postal_code')}
|
|
enable={enable}
|
|
/>
|
|
</div>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
<InputText
|
|
name="nationality"
|
|
label="Nationalité"
|
|
value={formData.nationality}
|
|
required
|
|
onChange={(e) => onChange('nationality', e.target.value)}
|
|
errorMsg={getError('nationality')}
|
|
errorLocalMsg={getLocalError('nationality')}
|
|
enable={enable}
|
|
/>
|
|
<InputText
|
|
name="address"
|
|
label="Adresse"
|
|
value={formData.address}
|
|
onChange={(e) => onChange('address', e.target.value)}
|
|
required
|
|
errorMsg={getError('address')}
|
|
errorLocalMsg={getLocalError('address')}
|
|
enable={enable}
|
|
/>
|
|
</div>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
<InputText
|
|
name="attending_physician"
|
|
label="Médecin Traitant"
|
|
value={formData.attending_physician}
|
|
onChange={(e) => onChange('attending_physician', e.target.value)}
|
|
required
|
|
errorMsg={getError('attending_physician')}
|
|
errorLocalMsg={getLocalError('attending_physician')}
|
|
enable={enable}
|
|
/>
|
|
<SelectChoice
|
|
name="level"
|
|
label="Niveau"
|
|
placeHolder="Sélectionner un niveau"
|
|
selected={formData.level}
|
|
callback={(e) => onChange('level', e.target.value)}
|
|
choices={levels}
|
|
required
|
|
errorMsg={getError('level')}
|
|
errorLocalMsg={getLocalError('level')}
|
|
disabled={!enable}
|
|
/>
|
|
</div>
|
|
<div className="grid grid-cols-1 md:grid-cols-1 gap-8">
|
|
<FileUpload
|
|
selectionMessage="Sélectionnez une photo"
|
|
onFileSelect={(file) => handlePhotoUpload(file)}
|
|
existingFile={formData.photo}
|
|
errorMsg={getError('photo')}
|
|
enable={enable}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|