"use client" import { useState, useEffect } from "react" import { useRouter } from "next/navigation" import { Card, CardContent } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Checkbox } from "@/components/ui/checkbox" import { Textarea } from "@/components/ui/textarea" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Folder, FolderOpen, Grid3X3, List, Search, Filter, Share2, Trash2, Users, FileText, Clock, Star, ChevronRight, FolderPlus, Upload, Download, Lock, SortAsc, SortDesc, X, UserPlus, Crown, Shield, User, CheckCircle, XCircle, Info, CloudUpload, Cloud, HardDrive, Brain, FileQuestion, Timer, ShieldCheck, Archive, FileCheck, } from "lucide-react" interface FolderData { id: number name: string description: string documentsCount: number subfoldersCount: number size: string created: Date modified: Date owner: string access: "shared" | "private" members: string[] tags: string[] color: string favorite: boolean storageType: "temporary" | "permanent" status: "active" | "archived" | "pending" | "completed" | "validated" type: "contracts" | "reports" | "projects" | "finance" | "hr" | "marketing" | "legal" | "general" expectedDocuments: Array<{ name: string required: boolean assignedRole: "owner" | "editor" | "validator" | "contributor" status: "missing" | "pending" | "received" }> activity: Array<{ user: string action: string item: string time: string }> permissions: { canView: boolean canEdit: boolean canDelete: boolean canInvite: boolean canArchive: boolean canAnalyze: boolean } temporaryStorageConfig?: { duration: number // en jours dataUsage: string thirdPartyAccess: string } documents?: Array<{ id: string name: string hasCertificate: boolean certificateId?: string }> } interface ActionModal { type: | "invite" | "delete" | "create" | "edit" | "archive" | "request_document" | "storage_config" | "certificate" | "documents_certificates" | null folder: FolderData | null folders: FolderData[] } interface UserWithRoles { id: string name: string email: string avatar: string folderRoles: { [folderId: string]: { role: "owner" | "editor" | "viewer" | "validator" | "contributor" assignedDate: Date } } spaceRole: "admin" | "manager" | "user" | "guest" spaceRoles: { [spaceId: string]: { role: "admin" | "manager" | "user" | "guest" spaceName: string } } } interface Role { id: string name: string description: string level: "folder" | "space" | "global" } export default function FoldersPage() { const router = useRouter() const [viewMode, setViewMode] = useState<'list'>('list') const [searchTerm, setSearchTerm] = useState("") const [selectedFolders, setSelectedFolders] = useState([]) const [sortBy, setSortBy] = useState("modified") const [sortOrder, setSortOrder] = useState<"asc" | "desc">("desc") const [filterAccess, setFilterAccess] = useState("all") const [filterOwner, setFilterOwner] = useState("all") const [filterStorage, setFilterStorage] = useState("all") const [showFilters, setShowFilters] = useState(false) const [currentPath, setCurrentPath] = useState(["Racine"]) const [actionModal, setActionModal] = useState({ type: null, folder: null, folders: [] }) // Modal states const [inviteMessage, setInviteMessage] = useState("") const [selectedUser, setSelectedUser] = useState("") const [selectedRole, setSelectedRole] = useState("") const [inviteScope, setInviteScope] = useState<"user" | "role">("user") const [folderName, setFolderName] = useState("") const [folderDescription, setFolderDescription] = useState("") const [folderColor, setFolderColor] = useState("blue") const [folderTags, setFolderTags] = useState("") const [folderAccess, setFolderAccess] = useState<"shared" | "private">("private") const [archiveReason, setArchiveReason] = useState("") const [retentionPeriod, setRetentionPeriod] = useState("5") const [selectedDocument, setSelectedDocument] = useState("") const [requestMessage, setRequestMessage] = useState("") const [notification, setNotification] = useState<{ type: "success" | "error" | "info"; message: string } | null>(null) // Storage config modal states const [storageDuration, setStorageDuration] = useState("30") const [dataUsage, setDataUsage] = useState("") const [thirdPartyAccess, setThirdPartyAccess] = useState("") const [folders, setFolders] = useState([]) const [stats, setStats] = useState({ total: 0, shared: 0, private: 0, thisWeek: 0, permanent: 0, temporary: 0, }) const [users] = useState([ { id: "1", name: "Marie Dubois", email: "marie.dubois@company.com", avatar: "MD", folderRoles: { "1": { role: "owner", assignedDate: new Date("2024-01-01") }, "4": { role: "editor", assignedDate: new Date("2024-01-05") }, }, spaceRole: "manager", spaceRoles: { main: { role: "manager", spaceName: "Espace Principal" }, legal: { role: "admin", spaceName: "Espace Juridique" }, }, }, { id: "2", name: "Sophie Laurent", email: "sophie.laurent@company.com", avatar: "SL", folderRoles: { "2": { role: "owner", assignedDate: new Date("2024-01-02") }, "3": { role: "contributor", assignedDate: new Date("2024-01-10") }, }, spaceRole: "user", spaceRoles: { main: { role: "user", spaceName: "Espace Principal" }, analytics: { role: "manager", spaceName: "Espace Analytics" }, }, }, { id: "3", name: "Jean Martin", email: "jean.martin@company.com", avatar: "JM", folderRoles: { "3": { role: "owner", assignedDate: new Date("2024-01-03") }, "2": { role: "viewer", assignedDate: new Date("2024-01-15") }, }, spaceRole: "user", spaceRoles: { main: { role: "user", spaceName: "Espace Principal" }, projects: { role: "admin", spaceName: "Espace Projets" }, }, }, { id: "4", name: "Pierre Durand", email: "pierre.durand@company.com", avatar: "PD", folderRoles: { "6": { role: "owner", assignedDate: new Date("2024-01-04") }, "5": { role: "validator", assignedDate: new Date("2024-01-08") }, }, spaceRole: "user", spaceRoles: { main: { role: "user", spaceName: "Espace Principal" }, training: { role: "admin", spaceName: "Espace Formation" }, }, }, { id: "5", name: "Admin Système", email: "admin@company.com", avatar: "AD", folderRoles: { "5": { role: "owner", assignedDate: new Date("2024-01-01") }, "1": { role: "validator", assignedDate: new Date("2024-01-01") }, "4": { role: "validator", assignedDate: new Date("2024-01-01") }, }, spaceRole: "admin", spaceRoles: { main: { role: "admin", spaceName: "Espace Principal" }, legal: { role: "admin", spaceName: "Espace Juridique" }, analytics: { role: "admin", spaceName: "Espace Analytics" }, projects: { role: "admin", spaceName: "Espace Projets" }, training: { role: "admin", spaceName: "Espace Formation" }, }, }, ]) const [roles] = useState([ { id: "folder-owner", name: "Propriétaire du dossier", description: "Contrôle total sur le dossier", level: "folder", }, { id: "folder-editor", name: "Éditeur du dossier", description: "Peut modifier les documents", level: "folder" }, { id: "folder-validator", name: "Validateur du dossier", description: "Peut valider les documents", level: "folder", }, { id: "folder-contributor", name: "Contributeur du dossier", description: "Peut ajouter des documents", level: "folder", }, { id: "folder-viewer", name: "Lecteur du dossier", description: "Lecture seule", level: "folder" }, { id: "space-admin", name: "Administrateur d'espace", description: "Contrôle total sur l'espace", level: "space" }, { id: "space-manager", name: "Gestionnaire d'espace", description: "Gestion des utilisateurs et dossiers", level: "space", }, { id: "space-user", name: "Utilisateur d'espace", description: "Accès standard à l'espace", level: "space" }, { id: "space-guest", name: "Invité d'espace", description: "Accès limité à l'espace", level: "space" }, { id: "global-admin", name: "Administrateur global", description: "Accès à tous les espaces", level: "global" }, { id: "global-manager", name: "Gestionnaire global", description: "Gestion multi-espaces", level: "global" }, ]) const colors = [ { id: "blue", name: "Bleu", class: "text-blue-600 bg-blue-100" }, { id: "green", name: "Vert", class: "text-green-600 bg-green-100" }, { id: "purple", name: "Violet", class: "text-purple-600 bg-purple-100" }, { id: "orange", name: "Orange", class: "text-orange-600 bg-orange-100" }, { id: "red", name: "Rouge", class: "text-red-600 bg-red-100" }, { id: "pink", name: "Rose", class: "text-pink-600 bg-pink-100" }, { id: "yellow", name: "Jaune", class: "text-yellow-600 bg-yellow-100" }, { id: "gray", name: "Gris", class: "text-gray-600 bg-gray-100" }, ] useEffect(() => { // Simuler le chargement des dossiers const loadFolders = () => { const mockFolders: FolderData[] = [ { id: 1, name: "Contrats", description: "Tous les contrats clients et fournisseurs", documentsCount: 45, subfoldersCount: 3, size: "125 MB", created: new Date("2024-01-01T10:00:00"), modified: new Date("2024-01-15T14:30:00"), owner: "Marie Dubois", access: "shared", members: ["Marie Dubois", "Jean Martin", "Sophie Laurent"], tags: ["juridique", "contrats", "clients"], color: "blue", favorite: true, storageType: "permanent", status: "active", type: "contracts", expectedDocuments: [ { name: "Contrat cadre", required: true, assignedRole: "owner", status: "received" }, { name: "Conditions générales", required: true, assignedRole: "validator", status: "received" }, { name: "Annexes techniques", required: false, assignedRole: "editor", status: "missing" }, { name: "Certificat d'assurance", required: true, assignedRole: "contributor", status: "pending" }, ], activity: [ { user: "Marie Dubois", action: "ajouté", item: "Contrat_ABC.pdf", time: "Il y a 2h" }, { user: "Jean Martin", action: "modifié", item: "Contrat_XYZ.pdf", time: "Il y a 5h" }, ], permissions: { canView: true, canEdit: true, canDelete: true, canInvite: true, canArchive: false, canAnalyze: true, }, temporaryStorageConfig: { duration: 90, dataUsage: "Contrats clients et négociations commerciales", thirdPartyAccess: "Avocats externes, clients contractants", }, documents: [ { id: "doc1", name: "Contrat_ABC.pdf", hasCertificate: true, certificateId: "CERT-DOC-001" }, { id: "doc2", name: "Contrat_XYZ.pdf", hasCertificate: true, certificateId: "CERT-DOC-002" }, { id: "doc3", name: "Annexe_A.pdf", hasCertificate: false }, { id: "doc4", name: "Conditions_Generales.pdf", hasCertificate: true, certificateId: "CERT-DOC-003" }, ], }, { id: 2, name: "Rapports", description: "Rapports mensuels et analyses", documentsCount: 28, subfoldersCount: 2, size: "89 MB", created: new Date("2024-01-05T09:15:00"), modified: new Date("2024-01-14T16:45:00"), owner: "Sophie Laurent", access: "private", members: ["Sophie Laurent", "Pierre Durand"], tags: ["rapports", "analyse", "mensuel"], color: "green", favorite: false, storageType: "temporary", status: "pending", type: "reports", expectedDocuments: [ { name: "Rapport mensuel", required: true, assignedRole: "owner", status: "received" }, { name: "Analyse KPI", required: true, assignedRole: "editor", status: "missing" }, { name: "Graphiques", required: false, assignedRole: "contributor", status: "received" }, ], activity: [ { user: "Sophie Laurent", action: "créé", item: "Rapport_Nov.docx", time: "Il y a 1j" }, { user: "Pierre Durand", action: "consulté", item: "Analyse_Q4.xlsx", time: "Il y a 2j" }, ], permissions: { canView: true, canEdit: true, canDelete: true, canInvite: true, canArchive: true, canAnalyze: true, }, temporaryStorageConfig: { duration: 30, dataUsage: "Analyses de performance et rapports internes", thirdPartyAccess: "Consultants externes, auditeurs", }, documents: [ { id: "doc5", name: "Rapport_Nov.docx", hasCertificate: true, certificateId: "CERT-DOC-004" }, { id: "doc6", name: "Analyse_Q4.xlsx", hasCertificate: false }, ], }, { id: 3, name: "Projets", description: "Documentation des projets en cours", documentsCount: 67, subfoldersCount: 8, size: "234 MB", created: new Date("2023-12-15T11:30:00"), modified: new Date("2024-01-15T09:20:00"), owner: "Jean Martin", access: "shared", members: ["Jean Martin", "Marie Dubois", "Sophie Laurent", "Pierre Durand"], tags: ["projets", "développement", "documentation"], color: "purple", favorite: true, storageType: "temporary", status: "active", type: "projects", expectedDocuments: [ { name: "Cahier des charges", required: true, assignedRole: "owner", status: "received" }, { name: "Spécifications techniques", required: true, assignedRole: "editor", status: "received" }, { name: "Planning projet", required: true, assignedRole: "validator", status: "received" }, { name: "Budget prévisionnel", required: true, assignedRole: "contributor", status: "missing" }, ], activity: [ { user: "Jean Martin", action: "partagé", item: "Specs_Alpha.pdf", time: "Il y a 3h" }, { user: "Marie Dubois", action: "commenté", item: "Design_Beta.figma", time: "Il y a 6h" }, ], permissions: { canView: true, canEdit: true, canDelete: true, canInvite: true, canArchive: true, canAnalyze: true, }, documents: [ { id: "doc7", name: "Specs_Alpha.pdf", hasCertificate: true, certificateId: "CERT-DOC-005" }, { id: "doc8", name: "Design_Beta.figma", hasCertificate: false }, { id: "doc9", name: "Planning.xlsx", hasCertificate: true, certificateId: "CERT-DOC-006" }, ], }, { id: 4, name: "Finance", description: "Documents financiers et budgets", documentsCount: 32, subfoldersCount: 4, size: "156 MB", created: new Date("2024-01-08T14:20:00"), modified: new Date("2024-01-13T11:10:00"), owner: "Marie Dubois", access: "private", members: ["Marie Dubois", "Admin"], tags: ["finance", "budget", "comptabilité"], color: "orange", favorite: false, storageType: "permanent", status: "completed", type: "finance", expectedDocuments: [ { name: "Budget annuel", required: true, assignedRole: "owner", status: "received" }, { name: "Bilan comptable", required: true, assignedRole: "validator", status: "received" }, { name: "Factures", required: true, assignedRole: "editor", status: "received" }, ], activity: [ { user: "Marie Dubois", action: "mis à jour", item: "Budget_2024.xlsx", time: "Il y a 1j" }, { user: "Admin", action: "vérifié", item: "Factures_Dec.pdf", time: "Il y a 2j" }, ], permissions: { canView: true, canEdit: true, canDelete: true, canInvite: true, canArchive: false, canAnalyze: true, }, documents: [ { id: "doc10", name: "Budget_2024.xlsx", hasCertificate: true, certificateId: "CERT-DOC-007" }, { id: "doc11", name: "Factures_Dec.pdf", hasCertificate: true, certificateId: "CERT-DOC-008" }, ], }, { id: 5, name: "Ressources Humaines", description: "Politiques RH et documents employés", documentsCount: 19, subfoldersCount: 2, size: "67 MB", created: new Date("2024-01-10T08:45:00"), modified: new Date("2024-01-12T15:30:00"), owner: "Admin Système", access: "shared", members: ["Admin", "Marie Dubois", "Sophie Laurent"], tags: ["RH", "politique", "employés"], color: "red", favorite: false, storageType: "temporary", status: "archived", type: "hr", expectedDocuments: [ { name: "Politique RH", required: true, assignedRole: "owner", status: "received" }, { name: "Contrats employés", required: true, assignedRole: "validator", status: "received" }, { name: "Formation", required: false, assignedRole: "editor", status: "missing" }, ], activity: [ { user: "Admin", action: "ajouté", item: "Politique_Télétravail.pdf", time: "Il y a 3j" }, { user: "Sophie Laurent", action: "lu", item: "Guide_Onboarding.docx", time: "Il y a 4j" }, ], permissions: { canView: true, canEdit: true, canDelete: true, canInvite: true, canArchive: true, canAnalyze: true, }, documents: [ { id: "doc12", name: "Politique_Télétravail.pdf", hasCertificate: false }, { id: "doc13", name: "Guide_Onboarding.docx", hasCertificate: true, certificateId: "CERT-DOC-009" }, ], }, { id: 6, name: "Marketing", description: "Matériel marketing et campagnes", documentsCount: 41, subfoldersCount: 5, size: "198 MB", created: new Date("2023-12-20T16:00:00"), modified: new Date("2024-01-11T13:45:00"), owner: "Pierre Durand", access: "shared", members: ["Pierre Durand", "Jean Martin", "Design Team"], tags: ["marketing", "campagne", "design"], color: "pink", favorite: true, storageType: "temporary", status: "validated", type: "marketing", expectedDocuments: [ { name: "Brief campagne", required: true, assignedRole: "owner", status: "received" }, { name: "Créations visuelles", required: true, assignedRole: "editor", status: "pending" }, { name: "Plan média", required: true, assignedRole: "contributor", status: "missing" }, { name: "Budget marketing", required: false, assignedRole: "validator", status: "received" }, ], activity: [ { user: "Pierre Durand", action: "uploadé", item: "Campagne_Q1.psd", time: "Il y a 4j" }, { user: "Design Team", action: "approuvé", item: "Logo_V2.png", time: "Il y a 5j" }, ], permissions: { canView: true, canEdit: false, canDelete: false, canInvite: true, canArchive: true, canAnalyze: true, }, documents: [ { id: "doc14", name: "Campagne_Q1.psd", hasCertificate: true, certificateId: "CERT-DOC-010" }, { id: "doc15", name: "Logo_V2.png", hasCertificate: true, certificateId: "CERT-DOC-011" }, { id: "doc16", name: "Brief_campagne.pdf", hasCertificate: false }, ], }, ] setFolders(mockFolders) setStats({ total: mockFolders.length, shared: mockFolders.filter((folder) => folder.access === "shared").length, private: mockFolders.filter((folder) => folder.access === "private").length, thisWeek: mockFolders.filter((folder) => { const weekAgo = new Date() weekAgo.setDate(weekAgo.getDate() - 7) return folder.modified > weekAgo }).length, permanent: mockFolders.filter((folder) => folder.storageType === "permanent").length, temporary: mockFolders.filter((folder) => folder.storageType === "temporary").length, }) } loadFolders() }, []) // Notification system const showNotification = (type: "success" | "error" | "info", message: string) => { setNotification({ type, message }) setTimeout(() => setNotification(null), 3000) } // Fonction pour envoyer une notification dans le chat du dossier const sendFolderChatNotification = (folderId: string, message: string, actionType: string) => { const folderUsers = users.filter((user) => user.folderRoles[folderId]) console.log("Notification envoyée dans le chat du dossier:", { folderId, recipients: folderUsers.map((u) => ({ name: u.name, role: u.folderRoles[folderId]?.role })), message, actionType, timestamp: new Date().toISOString(), }) folderUsers.forEach((user) => { console.log(`📱 Notification push envoyée à ${user.name} (${user.email})`) }) } // Fonction pour organiser les utilisateurs par rôles const organizeUsersForInvitation = (currentFolderId: string) => { const organized = { folderRoles: {} as { [role: string]: UserWithRoles[] }, spaceRoles: {} as { [role: string]: UserWithRoles[] }, otherSpaces: {} as { [spaceName: string]: UserWithRoles[] }, } users.forEach((user) => { if (user.folderRoles[currentFolderId]) { const role = user.folderRoles[currentFolderId].role if (!organized.folderRoles[role]) organized.folderRoles[role] = [] organized.folderRoles[role].push(user) } const spaceRole = user.spaceRole if (!organized.spaceRoles[spaceRole]) organized.spaceRoles[spaceRole] = [] organized.spaceRoles[spaceRole].push(user) Object.values(user.spaceRoles).forEach((spaceInfo) => { if (spaceInfo.spaceName !== "Espace Principal") { if (!organized.otherSpaces[spaceInfo.spaceName]) organized.otherSpaces[spaceInfo.spaceName] = [] organized.otherSpaces[spaceInfo.spaceName].push(user) } }) }) return organized } // Folder actions const handleOpenFolder = (folder: FolderData) => { // Rediriger vers la page documents avec le filtre du dossier router.push(`/dashboard/documents?folder=${encodeURIComponent(folder.name)}`) } const handleInviteFolder = (folder: FolderData) => { setInviteMessage("") setSelectedUser("") setSelectedRole("") setInviteScope("user") setActionModal({ type: "invite", folder, folders: [] }) } const handleArchiveFolder = (folder: FolderData) => { setArchiveReason("") setRetentionPeriod("5") setActionModal({ type: "archive", folder, folders: [] }) } const handleStorageConfig = (folder: FolderData) => { setStorageDuration(folder.temporaryStorageConfig?.duration.toString() || "30") setDataUsage(folder.temporaryStorageConfig?.dataUsage || "") setThirdPartyAccess(folder.temporaryStorageConfig?.thirdPartyAccess || "") setActionModal({ type: "storage_config", folder, folders: [] }) } const handleAIAnalysis = (folder: FolderData) => { showNotification("info", `Analyse IA en cours pour ${folder.name}...`) // Simuler une analyse IA setTimeout( () => { const analysisResults = [ `📊 **Analyse du dossier "${folder.name}"**\n\n` + `**Contenu :** ${folder.documentsCount} documents analysés (${folder.size})\n` + `**Thématiques principales :** ${folder.tags.join(", ")}\n` + `**Niveau d'activité :** ${folder.activity.length > 2 ? "Élevé" : "Modéré"} (dernière modification ${formatDate(folder.modified)})\n\n` + `**Recommandations :**\n` + `• ${folder.storageType === "temporary" ? "Considérer l'archivage vers le stockage permanent" : "Dossier déjà archivé de manière optimale"}\n` + `• ${folder.access === "private" ? "Évaluer les possibilités de partage avec l'équipe" : "Partage actuel avec " + folder.members.length + " membre(s)"}\n` + `• Dernière activité significative détectée il y a ${Math.floor(Math.random() * 7) + 1} jour(s)\n\n` + `**Score de pertinence :** ${Math.floor(Math.random() * 30) + 70}/100`, `🔍 **Analyse approfondie du dossier "${folder.name}"**\n\n` + `**Structure documentaire :**\n` + `• ${Math.floor(folder.documentsCount * 0.4)} documents principaux\n` + `• ${Math.floor(folder.documentsCount * 0.3)} documents de support\n` + `• ${Math.floor(folder.documentsCount * 0.3)} documents annexes\n\n` + `**Analyse temporelle :**\n` + `• Création : ${folder.created.toLocaleDateString("fr-FR")}\n` + `• Pic d'activité détecté en ${new Date().toLocaleDateString("fr-FR", { month: "long", year: "numeric" })}\n` + `• Tendance : ${Math.random() > 0.5 ? "Croissante" : "Stable"}\n\n` + `**Recommandations stratégiques :**\n` + `• ${folder.documentsCount > 50 ? "Envisager une réorganisation en sous-dossiers" : "Structure actuelle optimale"}\n` + `• ${folder.members.length < 3 ? "Potentiel de collaboration à explorer" : "Équipe collaborative active"}\n` + `• Prochaine révision recommandée : ${new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toLocaleDateString("fr-FR")}`, `🎯 **Insights IA pour "${folder.name}"**\n\n` + `**Analyse sémantique :**\n` + `• Cohérence thématique : ${Math.floor(Math.random() * 20) + 80}%\n` + `• Mots-clés dominants : ${folder.tags.slice(0, 3).join(", ")}\n` + `• Complexité moyenne : ${["Faible", "Modérée", "Élevée"][Math.floor(Math.random() * 3)]}\n\n` + `**Patterns détectés :**\n` + `• ${Math.random() > 0.5 ? "Cycle de révision régulier identifié" : "Activité sporadique détectée"}\n` + `• ${Math.random() > 0.5 ? "Collaboration inter-équipes active" : "Usage principalement individuel"}\n` + `• ${folder.storageType === "permanent" ? "Archivage conforme aux bonnes pratiques" : "Optimisation de stockage possible"}\n\n` + `**Actions suggérées :**\n` + `• ${Math.random() > 0.5 ? "Créer un template basé sur ce dossier" : "Standardiser la nomenclature"}\n` + `• ${Math.random() > 0.5 ? "Planifier une session de nettoyage" : "Maintenir la structure actuelle"}\n` + `• Prochaine analyse automatique : ${new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toLocaleDateString("fr-FR")}`, ] const randomAnalysis = analysisResults[Math.floor(Math.random() * analysisResults.length)] // Envoyer l'analyse dans le chat du dossier sendFolderChatNotification(folder.id.toString(), `🤖 ${randomAnalysis}`, "ai_analysis") showNotification("success", `Analyse IA terminée pour ${folder.name}. Redirection vers le chat...`) // Rediriger vers le chat après 1.5 secondes setTimeout(() => { router.push("/dashboard/chat") }, 1500) }, 2000 + Math.random() * 3000, ) } const handleViewCertificate = (folder: FolderData) => { setActionModal({ type: "certificate", folder, folders: [] }) } const handleViewDocumentsCertificates = (folder: FolderData) => { setActionModal({ type: "documents_certificates", folder, folders: [] }) } const handleDownloadCertificate = (folder: FolderData) => { if (folder.status === "validated") { showNotification("info", `Téléchargement du certificat blockchain pour le dossier ${folder.name}...`) sendFolderChatNotification( folder.id.toString(), `🔗 Certificat blockchain du dossier téléchargé`, "folder_blockchain_certificate_download", ) setTimeout(() => { showNotification("success", `Certificat blockchain du dossier ${folder.name} téléchargé avec succès`) }, 2000) } } const handleManageRoles = (folder: FolderData) => { // Rediriger vers la gestion des rôles du dossier router.push(`/dashboard/folders/${folder.id}/roles`) } const handleRequestDocument = (folder: FolderData) => { setSelectedDocument("") setRequestMessage("") setActionModal({ type: "request_document", folder, folders: [] }) } const handleDeleteFolder = (folder: FolderData) => { setActionModal({ type: "delete", folder, folders: [] }) } const handleCreateFolder = () => { setFolderName("") setFolderDescription("") setFolderColor("blue") setFolderTags("") setFolderAccess("private") setActionModal({ type: "create", folder: null, folders: [] }) } const handleToggleFavorite = (folderId: number) => { const folder = folders.find((f) => f.id === folderId) if (!folder) return setFolders((prev) => prev.map((f) => (f.id === folderId ? { ...f, favorite: !f.favorite } : f))) const action = folder.favorite ? "retiré des" : "ajouté aux" showNotification("success", `${folder.name} ${action} favoris`) sendFolderChatNotification(folderId.toString(), `⭐ Le dossier a été ${action} favoris`, "favorite") } // Bulk actions const handleBulkDownload = () => { const selectedFolderData = folders.filter((folder) => selectedFolders.includes(folder.id)) showNotification("info", `Téléchargement de ${selectedFolderData.length} dossier(s)...`) selectedFolderData.forEach((folder) => { sendFolderChatNotification(folder.id.toString(), `📥 Le dossier a été téléchargé`, "download") }) setTimeout(() => { showNotification("success", `${selectedFolderData.length} dossier(s) téléchargé(s) avec succès`) setSelectedFolders([]) }, 2000) } const handleBulkInvite = () => { const selectedFolderData = folders.filter( (folder) => selectedFolders.includes(folder.id) && folder.permissions.canInvite, ) if (selectedFolderData.length === 0) { showNotification("error", "Aucun dossier sélectionné ne peut être partagé") return } setInviteMessage("") setSelectedUser("") setSelectedRole("") setInviteScope("user") setActionModal({ type: "invite", folder: null, folders: selectedFolderData }) } const handleBulkArchive = () => { const selectedFolderData = folders.filter( (folder) => selectedFolders.includes(folder.id) && folder.permissions.canArchive, ) if (selectedFolderData.length === 0) { showNotification("error", "Aucun dossier sélectionné ne peut être archivé") return } setArchiveReason("") setRetentionPeriod("5") setActionModal({ type: "archive", folder: null, folders: selectedFolderData }) } const handleBulkAIAnalysis = () => { const selectedFolderData = folders.filter( (folder) => selectedFolders.includes(folder.id) && folder.permissions.canAnalyze, ) if (selectedFolderData.length === 0) { showNotification("error", "Aucun dossier sélectionné ne peut être analysé") return } showNotification("info", `Analyse IA en cours pour ${selectedFolderData.length} dossier(s)...`) // Analyser chaque dossier avec un délai échelonné selectedFolderData.forEach((folder, index) => { setTimeout(() => { const bulkAnalysis = `📊 **Analyse IA groupée - Dossier "${folder.name}"**\n\n` + `**Position dans l'analyse :** ${index + 1}/${selectedFolderData.length}\n` + `**Contenu :** ${folder.documentsCount} documents (${folder.size})\n` + `**Tags :** ${folder.tags.join(", ")}\n\n` + `**Analyse comparative :**\n` + `• Taille relative : ${folder.documentsCount > 40 ? "Au-dessus de la moyenne" : "Dans la moyenne"}\n` + `• Activité : ${folder.activity.length > 1 ? "Active" : "Modérée"}\n` + `• Collaboration : ${folder.members.length} membre(s)\n\n` + `**Recommandation :** ${folder.storageType === "temporary" ? "Candidat à l'archivage" : "Archivage optimal"}\n` + `**Score global :** ${Math.floor(Math.random() * 30) + 70}/100` sendFolderChatNotification(folder.id.toString(), `🤖 ${bulkAnalysis}`, "bulk_ai_analysis") }, index * 1500) // Échelonner les analyses }) setTimeout( () => { const totalDocs = selectedFolderData.reduce((sum, folder) => sum + folder.documentsCount, 0) showNotification( "success", `Analyse IA terminée pour ${selectedFolderData.length} dossier(s) (${totalDocs} documents). Redirection vers le chat...`, ) setSelectedFolders([]) // Rediriger vers le chat après l'analyse groupée setTimeout(() => { router.push("/dashboard/chat") }, 1500) }, selectedFolderData.length * 1500 + 1000, ) } const handleBulkDelete = () => { const selectedFolderData = folders.filter( (folder) => selectedFolders.includes(folder.id) && folder.permissions.canDelete, ) if (selectedFolderData.length === 0) { showNotification("error", "Aucun dossier sélectionné ne peut être supprimé") return } setActionModal({ type: "delete", folder: null, folders: selectedFolderData }) } // Modal actions const confirmInvite = () => { const recipient = inviteScope === "user" ? users.find((u) => u.id === selectedUser)?.name : roles.find((r) => r.id === selectedRole)?.name if (actionModal.folder) { showNotification("success", `${actionModal.folder.name} partagé avec ${recipient}. Un message a été envoyé.`) sendFolderChatNotification( actionModal.folder.id.toString(), `👥 Le dossier a été partagé avec ${recipient}. Message: ${inviteMessage}`, "invite", ) } else if (actionModal.folders.length > 0) { actionModal.folders.forEach((folder) => { sendFolderChatNotification( folder.id.toString(), `👥 Le dossier a été partagé avec ${recipient}. Message: ${inviteMessage}`, "bulk_invite", ) }) showNotification( "success", `${actionModal.folders.length} dossier(s) partagé(s) avec ${recipient}. Messages envoyés.`, ) setSelectedFolders([]) } setActionModal({ type: null, folder: null, folders: [] }) } const confirmRequestDocument = () => { if (actionModal.folder && selectedDocument) { const document = actionModal.folder.expectedDocuments.find((doc) => doc.name === selectedDocument) if (document) { // Trouver l'utilisateur avec le rôle assigné const assignedUser = users.find( (user) => user.folderRoles[actionModal.folder!.id.toString()]?.role === document.assignedRole, ) if (assignedUser) { // Préparer les données pour le chat const messageData = { userName: assignedUser.name, subject: `Demande de document - ${selectedDocument}`, content: `Bonjour ${assignedUser.name},\n\nPouvez-vous fournir le document "${selectedDocument}" pour le dossier "${actionModal.folder.name}" ?\n\n${requestMessage}\n\nMerci !`, } // Stocker dans sessionStorage pour le chat sessionStorage.setItem("newMessage", JSON.stringify(messageData)) showNotification("success", `Demande envoyée à ${assignedUser.name}. Redirection vers le chat...`) // Rediriger vers le chat avec l'utilisateur setTimeout(() => { router.push(`/dashboard/chat?user=${assignedUser.id}&message=new`) }, 1500) } else { showNotification("error", "Aucun utilisateur trouvé avec le rôle requis pour ce document") } } } setActionModal({ type: null, folder: null, folders: [] }) } const confirmStorageConfig = () => { if (actionModal.folder) { const updatedFolder = { ...actionModal.folder, temporaryStorageConfig: { duration: Number.parseInt(storageDuration), dataUsage: dataUsage, thirdPartyAccess: thirdPartyAccess, }, modified: new Date(), } setFolders((prev) => prev.map((f) => (f.id === updatedFolder.id ? updatedFolder : f))) showNotification("success", `Configuration du stockage temporaire mise à jour pour ${actionModal.folder.name}`) // Notification dans le chat du dossier const message = `⚙️ Configuration du stockage temporaire mise à jour :\n• Durée : ${storageDuration} jours\n• Usage : ${dataUsage}\n• Accès tiers : ${thirdPartyAccess}` sendFolderChatNotification(actionModal.folder.id.toString(), message, "storage_config") } setActionModal({ type: null, folder: null, folders: [] }) } const confirmArchive = () => { if (actionModal.folder) { const updatedFolder = { ...actionModal.folder, storageType: "permanent" as const, modified: new Date(), } setFolders((prev) => prev.map((f) => (f.id === updatedFolder.id ? updatedFolder : f))) showNotification( "success", `${actionModal.folder.name} et tous ses documents archivés vers le stockage permanent`, ) // Notification dans le chat du dossier let message = `📦 Le dossier et tous ses ${actionModal.folder.documentsCount} document(s) ont été archivés vers le stockage permanent (conservation: ${retentionPeriod} ans)` if (archiveReason.trim()) { message += ` - Raison: ${archiveReason}` } sendFolderChatNotification(actionModal.folder.id.toString(), message, "archive") } else if (actionModal.folders.length > 0) { const folderIds = actionModal.folders.map((f) => f.id) setFolders((prev) => prev.map((f) => folderIds.includes(f.id) ? { ...f, storageType: "permanent" as const, modified: new Date(), } : f, ), ) actionModal.folders.forEach((folder) => { let message = `📦 Le dossier et tous ses ${folder.documentsCount} document(s) ont été archivés vers le stockage permanent (conservation: ${retentionPeriod} ans)` if (archiveReason.trim()) { message += ` - Raison: ${archiveReason}` } sendFolderChatNotification(folder.id.toString(), message, "bulk_archive") }) const totalDocuments = actionModal.folders.reduce((sum, folder) => sum + folder.documentsCount, 0) showNotification( "success", `${actionModal.folders.length} dossier(s) et ${totalDocuments} document(s) archivés vers le stockage permanent`, ) setSelectedFolders([]) } setActionModal({ type: null, folder: null, folders: [] }) } const confirmCreate = () => { const newFolder: FolderData = { id: Math.max(...folders.map((f) => f.id)) + 1, name: folderName, description: folderDescription, documentsCount: 0, subfoldersCount: 0, size: "0 MB", created: new Date(), modified: new Date(), owner: "Utilisateur actuel", access: folderAccess, members: ["Utilisateur actuel"], tags: folderTags .split(",") .map((tag) => tag.trim()) .filter((tag) => tag), color: folderColor, favorite: false, storageType: "temporary", status: "active", type: "general", expectedDocuments: [], activity: [], permissions: { canView: true, canEdit: true, canDelete: true, canInvite: true, canArchive: true, canAnalyze: true, }, documents: [], } setFolders((prev) => [...prev, newFolder]) showNotification("success", `Dossier "${folderName}" créé avec succès`) setActionModal({ type: null, folder: null, folders: [] }) } const confirmDelete = () => { if (actionModal.folder) { sendFolderChatNotification(actionModal.folder.id.toString(), `🗑️ Le dossier a été supprimé`, "delete") setFolders((prev) => prev.filter((f) => f.id !== actionModal.folder!.id)) showNotification("success", `${actionModal.folder.name} supprimé`) } else if (actionModal.folders.length > 0) { actionModal.folders.forEach((folder) => { sendFolderChatNotification(folder.id.toString(), `🗑️ Le dossier a été supprimé`, "bulk_delete") }) const folderIds = actionModal.folders.map((f) => f.id) setFolders((prev) => prev.filter((f) => !folderIds.includes(f.id))) showNotification("success", `${actionModal.folders.length} dossier(s) supprimé(s)`) setSelectedFolders([]) } setActionModal({ type: null, folder: null, folders: [] }) } const filteredFolders = folders .filter((folder) => { if (searchTerm && !folder.name.toLowerCase().includes(searchTerm.toLowerCase())) { return false } if (filterAccess !== "all" && folder.access !== filterAccess) { return false } if (filterOwner !== "all" && folder.owner !== filterOwner) { return false } if (filterStorage !== "all" && folder.storageType !== filterStorage) { return false } return true }) .sort((a, b) => { let aValue, bValue switch (sortBy) { case "name": aValue = a.name.toLowerCase() bValue = b.name.toLowerCase() break case "size": aValue = Number.parseFloat(a.size.replace(/[^\d.]/g, "")) bValue = Number.parseFloat(b.size.replace(/[^\d.]/g, "")) break case "owner": aValue = a.owner.toLowerCase() bValue = b.owner.toLowerCase() break case "documents": aValue = a.documentsCount bValue = b.documentsCount break case "modified": default: aValue = a.modified.getTime() bValue = b.modified.getTime() break } if (sortOrder === "asc") { return aValue > bValue ? 1 : -1 } else { return aValue < bValue ? 1 : -1 } }) const getFolderColor = (color: string) => { const colorObj = colors.find((c) => c.id === color) return colorObj?.class || "text-gray-600 bg-gray-100" } const getStorageIcon = (storageType: string) => { return storageType === "permanent" ? ( ) : ( ) } const getRoleIcon = (role: string) => { switch (role) { case "owner": return case "editor": return case "validator": return case "contributor": return case "viewer": return case "admin": return case "manager": return case "user": return case "guest": return default: return } } const getStatusBadge = (status: string) => { switch (status) { case "active": return Actif case "pending": return En attente case "completed": return Terminé case "archived": return Archivé case "validated": return Validé default: return Inconnu } } const formatDate = (date: Date) => { const now = new Date() const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60) if (diffInHours < 1) { return "Il y a quelques minutes" } else if (diffInHours < 24) { return `Il y a ${Math.floor(diffInHours)} heure${Math.floor(diffInHours) > 1 ? "s" : ""}` } else if (diffInHours < 48) { return "Hier" } else { return date.toLocaleDateString("fr-FR") } } const toggleFolderSelection = (folderId: number) => { setSelectedFolders((prev) => (prev.includes(folderId) ? prev.filter((id) => id !== folderId) : [...prev, folderId])) } const selectAllFolders = () => { if (selectedFolders.length === filteredFolders.length) { setSelectedFolders([]) } else { setSelectedFolders(filteredFolders.map((folder) => folder.id)) } } return (
{/* Notification */} {notification && (
{notification.type === "success" && } {notification.type === "error" && } {notification.type === "info" && } {notification.message}
)} {/* Header */}

Dossiers

Organisez vos documents par dossiers

{/* Breadcrumb */}
{currentPath.map((path, index) => (
{index > 0 && }
))}
{/* Search and Filters */}
setSearchTerm(e.target.value)} className="pl-10" />
{/* Vue grille supprimée: forcer la vue liste uniquement */}
{/* Advanced Filters */} {showFilters && (
)}
{/* Bulk Actions minimalistes: certificats et rôles uniquement */} {selectedFolders.length > 0 && (
{selectedFolders.length} dossier{selectedFolders.length > 1 ? "s" : ""} sélectionné {selectedFolders.length > 1 ? "s" : ""}
)} {/* Folders List/Grid */} {viewMode === "list" ? (
{filteredFolders.map((folder) => ( ))}
Nom Taille Modifié Propriétaire Accès Statut
toggleFolderSelection(folder.id)} />
{folder.name} {getStorageIcon(folder.storageType)} {folder.access === "private" && }

{folder.description}

{folder.size} {formatDate(folder.modified)} {folder.owner} {folder.access === "shared" ? "Partagé" : "Privé"} {getStatusBadge(folder.status)}
) : (
{filteredFolders.map((folder) => (
handleOpenFolder(folder)} >
e.stopPropagation()}> toggleFolderSelection(folder.id)} />
e.stopPropagation()} > {folder.access === "private" && } {folder.storageType === "temporary" && ( )} {folder.status === "validated" && ( )} {folder.documents && folder.documents.some((doc) => doc.hasCertificate) && ( )}

{folder.name}

{folder.description}

{folder.size}

{formatDate(folder.modified)}

{getStorageIcon(folder.storageType)} {folder.storageType === "permanent" ? "Permanent" : "Temporaire"}
{folder.temporaryStorageConfig && folder.storageType === "temporary" && (
Durée: {folder.temporaryStorageConfig.duration} jours
)}
{getStatusBadge(folder.status)}
{folder.access === "shared" ? "Partagé" : "Privé"}
{/* Recent Activity */}

Activité récente

{folder.activity.slice(0, 2).map((activity, index) => (
{activity.user} a {activity.action}{" "} {activity.item}
{activity.time}
))}
))}
)} {filteredFolders.length === 0 && (

Aucun dossier trouvé

{searchTerm || filterAccess !== "all" || filterOwner !== "all" || filterStorage !== "all" ? "Essayez de modifier vos critères de recherche" : "Commencez par créer votre premier dossier"}

)}
{/* Modals */} {actionModal.type && (
{/* Documents Certificates Modal */} {actionModal.type === "documents_certificates" && actionModal.folder && ( <>

Certificats des documents - {actionModal.folder.name}

Certificats des documents

Téléchargez les certificats blockchain individuels des documents de ce dossier

{actionModal.folder.documents?.map((doc) => (
{doc.name}
{doc.hasCertificate && doc.certificateId && (

ID: {doc.certificateId}

)}
{doc.hasCertificate ? ( <> Certifié ) : ( Non certifié )}
))}
Actions groupées
)} {/* Storage Config Modal */} {actionModal.type === "storage_config" && actionModal.folder && ( <>

Configuration du stockage temporaire

Configuration du stockage temporaire

Configurez la durée de conservation et les informations d'usage pour le dossier{" "} {actionModal.folder.name} en stockage temporaire.

Durée pendant laquelle les données seront conservées en stockage temporaire avant archivage automatique