refactor: Revue de la modale permettant de créer un dossier

d'inscription
This commit is contained in:
N3WT DE COMPET
2025-01-26 15:43:11 +01:00
parent 1c4d96d4c3
commit 665625e028
5 changed files with 442 additions and 361 deletions

View File

@ -805,8 +805,7 @@ const handleFileUpload = ({file, name, is_required, order}) => {
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
setIsOpen={setIsOpen} setIsOpen={setIsOpen}
title={"Création d'un nouveau dossier d'inscription"} title={"Nouveau dossier d'inscription"}
size='sm:w-1/4'
ContentComponent={() => ( ContentComponent={() => (
<InscriptionForm students={students} <InscriptionForm students={students}
registrationDiscounts={registrationDiscounts} registrationDiscounts={registrationDiscounts}

View File

@ -5,9 +5,11 @@ import ToggleSwitch from '@/components/ToggleSwitch';
import Button from '@/components/Button'; import Button from '@/components/Button';
import Table from '@/components/Table'; import Table from '@/components/Table';
import FeesSection from '@/components/Structure/Tarification/FeesSection'; import FeesSection from '@/components/Structure/Tarification/FeesSection';
import DiscountsSection from '../Structure/Tarification/DiscountsSection'; import DiscountsSection from '@/components/Structure/Tarification/DiscountsSection';
import Navigation from '@/components/Navigation';
import StepTitle from '@/components/StepTitle';
const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, onSubmit }) => { const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, onSubmit, currentStep }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
studentLastName: '', studentLastName: '',
studentFirstName: '', studentFirstName: '',
@ -22,12 +24,47 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
selectedTuitionFees: [] selectedTuitionFees: []
}); });
const [step, setStep] = useState(1); const [step, setStep] = useState(currentStep || 1);
const [selectedStudent, setSelectedEleve] = useState(''); const [selectedStudent, setSelectedEleve] = useState('');
const [existingGuardians, setExistingGuardians] = useState([]); const [existingGuardians, setExistingGuardians] = useState([]);
const [totalRegistrationAmount, setTotalRegistrationAmount] = useState(0); const [totalRegistrationAmount, setTotalRegistrationAmount] = useState(0);
const [totalTuitionAmount, setTotalTuitionAmount] = useState(0); const [totalTuitionAmount, setTotalTuitionAmount] = useState(0);
const maxStep = 6
const stepTitles = {
1: 'Nouvel élève',
2: 'Nouveau Responsable',
3: "Frais d'inscription",
4: 'Frais de scolarité',
5: 'Récapitulatif'
};
const steps = ['1', '2', '3', '4', 'Récap'];
const isStep1Valid = formData.studentLastName && formData.studentFirstName;
const isStep2Valid = (
(formData.responsableType === "new" && formData.guardianEmail.length > 0) ||
(formData.responsableType === "existing" && formData.selectedGuardians.length > 0)
);
const isStep3Valid = formData.selectedRegistrationFees.length > 0;
const isStep4Valid = formData.selectedTuitionFees.length > 0;
const isStep5Valid = isStep1Valid && isStep2Valid && isStep3Valid && isStep4Valid;
const isStepValid = (stepNumber) => {
switch (stepNumber) {
case 1:
return isStep1Valid;
case 2:
return isStep2Valid;
case 3:
return isStep3Valid;
case 4:
return isStep4Valid;
case 5:
return isStep5Valid;
default:
return false;
}
};
useEffect(() => { useEffect(() => {
// Calcul du montant total des frais d'inscription lors de l'initialisation // Calcul du montant total des frais d'inscription lors de l'initialisation
@ -39,6 +76,10 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
}, [registrationDiscounts, registrationFees]); }, [registrationDiscounts, registrationFees]);
useEffect(() => {
setStep(currentStep || 1);
}, [currentStep]);
const handleToggleChange = () => { const handleToggleChange = () => {
setFormData({ ...formData, autoMail: !formData.autoMail }); setFormData({ ...formData, autoMail: !formData.autoMail });
}; };
@ -52,7 +93,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
}; };
const nextStep = () => { const nextStep = () => {
if (step < maxStep) { if (step < steps.length) {
setStep(step + 1); setStep(step + 1);
} }
}; };
@ -181,362 +222,358 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
return finalAmount.toFixed(2); return finalAmount.toFixed(2);
}; };
const isLabelAttenuated = (item) => {
return !formData.selectedRegistrationDiscounts.includes(parseInt(item.id));
};
const isLabelFunction = (item) => {
return item.name + ' : ' + item.amount
};
return ( return (
<div className="space-y-4 mt-8"> <div className="space-y-4 mt-6">
{step === 1 && ( <Navigation
<div> steps={steps}
<h2 className="text-l font-bold mb-4">Nouvel élève</h2> step={step}
<InputTextIcon setStep={setStep}
name="studentLastName" isStepValid={isStepValid}
type="text" stepTitles={stepTitles}
IconItem={User} />
placeholder="Nom de l'élève"
value={formData.studentLastName}
onChange={handleChange}
className="w-full"
/>
<InputTextIcon
name="studentFirstName"
type="text"
IconItem={User}
placeholder="Prénom de l'élève"
value={formData.studentFirstName}
onChange={handleChange}
className="w-full"
/>
</div>
)}
{step === 2 && ( {step === 1 && (
<div className="mt-6"> <div className="mt-6">
<h2 className="text-l font-bold mb-4">Responsable(s)</h2> <InputTextIcon
<div className="flex flex-col space-y-4"> name="studentLastName"
<label className="flex items-center space-x-3"> type="text"
<input IconItem={User}
type="radio" placeholder="Nom de l'élève"
name="responsableType" value={formData.studentLastName}
value="new" onChange={handleChange}
checked={formData.responsableType === 'new'} className="w-full"
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" <InputTextIcon
/> name="studentFirstName"
<span className="text-gray-900">Nouveau Responsable</span> type="text"
</label> IconItem={User}
<label className="flex items-center space-x-3"> placeholder="Prénom de l'élève"
<input value={formData.studentFirstName}
type="radio" onChange={handleChange}
name="responsableType" className="w-full"
value="existing" />
checked={formData.responsableType === 'existing'} </div>
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="guardianEmail"
type="email"
IconItem={Mail}
placeholder="Email du responsable"
value={formData.guardianEmail}
onChange={handleChange}
className="w-full mt-4"
/>
)}
{formData.responsableType === 'existing' && ( {step === 2 && (
<div className="mt-4"> <div className="mt-6">
<div className="mt-4" style={{ maxHeight: '300px', overflowY: 'auto' }}> <InputTextIcon
<table className="min-w-full bg-white border"> name="guardianPhone"
<thead> type="tel"
<tr> IconItem={Phone}
<th className="px-4 py-2 border">Nom</th> placeholder="Numéro de téléphone (optionnel)"
<th className="px-4 py-2 border">Prénom</th> value={formData.guardianPhone}
</tr> onChange={handleChange}
</thead> className="w-full mt-4"
<tbody> />
{students.map((student, index) => ( <div className="flex flex-col space-y-4 mt-6">
<tr <label className="flex items-center space-x-3">
key={student.id} <input
className={`cursor-pointer ${selectedStudent && selectedStudent.id === student.id ? 'bg-emerald-600 text-white' : index % 2 === 0 ? 'bg-emerald-100' : ''}`} type="radio"
onClick={() => handleEleveSelection(student)} name="responsableType"
> value="new"
<td className="px-4 py-2 border">{student.last_name}</td> checked={formData.responsableType === 'new'}
<td className="px-4 py-2 border">{student.first_name}</td> onChange={handleChange}
</tr> 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"
))} />
</tbody> <span className="text-gray-900">Nouveau Responsable</span>
</table> </label>
</div> <label className="flex items-center space-x-3">
{selectedStudent && ( <input
<div className="mt-4"> type="radio"
<h3 className="font-bold">Responsables associés à {selectedStudent.last_name} {selectedStudent.first_name} :</h3> name="responsableType"
{existingGuardians.map((guardian) => ( value="existing"
<div key={guardian.id}> checked={formData.responsableType === 'existing'}
<label className="flex items-center space-x-3 mt-2"> onChange={handleChange}
<input 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"
type="checkbox" />
checked={formData.selectedGuardians.includes(guardian.id)} <span className="text-gray-900">Responsable Existant</span>
className="form-checkbox h-5 w-5 text-emerald-600" </label>
onChange={() => handleResponsableSelection(guardian.id)}
/>
<span className="text-gray-900">
{guardian.last_name && guardian.first_name ? `${guardian.last_name} ${guardian.first_name}` : `${guardian.email}`}
</span>
</label>
</div>
))}
</div>
)}
</div>
)}
</div>
)}
{step === 3 && (
<div className="mt-6">
<h2 className="text-l font-bold mb-4">Téléphone (optionnel)</h2>
<InputTextIcon
name="guardianPhone"
type="tel"
IconItem={Phone}
placeholder="Numéro de téléphone"
value={formData.guardianPhone}
onChange={handleChange}
className="w-full mt-4"
/>
</div>
)}
{step === 4 && (
<div>
<h2 className="text-l font-bold mb-4">Frais d'inscription</h2>
{registrationFees.length > 0 ? (
<>
<div className="mb-4">
<FeesSection
fees={registrationFees}
type={0}
subscriptionMode={true}
selectedFees={formData.selectedRegistrationFees}
handleFeeSelection={handleRegistrationFeeSelection}
/>
</div>
<h2 className="text-l font-bold mb-4">Réductions</h2>
<div className="mb-4">
{registrationDiscounts.length > 0 ? (
<DiscountsSection
discounts={registrationDiscounts}
type={0}
subscriptionMode={true}
selectedDiscounts={formData.selectedRegistrationDiscounts}
handleDiscountSelection={handleRegistrationDiscountSelection}
/>
) : (
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Information</strong>
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais d'inscription.</span>
</p>
)}
</div>
<Table
data={[ {id: 1}]}
columns={[
{
name: 'LIBELLE',
transform: () => <span>MONTANT TOTAL</span>
},
{
name: 'TOTAL',
transform: () => <b>{totalRegistrationAmount} €</b>
}
]}
defaultTheme='bg-cyan-100'
/>
</>
) : (
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Attention!</strong>
<span className="block sm:inline"> Aucun frais d'inscription n'a été créé.</span>
</p>
)}
</div>
)}
{step === 5 && (
<div>
<h2 className="text-l font-bold mb-4">Frais de scolarité</h2>
{tuitionFees.length > 0 ? (
<>
<div className="mb-4">
<FeesSection
fees={tuitionFees}
type={1}
subscriptionMode={true}
selectedFees={formData.selectedTuitionFees}
handleFeeSelection={handleTuitionFeeSelection}
/>
</div>
<h2 className="text-l font-bold mb-4">Réductions</h2>
<div className="mb-4">
{tuitionDiscounts.length > 0 ? (
<DiscountsSection
discounts={tuitionDiscounts}
type={1}
subscriptionMode={true}
selectedDiscounts={formData.selectedTuitionDiscounts}
handleDiscountSelection={handleTuitionDiscountSelection}
/>
) : (
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Information</strong>
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais de scolarité.</span>
</p>
)}
</div>
<Table
data={[ {id: 1}]}
columns={[
{
name: 'LIBELLE',
transform: () => <span>MONTANT TOTAL</span>
},
{
name: 'TOTAL',
transform: () => <b>{totalTuitionAmount} </b>
}
]}
defaultTheme='bg-cyan-100'
/>
</>
) : (
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Attention!</strong>
<span className="block sm:inline"> Aucun frais de scolarité n'a été créé.</span>
</p>
)}
</div>
)}
{step === maxStep && (
<div>
<h2 className="text-l font-bold mb-4">Récapitulatif</h2>
<div className="space-y-4">
<section>
<h3 className="font-bold">Élève</h3>
<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>
<tr>
<td className="px-4 py-2 border">{formData.studentLastName}</td>
<td className="px-4 py-2 border">{formData.studentFirstName}</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 className="font-bold">Responsable(s)</h3>
{formData.responsableType === 'new' && (
<table className="min-w-full bg-white border">
<thead>
<tr>
<th className="px-4 py-2 border">Email</th>
<th className="px-4 py-2 border">Téléphone</th>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border">{formData.guardianEmail}</td>
<td className="px-4 py-2 border">{formData.guardianPhone}</td>
</tr>
</tbody>
</table>
)}
{formData.responsableType === 'existing' && selectedStudent && (
<div>
<p>Associé(s) à : {selectedStudent.nom} {selectedStudent.prenom}</p>
<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>
<th className="px-4 py-2 border">Email</th>
</tr>
</thead>
<tbody>
{existingGuardians.filter(guardian => formData.selectedGuardians.includes(guardian.id)).map((guardian) => (
<tr key={guardian.id}>
<td className="px-4 py-2 border">{guardian.last_name}</td>
<td className="px-4 py-2 border">{guardian.first_name}</td>
<td className="px-4 py-2 border">{guardian.email}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</section>
</div>
<div className='mt-4'>
<ToggleSwitch
label="Envoi automatique"
checked={formData.autoMail}
onChange={handleToggleChange}
/>
</div>
</div>
)}
<div className="flex justify-end mt-4 space-x-4">
{step > 1 && (
<Button text="Précédent"
onClick={prevStep}
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md shadow-sm hover:bg-gray-400 focus:outline-none"
secondary
name="Previous" />
)}
{step < maxStep ? (
<Button text="Suivant"
onClick={nextStep}
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
(step === 1 && (!formData.studentLastName || !formData.studentFirstName)) ||
(step === 2 && formData.responsableType === "new" && !formData.guardianEmail) ||
(step === 2 && formData.responsableType === "existing" && formData.selectedGuardians.length === 0)
? "bg-gray-300 text-gray-700 cursor-not-allowed"
: "bg-emerald-500 text-white hover:bg-emerald-600"
}`}
disabled={(step === 1 && (!formData.studentLastName || !formData.studentFirstName)) ||
(step === 2 && formData.responsableType === "new" && !formData.guardianEmail) ||
(step === 2 && formData.responsableType === "existing" && formData.selectedGuardians.length === 0)
}
primary
name="Next" />
) : (
<Button text="Créer"
onClick={submit}
className="px-4 py-2 bg-emerald-500 text-white rounded-md shadow-sm hover:bg-emerald-600 focus:outline-none"
primary
name="Create" />
)}
</div> </div>
{formData.responsableType === 'new' && (
<InputTextIcon
name="guardianEmail"
type="email"
IconItem={Mail}
placeholder="Email du responsable"
value={formData.guardianEmail}
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>
</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)}
/>
<span className="text-gray-900">
{guardian.last_name && guardian.first_name ? `${guardian.last_name} ${guardian.first_name}` : `${guardian.email}`}
</span>
</label>
</div>
))}
</div>
)}
</div>
)}
</div>
)}
{step === 3 && (
<div>
{registrationFees.length > 0 ? (
<>
<div className="mb-4">
<FeesSection
fees={registrationFees}
type={0}
subscriptionMode={true}
selectedFees={formData.selectedRegistrationFees}
handleFeeSelection={handleRegistrationFeeSelection}
/>
</div>
<StepTitle title='Réductions' />
<div className="mb-4">
{registrationDiscounts.length > 0 ? (
<DiscountsSection
discounts={registrationDiscounts}
type={0}
subscriptionMode={true}
selectedDiscounts={formData.selectedRegistrationDiscounts}
handleDiscountSelection={handleRegistrationDiscountSelection}
/>
) : (
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Information</strong>
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais d'inscription.</span>
</p>
)}
</div>
<StepTitle title='Montant total' />
<Table
data={[ {id: 1}]}
columns={[
{
name: 'LIBELLE',
transform: () => <span>MONTANT TOTAL</span>
},
{
name: 'TOTAL',
transform: () => <b>{totalRegistrationAmount} </b>
}
]}
defaultTheme='bg-cyan-100'
/>
</>
) : (
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Attention!</strong>
<span className="block sm:inline"> Aucun frais d'inscription n'a été créé.</span>
</p>
)}
</div>
)}
{step === 4 && (
<div>
{tuitionFees.length > 0 ? (
<>
<div className="mb-4">
<FeesSection
fees={tuitionFees}
type={1}
subscriptionMode={true}
selectedFees={formData.selectedTuitionFees}
handleFeeSelection={handleTuitionFeeSelection}
/>
</div>
<StepTitle title='Réductions' />
<div className="mb-4">
{tuitionDiscounts.length > 0 ? (
<DiscountsSection
discounts={tuitionDiscounts}
type={1}
subscriptionMode={true}
selectedDiscounts={formData.selectedTuitionDiscounts}
handleDiscountSelection={handleTuitionDiscountSelection}
/>
) : (
<p className="bg-orange-100 border border-orange-400 text-orange-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Information</strong>
<span className="block sm:inline"> Aucune réduction n'a été créée sur les frais de scolarité.</span>
</p>
)}
</div>
<StepTitle title='Montant total' />
<Table
data={[ {id: 1}]}
columns={[
{
name: 'LIBELLE',
transform: () => <span>MONTANT TOTAL</span>
},
{
name: 'TOTAL',
transform: () => <b>{totalTuitionAmount} €</b>
}
]}
defaultTheme='bg-cyan-100'
/>
</>
) : (
<p className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
<strong className="font-bold">Attention!</strong>
<span className="block sm:inline"> Aucun frais de scolarité n'a été créé.</span>
</p>
)}
</div>
)}
{step === steps.length && (
<div>
<div className="space-y-4">
<section>
<h3 className="font-bold">Élève</h3>
<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>
<tr>
<td className="px-4 py-2 border">{formData.studentLastName}</td>
<td className="px-4 py-2 border">{formData.studentFirstName}</td>
</tr>
</tbody>
</table>
</section>
<section>
<h3 className="font-bold">Responsable(s)</h3>
{formData.responsableType === 'new' && (
<table className="min-w-full bg-white border">
<thead>
<tr>
<th className="px-4 py-2 border">Email</th>
<th className="px-4 py-2 border">Téléphone</th>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border">{formData.guardianEmail}</td>
<td className="px-4 py-2 border">{formData.guardianPhone}</td>
</tr>
</tbody>
</table>
)}
{formData.responsableType === 'existing' && selectedStudent && (
<div>
<p>Associé(s) à : {selectedStudent.nom} {selectedStudent.prenom}</p>
<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>
<th className="px-4 py-2 border">Email</th>
</tr>
</thead>
<tbody>
{existingGuardians.filter(guardian => formData.selectedGuardians.includes(guardian.id)).map((guardian) => (
<tr key={guardian.id}>
<td className="px-4 py-2 border">{guardian.last_name}</td>
<td className="px-4 py-2 border">{guardian.first_name}</td>
<td className="px-4 py-2 border">{guardian.email}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</section>
</div>
<div className='mt-4'>
<ToggleSwitch
label="Envoi automatique"
checked={formData.autoMail}
onChange={handleToggleChange}
/>
</div>
</div>
)}
<div className="flex justify-end mt-4 space-x-4">
{step > 1 && (
<Button text="Précédent"
onClick={prevStep}
className="px-4 py-2 bg-gray-300 text-gray-700 rounded-md shadow-sm hover:bg-gray-400 focus:outline-none"
secondary
name="Previous" />
)}
{step < steps.length ? (
<Button text="Suivant"
onClick={nextStep}
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
(
(step === 1 && !isStep1Valid) ||
(step === 2 && !isStep2Valid) ||
(step === 3 && !isStep3Valid) ||
(step === 4 && !isStep4Valid)
)
? "bg-gray-300 text-gray-700 cursor-not-allowed"
: "bg-emerald-500 text-white hover:bg-emerald-600"
}`}
disabled={
(
(step === 1 && !isStep1Valid) ||
(step === 2 && !isStep2Valid) ||
(step === 3 && !isStep3Valid) ||
(step === 4 && !isStep4Valid)
)
}
primary
name="Next" />
) : (
<Button text="Valider"
onClick={submit}
className="px-4 py-2 bg-emerald-500 text-white rounded-md shadow-sm hover:bg-emerald-600 focus:outline-none"
primary
name="Create" />
)}
</div> </div>
</div>
); );
} }

View File

@ -1,13 +1,12 @@
import * as Dialog from '@radix-ui/react-dialog'; import * as Dialog from '@radix-ui/react-dialog';
import Button from '@/components/Button';
const Modal = ({ isOpen, setIsOpen, title, ContentComponent, size }) => { const Modal = ({ isOpen, setIsOpen, title, ContentComponent }) => {
return ( return (
<Dialog.Root open={isOpen} onOpenChange={setIsOpen}> <Dialog.Root open={isOpen} onOpenChange={setIsOpen}>
<Dialog.Portal> <Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" /> <Dialog.Overlay className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
<Dialog.Content className="fixed inset-0 flex items-center justify-center"> <Dialog.Content className="fixed inset-0 flex items-center justify-center">
<div className={`inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-4xl sm:p-6 ${size ? size : 'sm:w-full' }`} style={{ minWidth: '300px', width: 'auto' }}> <div className="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle" style={{ width: '600px', maxWidth: '90%' }}>
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<Dialog.Title className="text-xl font-medium text-gray-900"> <Dialog.Title className="text-xl font-medium text-gray-900">
{title} {title}

View File

@ -0,0 +1,30 @@
import React from 'react';
import StepTitle from '@/components/StepTitle';
const Navigation = ({ steps, step, setStep, isStepValid, stepTitles }) => {
return (
<div className="relative mb-4">
<div className="relative flex justify-between">
{steps.map((stepLabel, index) => {
const isCurrentStep = step === index + 1;
return (
<div key={index} className="flex flex-col items-center">
<div className={`mb-4 ${isCurrentStep ? 'text-gray-500 font-extrabold' : 'text-gray-500'}`}>
{stepLabel}
</div>
<div
className={`w-4 h-4 rounded-full mb-4 ${isStepValid(index + 1) ? 'bg-emerald-500' : 'bg-yellow-300'} cursor-pointer`}
onClick={() => setStep(index + 1)}
style={{ transform: 'translateY(-50%)' }}
></div>
</div>
);
})}
</div>
<StepTitle title={stepTitles[step]} />
</div>
);
};
export default Navigation;

View File

@ -0,0 +1,16 @@
import React from 'react';
const StepTitle = ({ title }) => {
return (
<div className="relative mb-4">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-gray-300"></div>
</div>
<div className="relative flex justify-center">
<div className="px-4 bg-white text-gray-500">{title}</div>
</div>
</div>
);
};
export default StepTitle;