From c9f6f8f068411f4baa73ce573f573d0d04ea28e0 Mon Sep 17 00:00:00 2001 From: Manus Sandbox Date: Mon, 17 Nov 2025 16:10:16 -0500 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20Ajout=20de=20la=20fonctionnalit?= =?UTF-8?q?=C3=A9=20de=20cr=C3=A9ation=20d'utilisateurs=20:=20ajout=20de?= =?UTF-8?q?=20la=20fonction=20createUser=20dans=20db.ts,=20cr=C3=A9ation?= =?UTF-8?q?=20de=20la=20proc=C3=A9dure=20tRPC=20users.create,=20ajout=20du?= =?UTF-8?q?=20bouton=20"Ajouter=20un=20utilisateur"=20dans=20la=20page=20A?= =?UTF-8?q?dminUsers=20avec=20ic=C3=B4ne=20Plus,=20cr=C3=A9ation=20du=20di?= =?UTF-8?q?alogue=20de=20cr=C3=A9ation=20avec=20formulaire=20complet=20(Op?= =?UTF-8?q?enID,=20nom,=20email,=20r=C3=B4le)=20et=20gestion=20des=20?= =?UTF-8?q?=C3=A9tats=20de=20cr=C3=A9ation=20avec=20validation=20et=20mess?= =?UTF-8?q?ages=20de=20succ=C3=A8s/erreur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/AdminUsers.tsx | 134 ++++++++++++++++++++++++++++++-- server/db.ts | 8 ++ server/routers.ts | 11 +++ todo.md | 7 ++ 4 files changed, 154 insertions(+), 6 deletions(-) diff --git a/client/src/pages/AdminUsers.tsx b/client/src/pages/AdminUsers.tsx index bed879b..da7bc87 100644 --- a/client/src/pages/AdminUsers.tsx +++ b/client/src/pages/AdminUsers.tsx @@ -28,15 +28,22 @@ import { } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { toast } from "sonner"; -import { Pencil, Trash2, UserCheck, UserX, Search } from "lucide-react"; +import { Pencil, Trash2, UserCheck, UserX, Search, Plus } from "lucide-react"; export default function AdminUsers() { const [searchTerm, setSearchTerm] = useState(""); const [filterRole, setFilterRole] = useState("all"); const [filterStatus, setFilterStatus] = useState("all"); + const [createDialogOpen, setCreateDialogOpen] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [selectedUser, setSelectedUser] = useState(null); + const [createForm, setCreateForm] = useState({ + openId: "", + name: "", + email: "", + role: "user" as "user" | "admin", + }); const [editForm, setEditForm] = useState({ name: "", email: "", @@ -44,6 +51,24 @@ export default function AdminUsers() { }); const { data: users = [], refetch } = trpc.users.list.useQuery(); + + const createMutation = trpc.users.create.useMutation({ + onSuccess: () => { + toast.success("Utilisateur créé avec succès"); + refetch(); + setCreateDialogOpen(false); + setCreateForm({ + openId: "", + name: "", + email: "", + role: "user", + }); + }, + onError: (error) => { + toast.error(`Erreur : ${error.message}`); + }, + }); + const updateMutation = trpc.users.update.useMutation({ onSuccess: () => { toast.success("Utilisateur modifié avec succès"); @@ -76,6 +101,25 @@ export default function AdminUsers() { }, }); + const handleCreate = () => { + setCreateDialogOpen(true); + }; + + const handleSaveCreate = () => { + if (!createForm.openId) { + toast.error("L'identifiant OpenID est obligatoire"); + return; + } + + createMutation.mutate({ + openId: createForm.openId, + name: createForm.name || undefined, + email: createForm.email || undefined, + role: createForm.role, + isActive: true, + }); + }; + const handleEdit = (user: any) => { setSelectedUser(user); setEditForm({ @@ -142,11 +186,17 @@ export default function AdminUsers() { return (
-
-

Gestion des Utilisateurs

-

- Gérez les comptes utilisateurs de l'application -

+
+
+

Gestion des Utilisateurs

+

+ Gérez les comptes utilisateurs de l'application +

+
+
{/* Filtres */} @@ -280,6 +330,78 @@ export default function AdminUsers() {
+ {/* Dialog de création */} + + + + Créer un nouvel utilisateur + + Ajoutez un nouvel utilisateur à l'application + + + +
+
+ + setCreateForm({ ...createForm, openId: e.target.value })} + placeholder="Identifiant unique de l'utilisateur" + /> +
+ +
+ + setCreateForm({ ...createForm, name: e.target.value })} + placeholder="Nom de l'utilisateur" + /> +
+ +
+ + setCreateForm({ ...createForm, email: e.target.value })} + placeholder="email@exemple.com" + /> +
+ +
+ + +
+
+ + + + + +
+
+ {/* Dialog de modification */} diff --git a/server/db.ts b/server/db.ts index 7c1d6f7..9c03231 100644 --- a/server/db.ts +++ b/server/db.ts @@ -376,6 +376,14 @@ export async function deleteInscription(id: number) { // ==================== GESTION DES UTILISATEURS ==================== +export async function createUser(data: InsertUser) { + const db = await getDb(); + if (!db) throw new Error("Database not available"); + + const result = await db.insert(users).values(data); + return result; +} + export async function getAllUsers() { const db = await getDb(); if (!db) return []; diff --git a/server/routers.ts b/server/routers.ts index 2170316..77f2a22 100644 --- a/server/routers.ts +++ b/server/routers.ts @@ -548,6 +548,17 @@ export const appRouter = router({ return db.getUserById(input.id); }), + create: adminProcedure.input(z.object({ + openId: z.string().min(1), + name: z.string().optional(), + email: z.string().email().optional(), + role: z.enum(["user", "admin"]).default("user"), + isActive: z.boolean().default(true), + })).mutation(async ({ input }) => { + await db.createUser(input); + return { success: true }; + }), + update: adminProcedure.input(z.object({ id: z.number(), name: z.string().optional(), diff --git a/todo.md b/todo.md index 54e894f..3eec80b 100644 --- a/todo.md +++ b/todo.md @@ -188,3 +188,10 @@ - [x] Ajouter la gestion des rôles (admin, user) - [x] Intégrer la page dans le menu de navigation - [x] Tester toutes les fonctionnalités de gestion des utilisateurs + +## Ajout de la fonctionnalité de création d'utilisateurs + +- [x] Ajouter une procédure tRPC pour créer un nouvel utilisateur +- [x] Ajouter un bouton "Ajouter un utilisateur" dans la page AdminUsers +- [x] Créer un dialogue de création avec formulaire (nom, email, rôle) +- [x] Tester la création d'un nouvel utilisateur