update api users and groups and users 2
This commit is contained in:
parent
e8c6a7e7f5
commit
aa76772c61
@ -11,8 +11,6 @@ import {
|
|||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { AddUserButton } from "./add-user-button";
|
|
||||||
import { SimplePagination } from "@/components/ui/pagination";
|
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { MoreHorizontal, Trash, Edit, UserPlus } from "lucide-react";
|
import { MoreHorizontal, Trash, Edit, UserPlus } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
@ -24,6 +22,21 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { toast } from "@/components/ui/use-toast";
|
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 {
|
interface User {
|
||||||
id: string;
|
id: string;
|
||||||
@ -54,6 +67,17 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [newUserDialog, setNewUserDialog] = useState(false);
|
||||||
|
const [editUserDialog, setEditUserDialog] = useState(false);
|
||||||
|
const [selectedUser, setSelectedUser] = useState<User | null>(null);
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
username: "",
|
||||||
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
|
email: "",
|
||||||
|
password: "",
|
||||||
|
roles: [] as string[],
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
@ -69,6 +93,11 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
setUsers(data);
|
setUsers(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching users:", error);
|
console.error("Error fetching users:", error);
|
||||||
|
toast({
|
||||||
|
title: "Erreur",
|
||||||
|
description: "Erreur lors de la récupération des utilisateurs",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@ -114,6 +143,155 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
return false;
|
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) => {
|
const handleDelete = async (userId: string) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/users/${userId}`, {
|
const response = await fetch(`/api/users/${userId}`, {
|
||||||
@ -148,9 +326,9 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
filtered = filtered.filter(user =>
|
filtered = filtered.filter(user =>
|
||||||
user.username.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
user.username.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
user.email.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
user.email?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
user.firstName.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
user.firstName?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
user.lastName.toLowerCase().includes(searchTerm.toLowerCase())
|
user.lastName?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,16 +346,6 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddUser = (newUser: User) => {
|
|
||||||
setUsers(prev => {
|
|
||||||
const updated = [...prev, newUser];
|
|
||||||
// Sort users by username
|
|
||||||
return updated.sort((a, b) => a.username.localeCompare(b.username));
|
|
||||||
});
|
|
||||||
// Reset to first page when adding new user
|
|
||||||
setCurrentPage(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
// First, let's debug the roles
|
// First, let's debug the roles
|
||||||
console.log("Current session:", {
|
console.log("Current session:", {
|
||||||
role: session?.user?.role,
|
role: session?.user?.role,
|
||||||
@ -185,173 +353,217 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
|
|||||||
isTeacher: session?.user?.role?.includes("Teacher")
|
isTeacher: session?.user?.role?.includes("Teacher")
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add this function for editing user
|
|
||||||
const handleEdit = async (userId: string) => {
|
|
||||||
try {
|
|
||||||
const user = users.find(u => u.id === userId);
|
|
||||||
if (!user) return;
|
|
||||||
|
|
||||||
const response = await fetch(`/api/users/${userId}`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
firstName: user.firstName,
|
|
||||||
lastName: user.lastName,
|
|
||||||
email: user.email,
|
|
||||||
enabled: true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
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 === userId ? { ...u, ...data } : u
|
|
||||||
));
|
|
||||||
|
|
||||||
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",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add this function for managing roles
|
|
||||||
const handleManageRoles = async (userId: string) => {
|
|
||||||
try {
|
|
||||||
const user = users.find(u => u.id === userId);
|
|
||||||
if (!user) return;
|
|
||||||
|
|
||||||
const response = await fetch(`/api/users/${userId}/roles`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
roles: user.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 === userId ? { ...u, roles: data.roles } : u
|
|
||||||
));
|
|
||||||
|
|
||||||
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",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!session) return null;
|
if (!session) return null;
|
||||||
if (loading) return <div className="text-center p-4">Loading...</div>;
|
if (loading) return <div className="text-center p-4">Loading...</div>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="space-y-4">
|
||||||
{/* Search and Add User row */}
|
<div className="flex justify-between items-center">
|
||||||
<div className="flex justify-between items-center mb-6">
|
<Input
|
||||||
<input
|
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Rechercher un utilisateur..."
|
placeholder="Rechercher un utilisateur..."
|
||||||
className="bg-black/20 border-0 rounded-md text-white/80 w-96"
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
className="max-w-sm"
|
||||||
/>
|
/>
|
||||||
<Button variant="secondary">
|
<Dialog open={newUserDialog} onOpenChange={setNewUserDialog}>
|
||||||
Ajouter un utilisateur
|
<DialogTrigger asChild>
|
||||||
</Button>
|
<Button>Ajouter un utilisateur</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Nouvel utilisateur</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<form onSubmit={handleAddUser} className="space-y-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="username">Nom d'utilisateur</Label>
|
||||||
|
<Input
|
||||||
|
id="username"
|
||||||
|
value={formData.username}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, username: e.target.value }))}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="firstName">Prénom</Label>
|
||||||
|
<Input
|
||||||
|
id="firstName"
|
||||||
|
value={formData.firstName}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, firstName: e.target.value }))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="lastName">Nom</Label>
|
||||||
|
<Input
|
||||||
|
id="lastName"
|
||||||
|
value={formData.lastName}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, lastName: e.target.value }))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="email">Email</Label>
|
||||||
|
<Input
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
value={formData.email}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="password">Mot de passe</Label>
|
||||||
|
<Input
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
value={formData.password}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, password: e.target.value }))}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="roles">Rôles</Label>
|
||||||
|
<Select
|
||||||
|
value={formData.roles[0] || ""}
|
||||||
|
onValueChange={(value) => setFormData(prev => ({ ...prev, roles: [value] }))}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Sélectionner un rôle" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value={ROLES.ADMIN}>Admin</SelectItem>
|
||||||
|
<SelectItem value={ROLES.TEACHER}>Enseignant</SelectItem>
|
||||||
|
<SelectItem value={ROLES.STUDENT}>Étudiant</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<Button type="submit" className="w-full">
|
||||||
|
Créer l'utilisateur
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Table content */}
|
<Table>
|
||||||
<div className="space-y-4">
|
<TableHeader>
|
||||||
<Table>
|
<TableRow>
|
||||||
<TableHeader>
|
<TableHead>Nom d'utilisateur</TableHead>
|
||||||
<TableRow>
|
<TableHead>Prénom</TableHead>
|
||||||
<TableHead>Nom d'utilisateur</TableHead>
|
<TableHead>Nom</TableHead>
|
||||||
<TableHead>Prénom</TableHead>
|
<TableHead>Email</TableHead>
|
||||||
<TableHead>Nom</TableHead>
|
<TableHead>Date d'inscription</TableHead>
|
||||||
<TableHead>Email</TableHead>
|
<TableHead>Rôles</TableHead>
|
||||||
<TableHead>Date d'inscription</TableHead>
|
<TableHead className="text-right">Actions</TableHead>
|
||||||
<TableHead>Roles</TableHead>
|
</TableRow>
|
||||||
<TableHead className="text-right">Actions</TableHead>
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{paginatedUsers.map((user) => (
|
||||||
|
<TableRow key={user.id}>
|
||||||
|
<TableCell>{user.username}</TableCell>
|
||||||
|
<TableCell>{user.firstName || "-"}</TableCell>
|
||||||
|
<TableCell>{user.lastName || "-"}</TableCell>
|
||||||
|
<TableCell>{user.email || "-"}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{new Date(user.createdTimestamp).toLocaleDateString()}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{(user.roles || []).join(", ") || "-"}</TableCell>
|
||||||
|
<TableCell className="text-right">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger asChild>
|
||||||
|
<Button variant="ghost" className="h-8 w-8 p-0">
|
||||||
|
<span className="sr-only">Open menu</span>
|
||||||
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent align="end">
|
||||||
|
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||||
|
<DropdownMenuItem onClick={() => handleEdit(user.id)}>
|
||||||
|
<Edit className="mr-2 h-4 w-4" />
|
||||||
|
Modifier
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem onClick={() => handleManageRoles(user.id)}>
|
||||||
|
<UserPlus className="mr-2 h-4 w-4" />
|
||||||
|
Gérer les rôles
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem
|
||||||
|
className="text-red-600"
|
||||||
|
onClick={() => handleDelete(user.id)}
|
||||||
|
>
|
||||||
|
<Trash className="mr-2 h-4 w-4" />
|
||||||
|
Supprimer
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHeader>
|
))}
|
||||||
<TableBody>
|
</TableBody>
|
||||||
{paginatedUsers.map((user) => (
|
</Table>
|
||||||
<TableRow key={user.id}>
|
|
||||||
<TableCell>{user.username}</TableCell>
|
|
||||||
<TableCell>{user.firstName}</TableCell>
|
|
||||||
<TableCell>{user.lastName}</TableCell>
|
|
||||||
<TableCell>{user.email}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{new Date(user.createdTimestamp).toLocaleDateString()}
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>{user.roles.join(", ")}</TableCell>
|
|
||||||
<TableCell className="text-right">
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<Button variant="ghost" className="h-8 w-8 p-0">
|
|
||||||
<span className="sr-only">Open menu</span>
|
|
||||||
<MoreHorizontal className="h-4 w-4" />
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="end">
|
|
||||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
|
||||||
<DropdownMenuItem onClick={() => handleEdit(user.id)}>
|
|
||||||
<Edit className="mr-2 h-4 w-4" />
|
|
||||||
Modifier
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem onClick={() => handleManageRoles(user.id)}>
|
|
||||||
<UserPlus className="mr-2 h-4 w-4" />
|
|
||||||
Gérer les rôles
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="text-red-600"
|
|
||||||
onClick={() => handleDelete(user.id)}
|
|
||||||
>
|
|
||||||
<Trash className="mr-2 h-4 w-4" />
|
|
||||||
Supprimer
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
|
|
||||||
<SimplePagination
|
<Dialog open={editUserDialog} onOpenChange={setEditUserDialog}>
|
||||||
currentPage={currentPage}
|
<DialogContent>
|
||||||
totalPages={totalPages}
|
<DialogHeader>
|
||||||
onPageChange={handlePageChange}
|
<DialogTitle>Modifier l'utilisateur</DialogTitle>
|
||||||
/>
|
</DialogHeader>
|
||||||
|
<form onSubmit={handleUpdateUser} className="space-y-4">
|
||||||
<div className="text-sm text-gray-500 text-center mt-2">
|
<div className="space-y-2">
|
||||||
Affichage de {Math.min(currentPage * ITEMS_PER_PAGE, filteredUsers.length)} sur {filteredUsers.length} utilisateurs
|
<Label htmlFor="edit-firstName">Prénom</Label>
|
||||||
</div>
|
<Input
|
||||||
</div>
|
id="edit-firstName"
|
||||||
|
value={formData.firstName}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, firstName: e.target.value }))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="edit-lastName">Nom</Label>
|
||||||
|
<Input
|
||||||
|
id="edit-lastName"
|
||||||
|
value={formData.lastName}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, lastName: e.target.value }))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="edit-email">Email</Label>
|
||||||
|
<Input
|
||||||
|
id="edit-email"
|
||||||
|
type="email"
|
||||||
|
value={formData.email}
|
||||||
|
onChange={(e) => setFormData(prev => ({ ...prev, email: e.target.value }))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="edit-roles">Rôles</Label>
|
||||||
|
<Select
|
||||||
|
value={formData.roles[0] || ""}
|
||||||
|
onValueChange={(value) => setFormData(prev => ({ ...prev, roles: [value] }))}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Sélectionner un rôle" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value={ROLES.ADMIN}>Admin</SelectItem>
|
||||||
|
<SelectItem value={ROLES.TEACHER}>Enseignant</SelectItem>
|
||||||
|
<SelectItem value={ROLES.STUDENT}>Étudiant</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<Button type="submit" className="flex-1">
|
||||||
|
Modifier
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={handleUpdateRoles}
|
||||||
|
className="flex-1"
|
||||||
|
>
|
||||||
|
Mettre à jour les rôles
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user