feat: Ajout de la sélection des modes de paiements / refactoring de

l'automate
This commit is contained in:
N3WT DE COMPET
2025-04-06 20:45:41 +02:00
parent 9559db59eb
commit 5a7661db93
19 changed files with 286 additions and 190 deletions

View File

@ -6,7 +6,7 @@ const FileStatusLabel = ({ status }) => {
switch (status) {
case 'sent':
return {
label: 'Envoyé',
label: 'En attente',
className: 'bg-green-50 text-green-600',
icon: <Check size={16} className="text-green-600" />
};

View File

@ -1,20 +1,17 @@
// Import des dépendances nécessaires
import React, { useState, useEffect } from 'react';
import InputText from '@/components/InputText';
import SelectChoice from '@/components/SelectChoice';
import ResponsableInputFields from '@/components/Inscription/ResponsableInputFields';
import Loader from '@/components/Loader';
import Button from '@/components/Button';
import DjangoCSRFToken from '@/components/DjangoCSRFToken';
import Table from '@/components/Table';
import { fetchRegisterForm, fetchTemplatesFromRegistrationFiles } from '@/app/actions/subscriptionAction';
import { fetchRegistrationFileFromGroup,
fetchRegistrationTemplateMaster,
downloadTemplate,
createRegistrationTemplates,
editRegistrationTemplates,
deleteRegistrationTemplates
} from '@/app/actions/registerFileGroupAction';
import { downloadTemplate,
createRegistrationTemplates,
editRegistrationTemplates,
deleteRegistrationTemplates
} from '@/app/actions/registerFileGroupAction';
import {
fetchRegistrationPaymentModes,
fetchTuitionPaymentModes } from '@/app/actions/schoolAction';
import { Download, Upload, Trash2, Eye } from 'lucide-react';
import { BASE_URL } from '@/utils/Url';
import DraggableFileUpload from '@/components/DraggableFileUpload';
@ -22,10 +19,8 @@ import Modal from '@/components/Modal';
import FileStatusLabel from '@/components/FileStatusLabel';
import logger from '@/utils/logger';
import StudentInfoForm, { validateStudentInfo } from '@/components/Inscription/StudentInfoForm';
import FilesToSign from '@/components/Inscription/FilesToSign';
import FilesToUpload from '@/components/Inscription/FilesToUpload';
import { DocusealForm } from '@docuseal/react';
import { ESTABLISHMENT_ID } from '@/utils/Url';
/**
* Composant de formulaire d'inscription partagé
@ -38,6 +33,7 @@ import { ESTABLISHMENT_ID } from '@/utils/Url';
export default function InscriptionFormShared({
studentId,
csrfToken,
selectedEstablishmentId,
onSubmit,
cancelUrl,
errors = {} // Nouvelle prop pour les erreurs
@ -54,11 +50,16 @@ export default function InscriptionFormShared({
birth_postal_code: '',
nationality: '',
attending_physician: '',
level: ''
level: '',
registration_payment: '',
tuition_payment: ''
});
const [guardians, setGuardians] = useState([]);
const [registrationPaymentModes, setRegistrationPaymentModes] = useState([]);
const [tuitionPaymentModes, setTuitionPaymentModes] = useState([]);
// États pour la gestion des fichiers
const [uploadedFiles, setUploadedFiles] = useState([]);
const [fileTemplates, setFileTemplates] = useState([]);
@ -95,7 +96,11 @@ export default function InscriptionFormShared({
birth_postal_code: data?.student?.birth_postal_code || '',
nationality: data?.student?.nationality || '',
attending_physician: data?.student?.attending_physician || '',
level: data?.student?.level || ''
level: data?.student?.level || '',
registration_payment: data?.registration_payment || '',
tuition_payment: data?.tuition_payment || '',
totalRegistrationFees: data?.totalRegistrationFees,
totalTuitionFees: data?.totalTuitionFees,
});
setGuardians(data?.student?.guardians || []);
setUploadedFiles(data.registration_files || []);
@ -111,6 +116,34 @@ export default function InscriptionFormShared({
})
}, []);
useEffect(() => {
if (selectedEstablishmentId) {
// Fetch data for registration payment modes
handleRegistrationPaymentModes();
// Fetch data for tuition payment modes
handleTuitionPaymentModes();
}
}, [selectedEstablishmentId]);
const handleRegistrationPaymentModes = () => {
fetchRegistrationPaymentModes(selectedEstablishmentId)
.then(data => {
const activePaymentModes = data.filter(mode => mode.is_active === true);
setRegistrationPaymentModes(activePaymentModes);
})
.catch(error => logger.error('Error fetching registration payment modes:', error));
};
const handleTuitionPaymentModes = () => {
fetchTuitionPaymentModes(selectedEstablishmentId)
.then(data => {
const activePaymentModes = data.filter(mode => mode.is_active === true);
setTuitionPaymentModes(activePaymentModes);
})
.catch(error => logger.error('Error fetching tuition payment modes:', error));
};
// Fonctions de gestion du formulaire et des fichiers
const updateFormField = (field, value) => {
setFormData(prev => ({...prev, [field]: value}));
@ -186,8 +219,10 @@ export default function InscriptionFormShared({
...formData,
guardians
},
establishment: 1,
status:3
establishment: selectedEstablishmentId,
status:3,
tuition_payment:formData.tuition_payment,
registration_payment:formData.registration_payment
}
onSubmit(data);
};
@ -200,16 +235,11 @@ export default function InscriptionFormShared({
...formData,
guardians
},
establishment: 1
establishment: selectedEstablishmentId
}
onSubmit(data);
};
// Récupération des messages d'erreur
const getError = (field) => {
return errors?.student?.[field]?.[0];
};
const handleNextPage = () => {
setCurrentPage(currentPage + 1);
};
@ -290,6 +320,8 @@ export default function InscriptionFormShared({
updateFormField={updateFormField}
guardians={guardians}
setGuardians={setGuardians}
registrationPaymentModes={registrationPaymentModes}
tuitionPaymentModes={tuitionPaymentModes}
errors={errors}
/>
)}

View File

@ -0,0 +1,34 @@
import React from 'react';
import SelectChoice from '@/components/SelectChoice';
export default function PaymentMethodSelector({ formData, title, name, updateFormField, selected, paymentModes, paymentModesOptions, amount, getError }) {
console.log(paymentModes)
console.log(selected)
return (
<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">{title}</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> {amount}
</p>
</div>
<SelectChoice
name={name}
label="Mode de Paiement"
placeHolder="Sélectionner un mode de paiement"
selected={selected || ''}
callback={(e) => updateFormField(name, e.target.value)}
choices={paymentModes.map((mode) => ({
value: mode.mode,
label: paymentModesOptions.find(option => option.id === mode.mode)?.name || 'Mode inconnu'
}))}
required
errorMsg={getError('payment_method')}
/>
</div>
);
}

View File

@ -2,6 +2,7 @@ import React from 'react';
import InputText from '@/components/InputText';
import SelectChoice from '@/components/SelectChoice';
import ResponsableInputFields from '@/components/Inscription/ResponsableInputFields';
import PaymentMethodSelector from '@/components/Inscription/PaymentMethodSelector';
const levels = [
{ value:'1', label: 'TPS - Très Petite Section'},
@ -10,6 +11,13 @@ const levels = [
{ value:'4', label: 'GS - Grande Section'},
];
const paymentModesOptions = [
{ id: 1, name: 'Prélèvement SEPA' },
{ id: 2, name: 'Virement' },
{ id: 3, name: 'Chèque' },
{ id: 4, name: 'Espèce' },
];
// Fonction de validation pour vérifier les champs requis
export function validateStudentInfo(formData) {
const requiredFields = [
@ -32,7 +40,7 @@ export function validateStudentInfo(formData) {
return isValid;
}
export default function StudentInfoForm({ formData, updateFormField, guardians, setGuardians, errors }) {
export default function StudentInfoForm({ formData, updateFormField, guardians, setGuardians, registrationPaymentModes, tuitionPaymentModes, errors }) {
const getError = (field) => {
return errors?.student?.[field]?.[0];
};
@ -143,6 +151,30 @@ export default function StudentInfoForm({ formData, updateFormField, guardians,
errors={errors?.student?.guardians || []}
/>
</div>
<PaymentMethodSelector
formData={formData}
title="Frais d'inscription"
name="registration_payment"
updateFormField={updateFormField}
selected={formData.registration_payment}
paymentModes={registrationPaymentModes}
paymentModesOptions={paymentModesOptions}
amount={formData.totalRegistrationFees}
getError={getError}
/>
<PaymentMethodSelector
formData={formData}
title="Frais de scolarité"
name="tuition_payment"
updateFormField={updateFormField}
selected={formData.tuition_payment}
paymentModes={tuitionPaymentModes}
paymentModesOptions={paymentModesOptions}
amount={formData.totalTuitionFees}
getError={getError}
/>
</>
);
}

View File

@ -5,9 +5,9 @@ import DropdownMenu from './DropdownMenu';
const StatusLabel = ({ status, onChange, showDropdown = true }) => {
const [dropdownOpen, setDropdownOpen] = useState(false);
const statusOptions = [
{ value: 1, label: 'Créé' },
{ value: 2, label: 'Envoyé' },
{ value: 3, label: 'En Validation' },
{ value: 1, label: 'A envoyer' },
{ value: 2, label: 'En attente' },
{ value: 3, label: 'Signé' },
{ value: 4, label: 'A Relancer' },
{ value: 5, label: 'Validé' },
{ value: 6, label: 'Archivé' },

View File

@ -4,7 +4,6 @@ import DiscountsSection from '@/components/Structure/Tarification/DiscountsSecti
import PaymentPlanSelector from '@/components/PaymentPlanSelector';
import PaymentModeSelector from '@/components/PaymentModeSelector';
import { BE_SCHOOL_FEES_URL, BE_SCHOOL_DISCOUNTS_URL, BE_SCHOOL_PAYMENT_PLANS_URL, BE_SCHOOL_PAYMENT_MODES_URL } from '@/utils/Url';
import { set } from 'lodash';
const FeesManagement = ({ registrationDiscounts,
setRegistrationDiscounts,