Files
n3wt-school/Front-End/src/components/PaymentPlanSelector.js

149 lines
4.7 KiB
JavaScript

import React, { useState, useEffect, useMemo } from 'react';
import { Calendar } from 'lucide-react';
import Table from '@/components/Table';
import Popup from '@/components/Popup';
import logger from '@/utils/logger';
import { useEstablishment } from '@/context/EstablishmentContext';
import CheckBox from '@/components/Form/CheckBox';
const paymentPlansOptions = [
{ 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 },
];
/**
* Affiche les plans de paiement communs aux deux types de frais.
* Quand `allPaymentPlans` est fourni (mode unifié), un plan coché est créé pour
* les deux types (inscription 0 ET scolarité 1) en même temps.
*
* Props (mode unifié) :
* allPaymentPlans : [{plan_type, type, ...}, ...] - liste combinée des deux types
* handleCreate : (data) => Promise - avec type et establishment déjà présent dans data
* handleDelete : (id) => Promise
*
* Props (mode legacy) :
* paymentPlans, handleCreate, handleDelete, type
*/
const PaymentPlanSelector = ({
paymentPlans,
allPaymentPlans,
handleCreate,
handleDelete,
type,
}) => {
const [popupVisible, setPopupVisible] = useState(false);
const [popupMessage, setPopupMessage] = useState('');
const { selectedEstablishmentId } = useEstablishment();
const [checkedPlans, setCheckedPlans] = useState([]);
const plans = useMemo(
() =>
Array.isArray(allPaymentPlans)
? allPaymentPlans
: Array.isArray(paymentPlans)
? paymentPlans
: [],
[allPaymentPlans, paymentPlans]
);
const unified = !!allPaymentPlans;
// Un plan est coché si au moins un enregistrement existe pour cette option
const isChecked = (planOption) => checkedPlans.includes(planOption.id);
const handlePlanToggle = (planOption) => {
if (isChecked(planOption)) {
// Supprimer tous les enregistrements correspondant à cette option (les deux types en mode unifié)
const toDelete = plans.filter(
(p) =>
(typeof p.plan_type === 'object' ? p.plan_type.id : p.plan_type) ===
planOption.id
);
setCheckedPlans((prev) => prev.filter((id) => id !== planOption.id));
toDelete.forEach((p) =>
handleDelete(p.id, null).catch((e) => logger.error(e))
);
} else {
setCheckedPlans((prev) => [...prev, planOption.id]);
if (unified) {
// Créer pour inscription (0) et scolarité (1)
[0, 1].forEach((t) =>
handleCreate({
plan_type: planOption.id,
type: t,
establishment: selectedEstablishmentId,
}).catch((e) => logger.error(e))
);
} else {
handleCreate({
plan_type: planOption.id,
type,
establishment: selectedEstablishmentId,
}).catch((e) => logger.error(e));
}
}
};
useEffect(() => {
if (plans.length > 0) {
const ids = plans.map((plan) =>
typeof plan.plan_type === 'object' ? plan.plan_type.id : plan.plan_type
);
setCheckedPlans([...new Set(ids)]);
} else {
setCheckedPlans([]);
}
}, [plans]);
return (
<div className="space-y-4">
<div className="flex items-center mb-4">
<Calendar className="w-6 h-6 text-emerald-500 mr-2" />
<h2 className="text-xl font-semibold">Paiement en plusieurs fois</h2>
</div>
<div className="grid grid-cols-2 gap-4">
<Table
data={paymentPlansOptions}
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;
}
}}
/>
</div>
<Popup
isOpen={popupVisible}
message={popupMessage}
onConfirm={() => setPopupVisible(false)}
onCancel={() => setPopupVisible(false)}
uniqueConfirmButton={true}
/>
</div>
);
};
export default PaymentPlanSelector;