mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
547 lines
17 KiB
JavaScript
547 lines
17 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import {
|
|
Download,
|
|
Edit3,
|
|
Trash2,
|
|
FolderPlus,
|
|
FileText,
|
|
AlertTriangle,
|
|
} from 'lucide-react';
|
|
import Modal from '@/components/Modal';
|
|
import Table from '@/components/Table';
|
|
import FormTemplateBuilder from '@/components/Form/FormTemplateBuilder';
|
|
import { BASE_URL } from '@/utils/Url';
|
|
import {
|
|
// GET
|
|
fetchRegistrationFileGroups,
|
|
fetchRegistrationSchoolFileMasters,
|
|
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';
|
|
import FileUploadDocuSeal from '@/components/Structure/Files/FileUploadDocuSeal';
|
|
|
|
export default function FilesGroupsManagement({
|
|
csrfToken,
|
|
selectedEstablishmentId,
|
|
}) {
|
|
const [schoolFileMasters, setSchoolFileMasters] = 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 [removePopupVisible, setRemovePopupVisible] = useState(false);
|
|
const [removePopupMessage, setRemovePopupMessage] = useState('');
|
|
const [removePopupOnConfirm, setRemovePopupOnConfirm] = useState(() => {});
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const { showNotification } = useNotification();
|
|
|
|
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(selectedEstablishmentId),
|
|
fetchRegistrationFileGroups(selectedEstablishmentId),
|
|
fetchRegistrationParentFileMasters(selectedEstablishmentId),
|
|
])
|
|
.then(([dataSchoolFileMasters, groupsData, dataParentFileMasters]) => {
|
|
setGroups(groupsData);
|
|
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);
|
|
});
|
|
}
|
|
}, [selectedEstablishmentId]);
|
|
|
|
const deleteTemplateMaster = (templateMaster) => {
|
|
setRemovePopupVisible(true);
|
|
setRemovePopupMessage(
|
|
`Attention ! \nVous êtes sur le point de supprimer le formulaire "${templateMaster.name}".\nÊtes-vous sûr(e) de vouloir poursuivre l'opération ?`
|
|
);
|
|
setRemovePopupOnConfirm(() => () => {
|
|
setIsLoading(true);
|
|
|
|
// Supprimer le formulaire 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 formulaire "${templateMaster.name}" a été correctement supprimé.`,
|
|
'success',
|
|
'Succès'
|
|
);
|
|
setRemovePopupVisible(false);
|
|
} else {
|
|
showNotification(
|
|
`Erreur lors de la suppression du formulaire "${templateMaster.name}".`,
|
|
'error',
|
|
'Erreur'
|
|
);
|
|
setRemovePopupVisible(false);
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
logger.error('Error deleting file from database:', error);
|
|
showNotification(
|
|
`Erreur lors de la suppression du formulaire "${templateMaster.name}".`,
|
|
'error',
|
|
'Erreur'
|
|
);
|
|
setRemovePopupVisible(false);
|
|
})
|
|
.finally(() => {
|
|
setIsLoading(false);
|
|
});
|
|
});
|
|
};
|
|
|
|
const editTemplateMaster = (file) => {
|
|
setIsEditing(true);
|
|
setFileToEdit(file);
|
|
setIsModalOpen(true);
|
|
};
|
|
|
|
const handleCreateTemplateMaster = ({ name, group_ids, formMasterData }) => {
|
|
const data = {
|
|
name: name,
|
|
groups: group_ids,
|
|
formMasterData: formMasterData, // Envoyer directement l'objet
|
|
};
|
|
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);
|
|
showNotification(
|
|
`Le formulaire "${name}" a été créé avec succès.`,
|
|
'success',
|
|
'Succès'
|
|
);
|
|
})
|
|
.catch((error) => {
|
|
logger.error('Error creating form:', error);
|
|
showNotification(
|
|
'Erreur lors de la création du formulaire',
|
|
'error',
|
|
'Erreur'
|
|
);
|
|
});
|
|
};
|
|
|
|
const handleEditTemplateMaster = ({
|
|
name,
|
|
group_ids,
|
|
formMasterData,
|
|
id,
|
|
}) => {
|
|
const data = {
|
|
name: name,
|
|
groups: group_ids,
|
|
formMasterData: formMasterData,
|
|
};
|
|
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);
|
|
showNotification(
|
|
`Le formulaire "${name}" a été modifié avec succès.`,
|
|
'success',
|
|
'Succès'
|
|
);
|
|
})
|
|
.catch((error) => {
|
|
logger.error('Error editing form:', error);
|
|
showNotification(
|
|
'Erreur lors de la modification du formulaire',
|
|
'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) => (
|
|
<div className="flex items-center justify-center gap-2">
|
|
<button
|
|
onClick={() => editTemplateMaster(row)}
|
|
className="text-blue-500 hover:text-blue-700"
|
|
title="Modifier le formulaire"
|
|
>
|
|
<Edit3 className="w-5 h-5" />
|
|
</button>
|
|
<button
|
|
onClick={() => deleteTemplateMaster(row)}
|
|
className="text-red-500 hover:text-red-700"
|
|
title="Supprimer le formulaire"
|
|
>
|
|
<Trash2 className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
),
|
|
},
|
|
];
|
|
|
|
const columnsGroups = [
|
|
{ name: 'Nom du dossier', transform: (row) => row.name },
|
|
{ name: 'Description', transform: (row) => row.description },
|
|
{
|
|
name: 'Actions',
|
|
transform: (row) => (
|
|
<div className="flex items-center justify-center gap-2">
|
|
<button
|
|
onClick={() => handleGroupEdit(row)}
|
|
className="text-blue-500 hover:text-blue-700"
|
|
>
|
|
<Edit3 className="w-5 h-5" />
|
|
</button>
|
|
<button
|
|
onClick={() => handleGroupDelete(row.id)}
|
|
className="text-red-500 hover:text-red-700"
|
|
>
|
|
<Trash2 className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
),
|
|
},
|
|
];
|
|
|
|
if (isLoading) {
|
|
return <Loader />;
|
|
}
|
|
|
|
return (
|
|
<div className="w-full">
|
|
{/* Modal pour les formulaires */}
|
|
<Modal
|
|
isOpen={isModalOpen}
|
|
setIsOpen={(isOpen) => {
|
|
setIsModalOpen(isOpen);
|
|
if (!isOpen) {
|
|
setFileToEdit(null);
|
|
setIsEditing(false);
|
|
}
|
|
}}
|
|
title={isEditing ? 'Modification du formulaire' : 'Créer un formulaire'}
|
|
modalClassName="w-11/12 h-5/6"
|
|
>
|
|
<FormTemplateBuilder
|
|
onSave={
|
|
isEditing ? handleEditTemplateMaster : handleCreateTemplateMaster
|
|
}
|
|
initialData={fileToEdit}
|
|
groups={groups}
|
|
isEditing={isEditing}
|
|
/>
|
|
</Modal>
|
|
|
|
{/* Modal pour les groupes */}
|
|
<Modal
|
|
isOpen={isGroupModalOpen}
|
|
setIsOpen={setIsGroupModalOpen}
|
|
title={
|
|
groupToEdit ? 'Modifier le dossier' : "Création d'un nouveau dossier"
|
|
}
|
|
>
|
|
<RegistrationFileGroupForm
|
|
onSubmit={handleGroupSubmit}
|
|
initialData={groupToEdit}
|
|
/>
|
|
</Modal>
|
|
|
|
{/* Section Groupes de fichiers */}
|
|
<div className="mt-8 w-3/5">
|
|
<SectionHeader
|
|
icon={FolderPlus}
|
|
title="Dossiers d'inscriptions"
|
|
description="Gérez les dossiers d'inscription pour organiser vos documents."
|
|
button={true}
|
|
buttonOpeningModal={true}
|
|
onClick={() => setIsGroupModalOpen(true)}
|
|
/>
|
|
<Table
|
|
data={groups}
|
|
columns={columnsGroups}
|
|
emptyMessage={
|
|
<AlertMessage
|
|
type="warning"
|
|
title="Aucun dossier d'inscription enregistré"
|
|
message="Veuillez procéder à la création d'un nouveau dossier d'inscription"
|
|
/>
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
{/* Section Formulaires */}
|
|
<div className="mt-12 mb-4 w-3/5">
|
|
<SectionHeader
|
|
icon={FileText}
|
|
title="Formulaires personnalisés"
|
|
description="Créez et gérez vos formulaires d'inscription personnalisés."
|
|
button={true}
|
|
buttonOpeningModal={true}
|
|
onClick={() => {
|
|
setIsModalOpen(true);
|
|
setIsEditing(false);
|
|
setFileToEdit(null);
|
|
}}
|
|
/>
|
|
<Table
|
|
data={filteredFiles}
|
|
columns={columnsFiles}
|
|
emptyMessage={
|
|
<AlertMessage
|
|
type="warning"
|
|
title="Aucun formulaire enregistré"
|
|
message="Veuillez procéder à la création d'un nouveau formulaire d'inscription"
|
|
/>
|
|
}
|
|
/>
|
|
</div>
|
|
|
|
{/* Section Pièces à fournir */}
|
|
<ParentFilesSection
|
|
parentFiles={parentFiles}
|
|
setParentFileMasters={setParentFileMasters}
|
|
groups={groups}
|
|
handleCreate={handleCreate}
|
|
handleEdit={handleEdit}
|
|
handleDelete={handleDelete}
|
|
/>
|
|
<Popup
|
|
isOpen={removePopupVisible}
|
|
message={removePopupMessage}
|
|
onConfirm={removePopupOnConfirm}
|
|
onCancel={() => setRemovePopupVisible(false)}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|