fix: Remplacement des enum par des modèles pour les payementModes et les

payementPlans
This commit is contained in:
N3WT DE COMPET
2025-05-18 10:45:00 +02:00
parent 00f7bfde4a
commit 7fe53465ac
12 changed files with 198 additions and 401 deletions

View File

@ -230,10 +230,7 @@ export default function InscriptionFormShared({
const handleRegistrationPaymentModes = () => {
fetchRegistrationPaymentModes(selectedEstablishmentId)
.then((data) => {
const activePaymentModes = data.filter(
(mode) => mode.is_active === true
);
setRegistrationPaymentModes(activePaymentModes);
setRegistrationPaymentModes(data);
})
.catch((error) =>
logger.error('Error fetching registration payment modes:', error)
@ -243,10 +240,7 @@ export default function InscriptionFormShared({
const handleTuitionPaymentModes = () => {
fetchTuitionPaymentModes(selectedEstablishmentId)
.then((data) => {
const activePaymentModes = data.filter(
(mode) => mode.is_active === true
);
setTuitionPaymentModes(activePaymentModes);
setTuitionPaymentModes(data);
})
.catch((error) =>
logger.error('Error fetching tuition payment modes:', error)
@ -256,10 +250,7 @@ export default function InscriptionFormShared({
const handleRegistrationPaymentPlans = () => {
fetchRegistrationPaymentPlans(selectedEstablishmentId)
.then((data) => {
const activePaymentPlans = data.filter(
(mode) => mode.is_active === true
);
setRegistrationPaymentPlans(activePaymentPlans);
setRegistrationPaymentPlans(data);
})
.catch((error) =>
logger.error('Error fetching registration payment plans:', error)
@ -269,10 +260,7 @@ export default function InscriptionFormShared({
const handleTuitionnPaymentPlans = () => {
fetchTuitionPaymentPlans(selectedEstablishmentId)
.then((data) => {
const activePaymentPlans = data.filter(
(mode) => mode.is_active === true
);
setTuitionPaymentPlans(activePaymentPlans);
setTuitionPaymentPlans(data);
})
.catch((error) =>
logger.error('Error fetching registration tuition plans:', error)

View File

@ -31,9 +31,9 @@ export default function PaymentMethodSelector({
const paymentPlansOptions = [
{ id: 1, name: '1 fois' },
{ id: 3, name: '3 fois' },
{ id: 10, name: '10 fois' },
{ id: 12, name: '12 fois' },
{ id: 2, name: '3 fois' },
{ id: 3, name: '10 fois' },
{ id: 4, name: '12 fois' },
];
const getError = (field) => {
@ -105,7 +105,7 @@ export default function PaymentMethodSelector({
items={paymentPlansOptions
.filter((option) =>
registrationPaymentPlans.some(
(plan) => plan.frequency === option.id
(plan) => plan.plan_type === option.id
)
)
.map((option) => ({
@ -167,7 +167,7 @@ export default function PaymentMethodSelector({
required
items={paymentPlansOptions
.filter((option) =>
tuitionPaymentPlans.some((plan) => plan.frequency === option.id)
tuitionPaymentPlans.some((plan) => plan.plan_type === option.id)
)
.map((option) => ({
id: option.id,

View File

@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react';
import { DollarSign } from 'lucide-react';
import { useEstablishment } from '@/context/EstablishmentContext';
const paymentModesOptions = [
{ id: 1, name: 'Prélèvement SEPA' },
@ -11,36 +12,31 @@ const paymentModesOptions = [
const PaymentModeSelector = ({
paymentModes,
setPaymentModes,
handleEdit,
handleCreate,
handleDelete,
type,
}) => {
const [activePaymentModes, setActivePaymentModes] = useState([]);
const { selectedEstablishmentId } = useEstablishment();
useEffect(() => {
// Initialiser activePaymentModes avec les modes dont is_active est à true
const activeModes = paymentModes
.filter((mode) => mode.is_active)
.map((mode) => mode.mode);
const activeModes = paymentModes.map((mode) => mode.mode);
setActivePaymentModes(activeModes);
}, [paymentModes]);
const handleModeToggle = (modeId) => {
setActivePaymentModes((prevActiveModes) => {
const newActiveModes = prevActiveModes.includes(modeId)
? prevActiveModes.filter((mode) => mode !== modeId)
: [...prevActiveModes, modeId];
const updatedMode = paymentModes.find((mode) => mode.mode === modeId);
const isActive = !!updatedMode;
// Mettre à jour le mode de paiement dans le backend
const updatedMode = paymentModes.find((mode) => mode.mode === modeId);
if (updatedMode) {
handleEdit(updatedMode.id, {
...updatedMode,
is_active: !updatedMode.is_active,
});
}
return newActiveModes;
});
if (!isActive) {
handleCreate({
mode: modeId,
type,
establishment: selectedEstablishmentId,
});
} else {
handleDelete(updatedMode.id, null);
}
};
return (
@ -55,7 +51,7 @@ const PaymentModeSelector = ({
key={mode.id}
type="button"
onClick={() => handleModeToggle(mode.id)}
className={`p-4 rounded-lg shadow-md text-center text-gray-700' ${
className={`p-4 rounded-lg shadow-md text-center text-gray-700 ${
activePaymentModes.includes(mode.id)
? 'bg-emerald-100'
: 'bg-stone-50'

View File

@ -1,281 +1,62 @@
import React, { useState, useEffect } from 'react';
import { Calendar, Eye, EyeOff, Clock, Check } from 'lucide-react';
import { Calendar } from 'lucide-react';
import Table from '@/components/Table';
import DateTab from '@/components/DateTab';
import InputTextIcon from '@/components/InputTextIcon';
import Popup from '@/components/Popup';
import logger from '@/utils/logger';
import { useEstablishment } from '@/context/EstablishmentContext';
import CheckBox from '@/components/CheckBox';
const paymentPlansOptions = [
{ id: 0, name: '1 fois', frequency: 1 },
{ id: 1, name: '3 fois', frequency: 3 },
{ id: 2, name: '10 fois', frequency: 10 },
{ id: 3, name: '12 fois', frequency: 12 },
{ id: 1, name: '1 fois', frequency: 1 },
{ id: 2, name: '3 fois', frequency: 3 },
{ id: 3, name: '10 fois', frequency: 10 },
{ id: 4, name: '12 fois', frequency: 12 },
];
const PaymentPlanSelector = ({
paymentPlans,
setPaymentPlans,
handleEdit,
handleCreate,
handleDelete,
type,
}) => {
const [dates, setDates] = useState({});
const [selectedFrequency, setSelectedFrequency] = useState(null);
const [activeFrequencies, setActiveFrequencies] = useState([]);
const [defaultDay, setDefaultDay] = useState('-');
const [isDefaultDayModified, setIsDefaultDayModified] = useState(false);
const [popupVisible, setPopupVisible] = useState(false);
const [popupMessage, setPopupMessage] = useState('');
const [errorMsg, setErrorMsg] = useState('');
const [resetModifiedDates, setResetModifiedDates] = useState(false);
const { selectedEstablishmentId } = useEstablishment();
const [checkedPlans, setCheckedPlans] = useState([]);
// Vérifie si un plan existe pour ce type (par id)
const isChecked = (planOption) => checkedPlans.includes(planOption.id);
// Création ou suppression du plan
const handlePlanToggle = (planOption) => {
const updatedPlan = paymentPlans.find(
(plan) => plan.plan_type === planOption.id
);
if (isChecked(planOption)) {
setCheckedPlans((prev) => prev.filter((id) => id !== planOption.id));
handleDelete(updatedPlan.id, null);
} else {
setCheckedPlans((prev) => [...prev, planOption.id]);
handleCreate({
plan_type: planOption.id,
type,
establishment: selectedEstablishmentId,
});
}
};
useEffect(() => {
if (paymentPlans && paymentPlans.length > 0) {
const activePlans = paymentPlans.filter((plan) => plan.is_active);
const frequencies = activePlans
.map((plan) => {
const paymentPlanOption = paymentPlansOptions.find(
(p) => p.frequency === plan.frequency
);
return paymentPlanOption ? paymentPlanOption.id : null;
})
.filter((id) => id !== null);
setActiveFrequencies(frequencies);
if (activePlans.length > 0) {
const firstDueDate = new Date(activePlans[0].due_dates[0]);
setDefaultDay(firstDueDate.getDate());
}
const initialDates = {};
paymentPlans.forEach((plan) => {
const paymentPlanOption = paymentPlansOptions.find(
(p) => p.frequency === plan.frequency
);
if (paymentPlanOption) {
initialDates[paymentPlanOption.id] = plan.due_dates;
}
});
setDates(initialDates);
setCheckedPlans(
paymentPlans.map((plan) =>
typeof plan.plan_type === 'object'
? plan.plan_type.id
: plan.plan_type
)
);
}
}, [paymentPlans]);
useEffect(() => {
updateDefaultDay();
}, [dates, selectedFrequency]);
const updateDefaultDay = () => {
const currentDates = dates[selectedFrequency];
if (currentDates && currentDates.length > 0) {
const days = currentDates.map((date) => new Date(date).getDate());
const allSameDay = days.every((day) => day === days[0]);
if (allSameDay) {
setDefaultDay(days[0]);
} else {
setDefaultDay('-');
setIsDefaultDayModified(false);
}
} else {
setDefaultDay('-');
}
};
const handleActivationChange = (value) => {
const selectedPlan = paymentPlans.find(
(plan) =>
plan.frequency ===
paymentPlansOptions.find((p) => p.id === value)?.frequency
);
if (!selectedPlan) return;
const updatedData = {
...selectedPlan,
is_active: !selectedPlan.is_active,
};
handleEdit(selectedPlan.id, updatedData)
.then(() => {
setPaymentPlans((prevPlans) =>
prevPlans.map((plan) =>
plan.id === selectedPlan.id
? { ...plan, is_active: updatedData.is_active }
: plan
)
);
setActiveFrequencies((prevFrequencies) => {
if (updatedData.is_active) {
setPopupMessage(
`L'option de paiement en ${paymentPlansOptions.find((p) => p.id === value).name} a été activée.`
);
setPopupVisible(true);
return [...prevFrequencies, value];
} else {
setPopupMessage(
`L'option de paiement en ${paymentPlansOptions.find((p) => p.id === value).name} a été désactivée.`
);
setPopupVisible(true);
return prevFrequencies.filter((item) => item !== value);
}
});
})
.catch((error) => {
logger.error(error);
});
};
const handleRowClick = (row) => {
const value = row.id;
if (selectedFrequency === value) {
setSelectedFrequency(null); // Désélectionner l'onglet si la ligne est déjà sélectionnée
} else {
setSelectedFrequency(value);
if (!dates[value]) {
const frequencyValue =
paymentPlansOptions.find((plan) => plan.id === value)?.frequency || 1;
const newDates = Array(frequencyValue)
.fill('')
.map((_, index) => {
const newDate = new Date();
// Validate defaultDay
const day =
typeof defaultDay === 'number' &&
defaultDay >= 1 &&
defaultDay <= 31
? defaultDay
: 1; // Fallback to 1 if defaultDay is invalid
newDate.setDate(day);
if (value === 1) {
newDate.setMonth(newDate.getMonth() + index * 4); // Espacer de 4 mois pour le paiement en 3 fois
} else {
newDate.setMonth(newDate.getMonth() + index);
}
return newDate.toISOString().split('T')[0];
});
setDates((prevDates) => ({ ...prevDates, [value]: newDates }));
}
}
};
const handleDateChange = (planId, index, date) => {
setDates((prevDates) => {
const newDates = { ...prevDates };
newDates[planId][index] = date;
return newDates;
});
};
const handleDefaultDayChange = (e) => {
const value = e.target.value;
if (value === '') {
setDefaultDay('-');
setErrorMsg('');
setIsDefaultDayModified(false);
return;
}
const day = parseInt(value, 10);
setDefaultDay(day);
if (day < 1 || day > 31) {
setErrorMsg('Le jour doit être compris entre 1 et 31.');
setIsDefaultDayModified(false);
return;
}
setErrorMsg('');
setIsDefaultDayModified(true);
setResetModifiedDates(true);
setTimeout(() => setResetModifiedDates(false), 0);
// Mettre à jour les dates d'échéance en fonction du jour sélectionné
const updatedDates = dates[selectedFrequency].map((date) => {
const newDate = new Date(date);
newDate.setDate(day);
return newDate.toISOString().split('T')[0];
});
setDates((prevDates) => ({
...prevDates,
[selectedFrequency]: updatedDates,
}));
};
const handleSubmitDefaultDay = () => {
const selectedPlan = paymentPlans.find(
(plan) =>
plan.frequency ===
paymentPlansOptions.find((p) => p.id === selectedFrequency)?.frequency
);
if (!selectedPlan) return;
const updatedData = {
...selectedPlan,
due_dates: dates[selectedFrequency],
};
handleEdit(selectedPlan.id, updatedData)
.then(() => {
setPopupMessage(
"Mise à jour des dates d'échéances effectuée avec succès"
);
setPopupVisible(true);
setIsDefaultDayModified(false);
})
.catch((error) => {
logger.error(error);
});
};
const columns = [
{ name: 'OPTIONS', label: 'Option' },
{ name: 'ACTIONS', label: 'Action' },
];
const renderCell = (row, column) => {
switch (column) {
case 'OPTIONS':
return (
<span className="text-sm font-medium text-gray-900">{row.name}</span>
);
case 'ACTIONS':
return (
<button
type="button"
onClick={(e) => {
e.stopPropagation();
handleActivationChange(row.id);
}}
className={
activeFrequencies.includes(row.id)
? 'text-emerald-500 hover:text-emerald-700'
: 'text-orange-500 hover:text-orange-700'
}
>
{activeFrequencies.includes(row.id) ? (
<Eye className="w-5 h-5" />
) : (
<EyeOff className="w-5 h-5" />
)}
</button>
);
default:
return null;
}
};
const selectedPaymentPlan = paymentPlans.find(
(plan) =>
plan.frequency ===
paymentPlansOptions.find((p) => p.id === selectedFrequency)?.frequency
);
return (
<div className="space-y-4">
<div className="flex items-center mb-4">
@ -285,49 +66,34 @@ const PaymentPlanSelector = ({
<div className="grid grid-cols-2 gap-4">
<Table
data={paymentPlansOptions}
columns={columns}
renderCell={renderCell}
isSelectable={true}
onRowClick={handleRowClick}
selectedRows={selectedFrequency !== null ? [selectedFrequency] : []}
columns={[
{ name: 'OPTION', label: 'Option' },
{ name: 'ACTIF', label: 'Actif' },
]}
renderCell={(row, column) => {
switch (column) {
case 'OPTION':
return (
<span className="text-sm font-medium text-gray-900">
{row.name}
</span>
);
case 'ACTIF':
return (
<CheckBox
item={{ id: row.id }}
formData={{ checked: isChecked(row) }}
handleChange={() => handlePlanToggle(row)}
fieldName="checked"
itemLabelFunc={() => ''}
horizontal={true}
/>
);
default:
return null;
}
}}
/>
{selectedFrequency !== null && selectedPaymentPlan && (
<div>
<div className="flex items-center space-x-3">
<div className="flex-grow">
<InputTextIcon
name="defaultDay"
type="number"
IconItem={Clock}
label="Jour d'échéance"
value={defaultDay}
onChange={handleDefaultDayChange}
placeholder="Jour d'échéance"
errorMsg={errorMsg}
/>
</div>
{isDefaultDayModified && defaultDay && (
<button
type="button"
onClick={handleSubmitDefaultDay}
className="text-emerald-500 hover:text-emerald-700 ml-2 cursor-pointer"
style={{ marginTop: errorMsg ? '3.5rem' : '1.75rem' }}
>
<Check className="w-5 h-5" />
</button>
)}
</div>
<DateTab
dates={dates}
activeTab={selectedFrequency}
handleDateChange={handleDateChange}
handleEdit={handleEdit}
type={type}
paymentPlanId={selectedPaymentPlan.id}
resetModifiedDates={resetModifiedDates}
/>
</div>
)}
</div>
<Popup
isOpen={popupVisible}

View File

@ -116,11 +116,17 @@ const FeesManagement = ({
<PaymentPlanSelector
paymentPlans={registrationPaymentPlans}
setPaymentPlans={setRegistrationPaymentPlans}
handleEdit={(id, updatedData) =>
handleEdit(
handleCreate={(newData) =>
handleCreate(
`${BE_SCHOOL_PAYMENT_PLANS_URL}`,
newData,
setRegistrationPaymentPlans
)
}
handleDelete={(id) =>
handleDelete(
`${BE_SCHOOL_PAYMENT_PLANS_URL}`,
id,
updatedData,
setRegistrationPaymentPlans
)
}
@ -131,11 +137,17 @@ const FeesManagement = ({
<PaymentModeSelector
paymentModes={registrationPaymentModes}
setPaymentModes={setRegistrationPaymentModes}
handleEdit={(id, updatedData) =>
handleEdit(
handleCreate={(newData) =>
handleCreate(
`${BE_SCHOOL_PAYMENT_MODES_URL}`,
newData,
setRegistrationPaymentModes
)
}
handleDelete={(id) =>
handleDelete(
`${BE_SCHOOL_PAYMENT_MODES_URL}`,
id,
updatedData,
setRegistrationPaymentModes
)
}
@ -200,12 +212,18 @@ const FeesManagement = ({
<PaymentPlanSelector
paymentPlans={tuitionPaymentPlans}
setPaymentPlans={setTuitionPaymentPlans}
handleEdit={(id, updatedData) =>
handleEdit(
handleCreate={(newData) =>
handleCreate(
`${BE_SCHOOL_PAYMENT_PLANS_URL}`,
newData,
setTuitionPaymentPlans
)
}
handleDelete={(id) =>
handleDelete(
`${BE_SCHOOL_PAYMENT_PLANS_URL}`,
id,
updatedData,
setRegistrationPaymentPlans
setTuitionPaymentPlans
)
}
type={1}
@ -215,11 +233,17 @@ const FeesManagement = ({
<PaymentModeSelector
paymentModes={tuitionPaymentModes}
setPaymentModes={setTuitionPaymentModes}
handleEdit={(id, updatedData) =>
handleEdit(
handleCreate={(newData) =>
handleCreate(
`${BE_SCHOOL_PAYMENT_MODES_URL}`,
newData,
setTuitionPaymentModes
)
}
handleDelete={(id) =>
handleDelete(
`${BE_SCHOOL_PAYMENT_MODES_URL}`,
id,
updatedData,
setTuitionPaymentModes
)
}