"use client"; import { useState, useEffect, useMemo } from "react"; import { Users, User, Trash2, Search, Building2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { useToast } from "@/hooks/use-toast"; import { AdminManagementService, Team, } from "@/services/admin-management-service"; import { TreeViewContainer, TreeCategoryHeader, TreeItemRow, TreeSearchControls, } from "@/components/admin"; interface User { uuid: string; firstName: string; lastName: string; teamName?: string; hasEvaluations: boolean; } interface UserFormData { firstName: string; lastName: string; teamId: string; } export function UsersManagement() { const [users, setUsers] = useState([]); const [teams, setTeams] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [deletingUserId, setDeletingUserId] = useState(null); const [searchTerm, setSearchTerm] = useState(""); const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); const [userFormData, setUserFormData] = useState({ firstName: "", lastName: "", teamId: "", }); const { toast } = useToast(); // État pour les équipes ouvertes/fermées const [expandedTeams, setExpandedTeams] = useState>(new Set()); // Grouper les utilisateurs par équipe et filtrer en fonction de la recherche const filteredUsersByTeam = useMemo(() => { // Grouper les utilisateurs par équipe const usersByTeam = users.reduce((acc, user) => { const teamKey = user.teamName || "Sans équipe"; if (!acc[teamKey]) { acc[teamKey] = []; } acc[teamKey].push(user); return acc; }, {} as Record); // Filtrer les utilisateurs en fonction de la recherche return Object.entries(usersByTeam).reduce((acc, [teamName, teamUsers]) => { const filteredUsers = teamUsers.filter((user) => { const matchesSearch = user.firstName.toLowerCase().includes(searchTerm.toLowerCase()) || user.lastName.toLowerCase().includes(searchTerm.toLowerCase()) || (user.teamName && user.teamName.toLowerCase().includes(searchTerm.toLowerCase())); return matchesSearch; }); if (filteredUsers.length > 0) { acc[teamName] = filteredUsers; } return acc; }, {} as Record); }, [users, searchTerm]); useEffect(() => { fetchUsers(); fetchTeams(); }, []); const fetchUsers = async () => { setIsLoading(true); setError(null); try { const response = await fetch("/api/admin/users"); if (!response.ok) { throw new Error("Erreur lors de la récupération des utilisateurs"); } const usersData = await response.json(); setUsers(usersData); } catch (err: any) { setError(err.message || "Erreur lors du chargement des utilisateurs"); } finally { setIsLoading(false); } }; const fetchTeams = async () => { try { const teamsData = await AdminManagementService.getTeams(); setTeams(teamsData); } catch (error) { console.error("Error fetching teams:", error); } }; // Fonctions pour gérer l'expansion des équipes const toggleTeam = useMemo( () => (teamName: string) => { setExpandedTeams((prev) => { const newExpanded = new Set(prev); if (newExpanded.has(teamName)) { newExpanded.delete(teamName); } else { newExpanded.add(teamName); } return newExpanded; }); }, [] ); const expandAll = useMemo( () => () => { setExpandedTeams(new Set(Object.keys(filteredUsersByTeam))); }, [filteredUsersByTeam] ); const collapseAll = useMemo( () => () => { setExpandedTeams(new Set()); }, [] ); // Ouvrir automatiquement les équipes qui contiennent des résultats lors de la recherche useEffect(() => { if (searchTerm.trim()) { const teamsWithResults = Object.keys(filteredUsersByTeam); setExpandedTeams(new Set(teamsWithResults)); } // Ne pas fermer automatiquement les équipes si pas de recherche // Cela évite que les équipes se ferment lors de la suppression d'utilisateurs }, [searchTerm]); // Retiré filteredUsersByTeam de la dépendance const handleCreateUser = async () => { if (!userFormData.firstName || !userFormData.lastName) { toast({ title: "Erreur", description: "Veuillez remplir tous les champs obligatoires", variant: "destructive", }); return; } try { // TODO: Implémenter la création d'utilisateur toast({ title: "Succès", description: "Utilisateur créé avec succès", }); setUserFormData({ firstName: "", lastName: "", teamId: "" }); setIsCreateDialogOpen(false); // Rafraîchir la liste fetchUsers(); } catch (error: any) { toast({ title: "Erreur", description: error.message || "Erreur lors de la création de l'utilisateur", variant: "destructive", }); } }; const handleDeleteUser = async (user: User) => { if (user.teamName) { toast({ title: "Action impossible", description: "Retirez d'abord l'utilisateur de son équipe avant de le supprimer", variant: "destructive", }); return; } if ( !confirm( `Êtes-vous sûr de vouloir supprimer définitivement ${user.firstName} ${user.lastName} ?\n\nCette action supprimera aussi toutes ses évaluations par skills et est irréversible.` ) ) { return; } setDeletingUserId(user.uuid); try { await AdminManagementService.deleteUser(user.uuid); // Mettre à jour la liste locale setUsers((prev) => prev.filter((u) => u.uuid !== user.uuid)); toast({ title: "Succès", description: `${user.firstName} ${user.lastName} a été supprimé avec succès`, }); } catch (err: any) { toast({ title: "Erreur", description: err.message || "Erreur lors de la suppression de l'utilisateur", variant: "destructive", }); } finally { setDeletingUserId(null); } }; if (isLoading) { return (

Gestion des utilisateurs

{[1, 2, 3].map((i) => (
))}
); } if (error) { return (

Gestion des utilisateurs

{error}

); } return (
{/* En-tête avec bouton de création */}

Gestion des utilisateurs

Créer un nouvel utilisateur
setUserFormData({ ...userFormData, firstName: e.target.value, }) } placeholder="Prénom de l'utilisateur" />
setUserFormData({ ...userFormData, lastName: e.target.value, }) } placeholder="Nom de l'utilisateur" />
{/* Filtres et contrôles */} {/* Vue arborescente des utilisateurs */} 0} emptyState={

{searchTerm ? "Aucun utilisateur trouvé" : "Aucun utilisateur"}

{searchTerm ? "Essayez de modifier vos critères de recherche" : "Commencez par créer votre premier utilisateur"}

} > {Object.entries(filteredUsersByTeam).map( ([teamName, teamUsers], index) => (
toggleTeam(teamName)} icon={} itemCount={teamUsers.length} itemLabel="utilisateur" showSeparator={index > 0} canDelete={false} isDirection={false} /> {/* Liste des utilisateurs de l'équipe */} {expandedTeams.has(teamName) && (
{teamUsers.map((user, userIndex) => ( } title={`${user.firstName} ${user.lastName}`} badges={[ { text: user.hasEvaluations ? "A des évaluations" : "Aucune évaluation", variant: user.hasEvaluations ? "default" : "outline", }, ]} onDelete={() => handleDeleteUser(user)} canDelete={!user.teamName} showSeparator={userIndex > 0} additionalInfo={

{user.teamName ? `Équipe: ${user.teamName}` : "Aucune équipe"}

} /> ))}
)}
) )}
); }