import React, { useState, useEffect } from 'react'; import { Download, Edit3, Trash2, FolderPlus, Signature } from 'lucide-react'; import Modal from '@/components/Modal'; import Table from '@/components/Table'; import FileUploadDocuSeal from '@/components/Structure/Files/FileUploadDocuSeal'; import { BASE_URL } from '@/utils/Url'; import { // GET fetchRegistrationFileGroups, fetchRegistrationSchoolFileMasters, fetchRegistrationSchoolFileTemplates, fetchRegistrationParentFileMasters, // POST createRegistrationFileGroup, createRegistrationSchoolFileMaster, createRegistrationParentFileMaster, // PUT editRegistrationFileGroup, editRegistrationSchoolFileMaster, editRegistrationParentFileMaster, // DELETE deleteRegistrationFileGroup, deleteRegistrationSchoolFileMaster, deleteRegistrationParentFileMaster, } from '@/app/actions/registerFileGroupAction'; import RegistrationFileGroupForm from '@/components/Structure/Files/RegistrationFileGroupForm'; import logger from '@/utils/logger'; import ParentFilesSection from '@/components/Structure/Files/ParentFilesSection'; import SectionHeader from '@/components/SectionHeader'; import Popup from '@/components/Popup'; import Loader from '@/components/Loader'; import { useNotification } from '@/context/NotificationContext'; import AlertMessage from '@/components/AlertMessage'; export default function FilesGroupsManagement({ csrfToken, selectedEstablishmentId, }) { const [schoolFileMasters, setSchoolFileMasters] = useState([]); const [schoolFileTemplates, setSchoolFileTemplates] = useState([]); const [parentFiles, setParentFileMasters] = useState([]); const [groups, setGroups] = useState([]); const [selectedGroup, setSelectedGroup] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [isEditing, setIsEditing] = useState(false); const [fileToEdit, setFileToEdit] = useState(null); const [isGroupModalOpen, setIsGroupModalOpen] = useState(false); const [groupToEdit, setGroupToEdit] = useState(null); const [reloadTemplates, setReloadTemplates] = useState(false); const [removePopupVisible, setRemovePopupVisible] = useState(false); const [removePopupMessage, setRemovePopupMessage] = useState(''); const [removePopupOnConfirm, setRemovePopupOnConfirm] = useState(() => {}); const [isLoading, setIsLoading] = useState(false); const { showNotification } = useNotification(); const handleReloadTemplates = () => { setReloadTemplates(true); }; const transformFileData = (file, groups) => { const groupInfos = file.groups.map( (groupId) => groups.find((g) => g.id === groupId) || { id: groupId, name: 'Groupe inconnu', } ); return { ...file, groups: groupInfos, }; }; useEffect(() => { if (selectedEstablishmentId) { Promise.all([ fetchRegistrationSchoolFileMasters(), fetchRegistrationFileGroups(selectedEstablishmentId), fetchRegistrationSchoolFileTemplates(), fetchRegistrationParentFileMasters(), ]) .then( ([ dataSchoolFileMasters, groupsData, dataSchoolFileTemplates, dataParentFileMasters, ]) => { setGroups(groupsData); setSchoolFileTemplates(dataSchoolFileTemplates); setParentFileMasters(dataParentFileMasters); // Transformer chaque fichier pour inclure les informations complètes du groupe const transformedFiles = dataSchoolFileMasters.map((file) => transformFileData(file, groupsData) ); setSchoolFileMasters(transformedFiles); } ) .catch((err) => { logger.debug(err.message); }) .finally(() => { setReloadTemplates(false); }); } }, [reloadTemplates, selectedEstablishmentId]); const deleteTemplateMaster = (templateMaster) => { setRemovePopupVisible(true); setRemovePopupMessage( `Attentions ! \nVous êtes sur le point de supprimer le document "${templateMaster.name}".\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?` ); setRemovePopupOnConfirm(() => () => { setIsLoading(true); // Supprimer les clones associés via l'API DocuSeal const removeClonesPromises = schoolFileTemplates .filter((template) => template.master === templateMaster.id) .map((template) => removeTemplate(template.id)); // Ajouter la suppression du master à la liste des promesses removeClonesPromises.push(removeTemplate(templateMaster.id)); // Attendre que toutes les suppressions dans DocuSeal soient terminées Promise.all(removeClonesPromises) .then((responses) => { const allSuccessful = responses.every((response) => response.ok); if (allSuccessful) { logger.debug('Master et clones supprimés avec succès de DocuSeal.'); // Supprimer le template master de la base de données deleteRegistrationSchoolFileMaster(templateMaster.id, csrfToken) .then((response) => { if (response.ok) { setSchoolFileMasters( schoolFileMasters.filter( (fichier) => fichier.id !== templateMaster.id ) ); showNotification( `Le document "${templateMaster.name}" a été correctement supprimé.`, 'success', 'Succès' ); setRemovePopupVisible(false); setIsLoading(false); } else { showNotification( `Erreur lors de la suppression du document "${templateMaster.name}".`, 'error', 'Erreur' ); setRemovePopupVisible(false); setIsLoading(false); } }) .catch((error) => { logger.error('Error deleting file from database:', error); showNotification( `Erreur lors de la suppression du document "${templateMaster.name}".`, 'error', 'Erreur' ); setRemovePopupVisible(false); setIsLoading(false); }); } else { showNotification( `Erreur lors de la suppression du document "${templateMaster.name}".`, 'error', 'Erreur' ); setRemovePopupVisible(false); setIsLoading(false); } }) .catch((error) => { logger.error('Error removing template from DocuSeal:', error); showNotification( `Erreur lors de la suppression du document "${templateMaster.name}".`, 'error', 'Erreur' ); setRemovePopupVisible(false); setIsLoading(false); }); }); }; const removeTemplate = (templateId) => { return fetch('/api/docuseal/removeTemplate/', { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken, }, body: JSON.stringify({ templateId, }), }) .then((response) => { if (!response.ok) { return response.json().then((err) => { throw new Error(err.message); }); } return response; }) .catch((error) => { logger.error('Error removing template:', error); throw error; }); }; const editTemplateMaster = (file) => { setIsEditing(true); setFileToEdit(file); setIsModalOpen(true); }; const handleCreateTemplateMaster = ({ name, group_ids, id, is_required }) => { const data = { name: name, id: id, groups: group_ids, is_required: is_required, }; logger.debug(data); createRegistrationSchoolFileMaster(data, csrfToken) .then((data) => { // Transformer le nouveau fichier avec les informations du groupe const transformedFile = transformFileData(data, groups); setSchoolFileMasters((prevFiles) => [...prevFiles, transformedFile]); setIsModalOpen(false); }) .catch((error) => { logger.error('Error uploading file:', error); }); }; const handleEditTemplateMaster = ({ name, group_ids, id, is_required }) => { const data = { name: name, id: id, groups: group_ids, is_required: is_required, }; logger.debug(data); editRegistrationSchoolFileMaster(id, data, csrfToken) .then((data) => { // Transformer le fichier mis à jour avec les informations du groupe const transformedFile = transformFileData(data, groups); setSchoolFileMasters((prevFichiers) => prevFichiers.map((f) => (f.id === id ? transformedFile : f)) ); setIsModalOpen(false); }) .catch((error) => { logger.error('Error editing file:', error); showNotification( 'Erreur lors de la modification du fichier', 'error', 'Erreur' ); }); }; const handleGroupSubmit = (groupData) => { if (groupToEdit) { editRegistrationFileGroup(groupToEdit.id, groupData, csrfToken) .then((updatedGroup) => { setGroups( groups.map((group) => group.id === groupToEdit.id ? updatedGroup : group ) ); setGroupToEdit(null); setIsGroupModalOpen(false); }) .catch((error) => { logger.error('Error handling group:', error); showNotification( "Erreur lors de l'opération sur le groupe", 'error', 'Erreur' ); }); } else { // Ajouter l'établissement sélectionné lors de la création d'un nouveau groupe const newGroupData = { ...groupData, establishment: selectedEstablishmentId, }; createRegistrationFileGroup(newGroupData, csrfToken) .then((newGroup) => { setGroups([...groups, newGroup]); setIsGroupModalOpen(false); }) .catch((error) => { logger.error('Error handling group:', error); showNotification( "Erreur lors de l'opération sur le groupe", 'error', 'Erreur' ); }); } }; const handleGroupEdit = (group) => { setGroupToEdit(group); setIsGroupModalOpen(true); }; const handleGroupDelete = (groupId) => { // Vérifier si des schoolFileMasters utilisent ce groupe const filesInGroup = schoolFileMasters.filter( (file) => file.group && file.group.id === groupId ); if (filesInGroup.length > 0) { showNotification( "Impossible de supprimer ce groupe car il contient déjà des formulaires. Veuillez d'abord retirer tous les formules de ce groupe.", 'error', 'Erreur' ); return; } setRemovePopupVisible(true); setRemovePopupMessage( 'Attentions ! \nÊtes-vous sûr de vouloir supprimer ce groupe ?' ); setRemovePopupOnConfirm(() => () => { setIsLoading(true); deleteRegistrationFileGroup(groupId, csrfToken) .then((response) => { if (response.status === 409) { throw new Error('Ce groupe est lié à des inscriptions existantes.'); } if (!response.ok) { throw new Error('Erreur lors de la suppression du groupe.'); } setGroups(groups.filter((group) => group.id !== groupId)); setRemovePopupVisible(false); setIsLoading(false); showNotification('Groupe supprimé avec succès.', 'success', 'Succès'); }) .catch((error) => { logger.error('Error deleting group:', error); setRemovePopupVisible(false); setIsLoading(false); showNotification( error.message || "Erreur lors de la suppression du groupe. Vérifiez qu'aucune inscription n'utilise ce groupe.", 'error', 'Erreur' ); }); }); }; const handleCreate = (newParentFile) => { return createRegistrationParentFileMaster(newParentFile, csrfToken) .then((response) => { const createdFile = response; // Ajouter le nouveau fichier parent à la liste existante setParentFileMasters((prevFiles) => [...prevFiles, createdFile]); logger.debug('Document parent créé avec succès:', createdFile); return createdFile; }) .catch((error) => { logger.error('Erreur lors de la création du document parent:', error); showNotification( 'Une erreur est survenue lors de la création du document parent.', 'error', 'Erreur' ); throw error; }); }; const handleEdit = (id, updatedFile) => { return editRegistrationParentFileMaster(id, updatedFile, csrfToken) .then((response) => { const modifiedFile = response.data; // Extraire les données mises à jour // Mettre à jour la liste des fichiers parents setParentFileMasters((prevFiles) => prevFiles.map((file) => (file.id === id ? modifiedFile : file)) ); logger.debug('Document parent mis à jour avec succès:', modifiedFile); return modifiedFile; // Retourner le fichier mis à jour }) .catch((error) => { logger.error( 'Erreur lors de la modification du document parent:', error ); showNotification( 'Une erreur est survenue lors de la modification du document parent.', 'error', 'Erreur' ); throw error; }); }; const handleDelete = (id) => { return deleteRegistrationParentFileMaster(id, csrfToken) .then(() => { // Mettre à jour la liste des fichiers parents en supprimant l'élément correspondant setParentFileMasters((prevFiles) => prevFiles.filter((file) => file.id !== id) ); logger.debug('Document parent supprimé avec succès:', id); }) .catch((error) => { logger.error('Erreur lors de la suppression du fichier parent:', error); }); }; const filteredFiles = schoolFileMasters.filter((file) => { if (!selectedGroup) return true; return ( file.groups && file.groups.some((group) => group.id === parseInt(selectedGroup)) ); }); const columnsFiles = [ { name: 'Nom du formulaire', transform: (row) => row.name }, { name: "Dossiers d'inscription", transform: (row) => row.groups && row.groups.length > 0 ? row.groups.map((group) => group.name).join(', ') : 'Aucun', }, { name: 'Actions', transform: (row) => (
), }, ]; const columnsGroups = [ { name: 'Nom du dossier', transform: (row) => row.name }, { name: 'Description', transform: (row) => row.description }, { name: 'Actions', transform: (row) => (