"use client"; import { useState, useEffect, useMemo } from "react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { useSession } from "next-auth/react"; import { Input } from "@/components/ui/input"; import { MoreHorizontal, Trash, Edit, UserPlus } from "lucide-react"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { toast } from "@/components/ui/use-toast"; 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"; interface User { id: string; username: string; firstName: string; lastName: string; email: string; createdTimestamp: number; roles: string[]; } interface UsersTableProps { userRole?: string[]; } // Constants for role names const ROLES = { ADMIN: "Admin", TEACHER: "Teacher", STUDENT: "Students" } as const; const ITEMS_PER_PAGE = 10; export function UsersTable({ userRole = [] }: UsersTableProps) { const { data: session, status } = useSession(); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [currentPage, setCurrentPage] = useState(1); const [searchTerm, setSearchTerm] = useState(""); const [newUserDialog, setNewUserDialog] = useState(false); const [editUserDialog, setEditUserDialog] = useState(false); const [selectedUser, setSelectedUser] = useState(null); const [formData, setFormData] = useState({ username: "", firstName: "", lastName: "", email: "", password: "", roles: [] as string[], }); useEffect(() => { fetchUsers(); }, []); const fetchUsers = async () => { try { setLoading(true); const response = await fetch("/api/users"); const data = await response.json(); console.log("Fetched users:", data); console.log("Current user role:", session?.user?.role); // Debug log setUsers(data); } catch (error) { console.error("Error fetching users:", error); toast({ title: "Erreur", description: "Erreur lors de la récupération des utilisateurs", variant: "destructive", }); } finally { setLoading(false); } }; const filterUsers = (users: User[]) => { console.log("Filtering users with role:", userRole); // Debug log if (!Array.isArray(users)) return []; // If no role specified or user is admin, show all users if (!userRole?.length || userRole.includes(ROLES.ADMIN)) { console.log("Showing all users - admin or no role"); return users; } // If user is teacher, show teachers and students if (userRole.includes(ROLES.TEACHER)) { console.log("Filtering for teacher view"); return users.filter(user => user.roles?.includes(ROLES.TEACHER) || user.roles?.includes(ROLES.STUDENT) ); } // If user is student, show only students if (userRole.includes(ROLES.STUDENT)) { console.log("Filtering for student view"); return users.filter(user => user.roles?.includes(ROLES.STUDENT)); } // Default: show all users console.log("Default case: showing all users"); return users; }; const canDelete = (targetUserRole: string[]) => { if (!userRole?.length) return false; if (userRole.includes(ROLES.ADMIN)) return true; if (userRole.includes(ROLES.TEACHER)) { return targetUserRole.includes(ROLES.STUDENT); } return false; }; const handleAddUser = async (e: React.FormEvent) => { e.preventDefault(); try { const response = await fetch("/api/users", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(formData), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Erreur lors de la création de l'utilisateur"); } setUsers(prev => [...prev, data.user]); setNewUserDialog(false); setFormData({ username: "", firstName: "", lastName: "", email: "", password: "", roles: [], }); toast({ title: "Succès", description: "L'utilisateur a été créé avec succès", }); } catch (error) { toast({ title: "Erreur", description: error instanceof Error ? error.message : "Une erreur est survenue", variant: "destructive", }); } }; const handleEdit = async (userId: string) => { const user = users.find(u => u.id === userId); if (!user) return; setSelectedUser(user); setFormData({ username: user.username, firstName: user.firstName || "", lastName: user.lastName || "", email: user.email || "", password: "", roles: user.roles || [], }); setEditUserDialog(true); }; const handleUpdateUser = async (e: React.FormEvent) => { e.preventDefault(); if (!selectedUser) return; try { const response = await fetch(`/api/users/${selectedUser.id}`, { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ firstName: formData.firstName, lastName: formData.lastName, email: formData.email, }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Erreur lors de la modification de l'utilisateur"); } setUsers(prevUsers => prevUsers.map(u => u.id === selectedUser.id ? { ...u, ...data } : u )); setEditUserDialog(false); setSelectedUser(null); toast({ title: "Succès", description: "L'utilisateur a été modifié avec succès", }); } catch (error) { toast({ title: "Erreur", description: error instanceof Error ? error.message : "Une erreur est survenue", variant: "destructive", }); } }; const handleManageRoles = async (userId: string) => { const user = users.find(u => u.id === userId); if (!user) return; setSelectedUser(user); setFormData(prev => ({ ...prev, roles: user.roles || [] })); setEditUserDialog(true); }; const handleUpdateRoles = async () => { if (!selectedUser) return; try { const response = await fetch(`/api/users/${selectedUser.id}/roles`, { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ roles: formData.roles, }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Erreur lors de la mise à jour des rôles"); } setUsers(prevUsers => prevUsers.map(u => u.id === selectedUser.id ? { ...u, roles: formData.roles } : u )); setEditUserDialog(false); setSelectedUser(null); toast({ title: "Succès", description: "Les rôles ont été mis à jour avec succès", }); } catch (error) { toast({ title: "Erreur", description: error instanceof Error ? error.message : "Une erreur est survenue", variant: "destructive", }); } }; const handleDelete = async (userId: string) => { try { const response = await fetch(`/api/users/${userId}`, { method: "DELETE", }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Erreur lors de la suppression de l'utilisateur"); } setUsers(prevUsers => prevUsers.filter(user => user.id !== userId)); toast({ title: "Succès", description: "L'utilisateur a été supprimé avec succès", }); } catch (error) { toast({ title: "Erreur", description: error instanceof Error ? error.message : "Une erreur est survenue", variant: "destructive", }); } }; const filteredUsers = useMemo(() => { let filtered = filterUsers(users); // Apply search filter if (searchTerm) { filtered = filtered.filter(user => user.username.toLowerCase().includes(searchTerm.toLowerCase()) || user.email?.toLowerCase().includes(searchTerm.toLowerCase()) || user.firstName?.toLowerCase().includes(searchTerm.toLowerCase()) || user.lastName?.toLowerCase().includes(searchTerm.toLowerCase()) ); } return filtered; }, [users, searchTerm, userRole]); // Calculate pagination const totalPages = Math.ceil(filteredUsers.length / ITEMS_PER_PAGE); const paginatedUsers = filteredUsers.slice( (currentPage - 1) * ITEMS_PER_PAGE, currentPage * ITEMS_PER_PAGE ); const handlePageChange = (page: number) => { setCurrentPage(page); }; // First, let's debug the roles console.log("Current session:", { role: session?.user?.role, isAdmin: session?.user?.role?.includes("Admin"), isTeacher: session?.user?.role?.includes("Teacher") }); if (!session) return null; if (loading) return
Loading...
; return (
setSearchTerm(e.target.value)} className="max-w-sm" /> Nouvel utilisateur
setFormData(prev => ({ ...prev, username: e.target.value }))} required />
setFormData(prev => ({ ...prev, firstName: e.target.value }))} />
setFormData(prev => ({ ...prev, lastName: e.target.value }))} />
setFormData(prev => ({ ...prev, email: e.target.value }))} required />
setFormData(prev => ({ ...prev, password: e.target.value }))} required />
Nom d'utilisateur Prénom Nom Email Date d'inscription Rôles Actions {paginatedUsers.map((user) => ( {user.username} {user.firstName || "-"} {user.lastName || "-"} {user.email || "-"} {new Date(user.createdTimestamp).toLocaleDateString()} {(user.roles || []).join(", ") || "-"} Actions handleEdit(user.id)}> Modifier handleManageRoles(user.id)}> Gérer les rôles handleDelete(user.id)} > Supprimer ))}
Modifier l'utilisateur
setFormData(prev => ({ ...prev, firstName: e.target.value }))} />
setFormData(prev => ({ ...prev, lastName: e.target.value }))} />
setFormData(prev => ({ ...prev, email: e.target.value }))} />
); }