mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
383 lines
12 KiB
JavaScript
383 lines
12 KiB
JavaScript
import React, { useState } from 'react';
|
|
import { Trash2, Edit3, Check, X, Percent, EuroIcon, Tag } from 'lucide-react';
|
|
import Table from '@/components/Table';
|
|
import Popup from '@/components/Popup';
|
|
import CheckBox from '@/components/CheckBox';
|
|
import InputText from '@/components/InputText';
|
|
import logger from '@/utils/logger';
|
|
import SectionHeader from '@/components/SectionHeader';
|
|
import { useEstablishment } from '@/context/EstablishmentContext';
|
|
|
|
const DiscountsSection = ({
|
|
discounts,
|
|
setDiscounts,
|
|
handleCreate,
|
|
handleEdit,
|
|
handleDelete,
|
|
type,
|
|
subscriptionMode = false,
|
|
selectedDiscounts,
|
|
handleDiscountSelection,
|
|
}) => {
|
|
const [editingDiscount, setEditingDiscount] = useState(null);
|
|
const [newDiscount, setNewDiscount] = useState(null);
|
|
const [formData, setFormData] = useState({});
|
|
const [localErrors, setLocalErrors] = useState({});
|
|
const [popupVisible, setPopupVisible] = useState(false);
|
|
const [popupMessage, setPopupMessage] = useState('');
|
|
const [removePopupVisible, setRemovePopupVisible] = useState(false);
|
|
const [removePopupMessage, setRemovePopupMessage] = useState('');
|
|
const [removePopupOnConfirm, setRemovePopupOnConfirm] = useState(() => {});
|
|
|
|
const { selectedEstablishmentId } = useEstablishment();
|
|
|
|
const handleAddDiscount = () => {
|
|
setNewDiscount({
|
|
id: Date.now(),
|
|
name: '',
|
|
amount: '',
|
|
description: '',
|
|
discount_type: 0,
|
|
type: type,
|
|
establishment: selectedEstablishmentId,
|
|
});
|
|
};
|
|
|
|
const handleRemoveDiscount = (id) => {
|
|
return handleDelete(id)
|
|
.then(() => {
|
|
setDiscounts((prevDiscounts) =>
|
|
prevDiscounts.filter((discount) => discount.id !== id)
|
|
);
|
|
})
|
|
.catch((error) => {
|
|
logger.error(error);
|
|
});
|
|
};
|
|
|
|
const handleSaveNewDiscount = () => {
|
|
if (newDiscount.name && newDiscount.amount) {
|
|
const discountData = {
|
|
...newDiscount,
|
|
establishment: selectedEstablishmentId,
|
|
};
|
|
handleCreate(discountData)
|
|
.then((createdDiscount) => {
|
|
setDiscounts([createdDiscount, ...discounts]);
|
|
setNewDiscount(null);
|
|
setLocalErrors({});
|
|
})
|
|
.catch((error) => {
|
|
if (error && typeof error === 'object') {
|
|
setLocalErrors(error);
|
|
} else {
|
|
logger.error(error);
|
|
}
|
|
});
|
|
} else {
|
|
setPopupMessage('Tous les champs doivent être remplis');
|
|
setPopupVisible(true);
|
|
}
|
|
};
|
|
|
|
const handleUpdateDiscount = (id, updatedDiscount) => {
|
|
if (updatedDiscount.name && updatedDiscount.amount) {
|
|
handleEdit(id, updatedDiscount)
|
|
.then(() => {
|
|
setEditingDiscount(null);
|
|
setLocalErrors({});
|
|
})
|
|
.catch((error) => {
|
|
if (error && typeof error === 'object') {
|
|
setLocalErrors(error);
|
|
} else {
|
|
logger.error(error);
|
|
}
|
|
});
|
|
} else {
|
|
setPopupMessage('Tous les champs doivent être remplis');
|
|
setPopupVisible(true);
|
|
}
|
|
};
|
|
|
|
const handleToggleDiscountType = (id) => {
|
|
const discount = discounts.find((discount) => discount.id === id);
|
|
if (!discount) return;
|
|
|
|
const updatedData = {
|
|
...discount,
|
|
discount_type: discount.discount_type === 0 ? 1 : 0,
|
|
};
|
|
|
|
handleEdit(id, updatedData)
|
|
.then(() => {
|
|
setDiscounts((prevDiscounts) =>
|
|
prevDiscounts.map((discount) =>
|
|
discount.id === id
|
|
? { ...discount, discount_type: updatedData.discount_type }
|
|
: discount
|
|
)
|
|
);
|
|
})
|
|
.catch((error) => {
|
|
logger.error(error);
|
|
});
|
|
};
|
|
|
|
const handleToggleDiscountTypeEdition = (id) => {
|
|
if (editingDiscount) {
|
|
setFormData((prevData) => ({
|
|
...prevData,
|
|
discount_type: prevData.discount_type === 0 ? 1 : 0,
|
|
}));
|
|
} else if (newDiscount) {
|
|
setNewDiscount((prevData) => ({
|
|
...prevData,
|
|
discount_type: prevData.discount_type === 0 ? 1 : 0,
|
|
}));
|
|
}
|
|
};
|
|
|
|
const handleChange = (e) => {
|
|
const { name, value } = e.target;
|
|
if (editingDiscount) {
|
|
setFormData((prevData) => ({
|
|
...prevData,
|
|
[name]: value,
|
|
}));
|
|
} else if (newDiscount) {
|
|
setNewDiscount((prevData) => ({
|
|
...prevData,
|
|
[name]: value,
|
|
}));
|
|
}
|
|
};
|
|
|
|
const renderInputField = (field, value, onChange, placeholder) => (
|
|
<div className="flex justify-center space-x-2">
|
|
<div className="w-full max-w-xs">
|
|
<InputText
|
|
name={field}
|
|
type={field === 'amount' ? 'number' : 'text'}
|
|
value={value}
|
|
onChange={onChange}
|
|
placeholder={placeholder}
|
|
errorMsg={
|
|
localErrors &&
|
|
localErrors[field] &&
|
|
Array.isArray(localErrors[field])
|
|
? localErrors[field][0]
|
|
: ''
|
|
}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
const renderDiscountCell = (discount, column) => {
|
|
const isEditing = editingDiscount === discount.id;
|
|
const isCreating = newDiscount && newDiscount.id === discount.id;
|
|
const currentData = isEditing ? formData : newDiscount;
|
|
|
|
if (isEditing || isCreating) {
|
|
switch (column) {
|
|
case 'LIBELLE':
|
|
return renderInputField(
|
|
'name',
|
|
currentData.name,
|
|
handleChange,
|
|
'Libellé de la réduction'
|
|
);
|
|
case 'REMISE':
|
|
return (
|
|
<div className="flex justify-center space-x-2">
|
|
{renderInputField(
|
|
'amount',
|
|
currentData.amount,
|
|
handleChange,
|
|
'Montant'
|
|
)}
|
|
|
|
<button
|
|
type="button"
|
|
onClick={() => handleToggleDiscountTypeEdition(discount.id)}
|
|
className="flex justify-center items-center text-emerald-500 hover:text-emerald-700 ml-2"
|
|
>
|
|
{currentData.discount_type === 0 ? (
|
|
<EuroIcon className="w-5 h-5" />
|
|
) : (
|
|
<Percent className="w-5 h-5" />
|
|
)}
|
|
</button>
|
|
</div>
|
|
);
|
|
case 'DESCRIPTION':
|
|
return renderInputField(
|
|
'description',
|
|
currentData.description,
|
|
handleChange,
|
|
'Description'
|
|
);
|
|
case 'ACTIONS':
|
|
return (
|
|
<div className="flex justify-center space-x-2">
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
isEditing
|
|
? handleUpdateDiscount(editingDiscount, formData)
|
|
: handleSaveNewDiscount()
|
|
}
|
|
className="text-green-500 hover:text-green-700"
|
|
>
|
|
<Check className="w-5 h-5" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
isEditing ? setEditingDiscount(null) : setNewDiscount(null)
|
|
}
|
|
className="text-red-500 hover:text-red-700"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
);
|
|
default:
|
|
return null;
|
|
}
|
|
} else {
|
|
switch (column) {
|
|
case 'LIBELLE':
|
|
return discount.name;
|
|
case 'REMISE':
|
|
return discount.discount_type === 0
|
|
? `${discount.amount} €`
|
|
: `${discount.amount} %`;
|
|
case 'DESCRIPTION':
|
|
return discount.description;
|
|
case 'MISE A JOUR':
|
|
return discount.updated_at_formatted;
|
|
case 'ACTIONS':
|
|
return (
|
|
<div className="flex justify-center space-x-2">
|
|
<button
|
|
type="button"
|
|
onClick={() => handleToggleDiscountType(discount.id)}
|
|
className="flex justify-center items-center text-emerald-500 hover:text-emerald-700"
|
|
>
|
|
{discount.discount_type === 0 ? (
|
|
<EuroIcon className="w-5 h-5" />
|
|
) : (
|
|
<Percent className="w-5 h-5" />
|
|
)}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
setEditingDiscount(discount.id) || setFormData(discount)
|
|
}
|
|
className="text-blue-500 hover:text-blue-700"
|
|
>
|
|
<Edit3 className="w-5 h-5" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => {
|
|
setRemovePopupVisible(true);
|
|
setRemovePopupMessage(
|
|
"Attentions ! \nVous êtes sur le point de supprimer un tarif personnalisé.\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?"
|
|
);
|
|
setRemovePopupOnConfirm(() => () => {
|
|
handleRemoveDiscount(discount.id)
|
|
.then((data) => {
|
|
logger.debug('Success:', data);
|
|
setPopupMessage('Réduction correctement supprimé');
|
|
setPopupVisible(true);
|
|
setRemovePopupVisible(false);
|
|
})
|
|
.catch((error) => {
|
|
logger.error('Error archiving data:', error);
|
|
setPopupMessage(
|
|
'Erreur lors de la suppression de la réduction'
|
|
);
|
|
setPopupVisible(true);
|
|
setRemovePopupVisible(false);
|
|
});
|
|
});
|
|
}}
|
|
className="text-red-500 hover:text-red-700"
|
|
>
|
|
<Trash2 className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
);
|
|
case '':
|
|
return (
|
|
<div className="flex justify-center">
|
|
<CheckBox
|
|
item={discount}
|
|
formData={{ selectedDiscounts }}
|
|
handleChange={() => handleDiscountSelection(discount.id)}
|
|
fieldName="selectedDiscounts"
|
|
/>
|
|
</div>
|
|
);
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
};
|
|
|
|
const columns = subscriptionMode
|
|
? [
|
|
{ name: 'LIBELLE', label: 'Libellé' },
|
|
{ name: 'DESCRIPTION', label: 'Description' },
|
|
{ name: 'REMISE', label: 'Remise' },
|
|
{ name: '', label: 'Sélection' },
|
|
]
|
|
: [
|
|
{ name: 'LIBELLE', label: 'Libellé' },
|
|
{ name: 'REMISE', label: 'Remise' },
|
|
{ name: 'DESCRIPTION', label: 'Description' },
|
|
{ name: 'MISE A JOUR', label: 'Date mise à jour' },
|
|
{ name: 'ACTIONS', label: 'Actions' },
|
|
];
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
{!subscriptionMode && (
|
|
<SectionHeader
|
|
icon={Tag}
|
|
discountStyle={true}
|
|
title={`${type == 0 ? "Liste des réductions sur les frais d'inscription" : 'Liste des réductions sur les frais de scolarité'}`}
|
|
description={`Gérez ${type == 0 ? " vos réductions sur les frais d'inscription" : ' vos réductions sur les frais de scolarité'}`}
|
|
button={!subscriptionMode}
|
|
onClick={handleAddDiscount}
|
|
/>
|
|
)}
|
|
<Table
|
|
data={newDiscount ? [newDiscount, ...discounts] : discounts}
|
|
columns={columns}
|
|
renderCell={renderDiscountCell}
|
|
defaultTheme="bg-yellow-50"
|
|
/>
|
|
<Popup
|
|
visible={popupVisible}
|
|
message={popupMessage}
|
|
onConfirm={() => setPopupVisible(false)}
|
|
onCancel={() => setPopupVisible(false)}
|
|
uniqueConfirmButton={true}
|
|
/>
|
|
<Popup
|
|
visible={removePopupVisible}
|
|
message={removePopupMessage}
|
|
onConfirm={removePopupOnConfirm}
|
|
onCancel={() => setRemovePopupVisible(false)}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DiscountsSection;
|