Checkpoint: Espace Formateur - Fonctionnalités complètes
✅ **Nouvelles fonctionnalités** : **Base de données** : - Nouvelle table `supportsFormation` pour stocker les documents uploadés par les formateurs - Champs : sequenceId, formateurId, nomFichier, typeFichier, tailleFichier, urlFichier, s3Key, description - Migration effectuée avec succès **Backend (server/formateurDb.ts)** : - `getCalendrierFormateur()` : Récupère les interventions à venir avec dates, lieux et nombre d'inscrits - `getApprenantsSequence()` : Liste des apprenants inscrits à une séquence - `getSupportsSequence()` : Liste des supports de formation d'une séquence - `ajouterSupport()` : Upload d'un nouveau support - `supprimerSupport()` : Suppression d'un support avec vérification de propriété - `validerPresence()` : Validation de la présence d'un apprenant - `getHistoriqueFormateur()` : Historique des formations passées avec statistiques - `getDetailSequence()` : Détails complets d'une séquence avec dates **API tRPC (server/routers.ts)** : - `formateur.calendrier` : Calendrier des interventions avec filtres de dates - `formateur.apprenants` : Liste des apprenants d'une séquence - `formateur.supports` : Gestion des supports (liste, ajout, suppression) - `formateur.validerPresence` : Validation des présences en ligne - `formateur.historique` : Historique complet des formations - `formateur.detailSequence` : Détails d'une séquence **Pages frontend** : - `/formateur` : **FormateurDashboard** - Calendrier des interventions à venir groupées par date - `/formateur/sequence/:id` : **FormateurSequence** - Détails séquence avec onglets Apprenants et Supports - `/formateur/historique` : **FormateurHistorique** - Historique des formations avec taux de présence **Fonctionnalités implémentées** : - 📅 Calendrier des interventions avec dates, heures, lieux et nombre d'inscrits - 👥 Liste des apprenants avec informations complètes (nom, email, fonction, établissement) - ✅ Validation des présences en ligne avec checkboxes interactives - 📎 Gestion des supports de formation (liste, téléchargement) - 📊 Historique des formations avec statistiques (inscrits, présents, taux) - 🎨 Interface moderne avec cartes, tableaux et onglets **Notes** : - L'ID du formateur est actuellement fixé à 1 (TODO: lier à l'utilisateur connecté) - La fonctionnalité d'upload de supports est préparée mais nécessite l'implémentation du composant d'upload - Les présences sont gérées via le statut de l'inscription (confirmée/annulée)
This commit is contained in:
@@ -1266,6 +1266,96 @@ export const appRouter = router({
|
||||
}),
|
||||
}),
|
||||
|
||||
// ===== ESPACE FORMATEUR =====
|
||||
formateur: router({
|
||||
calendrier: protectedProcedure
|
||||
.input(z.object({
|
||||
formateurId: z.number(),
|
||||
dateDebut: z.date().optional(),
|
||||
dateFin: z.date().optional(),
|
||||
}))
|
||||
.query(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
return formateurDb.getCalendrierFormateur(input.formateurId, input.dateDebut, input.dateFin);
|
||||
}),
|
||||
|
||||
apprenants: protectedProcedure
|
||||
.input(z.object({ sequenceId: z.number() }))
|
||||
.query(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
return formateurDb.getApprenantsSequence(input.sequenceId);
|
||||
}),
|
||||
|
||||
supports: protectedProcedure
|
||||
.input(z.object({ sequenceId: z.number() }))
|
||||
.query(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
return formateurDb.getSupportsSequence(input.sequenceId);
|
||||
}),
|
||||
|
||||
ajouterSupport: protectedProcedure
|
||||
.input(z.object({
|
||||
sequenceId: z.number(),
|
||||
formateurId: z.number(),
|
||||
nomFichier: z.string(),
|
||||
typeFichier: z.string(),
|
||||
tailleFichier: z.number(),
|
||||
urlFichier: z.string(),
|
||||
s3Key: z.string(),
|
||||
description: z.string().optional(),
|
||||
}))
|
||||
.mutation(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
return formateurDb.ajouterSupport(input);
|
||||
}),
|
||||
|
||||
supprimerSupport: protectedProcedure
|
||||
.input(z.object({
|
||||
supportId: z.number(),
|
||||
formateurId: z.number(),
|
||||
}))
|
||||
.mutation(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
const support = await formateurDb.supprimerSupport(input.supportId, input.formateurId);
|
||||
|
||||
// Note: La suppression du fichier S3 devrait être gérée par un processus de nettoyage séparé
|
||||
// car il n'y a pas de fonction storageDelete dans l'API actuelle
|
||||
|
||||
return { success: true, support };
|
||||
}),
|
||||
|
||||
validerPresence: protectedProcedure
|
||||
.input(z.object({
|
||||
inscriptionId: z.number(),
|
||||
present: z.boolean(),
|
||||
}))
|
||||
.mutation(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
await formateurDb.validerPresence(input.inscriptionId, input.present);
|
||||
return { success: true };
|
||||
}),
|
||||
|
||||
historique: protectedProcedure
|
||||
.input(z.object({
|
||||
formateurId: z.number(),
|
||||
limit: z.number().optional(),
|
||||
}))
|
||||
.query(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
return formateurDb.getHistoriqueFormateur(input.formateurId, input.limit);
|
||||
}),
|
||||
|
||||
detailSequence: protectedProcedure
|
||||
.input(z.object({
|
||||
sequenceId: z.number(),
|
||||
formateurId: z.number(),
|
||||
}))
|
||||
.query(async ({ input }) => {
|
||||
const formateurDb = await import("./formateurDb");
|
||||
return formateurDb.getDetailSequence(input.sequenceId, input.formateurId);
|
||||
}),
|
||||
}),
|
||||
|
||||
// ===== ÉTABLISSEMENTS =====
|
||||
etablissements: router({
|
||||
list: adminProcedure.query(async () => {
|
||||
|
||||
Reference in New Issue
Block a user