feat: Précablage du formulaire dynamique [N3WTS-17]

This commit is contained in:
Luc SORIGNET
2025-11-30 17:24:25 +01:00
parent 7486f6c5ce
commit dd00cba385
41 changed files with 2637 additions and 606 deletions

View File

@ -1,13 +1,20 @@
import React, { useState, useEffect } from 'react';
import { Download, Edit3, Trash2, FolderPlus, Signature, AlertTriangle } from 'lucide-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,
fetchRegistrationSchoolFileTemplates,
fetchRegistrationParentFileMasters,
// POST
createRegistrationFileGroup,
@ -20,7 +27,7 @@ import {
// DELETE
deleteRegistrationFileGroup,
deleteRegistrationSchoolFileMaster,
deleteRegistrationParentFileMaster
deleteRegistrationParentFileMaster,
} from '@/app/actions/registerFileGroupAction';
import RegistrationFileGroupForm from '@/components/Structure/Files/RegistrationFileGroupForm';
import logger from '@/utils/logger';
@ -34,10 +41,9 @@ import FileUploadDocuSeal from '@/components/Structure/Files/FileUploadDocuSeal'
export default function FilesGroupsManagement({
csrfToken,
selectedEstablishmentId
selectedEstablishmentId,
}) {
const [schoolFileMasters, setSchoolFileMasters] = useState([]);
const [schoolFileTemplates, setSchoolFileTemplates] = useState([]);
const [parentFiles, setParentFileMasters] = useState([]);
const [groups, setGroups] = useState([]);
const [selectedGroup, setSelectedGroup] = useState(null);
@ -46,7 +52,6 @@ export default function FilesGroupsManagement({
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('');
@ -54,10 +59,6 @@ export default function FilesGroupsManagement({
const [isLoading, setIsLoading] = useState(false);
const { showNotification } = useNotification();
const handleReloadTemplates = () => {
setReloadTemplates(true);
};
const transformFileData = (file, groups) => {
const groupInfos = file.groups.map(
(groupId) =>
@ -77,79 +78,67 @@ export default function FilesGroupsManagement({
Promise.all([
fetchRegistrationSchoolFileMasters(selectedEstablishmentId),
fetchRegistrationFileGroups(selectedEstablishmentId),
fetchRegistrationSchoolFileTemplates(selectedEstablishmentId),
fetchRegistrationParentFileMasters(selectedEstablishmentId),
])
.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);
}
)
.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);
})
.finally(() => {
setReloadTemplates(false);
});
}
}, [reloadTemplates, selectedEstablishmentId]);
}, [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 ?`
`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 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 {
// 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 document "${templateMaster.name}".`,
`Erreur lors de la suppression du formulaire "${templateMaster.name}".`,
'error',
'Erreur'
);
setRemovePopupVisible(false);
})
.finally(() => {
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);
});
});
});
};
@ -159,12 +148,11 @@ export default function FilesGroupsManagement({
setIsModalOpen(true);
};
const handleCreateTemplateMaster = ({ name, group_ids, id, is_required }) => {
const handleCreateTemplateMaster = ({ name, group_ids, formMasterData }) => {
const data = {
name: name,
id: id,
groups: group_ids,
is_required: is_required,
formMasterData: formMasterData, // Envoyer directement l'objet
};
logger.debug(data);
@ -174,18 +162,32 @@ export default function FilesGroupsManagement({
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 uploading file:', error);
logger.error('Error creating form:', error);
showNotification(
'Erreur lors de la création du formulaire',
'error',
'Erreur'
);
});
};
const handleEditTemplateMaster = ({ name, group_ids, id, is_required }) => {
const handleEditTemplateMaster = ({
name,
group_ids,
formMasterData,
id,
}) => {
const data = {
name: name,
id: id,
groups: group_ids,
is_required: is_required,
formMasterData: formMasterData,
};
logger.debug(data);
@ -197,11 +199,16 @@ export default function FilesGroupsManagement({
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 file:', error);
logger.error('Error editing form:', error);
showNotification(
'Erreur lors de la modification du fichier',
'Erreur lors de la modification du formulaire',
'error',
'Erreur'
);
@ -383,24 +390,17 @@ export default function FilesGroupsManagement({
name: 'Actions',
transform: (row) => (
<div className="flex items-center justify-center gap-2">
{row.file && (
<a
href={`${BASE_URL}${row.file}`}
target="_blank"
className="text-blue-500 hover:text-blue-700"
>
<Download className="w-5 h-5" />
</a>
)}
<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>
@ -439,23 +439,26 @@ export default function FilesGroupsManagement({
return (
<div className="w-full">
{/* Modal pour les fichiers */}
{/* Modal pour les formulaires */}
<Modal
isOpen={isModalOpen}
setIsOpen={(isOpen) => {
setIsModalOpen(isOpen);
if (!isOpen) {
setFileToEdit(null);
setIsEditing(false);
}
}}
title={isEditing ? 'Modification du document' : 'Ajouter un document'}
modalClassName="w-4/5 h-4/5"
title={isEditing ? 'Modification du formulaire' : 'Créer un formulaire'}
modalClassName="w-11/12 h-5/6"
>
<FileUploadDocuSeal
handleCreateTemplateMaster={handleCreateTemplateMaster}
handleEditTemplateMaster={handleEditTemplateMaster}
fileToEdit={fileToEdit}
onSuccess={handleReloadTemplates}
<FormTemplateBuilder
onSave={
isEditing ? handleEditTemplateMaster : handleCreateTemplateMaster
}
initialData={fileToEdit}
groups={groups}
isEditing={isEditing}
/>
</Modal>
@ -496,17 +499,18 @@ export default function FilesGroupsManagement({
/>
</div>
{/* Section Fichiers */}
{/* Section Formulaires */}
<div className="mt-12 mb-4 w-3/5">
<SectionHeader
icon={Signature}
title="Formulaires à remplir"
description="Gérez les formulaires nécessitant une signature électronique."
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
@ -516,7 +520,7 @@ export default function FilesGroupsManagement({
<AlertMessage
type="warning"
title="Aucun formulaire enregistré"
message="Veuillez procéder à la création d'un nouveau formulaire à signer"
message="Veuillez procéder à la création d'un nouveau formulaire d'inscription"
/>
}
/>