mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Ajout de la fratrie / Gestion des index de fratrie / Gestion des
required
This commit is contained in:
@ -40,7 +40,6 @@ class Sibling(models.Model):
|
|||||||
"""
|
"""
|
||||||
Représente un frère ou une sœur d’un élève.
|
Représente un frère ou une sœur d’un élève.
|
||||||
"""
|
"""
|
||||||
id = models.AutoField(primary_key=True)
|
|
||||||
last_name = models.CharField(max_length=200, default="")
|
last_name = models.CharField(max_length=200, default="")
|
||||||
first_name = models.CharField(max_length=200, default="")
|
first_name = models.CharField(max_length=200, default="")
|
||||||
birth_date = models.DateField(null=True, blank=True)
|
birth_date = models.DateField(null=True, blank=True)
|
||||||
|
|||||||
@ -231,7 +231,6 @@ class RegisterFormWithIdView(APIView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
studentForm_data = request.data.get('data', '{}')
|
studentForm_data = request.data.get('data', '{}')
|
||||||
print(f'studentForm_data : {studentForm_data}')
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(studentForm_data)
|
data = json.loads(studentForm_data)
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export default function InputText({
|
|||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
errorMsg,
|
errorMsg,
|
||||||
|
errorLocalMsg,
|
||||||
placeholder,
|
placeholder,
|
||||||
className,
|
className,
|
||||||
required,
|
required,
|
||||||
@ -20,7 +21,11 @@ export default function InputText({
|
|||||||
{required && <span className="text-red-500 ml-1">*</span>}
|
{required && <span className="text-red-500 ml-1">*</span>}
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
className={`mt-1 flex items-center border border-gray-200 rounded-md ${errorMsg ? 'border-red-500' : ''} hover:border-gray-400 focus-within:border-gray-500`}
|
className={`mt-1 flex items-center border rounded-md ${
|
||||||
|
errorMsg || errorLocalMsg
|
||||||
|
? 'border-red-500 hover:border-red-700'
|
||||||
|
: 'border-gray-200 hover:border-gray-400'
|
||||||
|
} ${!errorMsg && !errorLocalMsg ? 'focus-within:border-gray-500' : ''}`}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type={type}
|
type={type}
|
||||||
|
|||||||
@ -49,6 +49,7 @@ export default function InscriptionFormShared({
|
|||||||
photo: null,
|
photo: null,
|
||||||
last_name: '',
|
last_name: '',
|
||||||
first_name: '',
|
first_name: '',
|
||||||
|
gender: '',
|
||||||
address: '',
|
address: '',
|
||||||
birth_date: '',
|
birth_date: '',
|
||||||
birth_place: '',
|
birth_place: '',
|
||||||
@ -370,14 +371,18 @@ export default function InscriptionFormShared({
|
|||||||
|
|
||||||
// Vérifier si le mode de paiement sélectionné est un prélèvement SEPA
|
// Vérifier si le mode de paiement sélectionné est un prélèvement SEPA
|
||||||
const isSepaPayment =
|
const isSepaPayment =
|
||||||
formData.registration_payment === '1' || formData.tuition_payment === '1';
|
formData.registration_payment === 1 || formData.tuition_payment === 1;
|
||||||
|
|
||||||
// Préparer les données JSON
|
// Préparer les données JSON
|
||||||
const jsonData = {
|
const jsonData = {
|
||||||
student: {
|
student: {
|
||||||
...formData,
|
...formData,
|
||||||
guardians: guardians,
|
guardians: guardians,
|
||||||
siblings: siblings,
|
siblings: siblings.map(({ id, ...rest }) =>
|
||||||
|
id && typeof id === 'string' && id.startsWith('temp-')
|
||||||
|
? rest
|
||||||
|
: { id, ...rest }
|
||||||
|
), // Supprimer les IDs temporaires
|
||||||
},
|
},
|
||||||
establishment: selectedEstablishmentId,
|
establishment: selectedEstablishmentId,
|
||||||
status: isSepaPayment ? 8 : 3,
|
status: isSepaPayment ? 8 : 3,
|
||||||
@ -398,6 +403,8 @@ export default function InscriptionFormShared({
|
|||||||
formDataToSend.append('photo', formData.photo);
|
formDataToSend.append('photo', formData.photo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('submit : ', jsonData);
|
||||||
|
|
||||||
// Appeler la fonction onSubmit avec les données FormData
|
// Appeler la fonction onSubmit avec les données FormData
|
||||||
onSubmit(formDataToSend);
|
onSubmit(formDataToSend);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -82,18 +82,18 @@ export default function PaymentMethodSelector({
|
|||||||
label="Mode de Paiement"
|
label="Mode de Paiement"
|
||||||
placeHolder="Sélectionner un mode de paiement"
|
placeHolder="Sélectionner un mode de paiement"
|
||||||
selected={formData.registration_payment}
|
selected={formData.registration_payment}
|
||||||
callback={(e) => onChange('registration_payment', e.target.value)}
|
callback={(e) =>
|
||||||
|
onChange('registration_payment', parseInt(e.target.value, 10))
|
||||||
|
}
|
||||||
choices={registrationPaymentModes.map((mode) => ({
|
choices={registrationPaymentModes.map((mode) => ({
|
||||||
value: mode.mode,
|
value: mode.mode,
|
||||||
label:
|
label:
|
||||||
paymentModesOptions.find((option) => option.id === mode.mode)
|
paymentModesOptions.find((option) => option.id === mode.mode)
|
||||||
?.name || 'Mode inconnu',
|
?.name || 'Mode inconnu',
|
||||||
}))}
|
}))}
|
||||||
|
errorMsg={getError('registration_payment')}
|
||||||
|
errorLocalMsg={getLocalError('registration_payment')}
|
||||||
required
|
required
|
||||||
errorMsg={
|
|
||||||
getError('registration_payment') ||
|
|
||||||
getLocalError('registration_payment')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<RadioList
|
<RadioList
|
||||||
@ -143,17 +143,18 @@ export default function PaymentMethodSelector({
|
|||||||
label="Mode de Paiement"
|
label="Mode de Paiement"
|
||||||
placeHolder="Sélectionner un mode de paiement"
|
placeHolder="Sélectionner un mode de paiement"
|
||||||
selected={formData.tuition_payment}
|
selected={formData.tuition_payment}
|
||||||
callback={(e) => onChange('tuition_payment', e.target.value)}
|
callback={(e) =>
|
||||||
|
onChange('tuition_payment', parseInt(e.target.value, 10))
|
||||||
|
}
|
||||||
choices={tuitionPaymentModes.map((mode) => ({
|
choices={tuitionPaymentModes.map((mode) => ({
|
||||||
value: mode.mode,
|
value: mode.mode,
|
||||||
label:
|
label:
|
||||||
paymentModesOptions.find((option) => option.id === mode.mode)
|
paymentModesOptions.find((option) => option.id === mode.mode)
|
||||||
?.name || 'Mode inconnu',
|
?.name || 'Mode inconnu',
|
||||||
}))}
|
}))}
|
||||||
|
errorMsg={getError('tuition_payment')}
|
||||||
|
errorLocalMsg={getLocalError('tuition_payment')}
|
||||||
required
|
required
|
||||||
errorMsg={
|
|
||||||
getError('tuition_payment') || getLocalError('tuition_payment')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<RadioList
|
<RadioList
|
||||||
@ -167,7 +168,10 @@ export default function PaymentMethodSelector({
|
|||||||
label: option.name,
|
label: option.name,
|
||||||
}))}
|
}))}
|
||||||
formData={formData}
|
formData={formData}
|
||||||
handleChange={(e) => onChange('tuition_payment_plan', e.target.value)}
|
handleChange={(e) => {
|
||||||
|
const value = parseInt(e.target.value, 10);
|
||||||
|
onChange('tuition_payment_plan', value); // Convertir la valeur en entier
|
||||||
|
}}
|
||||||
fieldName="tuition_payment_plan"
|
fieldName="tuition_payment_plan"
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
errorMsg={
|
errorMsg={
|
||||||
|
|||||||
@ -33,6 +33,7 @@ export default function ResponsableInputFields({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getLocalError = (index, field) => {
|
const getLocalError = (index, field) => {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
if (
|
if (
|
||||||
// Student Form
|
// Student Form
|
||||||
(field === 'last_name' &&
|
(field === 'last_name' &&
|
||||||
@ -43,7 +44,8 @@ export default function ResponsableInputFields({
|
|||||||
guardians[index].first_name.trim() === '')) ||
|
guardians[index].first_name.trim() === '')) ||
|
||||||
(field === 'associated_profile_email' &&
|
(field === 'associated_profile_email' &&
|
||||||
(!guardians[index].associated_profile_email ||
|
(!guardians[index].associated_profile_email ||
|
||||||
guardians[index].associated_profile_email.trim() === '')) ||
|
guardians[index].associated_profile_email.trim() === '' ||
|
||||||
|
!emailRegex.test(guardians[index].associated_profile_email))) ||
|
||||||
(field === 'birth_date' &&
|
(field === 'birth_date' &&
|
||||||
(!guardians[index].birth_date ||
|
(!guardians[index].birth_date ||
|
||||||
guardians[index].birth_date.trim() === '')) ||
|
guardians[index].birth_date.trim() === '')) ||
|
||||||
@ -138,10 +140,8 @@ export default function ResponsableInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onGuardiansChange(item.id, 'last_name', event.target.value);
|
onGuardiansChange(item.id, 'last_name', event.target.value);
|
||||||
}}
|
}}
|
||||||
errorMsg={
|
errorMsg={getError('last_name')}
|
||||||
getError(index, 'last_name') ||
|
errorLocalMsg={getLocalError(index, 'last_name')}
|
||||||
getLocalError(index, 'last_name')
|
|
||||||
}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<InputText
|
<InputText
|
||||||
@ -152,10 +152,8 @@ export default function ResponsableInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onGuardiansChange(item.id, 'first_name', event.target.value);
|
onGuardiansChange(item.id, 'first_name', event.target.value);
|
||||||
}}
|
}}
|
||||||
errorMsg={
|
errorMsg={getError('first_name')}
|
||||||
getError(index, 'first_name') ||
|
errorLocalMsg={getLocalError(index, 'first_name')}
|
||||||
getLocalError(index, 'first_name')
|
|
||||||
}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -173,11 +171,9 @@ export default function ResponsableInputFields({
|
|||||||
event.target.value
|
event.target.value
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
errorMsg={getError('associated_profile_email')}
|
||||||
|
errorLocalMsg={getLocalError(index, 'associated_profile_email')}
|
||||||
required
|
required
|
||||||
errorMsg={
|
|
||||||
getError(index, 'associated_profile_email') ||
|
|
||||||
getLocalError(index, 'associated_profile_email')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<InputPhone
|
<InputPhone
|
||||||
name="telephoneResponsable"
|
name="telephoneResponsable"
|
||||||
@ -186,8 +182,9 @@ export default function ResponsableInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onGuardiansChange(item.id, 'phone', event.target.value);
|
onGuardiansChange(item.id, 'phone', event.target.value);
|
||||||
}}
|
}}
|
||||||
|
errorMsg={getError('phone')}
|
||||||
|
errorLocalMsg={getLocalError(index, 'phone')}
|
||||||
required
|
required
|
||||||
errorMsg={getError(index, 'phone')}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -200,11 +197,9 @@ export default function ResponsableInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onGuardiansChange(item.id, 'birth_date', event.target.value);
|
onGuardiansChange(item.id, 'birth_date', event.target.value);
|
||||||
}}
|
}}
|
||||||
|
errorMsg={getError('birth_date')}
|
||||||
|
errorLocalMsg={getLocalError(index, 'birth_date')}
|
||||||
required
|
required
|
||||||
errorMsg={
|
|
||||||
getError(index, 'birth_date') ||
|
|
||||||
getLocalError(index, 'birth_date')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<InputText
|
<InputText
|
||||||
name="professionResponsable"
|
name="professionResponsable"
|
||||||
@ -214,11 +209,9 @@ export default function ResponsableInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onGuardiansChange(item.id, 'profession', event.target.value);
|
onGuardiansChange(item.id, 'profession', event.target.value);
|
||||||
}}
|
}}
|
||||||
|
errorMsg={getError('profession')}
|
||||||
|
errorLocalMsg={getLocalError(index, 'profession')}
|
||||||
required
|
required
|
||||||
errorMsg={
|
|
||||||
getError(index, 'profession') ||
|
|
||||||
getLocalError(index, 'profession')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -231,10 +224,9 @@ export default function ResponsableInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onGuardiansChange(item.id, 'address', event.target.value);
|
onGuardiansChange(item.id, 'address', event.target.value);
|
||||||
}}
|
}}
|
||||||
|
errorMsg={getError('address')}
|
||||||
|
errorLocalMsg={getLocalError(index, 'address')}
|
||||||
required
|
required
|
||||||
errorMsg={
|
|
||||||
getError(index, 'address') || getLocalError(index, 'address')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import InputText from '@/components/InputText';
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Trash2, Plus, Users } from 'lucide-react';
|
import { Trash2, Plus, Users } from 'lucide-react';
|
||||||
import SectionHeader from '@/components/SectionHeader';
|
import SectionHeader from '@/components/SectionHeader';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
export default function SiblingInputFields({
|
export default function SiblingInputFields({
|
||||||
siblings,
|
siblings,
|
||||||
@ -67,6 +68,7 @@ export default function SiblingInputFields({
|
|||||||
setSiblings([
|
setSiblings([
|
||||||
...siblings,
|
...siblings,
|
||||||
{
|
{
|
||||||
|
id: `temp-${uuidv4()}`,
|
||||||
last_name: '',
|
last_name: '',
|
||||||
first_name: '',
|
first_name: '',
|
||||||
birth_date: '',
|
birth_date: '',
|
||||||
@ -105,10 +107,8 @@ export default function SiblingInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onSiblingsChange(item.id, 'last_name', event.target.value);
|
onSiblingsChange(item.id, 'last_name', event.target.value);
|
||||||
}}
|
}}
|
||||||
errorMsg={
|
errorMsg={getError('last_name')}
|
||||||
getError(index, 'last_name') ||
|
errorLocalMsg={getLocalError(index, 'last_name')}
|
||||||
getLocalError(index, 'last_name')
|
|
||||||
}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<InputText
|
<InputText
|
||||||
@ -119,10 +119,8 @@ export default function SiblingInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onSiblingsChange(item.id, 'first_name', event.target.value);
|
onSiblingsChange(item.id, 'first_name', event.target.value);
|
||||||
}}
|
}}
|
||||||
errorMsg={
|
errorMsg={getError('first_name')}
|
||||||
getError(index, 'first_name') ||
|
errorLocalMsg={getLocalError(index, 'first_name')}
|
||||||
getLocalError(index, 'first_name')
|
|
||||||
}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -136,10 +134,8 @@ export default function SiblingInputFields({
|
|||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
onSiblingsChange(item.id, 'birth_date', event.target.value);
|
onSiblingsChange(item.id, 'birth_date', event.target.value);
|
||||||
}}
|
}}
|
||||||
errorMsg={
|
errorMsg={getError('birth_date')}
|
||||||
getError(index, 'birth_date') ||
|
errorLocalMsg={getLocalError(index, 'birth_date')}
|
||||||
getLocalError(index, 'birth_date')
|
|
||||||
}
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -21,6 +21,11 @@ const levels = [
|
|||||||
{ value: '9', label: 'CM2' },
|
{ value: '9', label: 'CM2' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const genders = [
|
||||||
|
{ value: '1', label: 'Garçon' },
|
||||||
|
{ value: '2', label: 'Fille' },
|
||||||
|
];
|
||||||
|
|
||||||
export default function StudentInfoForm({
|
export default function StudentInfoForm({
|
||||||
studentId,
|
studentId,
|
||||||
formData,
|
formData,
|
||||||
@ -46,6 +51,7 @@ export default function StudentInfoForm({
|
|||||||
photo: photoPath,
|
photo: photoPath,
|
||||||
last_name: data?.student?.last_name || '',
|
last_name: data?.student?.last_name || '',
|
||||||
first_name: data?.student?.first_name || '',
|
first_name: data?.student?.first_name || '',
|
||||||
|
gender: data?.student?.gender || '',
|
||||||
address: data?.student?.address || '',
|
address: data?.student?.address || '',
|
||||||
birth_date: data?.student?.birth_date || '',
|
birth_date: data?.student?.birth_date || '',
|
||||||
birth_place: data?.student?.birth_place || '',
|
birth_place: data?.student?.birth_place || '',
|
||||||
@ -109,6 +115,8 @@ export default function StudentInfoForm({
|
|||||||
(!formData.last_name || formData.last_name.trim() === '')) ||
|
(!formData.last_name || formData.last_name.trim() === '')) ||
|
||||||
(field === 'first_name' &&
|
(field === 'first_name' &&
|
||||||
(!formData.first_name || formData.first_name.trim() === '')) ||
|
(!formData.first_name || formData.first_name.trim() === '')) ||
|
||||||
|
(field === 'gender' &&
|
||||||
|
(!formData.gender || String(formData.gender).trim() === '')) ||
|
||||||
(field === 'nationality' &&
|
(field === 'nationality' &&
|
||||||
(!formData.nationality || formData.nationality.trim() === '')) ||
|
(!formData.nationality || formData.nationality.trim() === '')) ||
|
||||||
(field === 'birth_date' &&
|
(field === 'birth_date' &&
|
||||||
@ -124,8 +132,7 @@ export default function StudentInfoForm({
|
|||||||
(!formData.attending_physician ||
|
(!formData.attending_physician ||
|
||||||
formData.attending_physician.trim() === '')) ||
|
formData.attending_physician.trim() === '')) ||
|
||||||
(field === 'level' &&
|
(field === 'level' &&
|
||||||
(!formData.level || String(formData.level).trim() === '')) ||
|
(!formData.level || String(formData.level).trim() === ''))
|
||||||
(field === 'photo' && !formData.photo)
|
|
||||||
) {
|
) {
|
||||||
return 'Champs requis';
|
return 'Champs requis';
|
||||||
}
|
}
|
||||||
@ -156,37 +163,44 @@ export default function StudentInfoForm({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
|
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200 space-y-8">
|
||||||
<SectionHeader
|
<SectionHeader
|
||||||
icon={User}
|
icon={User}
|
||||||
title={`Informations de l'élève`}
|
title={`Informations de l'élève`}
|
||||||
description={`Remplissez les champs requis`}
|
description={`Remplissez les champs requis`}
|
||||||
/>
|
/>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||||
<InputText
|
<InputText
|
||||||
name="last_name"
|
name="last_name"
|
||||||
label="Nom"
|
label="Nom"
|
||||||
value={formData.last_name}
|
value={formData.last_name}
|
||||||
onChange={(e) => onChange('last_name', e.target.value)}
|
onChange={(e) => onChange('last_name', e.target.value)}
|
||||||
required
|
required
|
||||||
errorMsg={getError('last_name') || getLocalError('last_name')}
|
errorMsg={getError('last_name')}
|
||||||
|
errorLocalMsg={getLocalError('last_name')}
|
||||||
/>
|
/>
|
||||||
<InputText
|
<InputText
|
||||||
name="first_name"
|
name="first_name"
|
||||||
label="Prénom"
|
label="Prénom"
|
||||||
value={formData.first_name}
|
value={formData.first_name}
|
||||||
onChange={(e) => onChange('first_name', e.target.value)}
|
onChange={(e) => onChange('first_name', e.target.value)}
|
||||||
errorMsg={getError('first_name') || getLocalError('first_name')}
|
errorMsg={getError('first_name')}
|
||||||
|
errorLocalMsg={getLocalError('first_name')}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<InputText
|
<SelectChoice
|
||||||
name="nationality"
|
name="gender"
|
||||||
label="Nationalité"
|
label="Genre"
|
||||||
value={formData.nationality}
|
placeHolder="Sélectionner un genre"
|
||||||
|
selected={formData.gender}
|
||||||
|
callback={(e) => onChange('gender', e.target.value)}
|
||||||
|
choices={genders}
|
||||||
required
|
required
|
||||||
onChange={(e) => onChange('nationality', e.target.value)}
|
errorMsg={getError('gender')}
|
||||||
errorMsg={getError('nationality') || getLocalError('nationality')}
|
errorLocalMsg={getLocalError('gender')}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||||
<InputText
|
<InputText
|
||||||
name="birth_date"
|
name="birth_date"
|
||||||
type="date"
|
type="date"
|
||||||
@ -194,7 +208,8 @@ export default function StudentInfoForm({
|
|||||||
value={formData.birth_date}
|
value={formData.birth_date}
|
||||||
onChange={(e) => onChange('birth_date', e.target.value)}
|
onChange={(e) => onChange('birth_date', e.target.value)}
|
||||||
required
|
required
|
||||||
errorMsg={getError('birth_date') || getLocalError('birth_date')}
|
errorMsg={getError('birth_date')}
|
||||||
|
errorLocalMsg={getLocalError('birth_date')}
|
||||||
/>
|
/>
|
||||||
<InputText
|
<InputText
|
||||||
name="birth_place"
|
name="birth_place"
|
||||||
@ -202,7 +217,8 @@ export default function StudentInfoForm({
|
|||||||
value={formData.birth_place}
|
value={formData.birth_place}
|
||||||
onChange={(e) => onChange('birth_place', e.target.value)}
|
onChange={(e) => onChange('birth_place', e.target.value)}
|
||||||
required
|
required
|
||||||
errorMsg={getError('birth_place') || getLocalError('birth_place')}
|
errorMsg={getError('birth_place')}
|
||||||
|
errorLocalMsg={getLocalError('birth_place')}
|
||||||
/>
|
/>
|
||||||
<InputText
|
<InputText
|
||||||
name="birth_postal_code"
|
name="birth_postal_code"
|
||||||
@ -210,31 +226,39 @@ export default function StudentInfoForm({
|
|||||||
value={formData.birth_postal_code}
|
value={formData.birth_postal_code}
|
||||||
onChange={(e) => onChange('birth_postal_code', e.target.value)}
|
onChange={(e) => onChange('birth_postal_code', e.target.value)}
|
||||||
required
|
required
|
||||||
errorMsg={
|
errorMsg={getError('birth_postal_code')}
|
||||||
getError('birth_postal_code') ||
|
errorLocalMsg={getLocalError('birth_postal_code')}
|
||||||
getLocalError('birth_postal_code')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<div className="md:col-span-2">
|
</div>
|
||||||
<InputText
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
name="address"
|
<InputText
|
||||||
label="Adresse"
|
name="nationality"
|
||||||
value={formData.address}
|
label="Nationalité"
|
||||||
onChange={(e) => onChange('address', e.target.value)}
|
value={formData.nationality}
|
||||||
required
|
required
|
||||||
errorMsg={getError('address') || getLocalError('address')}
|
onChange={(e) => onChange('nationality', e.target.value)}
|
||||||
/>
|
errorMsg={getError('nationality')}
|
||||||
</div>
|
errorLocalMsg={getLocalError('nationality')}
|
||||||
|
/>
|
||||||
|
<InputText
|
||||||
|
name="address"
|
||||||
|
label="Adresse"
|
||||||
|
value={formData.address}
|
||||||
|
onChange={(e) => onChange('address', e.target.value)}
|
||||||
|
required
|
||||||
|
errorMsg={getError('address')}
|
||||||
|
errorLocalMsg={getLocalError('address')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
<InputText
|
<InputText
|
||||||
name="attending_physician"
|
name="attending_physician"
|
||||||
label="Médecin Traitant"
|
label="Médecin Traitant"
|
||||||
value={formData.attending_physician}
|
value={formData.attending_physician}
|
||||||
onChange={(e) => onChange('attending_physician', e.target.value)}
|
onChange={(e) => onChange('attending_physician', e.target.value)}
|
||||||
required
|
required
|
||||||
errorMsg={
|
errorMsg={getError('attending_physician')}
|
||||||
getError('attending_physician') ||
|
errorLocalMsg={getLocalError('attending_physician')}
|
||||||
getLocalError('attending_physician')
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<SelectChoice
|
<SelectChoice
|
||||||
name="level"
|
name="level"
|
||||||
@ -244,25 +268,18 @@ export default function StudentInfoForm({
|
|||||||
callback={(e) => onChange('level', e.target.value)}
|
callback={(e) => onChange('level', e.target.value)}
|
||||||
choices={levels}
|
choices={levels}
|
||||||
required
|
required
|
||||||
errorMsg={getError('level') || getLocalError('level')}
|
errorMsg={getError('level')}
|
||||||
|
errorLocalMsg={getLocalError('level')}
|
||||||
|
/>
|
||||||
|
</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')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Section pour l'upload des fichiers */}
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200 mt-6">
|
|
||||||
<SectionHeader
|
|
||||||
icon={User}
|
|
||||||
title={`Photo de l'élève`}
|
|
||||||
description={`Ajoutez une photo de votre enfant`}
|
|
||||||
/>
|
|
||||||
<FileUpload
|
|
||||||
selectionMessage="Sélectionnez une photo à uploader"
|
|
||||||
onFileSelect={(file) => handlePhotoUpload(file)}
|
|
||||||
existingFile={formData.photo}
|
|
||||||
required
|
|
||||||
errorMsg={getError('photo') || getLocalError('photo')}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -8,9 +8,11 @@ export default function SelectChoice({
|
|||||||
callback,
|
callback,
|
||||||
selected,
|
selected,
|
||||||
errorMsg,
|
errorMsg,
|
||||||
|
errorLocalMsg,
|
||||||
IconItem,
|
IconItem,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}) {
|
}) {
|
||||||
|
const isPlaceholderSelected = selected === ''; // Vérifie si le placeholder est sélectionné
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
@ -22,7 +24,11 @@ export default function SelectChoice({
|
|||||||
{required && <span className="text-red-500 ml-1">*</span>}
|
{required && <span className="text-red-500 ml-1">*</span>}
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
className={`mt-1 flex items-center border border-gray-200 rounded-md ${errorMsg ? 'border-red-500' : ''} ${disabled ? '' : 'hover:border-gray-400 focus-within:border-gray-500'}`}
|
className={`mt-1 flex items-center border rounded-md ${
|
||||||
|
errorMsg || errorLocalMsg
|
||||||
|
? 'border-red-500 hover:border-red-700'
|
||||||
|
: 'border-gray-200 hover:border-gray-400'
|
||||||
|
} ${disabled ? '' : 'focus-within:border-gray-500'}`}
|
||||||
>
|
>
|
||||||
{IconItem && (
|
{IconItem && (
|
||||||
<span className="inline-flex items-center px-3 text-gray-500 text-sm">
|
<span className="inline-flex items-center px-3 text-gray-500 text-sm">
|
||||||
@ -30,7 +36,9 @@ export default function SelectChoice({
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<select
|
<select
|
||||||
className={`flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none rounded-md ${disabled ? 'bg-gray-100' : ''}`}
|
className={`flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none rounded-md ${
|
||||||
|
disabled ? 'bg-gray-100' : ''
|
||||||
|
} ${isPlaceholderSelected ? 'italic text-gray-500' : 'not-italic text-gray-800'}`} // Applique le style classique si une option autre que le placeholder est sélectionnée
|
||||||
type={type}
|
type={type}
|
||||||
id={name}
|
id={name}
|
||||||
name={name}
|
name={name}
|
||||||
@ -38,9 +46,17 @@ export default function SelectChoice({
|
|||||||
onChange={callback}
|
onChange={callback}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
<option value="">{placeHolder?.toLowerCase()}</option>
|
{/* Placeholder en italique */}
|
||||||
{choices.map(({ value, label }, index) => (
|
<option value="" className="italic text-gray-500">
|
||||||
<option key={value} value={value}>
|
{placeHolder?.toLowerCase()}
|
||||||
|
</option>
|
||||||
|
{/* Autres options sans italique */}
|
||||||
|
{choices.map(({ value, label }) => (
|
||||||
|
<option
|
||||||
|
key={value}
|
||||||
|
value={value}
|
||||||
|
className="not-italic text-gray-800"
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user