Files
n3wt-school/Front-End/src/components/Structure/Configuration/SpecialitiesSection.js
N3WT DE COMPET c269b89d3d fix: Calcul du montant total des tarif par RF + affichage des tarifs
actifs lors de la création d'un RF [#26]
2025-02-07 20:36:02 +01:00

241 lines
8.3 KiB
JavaScript

import { Plus, Trash2, Edit3, Check, X, BookOpen } from 'lucide-react';
import { useState } from 'react';
import Table from '@/components/Table';
import Popup from '@/components/Popup';
import InputTextWithColorIcon from '@/components/InputTextWithColorIcon';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import SpecialityItem from '@/components/Structure/Configuration/SpecialityItem';
const SpecialitiesSection = ({ specialities, setSpecialities, handleCreate, handleEdit, handleDelete }) => {
const [newSpeciality, setNewSpeciality] = useState(null);
const [editingSpeciality, setEditingSpeciality] = 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(() => {});
// Récupération des messages d'erreur
const getError = (field) => {
return localErrors?.[field]?.[0];
};
const handleAddSpeciality = () => {
setNewSpeciality({ id: Date.now(), name: '', color_code: '' });
};
const handleRemoveSpeciality = (id) => {
return handleDelete(id)
.then(() => {
setSpecialities(prevSpecialities => prevSpecialities.filter(speciality => speciality.id !== id));
})
.catch(error => {
console.error(error);
});
};
const handleSaveNewSpeciality = () => {
if (
newSpeciality.name) {
handleCreate(newSpeciality)
.then((createdSpeciality) => {
setSpecialities([createdSpeciality, ...specialities]);
setNewSpeciality(null);
setLocalErrors({});
})
.catch((error) => {
console.error('Error:', error.message);
if (error.details) {
console.error('Form errors:', error.details);
setLocalErrors(error.details);
}
});
} else {
setPopupMessage("Tous les champs doivent être remplis et valides");
setPopupVisible(true);
}
};
const handleUpdateSpeciality = (id, updatedSpeciality) => {
if (
updatedSpeciality.name) {
handleEdit(id, updatedSpeciality)
.then((updatedSpeciality) => {
setSpecialities(specialities.map(speciality => speciality.id === id ? updatedSpeciality : speciality));
setEditingSpeciality(null);
setLocalErrors({});
})
.catch((error) => {
console.error('Error:', error.message);
if (error.details) {
console.error('Form errors:', error.details);
setLocalErrors(error.details);
}
});
} else {
setPopupMessage("Tous les champs doivent être remplis et valides");
setPopupVisible(true);
}
};
const handleChange = (e) => {
const { name, value } = e.target;
let parsedValue = value;
if (name.includes('_color')) {
parsedValue = value;
}
const fieldName = name.includes('_color') ? 'color_code' : name;
if (editingSpeciality) {
setFormData((prevData) => ({
...prevData,
[fieldName]: parsedValue,
}));
} else if (newSpeciality) {
setNewSpeciality((prevData) => ({
...prevData,
[fieldName]: parsedValue,
}));
}
};
const renderSpecialityCell = (speciality, column) => {
const isEditing = editingSpeciality === speciality.id;
const isCreating = newSpeciality && newSpeciality.id === speciality.id;
const currentData = isEditing ? formData : newSpeciality;
if (isEditing || isCreating) {
switch (column) {
case 'LIBELLE':
return (
<InputTextWithColorIcon
name="name"
textValue={currentData.name}
colorValue={currentData.color_code}
onTextChange={handleChange}
onColorChange={handleChange}
placeholder="Nom de la spécialité"
errorMsg={getError('name')}
/>
);
case 'ACTIONS':
return (
<div className="flex justify-center space-x-2">
<button
type="button"
onClick={() => (isEditing ? handleUpdateSpeciality(editingSpeciality, formData) : handleSaveNewSpeciality())}
className="text-green-500 hover:text-green-700"
>
<Check className="w-5 h-5" />
</button>
<button
type="button"
onClick={() => (isEditing ? setEditingSpeciality(null) : setNewSpeciality(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 (
<SpecialityItem key={speciality.id} speciality={speciality} />
);
case 'MISE A JOUR':
return speciality.updated_date_formatted;
case 'ACTIONS':
return (
<div className="flex justify-center space-x-2">
<button
type="button"
onClick={() => setEditingSpeciality(speciality.id) || setFormData(speciality)}
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 la spécialité " + speciality.name + ".\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?");
setRemovePopupOnConfirm(() => () => {
handleRemoveSpeciality(speciality.id)
.then(data => {
console.log('Success:', data);
setPopupMessage("La spécialité " + speciality.name + " a été correctement supprimée");
setPopupVisible(true);
setRemovePopupVisible(false);
})
.catch(error => {
console.error('Error archiving data:', error);
setPopupMessage("Erreur lors de la suppression de la spécialité " + speciality.name);
setPopupVisible(true);
setRemovePopupVisible(false);
});
});
}}
className="text-red-500 hover:text-red-700"
>
<Trash2 className="w-5 h-5" />
</button>
</div>
);
default:
return null;
}
}
};
const columns = [
{ name: 'LIBELLE', label: 'Libellé' },
{ name: 'MISE A JOUR', label: 'Date mise à jour' },
{ name: 'ACTIONS', label: 'Actions' }
];
return (
<DndProvider backend={HTML5Backend}>
<div className="space-y-4">
<div className="flex justify-between items-center">
<div className="flex items-center mb-4">
<BookOpen className="w-6 h-6 text-emerald-500 mr-2" />
<h2 className="text-xl font-semibold">Spécialités</h2>
</div>
<button type="button" onClick={handleAddSpeciality} className="text-emerald-500 hover:text-emerald-700">
<Plus className="w-5 h-5" />
</button>
</div>
<Table
data={newSpeciality ? [newSpeciality, ...specialities] : specialities}
columns={columns}
renderCell={renderSpecialityCell}
/>
<Popup
visible={popupVisible}
message={popupMessage}
onConfirm={() => setPopupVisible(false)}
onCancel={() => setPopupVisible(false)}
uniqueConfirmButton={true}
/>
<Popup
visible={removePopupVisible}
message={removePopupMessage}
onConfirm={removePopupOnConfirm}
onCancel={() => setRemovePopupVisible(false)}
/>
</div>
</DndProvider>
);
};
export default SpecialitiesSection;