From 8549699dec253a9763a4074e05130c4d7d40ac6e Mon Sep 17 00:00:00 2001 From: N3WT DE COMPET Date: Mon, 5 Jan 2026 14:56:36 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20R=C3=A9organisation=20items=20dans=20la?= =?UTF-8?q?=20page=20[N3WTS-17]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Structure/Files/FilesGroupsManagement.js | 653 +++++++++++------- .../components/Structure/Files/ParentFiles.js | 2 +- 2 files changed, 418 insertions(+), 237 deletions(-) diff --git a/Front-End/src/components/Structure/Files/FilesGroupsManagement.js b/Front-End/src/components/Structure/Files/FilesGroupsManagement.js index aee1e66..bc75419 100644 --- a/Front-End/src/components/Structure/Files/FilesGroupsManagement.js +++ b/Front-End/src/components/Structure/Files/FilesGroupsManagement.js @@ -2,6 +2,10 @@ import React, { useState, useEffect, useRef } from 'react'; import { Edit3, Trash2, + FileText, + Star, + ChevronDown, + Plus } from 'lucide-react'; import Modal from '@/components/Modal'; import FormTemplateBuilder from '@/components/Form/FormTemplateBuilder'; @@ -31,12 +35,14 @@ import Loader from '@/components/Loader'; import { useNotification } from '@/context/NotificationContext'; import CreateDocumentModal from '@/components/Structure/Files/CreateDocumentModal'; import FileUpload from '@/components/Form/FileUpload'; +import SectionTitle from '@/components/SectionTitle'; +import DropdownMenu from '@/components/DropdownMenu'; function getItemBgColor(type, selected, forceTheme = false) { - // Colonne gauche : bleu, sélectionné plus soutenu + // Colonne gauche : blanc si rien n'est sélectionné, emerald si sélectionné if (type === 'blue') { - if (selected) return 'bg-blue-200'; - return 'bg-blue-50'; + if (selected) return 'bg-emerald-100'; + return 'bg-white'; } // Colonne droite : thème selon type, jamais sélectionné if (forceTheme) { @@ -57,38 +63,36 @@ function SimpleList({ minHeight = 'min-h-[200px]', selectable = true, forceTheme = false, + headerClassName = '', + listClassName = '', + itemClassName = '', + headerContent = null, + showGroups = false, + groupDocCount = null, }) { return (
{title && (
- {title} + {headerContent ? headerContent : ( + {title} + )}
)} -
); - // Correction : définition de handleBackToCreateMenu - const handleBackToCreateMenu = () => { - setCreateModalKey((k) => k + 1); // force le reset du composant modal - setIsCreateModalOpen(true); + // Filtrage des formulaires et pièces selon le dossier sélectionné + // Si aucun groupe sélectionné, la colonne de droite est vide + let filteredFiles = []; + let filteredParentFiles = []; + if (selectedGroupId) { + filteredFiles = schoolFileMasters + .map((file) => transformFileData(file, groups)) + .filter( + (file) => + file.groups && + file.groups.some((group) => group.id === selectedGroupId) + ); + filteredParentFiles = parentFiles.filter( + (file) => + file.groups && + file.groups.some((gid) => + (typeof gid === 'object' ? gid.id : gid) === selectedGroupId + ) + ); + } + + const mergedDocuments = + selectedGroupId + ? [ + ...filteredFiles.map((doc) => ({ ...doc, _type: 'emerald' })), + ...filteredParentFiles.map((doc) => ({ ...doc, _type: 'orange' })), + ] + : []; + + // Calcul du nombre de documents par groupe + const getGroupDocCount = (group) => { + const groupId = group.id; + let count = 0; + // Documents école + count += schoolFileMasters.filter( + (file) => + Array.isArray(file.groups) + ? file.groups.some((g) => (typeof g === 'object' ? g.id : g) === groupId) + : false + ).length; + // Pièces à fournir + count += parentFiles.filter( + (file) => + Array.isArray(file.groups) + ? file.groups.some((g) => (typeof g === 'object' ? g.id : g) === groupId) + : false + ).length; + return count; }; // Nouvelle disposition : sections côte à côte alignées return (
- {/* Aide optionnelle + bouton global de création */} -
- {renderExplanation()} -
- -
-
+ {/* Aide optionnelle */} +
{renderExplanation()}
-
- {/* Colonne gauche : Dossiers d'inscription */} -
+ {/* 2 colonnes : groupes à gauche, documents à droite */} +
+ {/* Colonne groupes (1/3) */} +
+
+ +
+ +
'blue'} - title="Dossiers d'inscription" - minHeight="min-h-[240px]" + minHeight="min-h-[60px]" selectable={true} forceTheme={false} + groupDocCount={getGroupDocCount} actionButtons={(row) => (
- {/* Colonne droite : Documents (fusion des formulaires et pièces à fournir) */} -
-
-
- Documents -
- {selectedGroupId === null ? ( -
- Sélectionnez un dossier pour voir les documents associés. -
- ) : ( - item._type} - // title="Documents" // Supprimé ici, header déjà affiché au-dessus - minHeight="min-h-[240px]" - selectable={false} - forceTheme={true} - actionButtons={(row) => ( -
- {row._type === 'emerald' ? ( - <> - - - - ) : ( - <> - - - - )} -
- )} - /> - )} + + {/* Colonne documents (2/3) */} +
+
+ +
+ + + + + } + items={[ + { + type: 'item', + label: ( + + + Formulaire personnalisé + + ), + onClick: () => handleDocDropdownSelect('formulaire'), + }, + { + type: 'item', + label: ( + + + Formulaire existant + + ), + onClick: () => handleDocDropdownSelect('formulaire_existant'), + }, + { + type: 'item', + label: ( + + + Pièce à fournir + + ), + onClick: () => handleDocDropdownSelect('parent'), + }, + ]} + buttonClassName="flex items-center justify-center bg-emerald-500 hover:bg-emerald-600 text-white px-3 py-2 rounded-lg shadow transition text-base font-semibold" + menuClassName="absolute right-0 mt-2 w-56 bg-white border border-gray-200 rounded shadow-lg z-20" + dropdownOpen={isDocDropdownOpen} + setDropdownOpen={setIsDocDropdownOpen} + />
+ {!selectedGroupId ? ( +
+ Sélectionner un dossier d'inscription +
+ ) : ( + item._type} + minHeight="min-h-[240px]" + selectable={false} + forceTheme={true} + listClassName="" + itemClassName="text-gray-800 bg-white" + title="" + headerContent={null} + showGroups={false} + actionButtons={(row) => ( +
+ {row._type === 'emerald' ? ( + <> + + + + ) : ( + <> + + + + )} +
+ )} + /> + )}
- {/* Modal de création centralisée */} - setIsCreateModalOpen(false)} - onCreateGroup={() => { - setIsGroupModalOpen(true); - setIsCreateModalOpen(false); - }} - onCreateForm={() => { - setIsCreateModalOpen(false); - setTimeout(() => setIsModalOpen(true), 0); - }} - onCreateParentFile={() => { - openParentFileModal(); - setIsCreateModalOpen(false); - }} - onBack={handleBackToCreateMenu} - onCreateSchoolFileMaster={handleCreateSchoolFileMaster} - groups={groups} - /> - {/* Modal pour upload de formulaire existant */} + {/* Modals pour création/édition */} - { - // Ici, il faut gérer le nom et les groupes (à adapter selon vos besoins UI) - // Par exemple, ouvrir un petit formulaire pour compléter les infos puis submit + { + handleCreateSchoolFileMaster(data); + setIsFormBuilderOpen(false); }} - onSubmit={handleSubmitFileUpload} - required - enable + groups={groups} + isEditing={false} /> - {/* Modal création/édition pièce à fournir */} + {/* Popup pour téléchargement d'un document existant */} + +
{ + e.preventDefault(); + if (!fileToEdit?.name || !fileToEdit?.group_ids || !fileToEdit?.file) return; + handleCreateSchoolFileMaster({ + name: fileToEdit.name, + group_ids: fileToEdit.group_ids, + file: fileToEdit.file, + }); + setIsFileUploadPopupOpen(false); + setFileToEdit(null); + }} + > + setFileToEdit({ ...fileToEdit, name: e.target.value })} + required + /> +
+ +
+ {groups && groups.length > 0 ? ( + groups.map((group) => ( + + )) + ) : ( +

+ Aucun groupe disponible +

+ )} +
+
+ + setFileToEdit({ ...fileToEdit, file }) + } + required + enable + /> + + +
+ { - if (!open) closeParentFileModal(); + setIsParentFileModalOpen(open); + if (!open) setEditingParentFile(null); }} title={editingParentFile ? 'Modifier la pièce à fournir' : 'Créer une pièce à fournir'} modalClassName="w-full max-w-md" @@ -790,11 +972,11 @@ export default function FilesGroupsManagement({ handleDelete={handleDelete} singleForm // affiche uniquement le formulaire, pas la liste initialData={editingParentFile} - onCancel={closeParentFileModal} + onCancel={() => setIsParentFileModalOpen(false)} /> - {/* Modals et popups */} + {/* Modals et popups pour édition */} { @@ -802,8 +984,6 @@ export default function FilesGroupsManagement({ if (!isOpen) { setFileToEdit(null); setIsEditing(false); - // Retour au menu principal de création si fermeture - handleBackToCreateMenu(); } }} title={isEditing ? 'Modification du formulaire' : 'Créer un formulaire'} @@ -812,6 +992,7 @@ export default function FilesGroupsManagement({ { (isEditing ? handleEditSchoolFileMaster : handleCreateSchoolFileMaster)(data); + setIsModalOpen(false); }} initialData={fileToEdit} groups={groups} @@ -824,8 +1005,7 @@ export default function FilesGroupsManagement({ setIsOpen={(isOpen) => { setIsGroupModalOpen(isOpen); if (!isOpen) { - // Retour au menu principal de création si fermeture - handleBackToCreateMenu(); + setGroupToEdit(null); } }} title={ @@ -835,6 +1015,7 @@ export default function FilesGroupsManagement({ { handleGroupSubmit(data); + setIsGroupModalOpen(false); }} initialData={groupToEdit} /> diff --git a/Front-End/src/components/Structure/Files/ParentFiles.js b/Front-End/src/components/Structure/Files/ParentFiles.js index 8092fab..dc102b7 100644 --- a/Front-End/src/components/Structure/Files/ParentFiles.js +++ b/Front-End/src/components/Structure/Files/ParentFiles.js @@ -76,7 +76,7 @@ function ParentFileForm({ initialData, groups, onSubmit, onCancel }) {