mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: Gestion des pièces à fournir par les parents (configuration école)
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Plus, Download, Edit3, Trash2, FolderPlus, Signature } from 'lucide-react';
|
||||
import { Plus, Download, Edit3, Trash2, FolderPlus, Signature, FileText, Check, X } from 'lucide-react';
|
||||
import Modal from '@/components/Modal';
|
||||
import Table from '@/components/Table';
|
||||
import FileUpload from '@/components/Structure/Files/FileUpload';
|
||||
import FileUploadDocuSeal from '@/components/Structure/Files/FileUploadDocuSeal';
|
||||
import { BASE_URL } from '@/utils/Url';
|
||||
import {
|
||||
fetchRegistrationFileGroups,
|
||||
@ -13,10 +13,15 @@ import {
|
||||
createRegistrationTemplateMaster,
|
||||
editRegistrationTemplateMaster,
|
||||
deleteRegistrationTemplateMaster,
|
||||
fetchRegistrationTemplates
|
||||
fetchRegistrationTemplates,
|
||||
fetchRegistrationParentFiles,
|
||||
createRegistrationParentFiles,
|
||||
editRegistrationParentFiles,
|
||||
deleteRegistrationParentFiles
|
||||
} from '@/app/actions/registerFileGroupAction';
|
||||
import RegistrationFileGroupForm from '@/components/Structure/Files/RegistrationFileGroupForm';
|
||||
import logger from '@/utils/logger';
|
||||
import ParentFilesSection from '@/components/Structure/Files/ParentFilesSection';
|
||||
|
||||
export default function FilesGroupsManagement({ csrfToken, selectedEstablishmentId }) {
|
||||
const [templateMasters, setTemplateMasters] = useState([]);
|
||||
@ -29,6 +34,10 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
const [isGroupModalOpen, setIsGroupModalOpen] = useState(false);
|
||||
const [groupToEdit, setGroupToEdit] = useState(null);
|
||||
const [reloadTemplates, setReloadTemplates] = useState(false);
|
||||
const [editingDocumentId, setEditingDocumentId] = useState(null);
|
||||
const [formData, setFormData] = useState({});
|
||||
|
||||
const [parentFiles, setParentFiles] = useState([]);
|
||||
|
||||
const handleReloadTemplates = () => {
|
||||
setReloadTemplates(true);
|
||||
@ -47,10 +56,12 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
Promise.all([
|
||||
fetchRegistrationTemplateMaster(),
|
||||
fetchRegistrationFileGroups(selectedEstablishmentId),
|
||||
fetchRegistrationTemplates()
|
||||
]).then(([filesTemplateMasters, groupsData, filesTemplates]) => {
|
||||
fetchRegistrationTemplates(),
|
||||
fetchRegistrationParentFiles()
|
||||
]).then(([filesTemplateMasters, groupsData, filesTemplates, filesParentFiles]) => {
|
||||
setGroups(groupsData);
|
||||
setTemplates(filesTemplates);
|
||||
setParentFiles(filesParentFiles);
|
||||
// Transformer chaque fichier pour inclure les informations complètes du groupe
|
||||
const transformedFiles = filesTemplateMasters.map(file => transformFileData(file, groupsData));
|
||||
setTemplateMasters(transformedFiles);
|
||||
@ -189,7 +200,13 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
alert('Erreur lors de l\'opération sur le groupe');
|
||||
});
|
||||
} else {
|
||||
createRegistrationFileGroup(groupData, csrfToken)
|
||||
// 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);
|
||||
@ -233,14 +250,135 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
}
|
||||
};
|
||||
|
||||
const renderRequiredDocumentCell = (document, column) => {
|
||||
const isEditing = editingDocumentId === document.id;
|
||||
|
||||
if (isEditing) {
|
||||
switch (column) {
|
||||
case 'Nom de la pièce':
|
||||
return (
|
||||
<InputText
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={(e) => handleChange(e, 'name')}
|
||||
placeholder="Nom de la pièce"
|
||||
className="w-full"
|
||||
/>
|
||||
);
|
||||
case 'Description':
|
||||
return (
|
||||
<InputText
|
||||
name="description"
|
||||
value={formData.description}
|
||||
onChange={(e) => handleChange(e, 'description')}
|
||||
placeholder="Description"
|
||||
className="w-full"
|
||||
/>
|
||||
);
|
||||
case 'Actions':
|
||||
return (
|
||||
<div className="flex justify-center space-x-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleSaveDocument(document.id)}
|
||||
className="text-green-500 hover:text-green-700"
|
||||
>
|
||||
<Check className="w-5 h-5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleCancelEdit}
|
||||
className="text-red-500 hover:text-red-700"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
switch (column) {
|
||||
case 'Nom de la pièce':
|
||||
return <span>{document.name}</span>;
|
||||
case 'Description':
|
||||
return <span>{document.description}</span>;
|
||||
case 'Actions':
|
||||
return (
|
||||
<div className="flex justify-center space-x-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleEditDocument(document)}
|
||||
className="text-blue-500 hover:text-blue-700"
|
||||
>
|
||||
<Edit3 className="w-5 h-5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleDeleteRequiredDocument(document.id)}
|
||||
className="text-red-500 hover:text-red-700"
|
||||
>
|
||||
<Trash2 className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreate = (newParentFile) => {
|
||||
return createRegistrationParentFiles(newParentFile, csrfToken)
|
||||
.then((createdFile) => {
|
||||
// Ajouter le nouveau fichier parent à la liste existante
|
||||
setParentFiles((prevFiles) => [...prevFiles, createdFile]);
|
||||
logger.debug('Document parent créé avec succès:', createdFile);
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error('Erreur lors de la création du document parent:', error);
|
||||
alert('Une erreur est survenue lors de la création du document parent.');
|
||||
});
|
||||
};
|
||||
|
||||
const handleEdit = (id, updatedFile) => {
|
||||
return editRegistrationParentFiles(id, updatedFile, csrfToken)
|
||||
.then((response) => {
|
||||
const modifiedFile = response.data; // Extraire les données mises à jour
|
||||
// Mettre à jour la liste des fichiers parents
|
||||
setParentFiles((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);
|
||||
alert('Une erreur est survenue lors de la modification du document parent.');
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (id) => {
|
||||
return deleteRegistrationParentFiles(id, csrfToken)
|
||||
.then(() => {
|
||||
// Mettre à jour la liste des fichiers parents en supprimant l'élément correspondant
|
||||
setParentFiles((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 = templateMasters.filter(file => {
|
||||
if (!selectedGroup) return true;
|
||||
return file.groups && file.groups.some(group => group.id === parseInt(selectedGroup));
|
||||
});
|
||||
|
||||
const columnsFiles = [
|
||||
{ name: 'Nom du fichier', transform: (row) => row.name },
|
||||
{ name: 'Groupes', transform: (row) => row.groups && row.groups.length > 0 ? row.groups.map(group => group.name).join(', ') : 'Aucun' },
|
||||
{ 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">
|
||||
{row.file && (
|
||||
@ -259,7 +397,7 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
];
|
||||
|
||||
const columnsGroups = [
|
||||
{ name: 'Nom du groupe', transform: (row) => row.name },
|
||||
{ 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">
|
||||
@ -273,8 +411,15 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
)}
|
||||
];
|
||||
|
||||
const columnsRequiredDocuments = [
|
||||
{ name: 'Nom de la pièce', transform: (row) => renderRequiredDocumentCell(row, 'Nom de la pièce') },
|
||||
{ name: 'Description', transform: (row) => renderRequiredDocumentCell(row, 'Description') },
|
||||
{ name: 'Actions', transform: (row) => renderRequiredDocumentCell(row, 'Actions') },
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="space-y-12">
|
||||
{/* Modal pour les fichiers */}
|
||||
<Modal
|
||||
isOpen={isModalOpen}
|
||||
setIsOpen={(isOpen) => {
|
||||
@ -285,19 +430,21 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
}}
|
||||
title={isEditing ? 'Modification du document' : 'Ajouter un document'}
|
||||
ContentComponent={() => (
|
||||
<FileUpload
|
||||
<FileUploadDocuSeal
|
||||
handleCreateTemplateMaster={handleCreateTemplateMaster}
|
||||
handleEditTemplateMaster={handleEditTemplateMaster}
|
||||
fileToEdit={fileToEdit}
|
||||
onSuccess={handleReloadTemplates}
|
||||
/>
|
||||
)}
|
||||
modalClassName='w-4/5 h-4/5'
|
||||
modalClassName="w-4/5 h-4/5"
|
||||
/>
|
||||
|
||||
{/* Modal pour les groupes */}
|
||||
<Modal
|
||||
isOpen={isGroupModalOpen}
|
||||
setIsOpen={setIsGroupModalOpen}
|
||||
title={groupToEdit ? "Modifier le groupe" : "Ajouter un groupe de templateMasters"}
|
||||
title={groupToEdit ? 'Modifier le groupe' : 'Ajouter un groupe de templateMasters'}
|
||||
ContentComponent={() => (
|
||||
<RegistrationFileGroupForm
|
||||
onSubmit={handleGroupSubmit}
|
||||
@ -305,56 +452,73 @@ export default function FilesGroupsManagement({ csrfToken, selectedEstablishment
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div className="mt-8 mb-4">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h2 className="text-xl font-bold">Groupes de fichiers</h2>
|
||||
|
||||
{/* Section Groupes de fichiers */}
|
||||
<div className="mt-8 mb-4 w-3/5">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="bg-emerald-100 p-3 rounded-full shadow-md">
|
||||
<FolderPlus className="w-8 h-8 text-emerald-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-gray-800">Dossiers d'inscriptions</h2>
|
||||
<p className="text-sm text-gray-500 italic">
|
||||
Gérez les dossiers d'inscription pour organiser vos documents.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsGroupModalOpen(true)}
|
||||
className="flex items-center bg-blue-600 text-white p-2 rounded-full shadow hover:bg-blue-900 transition duration-200"
|
||||
className="flex items-center bg-emerald-600 text-white p-2 rounded-full shadow hover:bg-emerald-700 transition duration-200"
|
||||
>
|
||||
<FolderPlus className="w-5 h-5" />
|
||||
<Plus className="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
<Table
|
||||
data={groups}
|
||||
columns={columnsGroups}
|
||||
itemsPerPage={5}
|
||||
currentPage={1}
|
||||
totalPages={Math.ceil(groups.length / 5)}
|
||||
/>
|
||||
</div>
|
||||
{groups.length > 0 && (
|
||||
<div className="mt-8">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h2 className="text-xl font-bold">Fichiers</h2>
|
||||
<div className="flex items-center gap-4">
|
||||
<select
|
||||
className="border rounded p-2"
|
||||
value={selectedGroup || ''}
|
||||
onChange={(e) => setSelectedGroup(e.target.value)}
|
||||
>
|
||||
<option value="">Tous les groupes</option>
|
||||
{groups.map(group => (
|
||||
<option key={group.id} value={group.id}>{group.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
onClick={() => { setIsModalOpen(true); setIsEditing(false); }}
|
||||
className="flex items-center bg-emerald-600 text-white p-2 rounded-full shadow hover:bg-emerald-900 transition duration-200"
|
||||
>
|
||||
<Plus className="w-5 h-5" />
|
||||
</button>
|
||||
|
||||
{/* Section Fichiers */}
|
||||
<div className="mt-8 mb-4 w-3/5">
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="bg-emerald-100 p-3 rounded-full shadow-md">
|
||||
<Signature className="w-8 h-8 text-emerald-600" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-gray-800">Formulaires à remplir</h2>
|
||||
<p className="text-sm text-gray-500 italic">
|
||||
Gérez les formulaires nécessitant une signature électronique.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Table
|
||||
data={filteredFiles}
|
||||
columns={columnsFiles}
|
||||
itemsPerPage={10}
|
||||
currentPage={1}
|
||||
totalPages={Math.ceil(filteredFiles.length / 10)}
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
setIsModalOpen(true);
|
||||
setIsEditing(false);
|
||||
}}
|
||||
className="flex items-center bg-emerald-600 text-white p-2 rounded-full shadow hover:bg-emerald-700 transition duration-200"
|
||||
>
|
||||
<Plus className="w-6 h-6" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<Table
|
||||
data={filteredFiles}
|
||||
columns={columnsFiles}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Section Pièces à fournir */}
|
||||
<ParentFilesSection
|
||||
parentFiles={parentFiles}
|
||||
setParentFiles={setParentFiles}
|
||||
groups={groups}
|
||||
handleCreate={handleCreate}
|
||||
handleEdit={handleEdit}
|
||||
handleDelete={handleDelete}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user