diff --git a/client/src/App.tsx b/client/src/App.tsx index 1dc887e..d0cedc7 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -10,6 +10,7 @@ import Admin from "./pages/Admin"; import AdminFormations from "./pages/AdminFormations"; import AdminSequences from "./pages/AdminSequences"; import AdminApprenants from "./pages/AdminApprenants"; +import AdminApprenantDetail from "./pages/AdminApprenantDetail"; import AdminSequenceInscrits from "./pages/AdminSequenceInscrits"; import AdminUsers from "./pages/AdminUsers"; import AdminEmailTemplates from "./pages/AdminEmailTemplates"; @@ -28,6 +29,7 @@ function Router() { + diff --git a/client/src/pages/AdminApprenantDetail.tsx b/client/src/pages/AdminApprenantDetail.tsx new file mode 100644 index 0000000..1a42d35 --- /dev/null +++ b/client/src/pages/AdminApprenantDetail.tsx @@ -0,0 +1,191 @@ +import { useState } from "react"; +import { useLocation, useParams } from "wouter"; +import DashboardLayout from "@/components/DashboardLayout"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; +import { Badge } from "@/components/ui/badge"; +import { trpc } from "@/lib/trpc"; +import { ArrowLeft, Calendar, MapPin, User } from "lucide-react"; +import { format } from "date-fns"; +import { fr } from "date-fns/locale"; + +export default function AdminApprenantDetail() { + const params = useParams(); + const apprenantId = params.id ? parseInt(params.id) : 0; + const [, setLocation] = useLocation(); + + const { data: apprenant, isLoading: loadingApprenant } = trpc.apprenants.getById.useQuery({ id: apprenantId }); + const { data: inscriptions, isLoading: loadingInscriptions } = trpc.apprenants.getInscriptions.useQuery({ id: apprenantId }); + + if (loadingApprenant || loadingInscriptions) { + return ( + +
+
Chargement...
+
+
+ ); + } + + if (!apprenant) { + return ( + +
+
Apprenant introuvable
+
+
+ ); + } + + const getStatutBadge = (statut: string) => { + switch (statut) { + case 'confirmee': + return Confirmée; + case 'en_attente': + return En attente; + case 'annulee': + return Annulée; + default: + return {statut}; + } + }; + + const getFonctionLabel = (fonction: string) => { + switch (fonction) { + case 'directeur': + return 'Directeur'; + case 'chef_service': + return 'Chef de service'; + default: + return 'Autre'; + } + }; + + const getPublicCibleLabel = (publicCible: string) => { + switch (publicCible) { + case 'directeur': + return 'Directeurs'; + case 'chef_service': + return 'Chefs de service'; + case 'tous': + return 'Tous'; + default: + return 'Autre'; + } + }; + + return ( + +
+ {/* Header */} +
+
+ +

Détail de l'apprenant

+

+ Consultez toutes les inscriptions de cet apprenant +

+
+
+ + {/* Informations de l'apprenant */} + + + + + Informations personnelles + + + +
+
+
Nom complet
+
{apprenant.nom} {apprenant.prenom}
+
+
+
Email
+
{apprenant.email}
+
+
+
Code établissement
+
{apprenant.codeEtablissement}
+
+
+
Fonction
+
{getFonctionLabel(apprenant.fonction)}
+
+
+
+
+ + {/* Liste des inscriptions */} + + + Inscriptions aux formations + + {inscriptions?.length || 0} inscription(s) au total + + + + {!inscriptions || inscriptions.length === 0 ? ( +
+ Aucune inscription trouvée pour cet apprenant +
+ ) : ( + + + + Formation + Séquence + Dates + Lieu + Public cible + Date d'inscription + Statut + + + + {inscriptions.map((insc: any) => ( + + {insc.formation?.nom || 'N/A'} + {insc.sequence?.nom || 'N/A'} + +
+ {insc.sequence?.dates?.map((date: any, idx: number) => ( +
+ + {format(new Date(date.dateDebut), 'dd/MM/yyyy HH:mm', { locale: fr })} +
+ ))} +
+
+ +
+ + {insc.sequence?.lieu || 'N/A'} +
+
+ {getPublicCibleLabel(insc.sequence?.publicCible || '')} + + {format(new Date(insc.dateInscription), 'dd/MM/yyyy HH:mm', { locale: fr })} + + {getStatutBadge(insc.statut)} +
+ ))} +
+
+ )} +
+
+
+
+ ); +} diff --git a/client/src/pages/AdminApprenants.tsx b/client/src/pages/AdminApprenants.tsx index 7ac7ca8..e5f5162 100644 --- a/client/src/pages/AdminApprenants.tsx +++ b/client/src/pages/AdminApprenants.tsx @@ -7,12 +7,14 @@ import { Label } from "@/components/ui/label"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { trpc } from "@/lib/trpc"; -import { Plus, Pencil, Trash2, Search, SlidersHorizontal } from "lucide-react"; +import { Plus, Pencil, Trash2, Search, SlidersHorizontal, Eye } from "lucide-react"; import { useState, useMemo } from "react"; +import { useLocation } from "wouter"; import { toast } from "sonner"; import { Skeleton } from "@/components/ui/skeleton"; export default function AdminApprenants() { + const [, setLocation] = useLocation(); const [open, setOpen] = useState(false); const [editingId, setEditingId] = useState(null); const [searchTerm, setSearchTerm] = useState(""); @@ -298,6 +300,14 @@ export default function AdminApprenants() {
+