mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
feat: Gestion de la création d'un nouveau guardian, de l'association
avec un guardian dumême établissement, et de l'association avec un guardian d'un autre établissement
This commit is contained in:
@ -9,11 +9,14 @@ import DiscountsSection from '@/components/Structure/Tarification/DiscountsSecti
|
||||
import SectionTitle from '@/components/SectionTitle';
|
||||
import ProgressStep from '@/components/ProgressStep';
|
||||
import logger from '@/utils/logger';
|
||||
import Popup from '@/components/Popup';
|
||||
|
||||
const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, onSubmit, currentStep, groups }) => {
|
||||
const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, profiles, onSubmit, currentStep, groups }) => {
|
||||
const [formData, setFormData] = useState({
|
||||
studentLastName: '',
|
||||
studentFirstName: '',
|
||||
guardianLastName: '',
|
||||
guardianFirstName: '',
|
||||
guardianEmail: '',
|
||||
guardianPhone: '',
|
||||
selectedGuardians: [],
|
||||
@ -31,6 +34,10 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
const [existingGuardians, setExistingGuardians] = useState([]);
|
||||
const [totalRegistrationAmount, setTotalRegistrationAmount] = useState(0);
|
||||
const [totalTuitionAmount, setTotalTuitionAmount] = useState(0);
|
||||
const [filteredStudents, setFilteredStudents] = useState(students);
|
||||
|
||||
const [popupVisible, setPopupVisible] = useState(false);
|
||||
const [popupMessage, setPopupMessage] = useState("");
|
||||
|
||||
const stepTitles = {
|
||||
1: 'Nouvel élève',
|
||||
@ -45,8 +52,8 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
|
||||
const isStep1Valid = formData.studentLastName && formData.studentFirstName;
|
||||
const isStep2Valid = (
|
||||
(formData.responsableType === "new" && formData.guardianEmail.length > 0) ||
|
||||
(formData.responsableType === "existing" && formData.selectedGuardians.length > 0)
|
||||
formData.selectedGuardians.length > 0 ||
|
||||
(!formData.emailError && formData.guardianEmail.length > 0 && filteredStudents.length === 0)
|
||||
);
|
||||
const isStep3Valid = formData.selectedRegistrationFees.length > 0;
|
||||
const isStep4Valid = formData.selectedTuitionFees.length > 0;
|
||||
@ -99,9 +106,35 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
};
|
||||
|
||||
const nextStep = () => {
|
||||
if (step < steps.length) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
if (step === 2) {
|
||||
// Vérifier si l'adresse email saisie est rattachée à un profil existant
|
||||
const existingProfile = profiles.find(profile => profile.email === formData.guardianEmail);
|
||||
|
||||
if (existingProfile) {
|
||||
// Vérifier si le profil a un rôle de type PARENT
|
||||
const parentRole = existingProfile.roles.find(role => role.role_type === 2);
|
||||
|
||||
if (parentRole) {
|
||||
console.log('Profil parent associé trouvé !', existingProfile);
|
||||
setFormData((prevData) => ({
|
||||
...prevData,
|
||||
guardianEmail: existingProfile.email, // Mettre à jour le champ guardianEmail avec l'email du profil
|
||||
isExistingParentProfile: true, // Indiquer que le profil est un parent existant
|
||||
existingProfileId: existingProfile.id
|
||||
}));
|
||||
} else {
|
||||
console.log('Le profil existe mais n\'est pas de type PARENT.');
|
||||
setFormData((prevData) => ({
|
||||
...prevData,
|
||||
isExistingParentProfile: false, // Réinitialiser si le profil n'est pas de type PARENT
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (step < steps.length) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
};
|
||||
|
||||
const prevStep = () => {
|
||||
@ -120,13 +153,27 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
};
|
||||
|
||||
const handleResponsableSelection = (guardianId, guardianEmail) => {
|
||||
setFormData((prevData) => {
|
||||
const isSelected = prevData.selectedGuardians.includes(guardianId);
|
||||
const selectedGuardians = isSelected
|
||||
? prevData.selectedGuardians.filter(id => id !== guardianId)
|
||||
: [...prevData.selectedGuardians, guardianId];
|
||||
return { ...prevData, selectedGuardians, guardianEmail };
|
||||
});
|
||||
setFormData((prevData) => {
|
||||
const isSelected = prevData.selectedGuardians.includes(guardianId);
|
||||
const selectedGuardians = isSelected
|
||||
? prevData.selectedGuardians.filter(id => id !== guardianId) // Retirer le guardian si déjà sélectionné
|
||||
: [...prevData.selectedGuardians, guardianId]; // Ajouter le guardian s'il n'est pas sélectionné
|
||||
|
||||
// Mettre à jour l'email uniquement si un guardian est sélectionné
|
||||
const updatedGuardianEmail = isSelected ? '' : guardianEmail;
|
||||
|
||||
// Si aucun guardian n'est sélectionné, réinitialiser le tableau des élèves
|
||||
if (selectedGuardians.length === 0) {
|
||||
setFilteredStudents(students); // Réafficher tous les élèves
|
||||
setSelectedEleve(null);
|
||||
}
|
||||
|
||||
return {
|
||||
...prevData,
|
||||
selectedGuardians,
|
||||
guardianEmail: updatedGuardianEmail,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
@ -265,117 +312,141 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
|
||||
{step === 2 && (
|
||||
<div className="mt-6">
|
||||
<div className="flex flex-col space-y-4 mt-6">
|
||||
<label className="flex items-center space-x-3">
|
||||
<input
|
||||
type="radio"
|
||||
name="responsableType"
|
||||
value="new"
|
||||
checked={formData.responsableType === 'new'}
|
||||
onChange={handleChange}
|
||||
className="form-radio h-3 w-3 text-emerald-600 focus:ring-emerald-500 hover:ring-emerald-400 checked:bg-emerald-600 checked:h-3 checked:w-3"
|
||||
/>
|
||||
<span className="text-gray-900">Nouveau Responsable</span>
|
||||
</label>
|
||||
<label className="flex items-center space-x-3">
|
||||
<input
|
||||
type="radio"
|
||||
name="responsableType"
|
||||
value="existing"
|
||||
checked={formData.responsableType === 'existing'}
|
||||
onChange={handleChange}
|
||||
className="form-radio h-3 w-3 text-emerald-600 focus:ring-emerald-500 hover:ring-emerald-400 checked:bg-emerald-600 checked:h-3 checked:w-3"
|
||||
/>
|
||||
<span className="text-gray-900">Responsable Existant</span>
|
||||
</label>
|
||||
</div>
|
||||
{formData.responsableType === 'new' && (
|
||||
<>
|
||||
<InputTextIcon
|
||||
name="guardianLastName"
|
||||
type="text"
|
||||
IconItem={User}
|
||||
placeholder="Nom du responsable (optionnel)"
|
||||
value={formData.guardianLastName}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
<InputTextIcon
|
||||
name="guardianFirstName"
|
||||
type="text"
|
||||
IconItem={User}
|
||||
placeholder="Prénom du responsable (optionnel)"
|
||||
value={formData.guardianFirstName}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
<InputTextIcon
|
||||
name="guardianEmail"
|
||||
type="email"
|
||||
IconItem={Mail}
|
||||
placeholder="Email du responsable"
|
||||
value={formData.guardianEmail}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
<InputTextIcon
|
||||
name="guardianPhone"
|
||||
type="tel"
|
||||
IconItem={Phone}
|
||||
placeholder="Numéro de téléphone (optionnel)"
|
||||
value={formData.guardianPhone}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
{/* Nom, Prénom et Téléphone */}
|
||||
<InputTextIcon
|
||||
name="guardianLastName"
|
||||
type="text"
|
||||
IconItem={User}
|
||||
placeholder="Nom du responsable (optionnel)"
|
||||
value={formData.guardianLastName}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
<InputTextIcon
|
||||
name="guardianFirstName"
|
||||
type="text"
|
||||
IconItem={User}
|
||||
placeholder="Prénom du responsable (optionnel)"
|
||||
value={formData.guardianFirstName}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
<InputTextIcon
|
||||
name="guardianPhone"
|
||||
type="tel"
|
||||
IconItem={Phone}
|
||||
placeholder="Numéro de téléphone (optionnel)"
|
||||
value={formData.guardianPhone}
|
||||
onChange={handleChange}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{formData.responsableType === 'existing' && (
|
||||
<div className="mt-4">
|
||||
<div className="mt-4" style={{ maxHeight: '300px', overflowY: 'auto' }}>
|
||||
<table className="min-w-full bg-white border">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="px-4 py-2 border">Nom</th>
|
||||
<th className="px-4 py-2 border">Prénom</th>
|
||||
{/* Email du responsable */}
|
||||
<InputTextIcon
|
||||
name="guardianEmail"
|
||||
type="email"
|
||||
IconItem={Mail}
|
||||
placeholder="Email du responsable"
|
||||
value={formData.guardianEmail}
|
||||
onChange={(e) => {
|
||||
const email = e.target.value;
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
setFormData((prevData) => ({
|
||||
...prevData,
|
||||
guardianEmail: email,
|
||||
emailError:
|
||||
email.length > 0 && // Le champ de mail est non null
|
||||
(!emailRegex.test(email) && filteredStudents.length === 0) // Format invalide ou aucun résultat
|
||||
? "Format d'email invalide ou aucun élève trouvé"
|
||||
: "",
|
||||
}));
|
||||
|
||||
// Filtrer les responsables affichés dans le tableau
|
||||
const filteredGuardians = students
|
||||
.flatMap((student) => student.guardians) // Récupérer tous les guardians
|
||||
.filter((guardian) =>
|
||||
guardian.associated_profile_email.toLowerCase().includes(email.toLowerCase())
|
||||
);
|
||||
|
||||
// Filtrer les élèves en fonction des responsables
|
||||
const filteredStudents = students.filter((student) =>
|
||||
student.guardians.some((guardian) =>
|
||||
filteredGuardians.some((filteredGuardian) => filteredGuardian.id === guardian.id)
|
||||
)
|
||||
);
|
||||
|
||||
setFilteredStudents(filteredStudents); // Mettre à jour l'état des élèves filtrés
|
||||
|
||||
// Réinitialiser existingGuardians et selectedStudent si l'élève sélectionné n'est plus dans le tableau
|
||||
if (!filteredStudents.some((student) => student.id === selectedStudent?.id)) {
|
||||
setSelectedEleve(null); // Réinitialiser l'élève sélectionné
|
||||
setExistingGuardians([]); // Réinitialiser les responsables associés
|
||||
setFormData((prevData) => ({
|
||||
...prevData,
|
||||
selectedGuardians: [] // Réinitialiser les responsables sélectionnés
|
||||
}));
|
||||
}
|
||||
}}
|
||||
errorMsg={formData.emailError}
|
||||
className="w-full mt-4"
|
||||
/>
|
||||
|
||||
{/* Tableau des élèves */}
|
||||
<div className="mt-4">
|
||||
<div className="mt-4" style={{ maxHeight: '300px', overflowY: 'auto' }}>
|
||||
<table className="min-w-full bg-white border">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="px-4 py-2 border">Nom</th>
|
||||
<th className="px-4 py-2 border">Prénom</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredStudents.map((student, index) => ( // Utiliser les élèves filtrés
|
||||
<tr
|
||||
key={student.id}
|
||||
className={`cursor-pointer ${
|
||||
selectedStudent && selectedStudent.id === student.id
|
||||
? 'bg-emerald-600 text-white'
|
||||
: index % 2 === 0
|
||||
? 'bg-emerald-100'
|
||||
: ''
|
||||
}`}
|
||||
onClick={() => handleEleveSelection(student)}
|
||||
>
|
||||
<td className="px-4 py-2 border">{student.last_name}</td>
|
||||
<td className="px-4 py-2 border">{student.first_name}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{students.map((student, index) => (
|
||||
<tr
|
||||
key={student.id}
|
||||
className={`cursor-pointer ${selectedStudent && selectedStudent.id === student.id ? 'bg-emerald-600 text-white' : index % 2 === 0 ? 'bg-emerald-100' : ''}`}
|
||||
onClick={() => handleEleveSelection(student)}
|
||||
>
|
||||
<td className="px-4 py-2 border">{student.last_name}</td>
|
||||
<td className="px-4 py-2 border">{student.first_name}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{selectedStudent && (
|
||||
<div className="mt-4">
|
||||
<h3 className="font-bold">Responsables associés à {selectedStudent.last_name} {selectedStudent.first_name} :</h3>
|
||||
{existingGuardians.map((guardian) => (
|
||||
<div key={guardian.id}>
|
||||
<label className="flex items-center space-x-3 mt-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={formData.selectedGuardians.includes(guardian.id)}
|
||||
className="form-checkbox h-5 w-5 text-emerald-600"
|
||||
onChange={() => handleResponsableSelection(guardian.id, guardian.associated_profile_email)}
|
||||
/>
|
||||
<span className="text-gray-900">
|
||||
{guardian.last_name && guardian.first_name ? `${guardian.last_name} ${guardian.first_name}` : `${guardian.associated_profile_email}`}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
{selectedStudent && (
|
||||
<div className="mt-4">
|
||||
<h3 className="font-bold">
|
||||
Responsables associés à {selectedStudent.last_name} {selectedStudent.first_name} :
|
||||
</h3>
|
||||
{existingGuardians.map((guardian) => (
|
||||
<div key={guardian.id}>
|
||||
<label className="flex items-center space-x-3 mt-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={formData.selectedGuardians.includes(guardian.id)}
|
||||
className="form-checkbox h-5 w-5 text-emerald-600"
|
||||
onChange={() => handleResponsableSelection(guardian.id, guardian.associated_profile_email)}
|
||||
/>
|
||||
<span className="text-gray-900">
|
||||
{guardian.last_name && guardian.first_name
|
||||
? `${guardian.last_name} ${guardian.first_name} - ${guardian.associated_profile_email}`
|
||||
: `${guardian.associated_profile_email}`}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -641,6 +712,13 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
||||
name="Create" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Popup
|
||||
visible={popupVisible}
|
||||
message={popupMessage}
|
||||
onConfirm={() => setPopupVisible(false)}
|
||||
onCancel={() => setPopupVisible(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user