# Gestion des Formations Manager Itinova - TODO ## Fonctionnalités principales - [x] Gestion des formations (CRUD) - [x] Gestion des séquences avec jusqu'à 4 dates par séquence - [x] Gestion des apprenants (CRUD) - [x] Système d'inscription avec validation de capacité - [x] Génération d'invitations Outlook (.ics) - [x] Envoi d'emails automatiques (confirmation, teaser, rappels) - [x] Exports PDF et Excel - [x] Filtres et recherche sur toutes les pages - [x] Champ "Fonction" dans la fiche apprenant - [x] Filtres par fonction sur les pages apprenants et inscrits - [x] Graphique de répartition par fonction sur le tableau de bord - [x] Personnalisation des templates d'emails - [x] Gestion des utilisateurs avec rôles (admin/user) - [x] Configuration SMTP pour l'envoi d'emails - [x] Authentification locale avec email/mot de passe - [x] Cohabitation OAuth Manus + authentification locale ## Champ "Public cible" dans les séquences - [x] Ajouter le champ "Public cible" dans la table sequences - [x] Ajouter le champ dans le formulaire de création de séquence - [x] Ajouter le champ dans le formulaire de modification de séquence - [x] Afficher le public cible sur la page d'inscription publique - [x] Ajouter "Tous" dans la liste des publics cible - [x] Ajouter le badge de public cible dans le tableau des séquences - [x] Ajouter le filtre par public cible sur la page de gestion des séquences - [x] Ajouter le public cible dans tous les exports (Excel, PDF) ## Alerte d'incohérence public cible / fonction - [x] Ajouter une alerte d'information lors de l'inscription - [x] Afficher l'alerte si le public cible ne correspond pas à la fonction - [x] Laisser l'inscription se faire (alerte non bloquante) - [x] Pas d'alerte si le public cible est "Tous" ## Rapport d'analyse public cible - [x] Créer une page de rapport comparant public cible et fonction des inscrits - [x] Afficher les écarts entre public cible et fonction réelle - [x] Ajouter des statistiques et graphiques pour visualiser les écarts - [x] Ajouter le lien dans le menu de navigation ## Gestion des formateurs - [x] Créer la table formateurs dans la base de données - [x] Créer les procédures tRPC (list, create, delete) - [x] Créer le composant FormateurCombobox avec autocomplétion - [x] Ajouter le champ formateur dans le formulaire de création de séquence - [x] Ajouter le champ formateur dans le formulaire de modification de séquence - [x] Afficher le formateur dans le tableau des séquences - [x] Afficher le formateur dans les emails d'invitation - [x] Corriger le stockage pour utiliser formateurId au lieu du nom ## Barre de progression colorée pour les séquences - [x] Créer le composant CapacityProgressBar - [x] Afficher "nbInscrits / capacité" avec pourcentage - [x] Code couleur automatique : vert (<70%), orange (70-90%), rouge (>90%) - [x] Intégrer dans le tableau des séquences - [x] Corriger le composant Progress pour supporter indicatorClassName ## Vue calendrier mensuel - [x] Créer la page AdminCalendrier - [x] Afficher un calendrier mensuel avec navigation - [x] Afficher les séquences sur leurs dates respectives - [x] Ajouter un dialog de détails au clic sur une séquence - [x] Ajouter le lien "Calendrier" dans le menu de navigation - [x] Afficher le nom de la formation + nom de la séquence - [x] Afficher le lieu, le formateur et le nombre d'inscrits - [x] Corriger le bug de dates (parseISO vs Date) - [x] Corriger le bug React #31 (clés stables pour les jours) ## Système de rappels automatiques - [x] Créer la table rappels dans la base de données - [x] Créer les procédures tRPC (list, create, update, delete) - [x] Créer la page AdminRappels pour configurer les rappels - [x] Permettre de configurer des rappels multiples (J-15, J-7, J-1) - [x] Templates d'emails personnalisables avec variables dynamiques - [x] Activation/désactivation des rappels - [x] Infrastructure pour l'envoi automatique (scheduler) - [x] Ajouter le lien "Rappels" dans le menu de navigation - [x] Créer les templates J-7 et J-1 avec style Itinova - [x] Implémenter le scheduler automatique (vérification toutes les heures) - [x] Corriger le bug d'envois multiples (un seul email par séquence) ## Améliorations diverses - [x] Réorganisation du menu de navigation en 4 zones (Tableau de bord, Gestion, Configuration, Analyses) - [x] Couleur bleue pour les titres des zones du menu - [x] Icône œil en bleu pour la visualisation - [x] Icône corbeille en rouge pour la suppression - [x] Badges de couleur pour les fonctions des apprenants - [x] Badges de couleur pour le public cible des séquences - [x] Couleurs uniques pour chaque formation dans le tableau des séquences - [x] Badges Actif/Inactif pour les apprenants - [x] Page dédiée aux établissements avec statistiques ## Améliorations du calendrier - [x] Ajout de filtres (formation, lieu, public cible) - [x] Vues alternatives (semaine, jour) en plus de la vue mensuelle - [x] Export PDF du calendrier - [x] Export iCal (.ics) pour import dans Outlook/Google Calendar ## Import Excel pour créer formations et séquences en masse - [x] Créer le template Excel avec colonnes prédéfinies - [x] Créer la procédure backend de parsing et validation - [x] Créer l'interface frontend avec upload et prévisualisation - [x] Ajouter la documentation utilisateur - [x] Corriger le bug de conflit de noms (formations vs table formations) - [x] Corriger le bug de colonne lienInscription → lienUnique - [x] Corriger le bug de récupération des IDs après insertion - [x] Ajouter le menu de navigation sur la page Import Excel - [x] Déplacer le menu Import Excel vers le bloc Configuration ## Corrections décalage horaire - [x] Correction du décalage horaire dans le formulaire de création de séquence - [x] Correction du décalage horaire dans le formulaire d'édition de séquence - [x] Correction du décalage horaire dans l'affichage des séquences - [x] Correction du décalage horaire dans la page d'inscription publique - [x] Utilisation des méthodes locales (getHours, getMinutes) au lieu des méthodes UTC ## Scripts de déploiement VPS - [x] Créer backup-before-update.sh (sauvegarde automatique) - [x] Créer update-app.sh (mise à jour automatique) - [x] Créer create-deployment-package.sh (création de package) - [x] Créer GUIDE_MISE_A_JOUR.md (documentation complète) - [x] Corriger les chemins pour utiliser formation-manager-itinova - [x] Corriger le bug "drizzle-kit: not found" (pnpm install sans --prod) - [x] Créer DEPLOIEMENT-MANUEL.md (guide déploiement sans Git) - [x] Créer deploy-update-manual.sh (script sans git pull) - [x] Créer DEPLOIEMENT-TARGZ.md (guide avec archive tar.gz) - [x] Créer deploy-update-targz.sh (script pour archive) ## Support SMTP Direct (sans Resend) - [x] Ajouter les champs SMTP dans la table emailConfig - [x] Créer server/_core/smtpSender.ts avec Nodemailer - [x] Modifier emailSender.ts pour supporter SMTP et Resend - [x] Ajouter l'interface de configuration SMTP dans AdminEmailConfig - [x] Corriger le bug d'enregistrement des champs SMTP - [x] Corriger la fonction upsertEmailConfig pour éviter les doublons - [x] Corriger l'affichage du statut (SMTP Direct au lieu de Resend) ## Améliorations emails groupés (teaser et rappel) - [x] Ajouter des logs serveur détaillés pour l'envoi groupé - [x] Afficher le nombre d'emails envoyés avec succès et échoués - [x] Avertir si aucun email n'est envoyé (aucun apprenant confirmé) - [x] Corriger le remplacement des tags {{nomFormation}}, {{nomSequence}}, etc. - [x] Ajouter le formateur et le lieu dans l'email de teaser - [x] Ajouter toutes les variables disponibles dans les templates ## Améliorations templates d'emails - [x] Ajouter la possibilité de personnaliser le corps du message - [x] Ajouter un éditeur de texte riche (TipTap) pour formater le contenu - [x] Ajouter 7 boutons pour insérer rapidement des variables dynamiques - [x] Afficher la prévisualisation HTML en temps réel - [x] Implémenter le remplacement automatique des variables lors de l'envoi - [x] Ajouter un bouton d'aperçu avec données réelles d'un apprenant - [x] Ajouter le template de rappel J-1 dans la liste - [x] Corriger les templates J-7 et J-1 pour afficher toutes les dates - [x] Ajouter la variable {{datesHTML}} pour afficher toutes les dates formatées - [x] Ajouter le bouton {{datesHTML}} dans l'interface - [x] Corriger la variable {{datesHTML}} dans l'email de confirmation ## Tableau de bord analytique - [x] Créer la page AdminTableauBordAnalytique - [x] Afficher les statistiques globales (cartes) - [x] Graphique d'évolution des inscriptions par mois - [x] Graphique du taux de remplissage des séquences - [x] Top 10 des établissements participants - [x] Répartition par fonction - [x] Ajouter des filtres de période (mois, trimestre, année) - [x] Implémenter l'export Excel des rapports analytiques - [x] Corriger l'incohérence des statistiques de répartition par fonction - [x] Ajouter le graphique de répartition par établissement sur le tableau de bord principal ## Améliorations visuelles - [x] Afficher le taux de remplissage en couleur conditionnelle - [x] Icône corbeille en rouge pour la suppression - [x] Icône œil en bleu pour la visualisation - [x] Couleurs uniques pour chaque formation dans le tableau des séquences - [x] Badges de couleur pour les fonctions des apprenants - [x] Badges Actif/Inactif pour les apprenants ## Feuilles de présence améliorées - [x] Ajouter le logo Itinova en haut à droite (40x15mm) - [x] Afficher le nom du formateur dans l'en-tête - [x] Ajouter deux colonnes de signature par apprenant (Matin / Après-midi) - [x] Générer une page par date de formation - [x] Ajouter la signature du formateur en bas de page avec date ## Détail par apprenant - [x] Créer la procédure tRPC apprenants.getInscriptions - [x] Créer la page AdminApprenantDetail - [x] Afficher les informations personnelles de l'apprenant - [x] Afficher le tableau de toutes ses inscriptions - [x] Ajouter le bouton "Détail" dans la page AdminApprenants - [x] Ajouter la route /admin/apprenants/:id dans App.tsx ## Correction problème création excessive d'utilisateurs - [x] Analyser la base de données pour identifier les doublons - [x] Nettoyer les utilisateurs en double - [x] Ajouter la contrainte UNIQUE sur la colonne openId - [x] Vérifier que onDuplicateKeyUpdate fonctionne correctement ## Ajout identifiant de connexion et modification mot de passe - [x] Ajouter le champ username dans le schéma de la base de données - [x] Mettre à jour les procédures tRPC create et update - [x] Implémenter le hashage du mot de passe avec bcryptjs - [x] Ajouter la colonne "Identifiant" dans le tableau des utilisateurs - [x] Ajouter les champs dans le formulaire de création - [x] Ajouter les champs dans le formulaire d'édition ## Utilisateur administrateur spécial - [x] Créer l'utilisateur "Administrateur" avec identifiant "adminServFormation" - [x] Désactiver le bouton de suppression pour cet utilisateur - [x] Rendre les champs nom et identifiant en lecture seule - [x] Permettre la modification de l'email et du mot de passe uniquement - [x] Garantir un accès administrateur permanent au système ## Page de connexion locale - [x] Créer la route d'authentification backend avec hashage bcrypt - [x] Créer la page Login.tsx avec formulaire username/password - [x] Implémenter la session JWT - [x] Tester avec l'utilisateur adminServFormation - [x] Ajouter la route /login dans App.tsx - [x] Créer une page de choix de connexion à la racine (/) - [x] Corriger la redirection après déconnexion vers la page de choix - [x] Ajouter la détection automatique de l'état de connexion - [x] Corriger l'authentification locale pour compatibilité avec OAuth ## Guide de configuration HTTPS - [x] Créer le guide complet de configuration HTTPS avec Let's Encrypt - [x] Créer le script d'installation automatique - [x] Créer le template nginx optimisé ## Questionnaires de satisfaction et évaluation des acquis - [x] Créer le schéma de base de données (tables questionnaires, questions, réponses) - [x] Développer les procédures backend tRPC pour la gestion des questionnaires - [x] Créer l'interface d'administration des questionnaires - [x] Créer l'interface publique de réponse aux questionnaires - [x] Implémenter l'envoi automatique post-formation - [x] Créer les tableaux de bord d'analyse avec graphiques (satisfaction par formation/formateur) - [x] Implémenter les exports Excel/PDF des feedbacks - [x] Tester le système complet (création, envoi, réponse, analyse) - [ ] Déployer sur le serveur VPS ## Amélioration : Prévisualisation des questionnaires - [x] Ajouter un bouton "Prévisualiser" dans la page d'édition de questionnaire - [x] Créer un modal de prévisualisation avec le rendu exact du questionnaire ## Exports et notifications pour les questionnaires - [x] Créer les fonctions backend d'export Excel des résultats - [x] Créer les fonctions backend d'export PDF des résultats - [x] Ajouter les boutons d'export dans la page d'analyse - [x] Implémenter le système de notifications pour les administrateurs - [x] Envoyer une notification lors de chaque nouvelle réponse à un questionnaire ## Tableau de bord de suivi des questionnaires - [x] Créer les fonctions backend pour les statistiques par formation - [x] Créer les fonctions backend pour l'évolution temporelle - [x] Créer les fonctions backend pour la comparaison par formateur - [x] Créer les procédures tRPC pour le tableau de bord - [x] Créer la page AdminQuestionnaireSuivi avec graphiques - [x] Ajouter le lien dans le menu de navigation - [x] Tester toutes les fonctionnalités ## Correction des erreurs SQL du tableau de bord de suivi - [x] Corriger la requête getEvolutionTemporelle (DATE_FORMAT) - [x] Corriger la requête getStatsByFormateur (sous-requête AVG) - [x] Simplifier les requêtes pour compatibilité MySQL - [x] Tester toutes les requêtes corrigées ## Espace Formateur ### Schéma de base de données - [x] Créer la table supportsFormation pour stocker les documents - [x] Ajouter les relations avec sequences - [x] Migrer le schéma avec pnpm db:push ### Backend - [x] Créer formateurDb.ts avec les fonctions de requête - [x] Ajouter les procédures tRPC pour le calendrier du formateur - [x] Ajouter les procédures tRPC pour la liste des apprenants - [x] Ajouter les procédures tRPC pour l'upload de supports - [x] Ajouter les procédures tRPC pour la validation des présences - [x] Ajouter les procédures tRPC pour l'historique ### Frontend - [x] Créer la page FormateurDashboard (calendrier) - [x] Créer la page FormateurSequence (détail séquence avec apprenants) - [x] Créer la page FormateurSupports (gestion des supports) - [x] Créer la page FormateurPresences (validation présences) - [x] Créer la page FormateurHistorique (historique formations) - [x] Ajouter les routes dans App.tsx - [x] Ajouter le menu de navigation formateur ### Tests - [x] Tester toutes les fonctionnalités de l'espace formateur ## Correction bug rappels multiples - [x] Analyser le code du scheduler de rappels - [x] Identifier pourquoi plusieurs emails sont envoyés - [x] Corriger la logique pour envoyer un seul email par séquence - [x] Tester avec la formation JetSki du 15/12/2025 ## Améliorations système de rappels ### Historique des rappels - [x] Créer la table logsRappels dans le schéma - [x] Migrer le schéma avec pnpm db:push - [x] Créer les fonctions de log dans rappelDb.ts - [x] Intégrer le logging dans rappelScheduler.ts - [x] Ajouter la vérification des doublons avant envoi ### Test manuel des rappels - [x] Créer la procédure tRPC pour tester un rappel - [ ] Ajouter le bouton de test dans AdminRappels.tsx (optionnel) - [ ] Implémenter la logique de test sans modifier les logs (optionnel) ### Notifications d'échec - [x] Créer la fonction de notification admin - [x] Intégrer les notifications dans le catch des erreurs d'envoi - [x] Ajouter un résumé des échecs dans les logs ## Historique et statistiques des rappels ### Backend - [x] Créer les fonctions de récupération des logs avec filtres - [x] Créer les fonctions de statistiques (taux succès, emails problématiques) - [x] Ajouter les procédures tRPC pour l'historique - [x] Ajouter les procédures tRPC pour les statistiques ### Page d'historique - [x] Créer AdminRappelsHistorique.tsx avec tableau des logs - [x] Ajouter les filtres (date, séquence, statut, email) - [x] Ajouter la recherche par email - [x] Ajouter la pagination - [x] Ajouter la route dans App.tsx ### Tableau de bord statistiques - [x] Créer AdminRappelsStats.tsx avec cartes de statistiques - [x] Ajouter le graphique d'évolution des envois - [x] Ajouter le graphique du taux de succès - [x] Ajouter la liste des emails problématiques - [x] Ajouter la route dans App.tsx ### Système de réessai automatique - [x] Ajouter le champ nbTentatives dans logsRappels - [x] Ajouter le champ prochainEssai dans logsRappels - [x] Créer la fonction de retry avec délai exponentiel - [x] Intégrer le retry dans rappelScheduler - [x] Limiter à 3 tentatives maximum ## Correction erreurs tRPC (HTML au lieu de JSON) - [x] Analyser les logs du serveur pour identifier les requêtes qui échouent - [x] Identifier les procédures tRPC qui causent les erreurs - [x] Corriger les erreurs côté serveur (emailBody, reduce) - [x] Tester la page admin pour vérifier que les erreurs sont résolues ## Rendre accessibles les pages d'historique et statistiques des rappels - [x] Vérifier que les routes sont bien définies dans App.tsx - [x] Vérifier que les liens sont bien dans le menu DashboardLayout - [x] Ajouter la gestion des sous-menus dans DashboardLayout - [x] Tester l'accès aux pages /admin/rappels/historique et /admin/rappels/statistiques ## Système plier/déplier pour le menu de navigation - [x] Ajouter un état pour gérer les sections ouvertes/fermées - [x] Ajouter des icônes chevron pour indiquer l'état - [x] Implémenter la logique de toggle pour chaque section - [x] Garder la section active automatiquement ouverte - [x] Tester le comportement sur toutes les sections ## Correction bug accordéons qui s'ouvrent tous - [x] Corriger le useEffect pour n'ouvrir que la section contenant l'item actif - [x] Supprimer le useEffect problématique (toutes sections ouvertes par défaut) - [x] Utiliser localStorage pour persister l'état des sections - [x] Tester le comportement en cliquant sur différents items ## Modification comportement par défaut accordéon menu - [x] Modifier l'initialisation pour ouvrir uniquement TABLEAU DE BORD par défaut - [x] Fermer GESTION, CONFIGURATION, ANALYSES par défaut - [x] Tester le comportement à l'ouverture ## Bug compteur d'inscrits après suppression - [x] Analyser le code de suppression d'inscription - [x] Identifier pourquoi le compteur ne se met pas à jour - [x] Corriger le bug de rafraîchissement du compteur - [x] Tester la suppression d'un apprenant et vérifier le compteur ## Bug nom formateur dans email rappel J-7 - [x] Analyser le code d'envoi des emails de rappel - [x] Comparer avec le code de prévisualisation - [x] Identifier pourquoi le nom du formateur n'est pas remplacé - [x] Corriger le bug de remplacement du nom du formateur - [x] Bug persistant : J-1 fonctionne mais J-7 ne fonctionne toujours pas - [x] Analyser la différence entre le template J-7 et J-1 - [x] Corriger le template J-7 définitivement ## 🔔 Système de notifications enrichi - [x] Email de remerciement post-formation - [x] Notification aux formateurs (nouvelle inscription) - [x] Notification aux formateurs (annulation) - [x] Alerte capacité atteinte (pour les admins) - [x] Notification d'annulation aux apprenants en liste d'attente - [x] Ajout du champ email pour les formateurs - [x] Scheduler automatique pour les remerciements post-formation - [x] Procédure tRPC pour envoi manuel des remerciements ## Améliorations notifications (15/12/2025) - [x] Interface de gestion des emails formateurs dans Configuration - [x] Tableau de bord des notifications avec historique des emails envoyés - [x] Lien vers questionnaire de satisfaction dans l'email de remerciement ## Réimplémentation attestations (16/12/2025) - [x] Recréer les tables en base de données - [x] Recréer le service de génération PDF - [x] Recréer les procédures tRPC - [x] Créer la page de configuration - [x] Intégrer le bouton dans la page de validation des présences - [x] Tester la génération complète ## Authentification et accès formateurs - [x] Analyser le système d'authentification actuel (users, roles) - [x] Créer le rôle "formateur" dans la base de données - [x] Lier les comptes utilisateurs aux formateurs existants (champ formateurId) - [x] Utiliser la page de connexion locale existante - [x] Implémenter la redirection selon le rôle (admin → /admin, formateur → /formateur) - [ ] Tester la connexion et l'accès aux fonctionnalités formateur ## Upload logo et signature pour attestations - [x] Ajouter les champs logoUrl et signatureUrl dans configAttestation (déjà existants) - [x] Créer le composant d'upload d'images vers S3 (ImageUpload.tsx) - [x] Créer l'endpoint d'upload serveur (/api/upload-image) - [x] Intégrer l'upload dans la page de configuration des attestations - [x] Modifier le service PDF pour inclure le logo et la signature - [ ] Tester la génération d'attestations avec logo et signature personnalisés ## Réorganisation du menu de navigation - [x] Déplacer le menu "Notifications" de CONFIGURATION vers ANALYSES ## Nouvelles modifications du menu - [x] Renommer "Attestations" en "Attestations de formation" - [x] Déplacer "Statistiques" de Rappels vers ANALYSES et le renommer "Rappels" ## Création de la section TRAÇABILITÉ - [x] Renommer "Rappels" (ANALYSES) en "Statistiques des rappels" - [x] Créer une nouvelle section "TRAÇABILITÉ" - [x] Déplacer "Notifications" vers TRAÇABILITÉ - [x] Déplacer "Suivi Questionnaires" vers TRAÇABILITÉ - [x] Déplacer "Établissements" vers TRAÇABILITÉ - [x] Déplacer "Historique" (sous-menu de Rappels) vers TRAÇABILITÉ avec le nom "Rappels" ## Centralisation de la création des formateurs - [x] Retirer le bouton de création de formateur de la page Formateurs - [x] Supprimer le dialogue de création et les mutations associées - [x] Ajouter un message explicatif indiquant que la création se fait via la page Utilisateurs ## Liaison formateurs existants avec utilisateurs - [x] Analyser les formateurs existants dans la table formateurs - [x] Créer une procédure listWithFormateurs pour afficher tous les formateurs - [x] Afficher les formateurs sans compte dans une section dédiée - [x] Ajouter un bouton "Créer un compte" qui pré-remplit le formulaire - [x] Lier automatiquement le formateurId lors de la création ## Renommage des templates de rappels - [x] Renommer "Rappel J-7" en "Rappel 1" dans AdminEmailTemplates.tsx - [x] Renommer "Rappel J-1" en "Rappel 2" dans AdminEmailTemplates.tsx - [x] Renommer "Rappel J-7" en "Rappel 1" dans AdminRappels.tsx - [x] Renommer "Rappel J-1" en "Rappel 2" dans AdminRappels.tsx ## Remise du menu Rappels dans CONFIGURATION - [x] Ajouter le menu "Rappels" dans la section CONFIGURATION - [x] Pointer vers /admin/rappels pour la gestion des rappels ## Renommage du label dans la gestion des rappels - [x] Renommer "Type de rappel" en "Template d'email utilisé" dans les dialogues de création/modification - [x] Renommer "Type" en "Template" dans le header du tableau ## Ajout de 4 nouveaux templates de rappels - [x] Ajouter "Rappel 3", "Rappel 4", "Rappel 5", "Rappel 6" dans AdminEmailTemplates.tsx - [x] Ajouter les mêmes templates dans AdminRappels.tsx avec délais (14, 21, 30, 60 jours) - [x] Modifier initializeDefaultEmailTemplates dans db.ts pour créer ces templates basés sur Rappel 1 ## Correction erreur emailTemplates.getByType - [x] Modifier getEmailTemplateByType dans db.ts pour retourner null au lieu de undefined ## Modification de la fenêtre de création des rappels - [x] Analyser le schéma actuel de la table rappels - [x] Ajouter un champ "timing" (pre_formation / post_formation) dans le schéma - [x] Appliquer la modification en base de données (ALTER TABLE) - [x] Modifier AdminRappels.tsx pour ajouter les radio buttons pré/post-formation - [x] Ajouter un champ de saisie du nombre de jours avec label dynamique - [x] Mettre à jour les procédures tRPC (create et update) pour gérer timing ## Ajout de pièces jointes dans les rappels par email - [x] Modifier le schéma de la table rappels pour ajouter les champs de fichier (nomFichier, urlFichier, s3Key, typeFichier, tailleFichier) - [x] Appliquer la migration en base de données - [x] Créer un composant FileUpload pour l'upload de fichiers vers S3 - [x] Modifier AdminRappels.tsx pour intégrer le composant d'upload - [x] Créer un endpoint API pour l.upload de fichiers vers S3 - [x] Mettre à jour les procédures tRPC create et update pour gérer les fichiers - [x] Modifier le service d.envoi d.emails pour inclure les pièces jointes - [x] Tester l.upload et l.envoi d.emails avec pièce jointe ## Correction affichage délai rappels post-formation - [x] Corriger l.affichage de la colonne "Délai" pour afficher J+X pour les rappels post-formation - [x] Tester l.affichage avec un rappel pré-formation et un rappel post-formation ## Refonte système de rappels - Gestion par séquence - [x] Créer la table rappelSequences (relation many-to-many entre rappels et séquences) - [x] Appliquer la migration en base de données - [x] Créer un composant de sélection multi-séquences - [x] Modifier le formulaire AdminRappels pour intégrer le sélecteur de séquences - [x] Créer les fonctions DB pour gérer les associations rappel-séquence - [x] Mettre à jour les procédures tRPC create et update pour gérer les associations - [x] Modifier le scheduler pour ne traiter que les séquences associées à chaque rappel - [ ] Adapter l'affichage du tableau pour montrer les séquences associées - [ ] Tester la création d'un rappel avec sélection de séquences spécifiques - [ ] Tester l'envoi automatique avec le nouveau système ## Refonte granulaire : sélection par date de formation - [x] Modifier rappelSequences pour pointer vers dateFormationId au lieu de sequenceId - [x] Créer le composant DateFormationMultiSelect hiérarchique - [x] Intégrer le nouveau sélecteur dans AdminRappels - [x] Adapter les fonctions DB pour gérer dateFormationId - [x] Mettre à jour les procédures tRPC pour dateFormationId - [x] Modifier le scheduler pour filtrer par dateFormationId - [ ] Tester la création avec dates spécifiques - [ ] Vérifier l'affichage et l'édition ## Améliorations tableau des rappels - [x] Renommer la colonne "Template" en "Template d'email" - [x] Ajouter une colonne "Dates concernées" avec formations, séquences et dates - [x] Modifier la procédure tRPC pour inclure les informations de dates - [x] Tester l'affichage avec plusieurs rappels ## Améliorations avancées du tableau des rappels - [x] Ajouter des badges visuels Global/Ciblé dans la colonne Nom - [x] Implémenter les filtres par formation et séquence - [x] Créer la fonction d'export CSV des rappels - [x] Tester toutes les fonctionnalités ## Cohérence visuelle des icônes - [x] Vérifier et corriger la couleur de l'icône corbeille (rouge) sur toutes les pages - [x] Vérifier et corriger la couleur de l'icône œil (bleu) sur toutes les pages ## Colorisation des icônes du menu latéral - [x] Appliquer des couleurs par catégorie aux icônes du menu (Tableau de bord: bleu, Gestion: vert, Configuration: orange, Traçabilité: violet, Analyses: rose) - [x] Vérifier l'affichage visuel du menu colorisé ## Amélioration visuelle de la colonne Dates concernées dans les rappels - [x] Ajouter des badges colorés pour distinguer formations, séquences et dates - [x] Utiliser des icônes pour identifier chaque type d'élément - [x] Améliorer la hiérarchie typographique pour faciliter la lecture ## Colonne Rappels configurés dans la gestion des séquences - [x] Modifier le backend pour récupérer les rappels associés à chaque date - [x] Ajouter la colonne "Rappels configurés" dans le tableau des séquences - [x] Afficher les rappels avec badges visuels similaires à la page des rappels ## Vues complète et réduite pour la gestion des séquences - [x] Ajouter un bouton de basculement entre vue complète et vue réduite - [x] Masquer les colonnes Lieu, Public cible, Formateur en vue réduite - [x] Simplifier l'affichage des rappels (supprimer "Date 1:", afficher sur une ligne) ## Séparation des rappels pré et post-formation - [x] Séparer l'affichage des rappels en deux catégories (pré-formation et post-formation) - [x] Ajouter des labels visuels pour distinguer les deux types de rappels ## Amélioration affichage des rappels dans les séquences - [x] Remplacer la colonne "Rappels configurés" par deux colonnes distinctes - [x] Créer colonne "Rappels pré-formation" avec badges bleus - [x] Créer colonne "Rappels post-formation" avec badges verts - [x] Tester l'affichage dans les vues complète et réduite ## Restriction d'accès pour les formateurs - [x] Ajouter le rôle "formateur" dans la table users - [x] Modifier le menu DashboardLayout pour masquer Configuration et Traçabilité aux formateurs - [x] Filtrer les formations pour ne montrer que celles du formateur connecté - [x] Filtrer les séquences pour ne montrer que celles du formateur connecté - [x] Filtrer les apprenants pour ne montrer que ceux inscrits aux séquences du formateur - [x] Créer une procédure backend pour vérifier si un utilisateur est formateur - [x] Tester avec un compte formateur ## Tableau de bord personnalisé pour formateurs - [x] Créer les procédures backend pour récupérer les prochaines séquences du formateur - [x] Créer les procédures backend pour calculer les statistiques du formateur - [x] Créer la page FormateurDashboard avec cartes de statistiques - [x] Afficher la liste des prochaines séquences avec nombre d'inscrits - [x] Afficher les rappels à venir pour chaque séquence - [x] Modifier DashboardLayout pour rediriger les formateurs vers /formateur/dashboard ## Notifications automatiques pour formateurs - [x] Envoyer une notification au formateur lors d'une nouvelle inscription - [x] Envoyer une notification au formateur lors d'une annulation - [x] Envoyer une notification au formateur quand la capacité maximale est atteinte - [x] Envoyer une notification au formateur quand une place se libère - [x] Intégrer les notifications dans les mutations d'inscription existantes ## Bug à corriger - [x] Corriger l'affichage du menu latéral pour les formateurs (menu invisible actuellement) ## Erreurs TypeScript à corriger pour publication - [x] Corriger l'erreur dans AdminSequences.tsx (propriété formateur manquante) - [x] Corriger les erreurs dans QuestionnaireReponse.tsx (questionnaire possibly null) ## Émargement numérique et attestations automatiques ### Schéma de base de données - [x] Créer la table presences (inscription, date, heurePresence, modeValidation) - [ ] Créer la table attestations (inscription, sequence, dateGeneration, pdfUrl) - [x] Ajouter le champ qrCodeToken dans la table sequences ### Backend - [x] Créer les procédures tRPC pour les présences (valider, lister, exporter) - [ ] Créer les procédures tRPC pour les attestations (générer, télécharger, lister) - [x] Implémenter la génération de QR code unique par séquence - [ ] Implémenter la génération de PDF d'attestation avec logo Itinova - [ ] Créer la fonction d'envoi automatique d'attestation par email ### Interface formateur - [x] Créer la page FormateurEmargement avec affichage QR code - [x] Ajouter la liste des apprenants avec statut de présence - [x] Permettre la validation manuelle de présence - [ ] Afficher l'historique des présences par date ### Interface publique - [x] Créer la page publique de scan QR code (/emargement/:token) - [x] Implémenter le scan avec la caméra du téléphone - [x] Afficher la confirmation de présence validée - [x] Gérer les erreurs (token invalide, déjà émargé, etc.) ### Génération d'attestations - [x] Créer le template PDF d'attestation personnalisable - [x] Générer automatiquement après validation de toutes les présences - [x] Envoyer par email aux apprenants - [x] Permettre le téléchargement depuis l'espace formateur ## Corrections techniques - [x] Corriger le problème d'aperçu de l'application (erreurs TypeScript) - [x] Corriger les références à heureDebut/heureFin dans AdminRappels.tsx - [x] Corriger l'accès à la propriété dates dans EmargementScan.tsx - [x] Corriger l'import manquant de QrCode dans DashboardLayout.tsx - [x] Corriger les erreurs TypeScript dans DashboardLayout.tsx (subItems) - [x] Ajouter downlevelIteration dans tsconfig.json - [x] Corriger l'utilisation de Set dans DateFormationMultiSelect.tsx - [x] Corriger l'appel à createAttestation (utiliser enregistrerAttestation) - [x] Corriger le lien QR code pour utiliser l'URL publique au lieu de localhost ## Page de paramètres de l'application - [x] Créer la table parametres dans la base de données - [x] Créer les procédures tRPC pour gérer les paramètres - [x] Créer la page AdminParametres - [x] Ajouter le lien dans le menu après "Configuration SMTP" - [x] Modifier qrCodeGenerator pour utiliser l'URL de la BDD - [x] Définir l'URL par défaut : https://formations.itinova.org - [x] Ajouter DashboardLayout à la page AdminParametres - [x] Ajouter DashboardLayout à la page FormateurEmargement ## Améliorations page Paramètres - [x] Ajouter les champs dans la table parametres : delaiExpirationQR, dureeValiditeToken, notificationsActives - [x] Créer la table historiqueParametres pour tracer les modifications - [x] Créer les fonctions backend pour gérer les nouveaux paramètres - [x] Créer la procédure tRPC pour tester l'accessibilité d'une URL - [x] Créer la procédure tRPC pour récupérer l'historique des modifications - [x] Mettre à jour l'interface AdminParametres avec les nouveaux champs - [x] Ajouter le bouton "Tester l'URL" avec indicateur de statut - [x] Ajouter une section "Historique des modifications" dans la page - [x] Tester toutes les fonctionnalités ## Correction menu de navigation formateur - [x] Identifier les pages formateur sans DashboardLayout - [x] Ajouter DashboardLayout à toutes les pages formateur - [x] Vérifier que le menu s'affiche correctement pour le rôle formateur - [x] Tester la navigation dans l'espace formateur ## Correction colonnes manquantes dans les tables - [x] Vérifier les colonnes manquantes dans la table apprenants - [x] Vérifier les colonnes manquantes dans la table sequences - [x] Ajouter les colonnes manquantes via SQL - [x] Tester les requêtes sur le dashboard admin ## Correction table rappels - [x] Vérifier les noms de colonnes dans la table rappels - [x] Corriger le schéma Drizzle pour correspondre à la base de données - [x] Tester les requêtes sur la page Rappels ## Améliorations attestations de formation ### Base de données - [x] Ajouter le paramètre envoiAutomatiqueAttestations dans la table parametres - [x] Créer la table historiqueAttestations pour tracer les envois ### Backend - [x] Créer les fonctions de gestion du paramètre d'envoi automatique - [x] Créer les procédures tRPC pour l'historique des attestations - [x] Créer la procédure de prévisualisation du PDF ### Frontend - [x] Ajouter le toggle d'envoi automatique dans AdminParametres - [x] Ajouter la prévisualisation PDF dans AdminAttestations - [x] Créer la page HistoriqueAttestations dans Traçabilité - [x] Ajouter le lien dans le menu de navigation ### Tes### Tests - [x] Tester le paramètre d'envoi automatique - [x] Tester la prévisualisation du modèle - [x] Tester la page d'historique ## Gestion des attestations de formation (Nouvelle page dans Gestion) ### Phase 1 : Schéma de base de données - [x] Ajouter les colonnes dans la table formations : modeAttestation (ENUM: 'auto', 'manuel'), modeEnvoi (ENUM: 'auto', 'manuel') - [x] Modifier la table attestations pour supporter les documents uploadés manuellement - [x] Ajouter les colonnes : documentUrl, documentS3Key, uploadedBy, uploadedAt ### Phase 2 : Backend - [x] Créer les procédures tRPC pour configurer le mode par formation - [x] Créer les procédures pour uploader des documents par apprenant - [x] Créer la procédure pour envoyer manuellement une attestation - [x] Créer la procédure pour lister les attestations par formation avec filtres ### Phase 3 : Interface utilisateur - [x] Créer la page AdminGestionAttestations dans le menu Gestion - [x] Ajouter la sélection de formation avec configuration des modes - [x] Créer l'interface d'upload de documents par apprenant - [x] Ajouter les boutons de prévisualisation et d'envoi manuel - [x] Créer le tableau des apprenants avec statut des attestations ### Phase 4 : Tests - [x] Tester la configuration par formation - [x] Tester l'upload de documents - [x] Tester la prévisualisation - [x] Tester l'envoi manuel ## Retrait du paramètre d'envoi automatique de la page Paramètres - [x] Retirer le paramètre d'envoi automatique des attestations de la fenêtre des paramètres (maintenant géré dans la gestion des attestations) ## Finalisation du retrait du paramètre d'envoi automatique - [x] Vérifier la cohérence des paramètres dans la page de gestion des attestations - [x] Retirer le champ envoiAutomatiqueAttestations de la table parametres dans le schéma - [x] Mettre à jour les procédures tRPC liées aux paramètres - [x] Tester le workflow complet de configuration et d'envoi automatique des attestations ## Améliorations techniques et documentation - [x] Corriger les erreurs TypeScript liées aux types templateType dans les rappels - [x] Nettoyer les fichiers de migration Drizzle pour éviter les conflits - [x] Créer un guide utilisateur pour la configuration des attestations ## Bug : Erreur replaceVariables - [x] Corriger l'erreur "Cannot read properties of undefined (reading 'replace')" dans AdminEmailTemplates.tsx ## Ajout template Réinitialisation mot de passe - [ ] Ajouter le type reset_password au schéma Drizzle - [ ] Modifier l'enum dans la base de données - [ ] Mettre à jour le code frontend - [ ] Créer le template par défaut - [x] Corriger le bug de mise à jour du type de template lors du changement de sélection dans AdminEmailTemplates.tsx - [x] Corriger le bug nécessitant deux clics pour mettre à jour le template (ajout de key pour forcer remontage) - [x] Corriger l'erreur SQL dans la modification de configuration SMTP (correction du schéma emailConfig) - [x] Corriger l'erreur de type dans la modification des séquences (formateurId string au lieu de number) - [x] Corriger la conservation de la date de blocage lors de la modification des séquences (ajout du champ dans le schéma Drizzle) - [x] Corriger les rappels envoyés plusieurs fois et l'historique vide (nettoyage de la table logsRappels) ## Nouvelles fonctionnalités à implémenter - [ ] Créer la table passwordResetTokens dans le schéma Drizzle - [ ] Implémenter la route backend pour demander une réinitialisation de mot de passe - [ ] Implémenter la route backend pour valider le token et réinitialiser le mot de passe - [ ] Créer la page frontend de demande de réinitialisation - [ ] Créer la page frontend de réinitialisation avec token - [x] Ajouter le bouton "Tester le rappel" dans AdminSequences.tsx - [ ] Corriger les erreurs TypeScript dans les fonctions de gestion des présences - [ ] Corriger les erreurs TypeScript dans les fonctions de gestion des logs - [x] Corriger l'erreur de validation du type de rappel dans la procédure testerRappel (typeRappel invalide) - [x] Corriger l'erreur "Cannot read properties of undefined (reading 'replace')" lors de l'envoi de test de rappel - [x] Améliorer le bouton "Tester le rappel" pour utiliser automatiquement le bon template configuré pour la séquence (au lieu de toujours envoyer rappel J-7) - [x] Modifier la procédure testerRappel pour envoyer le rappel à tous les inscrits confirmés (au lieu du premier uniquement) - [x] Corriger le problème "undefined" au début du texte dans le template de rappel 3 - [ ] Ajouter un headerTitle par défaut au template "rappel 3" - [x] Créer la page /forgot-password pour demander la réinitialisation de mot de passe - [x] Créer la page /reset-password/:token pour définir le nouveau mot de passe - [x] Installer le module bcrypt sur le VPS pour activer la réinitialisation de mot de passe (temporairement désactivé en attendant la résolution du problème de store pnpm) - [ ] Corriger l'erreur "(void 0) is not a function" sur la page de réinitialisation de mot de passe - [ ] Corriger le problème des rappels envoyés en boucle (non enregistrés dans l'historique) - [x] Modifier la page AdminSequences pour ouvrir en vue réduite par défaut - [x] Modifier le DashboardLayout pour réduire tous les menus sauf "Gestion" à la connexion - [x] Supprimer les boutons "Aperçu rappel J-7", "Envoyer rappel J-7", "Aperçu rappel J-1", "Envoyer rappel J-1" de la fenêtre de détails des séquences - [x] Corriger le bouton "Tester le rappel" pour enregistrer les envois dans l'historique des rappels (table logsRappels) - [x] Corriger l'enregistrement des logs de rappels : type erroné (J-1 au lieu de J+2), statut erroné (success/failed au lieu de succes/echec), email erroné (emailDestinataire au lieu de email) - [x] Ajouter une colonne "Type d'envoi" avec badge coloré dans l'interface d'historique des rappels - [x] Nettoyer les anciens logs erronés de la base de données - [x] Corriger les erreurs TypeScript critiques liées aux types null/undefined (réduction de 115 à 88 erreurs) - [x] Diagnostiquer pourquoi le rappel J+2 pour la séquence Test3 n'a pas été envoyé à opareige@gmail.com (déjà envoyé automatiquement) - [x] Corriger l'erreur de connexion à la base de données qui empêche adminServFormation de se connecter (PM2 ne chargeait pas le fichier .env) - [x] Ajouter un bouton pour vider la table des logs d'historique des rappels avec une boîte de dialogue de confirmation - [x] Diagnostiquer et corriger pourquoi le rappel J+2 automatique pour la séquence TEST 3 n'est toujours pas envoyé à opareige@gmail.com (problème de casse MySQL) - [x] Diagnostiquer et corriger pourquoi les emails de rappel automatiques ne sont pas reçus (code du scheduler ne gérait pas rappel3, rappel4, etc.) - [x] Diagnostiquer et corriger pourquoi le rappel J+2 automatique pour la séquence TEST 3 n'est toujours pas envoyé à opareige@gmail.com (problème de casse MySQL) - [x] Simplifier le code du scheduler pour utiliser uniquement sendRappelEmail de manière générique pour tous les types de rappels - [x] Corriger le schéma Drizzle pour utiliser des noms de tables en minuscules (logsrappels au lieu de logsRappels) - [x] Tester que tous les types de rappels fonctionnent correctement - [x] Corriger le problème du bouton de vidage de l'historique des rappels qui ne fonctionne plus (nom de table incorrect) - [ ] Déployer l'intégralité du projet mis à jour sur le VPS (bouton de suppression des rappels et toutes les fonctionnalités manquantes) - [x] Configurer l'upload de fichiers pour utiliser le stockage local sur le VPS au lieu du service S3 - [x] Corriger l'erreur d'upload de fichier depuis le navigateur sur le VPS (augmentation de la limite Nginx à 10 Mo) - [x] Ajouter une colonne dans le tableau de gestion des rappels pour indiquer la présence d'une pièce jointe - [x] Corriger la détection de la pièce jointe dans le tableau des rappels (vérification de nomFichier et urlFichier au lieu de pieceJointe) - [x] Corriger l'envoi de la pièce jointe dans les emails de rappel (support des fichiers locaux et S3) - [x] Corriger la corruption de la pièce jointe lors de l'envoi par email (ajout de l'encoding base64 pour SMTP/Nodemailer) - [x] Modifier le comportement par défaut des menus de la sidebar : tous repliés à la connexion sauf le menu "Gestion" (MENU_VERSION incrémentée à 5) - [x] Modifier le comportement des menus de la sidebar en mode accordéon : lorsqu'un menu s'ouvre, les autres se replient automatiquement - [x] Implémenter la fonctionnalité du bouton "Charger" dans la gestion des attestations de formation (upload de PDF avec validation) - [x] Corriger l'erreur "No procedure found on path attestations.uploadDocument" lors de l'upload d'attestations (utilisation de gestionAttestations.uploadDocument) - [x] Corriger l'erreur SQL "Failed query: insert into attestations" lors de l'upload d'attestation manuelle (ajout de apprenantId et sequenceId) - [x] Corriger l'erreur "refetchInscrits is not defined" lors de l'upload d'attestation manuelle (remplacement par refetchApprenants) - [x] Corriger l'erreur "aucune attestation disponible pour cet apprenant" lors de l'envoi manuel d'une attestation uploadée (vérification de documentUrl ou urlPdf) - [x] Modifier l'envoi d'attestation pour joindre le PDF directement en pièce jointe au lieu d'un lien de téléchargement - [x] Permettre le renvoi d'une attestation même après qu'elle ait été envoyée (afficher bouton Renvoyer au lieu de masquer Envoyer) - [x] Corriger l'erreur "Failed to parse URL" lors de l'envoi d'attestation avec un chemin local (gérer les chemins locaux et URLs complètes) - [x] Corriger le bouton Renvoyer inactif dans la gestion des attestations (correction selectedSequenceId -> apprenant.sequence.id) - [x] Corriger le problème d'envoi automatique des rappels qui ne se déclenchent pas à l'heure programmée (ajout vérification heure + intervalle 15 min au lieu de 1h) - [x] Ajouter un bouton "Tout renvoyer" pour envoyer en masse toutes les attestations chargées manuellement sur une séquence - [x] Corriger le scheduler de rappels qui ne trouve aucune date de formation (utilisation table rappelDates + correction heureEnvoi) - [x] Augmenter la tolérance du scheduler de rappels de 20 à 30 minutes pour couvrir 2 cycles de vérification - [x] Vérifier l'heure configurée en base de données pour le rappel J+2 - [x] Diagnostiquer et résoudre le problème de connexion SSH au VPS depuis le sandbox (résolu après modifications config SSH) - [x] Identifier la cause de l'erreur "banner line contains invalid characters" - [x] Optimiser la sécurité SSH avec Fail2Ban renforcé (maxretry=3, bantime=3600) - [x] Créer une whitelist d'IPs de confiance pour éviter les blocages - [x] Créer les fonctions backend pour récupérer les données Fail2Ban (IPs bannies, statistiques) - [x] Créer l'interface admin du tableau de bord Fail2Ban avec possibilité de débannir - [x] Implémenter le système d'alertes email pour les attaques massives (>10 IPs/heure) - [x] Tester et déployer le monitoring Fail2Ban sur le VPS - [x] Créer une nouvelle section "Gestion technique" dans le menu de navigation - [x] Déplacer "Sécurité SSH (Fail2Ban)" de Configuration vers Gestion technique - [x] Intégrer la page AdminFail2Ban dans DashboardLayout pour afficher le menu latéral - [x] Déplacer la section "Gestion technique" en dernière position du menu - [x] Corriger le problème d'affichage vide du menu Gestion technique (rebuild forcé) - [x] Redéployer correctement DashboardLayout.tsx sur le VPS avec Gestion technique en dernier - [ ] Corriger l'erreur qui cause l'affichage d'une page vide sur le VPS - [x] Identifier les 5 erreurs TypeScript les plus critiques - [x] Corriger les erreurs TypeScript critiques identifiées (89 → 78 erreurs) - [x] Déployer les corrections TypeScript sur le VPS - [ ] Vérifier le schéma de la table logsrappels dans la base de données - [ ] Exécuter la migration de base de données si nécessaire - [ ] Analyser la correspondance entre types de rappels et templates d'emails - [ ] Corriger l'enum de la colonne type dans logsrappels si nécessaire ## Correction cohérence types de rappels - [x] Analyser la correspondance entre types de rappels et templates d'emails - [x] Renommer rappel → rappel1 et rappelJ1 → rappel2 dans le schéma Drizzle - [x] Mettre à jour tous les fichiers utilisant rappel et rappelJ1 - [x] Modifier l'enum dans la base de données MySQL - [x] Déployer et tester les corrections ## Correction colonne statut dans envoisQuestionnaires - [x] Analyser le schéma Drizzle de la table envoisQuestionnaires - [x] Vérifier la structure de la table dans la base de données MySQL - [x] Créer le script SQL pour ajouter la colonne statut - [x] Exécuter la migration sur le VPS - [x] Déployer et tester ## Correction affichage nombre de dates sélectionnées - [x] Analyser le code de la boîte de dialogue de modification des rappels - [x] Identifier le bug de comptage des dates sélectionnées (références orphelines) - [x] Nettoyer les références orphelines dans rappelDates - [x] Ajouter les contraintes de clé étrangère pour éviter le problème - [x] Tester et déployer ## Amélioration affichage pièce jointe dans configuration rappels - [x] Analyser l'affichage actuel de la pièce jointe dans AdminRappels - [x] Ajouter une icône colorée (vert pour OUI, gris pour NON) - [x] Tester l'affichage - [x] Déployer sur le VPS ## Améliorations supplémentaires affichage pièces jointes - [x] Changer la couleur du badge "Non" en rouge (au lieu de gris) - [x] Ajouter un tooltip au survol du badge "Oui" avec nom et taille du fichier - [x] Rendre le badge "Oui" cliquable pour télécharger directement la pièce jointe - [x] Tester les fonctionnalités - [x] Déployer sur le VPS ## Alternance de couleurs sur tableau des rappels - [x] Ajouter une classe CSS pour l'alternance de couleurs (zebra striping) - [x] Appliquer la classe aux lignes du tableau - [x] Tester le rendu visuel - [x] Déployer sur le VPS ## Changement couleur alternance tableau rappels - [x] Remplacer le gris par un bleu légèrement soutenu (bg-blue-50/70) - [x] Déployer sur le VPS ## Correction erreur validation création rappel - [x] Identifier la source de l'erreur de validation templateType - [x] Corriger la validation pour accepter rappel1-6 au lieu de rappel/rappelJ1 - [x] Tester la création d'un rappel - [x] Déployer sur le VPS ## Recherche exhaustive des enums de types de rappels - [x] Rechercher tous les enums dans le code (backend + frontend) - [x] Corriger tous les endroits manqués (TEMPLATE_TYPES dans AdminRappels.tsx) - [x] Déployer et tester ## Ajout manuel d'apprenant dans la fenêtre "Inscrits à la séquence" - [x] Analyser la fenêtre des inscrits (AdminSequenceInscrits.tsx) - [x] Ajouter un bouton "Ajouter un inscrit" avec icône UserPlus dans le header - [x] Créer un dialogue de sélection d'apprenant (AddInscritForm.tsx) - [x] Implémenter la mutation backend inscriptions.create - [x] Tester l'ajout manuel - [x] Déployer sur le VPS ## Correction erreur validation modification template "Rappel 1" - [x] Rechercher tous les enums de types de templates dans le code - [x] Corriger les enums manqués dans AdminEmailTemplates.tsx (types ET liste déroulante) - [x] Déployer - [x] Mettre à jour les données dans la table emailTemplates (déjà fait lors de la migration précédente) - [x] Tester ## Restauration boutons d'ajout de balises dans templates - [x] Identifier pourquoi les boutons ont disparu - [x] Restaurer les boutons - [x] Déployer et tester ## Renommage bouton ajout d'apprenant - [x] Renommer "Ajouter un inscrit" en "Ajouter un apprenant" - [x] Ajouter précision dans la boîte de dialogue - [x] Déployer et tester ## Alternance de couleurs blanc/bleu sur tous les tableaux - [x] Liste des formations - [x] Liste des séquences - [x] Liste des apprenants - [x] Liste des inscrits (fenêtre gestion des attestations) - [x] Liste des utilisateurs - [x] Liste des formateurs - [x] Déployer et tester ## Refonte ergonomie du tableau de bord - [x] Analyser le tableau de bord actuel (Admin.tsx) - [x] Créer nouvelle version avec icônes modernes et colorées - [x] Ajouter liserés colorés sur les cartes - [x] Implémenter animations au survol et au chargement - [x] Améliorer la palette de couleurs - [x] Tester sur sandbox - [x] Déployer après validation utilisateur ## Refonte ergonomie du menu latéral accordéon - [x] Analyser le menu latéral actuel (DashboardLayout.tsx) - [x] Créer nouvelle version avec icônes colorées et animations - [x] Ajouter effets hover et transitions fluides - [x] Implémenter indicateur de page active - [x] Améliorer les couleurs et gradients - [x] Tester sur sandbox - [x] Déployer après validation utilisateur ## Correction bug page émargement formateur - [x] Analyser l'erreur "Cannot convert undefined or null to object" - [x] Identifier la requête tRPC qui échoue - [x] Corriger le bug - [x] Tester la correction ## Harmonisation tableau de bord avec palette pastel - [x] Adapter les couleurs des cartes statistiques en pastel - [x] Harmoniser les gradients avec le menu latéral - [x] Tester sur sandbox ## Correction bug page suivi questionnaires - [x] Analyser l'erreur "Cannot convert undefined or null to object" - [x] Identifier la requête tRPC qui échoue - [x] Corriger le bug - [x] Tester la correction ## Correction erreurs SQL suivi questionnaires - [x] Analyser les erreurs SQL (champs manquants dans WHERE) - [x] Identifier les requêtes concernées dans server/routers.ts - [x] Corriger les requêtes SQL - [x] Tester les corrections ## Déploiement VPS de toutes les améliorations - [x] Identifier tous les fichiers modifiés - [x] Déployer les fichiers sur le VPS - [x] Rebuild et redémarrer l'application - [x] Vérifier le déploiement ## Suppression mention rappel 7 jours dans message inscription - [x] Supprimer la ligne "Un email de rappel vous sera envoyé 7 jours avant la formation" - [x] Déployer sur le VPS ## Correction erreur mutation formateurs - [x] Analyser l'erreur "Unexpected token '<', ' date début dans la boîte de dialogue de modification des séquences - [x] Ajouter une validation frontend en temps réel dans les champs de date pour afficher un message d'erreur immédiat - [ ] Restreindre les droits des formateurs (pas de modification/suppression de formations et séquences) - [ ] Restreindre les droits des formateurs pour qu'ils ne puissent pas créer/modifier/supprimer des apprenants ## Autoriser les formateurs à accéder aux exports et feuilles de présence - [x] Identifier les procédures backend concernées (exports PDF/Excel, feuille de présence) - [x] Modifier les restrictions pour autoriser les formateurs - [x] Tester les modifications - [x] Déployer sur le VPS ## Corriger l'accès des formateurs à la liste des inscrits - [x] Identifier les procédures concernées (listBySequence, getWithDates) - [x] Remplacer adminProcedure par protectedProcedure - [x] Déployer sur le VPS ## Masquer le menu "Gestion technique" pour les formateurs - [x] Identifier le composant DashboardLayout où le menu est défini - [x] Ajouter une condition isAdmin pour masquer la section Gestion technique - [x] Tester et déployer sur le VPS ## Synchronisation entre table users (rôle formateur) et table formateurs - [x] Analyser la structure des deux tables - [x] Comprendre la relation entre users.role='formateur' et la table formateurs - [x] Proposer une solution pour synchroniser ou clarifier l'usage - [x] Implémenter la solution (auto-création dans createUser et updateUser) - [x] Créer un script de migration pour les formateurs existants - [x] Déployer sur le VPS et exécuter la migration ## Corriger la désactivation des rappels lors du changement de formateur - [x] Identifier le code de modification de séquence qui désactive les rappels - [x] Corriger pour ne désactiver que lors de changement de dates - [x] Tester la modification - [x] Déployer sur le VPS ## Créer un tableau de bord spécifique pour les formateurs - [x] Analyser le tableau de bord actuel (Admin.tsx) - [x] Vérifier les procédures backend existantes (déjà présentes) - [x] Réécrire FormateurDashboard.tsx avec le même design moderne - [x] Vérifier la route dans App.tsx (déjà présente) - [x] Ajouter la redirection automatique des formateurs vers /formateur - [x] Déployer sur le VPS ## Coloriser les boutons d'actions de la fenêtre "Inscrits à la séquence" - [x] Identifier le fichier AdminSequenceInscrits.tsx - [x] Appliquer des couleurs pastel aux boutons d'actions - [x] Déployer sur le VPS ## Permettre deux signatures par jour pour l'émargement (matin et après-midi) - [x] Analyser le système d'émargement actuel (schéma DB, backend, frontend) - [x] Modifier le schéma de base de données pour ajouter un champ "periode" (matin/apres-midi) - [x] Adapter les procédures backend pour gérer les deux périodes - [x] Modifier l'interface d'émargement pour proposer le choix matin/après-midi (EmargementScan + FormateurEmargement) - [x] Vérifier l'export de feuille de présence (déjà configuré avec deux colonnes) - [x] Déployer sur le VPS ## Corriger l'affichage vide de la liste des apprenants dans la gestion des attestations pour les formateurs - [x] Identifier le fichier de gestion des attestations - [x] Analyser les procédures backend concernées - [x] Corriger les restrictions d'accès pour les formateurs (getApprenantsWithStatus) - [x] Déployer sur le VPS ## Regrouper les apprenants par séquence dans la gestion des attestations - [x] Analyser l'affichage actuel (regroupement par formation) - [x] Vérifier le backend (données de séquence déjà présentes) - [x] Adapter l'interface pour afficher les apprenants regroupés par séquence - [x] Déployer sur le VPS ## Trier les séquences par ordre chronologique dans la gestion des attestations - [x] Modifier le backend pour inclure la première date de chaque séquence - [x] Adapter le frontend pour trier les séquences par date - [x] Déployer sur le VPS ## Corriger l'affichage vide de la liste des apprenants après le tri chronologique - [x] Identifier la cause du problème (structure imbriquée Drizzle ORM) - [x] Corriger le code backend (aplatir la structure de la requête) - [x] Corriger le code frontend (utiliser l'ID de séquence pour le tri) - [ ] Déployer sur le VPS - [x] Corriger le bouton "œil" dans la page apprenants (formateur) qui n'affiche pas le détail - [x] Corriger la page vide lors de l'émargement via QR code sur smartphone - [x] Ajouter confirmation visuelle après émargement réussi (animation + heure) - [x] Implémenter signature manuscrite sur smartphone pour attestations (annulé - changement de besoin) - [x] Implémenter signature manuscrite tactile pour émargement via QR code ## Signature tactile pour émargement via QR code - [x] Créer le composant SignaturePad avec signature_pad - [x] Ajouter les champs de signature dans la table presences (signatureUrl, signatureS3Key, dateSigned) - [x] Intégrer SignaturePad dans EmargementScan.tsx - [x] Modifier presences.valider pour accepter signatureDataUrl - [x] Uploader la signature en stockage local lors de la validation (S3 abandonné pour DNS) - [x] Stocker l'URL dans la base de données - [x] Afficher les informations de signature dans l'émargement formateur - [x] Ajouter une modale pour visualiser les signatures en grand format - [x] Corriger le problème Drizzle ORM avec sql.raw pour les colonnes de signature - [x] Déployer sur le VPS (formations.itinova.org) - [x] Retirer les logs de debug - [ ] Intégrer les signatures dans la feuille de présence PDF (optionnel) - [ ] Tester le flux complet sur smartphone - [ ] Déployer sur le VPS ## Stockage local des signatures d'émargement - [x] Modifier routers.ts pour stocker les signatures localement au lieu de S3 - [x] Créer la structure de dossiers uploads/signatures/[formation-id]-[sequence-id]/ - [x] Générer des noms de fichiers uniques pour chaque signature - [ ] Configurer Nginx pour servir les fichiers de signatures - [ ] Tester le flux complet sur le VPS ## Affichage des signatures dans l'émargement numérique - [ ] Modifier l'API pour récupérer les présences avec signatures - [ ] Afficher nom du signataire, date/heure et icône à côté de chaque puce matin/après-midi - [ ] Ajouter une modale pour visualiser la signature en grand format - [ ] Tester l'affichage sur smartphone - [ ] Déployer sur le VPS ## BUG: Signatures non enregistrées lors de la validation - [x] Vérifier les logs serveur lors de la validation avec signature - [x] Vérifier le code d'upload de signature dans routers.ts - [x] Vérifier que signatureUrl et signatureS3Key sont bien enregistrés en base - [x] Corriger le problème (ajouter les champs dans getPresencesBySequence) - [x] Déployer sur VPS - [ ] Tester l'affichage des icônes ## BUG CRITIQUE: Informations de validation disparues à nouveau - [x] Vérifier les logs navigateur pour erreurs JavaScript - [x] Vérifier si l'API retourne bien les données - [x] Comparer le code actuel avec la version qui fonctionnait - [x] Corriger de manière définitive et robuste - [x] Tester localement avant déploiement (fonctionne en local) - [x] Déployer sur VPS (rebuild complet effectué) - [ ] Tester sur VPS après rebuild ## Intégration des signatures dans les feuilles de présence PDF - [x] Analyser le code actuel de génération des feuilles de présence PDF - [x] Modifier exportService.ts pour charger les images de signatures - [x] Intégrer les signatures dans le layout du PDF (colonnes Matin/Après-midi) - [x] Gérer les cas où la signature n'existe pas (affichage vide) - [x] Modifier routers.ts pour récupérer les présences avec signatures - [x] Tester la génération avec et sans signatures (code implémenté, test utilisateur requis) - [x] Vérifier la qualité et la taille des signatures dans le PDF (test utilisateur requis) - [x] Créer un checkpoint ## Déploiement VPS - Intégration signatures PDF - [x] Se connecter au VPS en SSH - [x] Copier server/exportService.ts vers le VPS - [x] Copier server/routers.ts vers le VPS - [x] Redémarrer l'application avec PM2 - [x] Vérifier que l'application fonctionne correctement - [ ] Tester l'export PDF avec signatures sur production (test utilisateur requis) ## Bug - Signatures manquantes dans PDF - [x] Analyser pourquoi les signatures n'apparaissent pas dans le PDF généré - [x] Vérifier la logique de correspondance entre présences et dates - [x] Problème identifié : utilisation de dateInfo.ordre au lieu de dateInfo.id - [x] Corriger le code (exportService.ts et routers.ts) - [x] Ajouter l'ID de la date dans l'interface FeuillePresenceInfo - [x] Corriger la logique de recherche des présences - [x] Déployer sur VPS - [ ] Tester la génération PDF avec signatures (test utilisateur requis) ## Bug VPS - Signatures toujours manquantes dans PDF - [ ] Vérifier l'existence des fichiers de signatures sur le VPS - [ ] Vérifier les chemins d'accès aux fichiers - [ ] Ajouter des logs de debug dans exportService.ts - [ ] Identifier le problème exact (fichiers manquants, chemin incorrect, erreur de lecture) - [ ] Corriger le problème - [ ] Redéployer et tester ## Ajout signatures après-midi dans PDF - [x] Modifier exportService.ts pour chercher les présences après-midi - [x] Afficher les signatures après-midi dans la colonne correspondante - [x] Corriger le bug apres-midi vs apres_midi (underscore vs tiret) - [x] Déployer sur VPS - [x] Tester avec une séquence ayant des signatures matin et après-midi - [x] Retirer les logs de debug - [x] Déployer la version finale sur VPS - [x] Créer un checkpoint final ## Évolution rappels - 2 pièces jointes - [x] Analyser le schéma actuel de la table rappels - [x] Planifier la migration pour passer de 1 à 2 pièces jointes - [x] Modifier le schéma Drizzle (drizzle/schema.ts) - [x] Créer et appliquer la migration SQL en local - [x] Adapter le backend (emailService.ts, rappelScheduler.ts, routers.ts, db.ts) - [x] Adapter le frontend (AdminRappels.tsx) - [x] Tester localement avec rappels existants - [x] Déployer sur VPS avec migration - [x] Vérifier que les rappels existants sont préservés (migration additive) - [x] Créer un checkpoint ## Bug - Labels pièces jointes dupliqués - [x] Identifier pourquoi les labels apparaissent en double (FileUpload affiche déjà un label) - [x] Ajouter un prop label au composant FileUpload - [x] Corriger l'affichage dans AdminRappels.tsx - [x] Déployer sur VPS - [x] Créer un checkpoint ## Bug - Deuxième pièce jointe non envoyée - [x] Vérifier le code d'envoi des emails de rappel - [x] Identifier pourquoi seule la première pièce jointe est envoyée (paramètres manquants dans routers.ts) - [x] Corriger le code pour envoyer les 2 pièces jointes - [x] Déployer sur VPS - [x] Tester l'envoi avec 2 pièces jointes (test utilisateur validé) - [x] Créer un checkpoint ## Nouveau rôle - Super formateur - [ ] Modifier le schéma de base de données pour ajouter le rôle "super_formateur" - [ ] Créer et appliquer la migration SQL - [ ] Adapter les requêtes backend pour donner accès à toutes les formations au super formateur - [ ] Modifier le frontend pour afficher toutes les formations au super formateur - [ ] Ajouter une interface admin pour promouvoir un formateur en super formateur - [ ] Tester localement - [ ] Déployer sur VPS - [ ] Créer un checkpoint ## Nouveau rôle - Super formateur - [x] Modifier le schéma de base de données pour ajouter le rôle super_formateur - [x] Créer et appliquer la migration SQL en local - [x] Adapter le backend (routers.ts) pour gérer les permissions - [x] Adapter le frontend (DashboardLayout, Home, AdminUsers) - [x] Tester localement - [x] Déployer sur VPS avec migration - [x] Créer un checkpoint ## Correction - Super formateur ne doit pas avoir accès à Configuration - [x] Modifier DashboardLayout pour masquer Configuration aux super formateurs - [x] Déployer sur VPS - [x] Créer un checkpoint ## Template email attestations - [x] Analyser le système actuel d'envoi des attestations - [x] Ajouter le template "attestation" dans la table emailTemplates - [x] Créer le template par défaut avec variables dynamiques - [x] Intégrer le template dans le code d'envoi des attestations - [x] Déployer sur VPS (migration SQL + fichiers) - [x] Créer un checkpoint - [x] Moderniser l'interface de chargement des attestations (design coloré et ergonomique) - [x] Corriger le bug où le statut reste "envoyé" après la suppression d'une attestation - [x] Corriger l'erreur de validation lors de la modification du template attestation - [x] Corriger le remplacement des variables dans le template email d'attestation - [x] Corriger le bug de la modal de chargement d'attestation qui reste bloquée sur l'état précédent - [x] Améliorer le feedback visuel pendant le chargement du fichier d'attestation (indicateur immédiat) - [x] Corriger la latence d'affichage du message d'upload (forcer le rendu avant traitement) - [x] Restructurer le flux d'upload avec useEffect pour affichage immédiat - [x] Corriger la latence avec requestAnimationFrame pour affichage avant fetch bloquant - [x] Afficher immédiatement le nom du fichier sélectionné dans la boîte de dialogue - [x] Appliquer la même ergonomie de boîte de dialogue pour les pièces jointes des rappels - [ ] Réorganiser la boîte de dialogue des rappels pour réduire la hauteur et élargir la largeur - [x] Déployer la réorganisation complète de la modal des rappels sur le VPS - [x] Modifier la feuille de présence pour ajouter deux colonnes de signature pour le formateur (Matin et Après-midi) - [x] Retirer la ligne de date en dessous des signatures du formateur dans la feuille de présence - [x] Créer l'interface de gestion des attestations pour formateurs et super-formateurs (charger, supprimer, modifier, envoyer) - [x] Ajouter un rafraîchissement automatique toutes les 30 secondes sur la page d'émargement numérique - [x] Ajouter un indicateur visuel de rafraîchissement avec badge "Mis à jour il y a X secondes" - [x] Ajouter des statistiques en temps réel du taux de présence par période - [x] Retirer les compteurs dynamiques de taux de présence de la page d'émargement numérique - [x] Empêcher l'émargement avant la date de formation concernée (vérification backend) - [ ] Permettre aux formateurs d'émarger par QR code (matin et après-midi) avec signature tactile (en cours - à finaliser lors d'une prochaine session) ## QR Code Formateur (Réimplémentation méthodique) ### Phase 1 : Analyse - [x] Analyser le code existant pour le QR code apprenant - [x] Identifier les modifications nécessaires pour le formateur - [x] Planifier l'architecture de la solution ### Phase 2 : Implémentation - [ ] Ajouter le bouton "QR Code Formateur" dans FormateurEmargement.tsx - [ ] Créer/modifier la procédure backend generateQRCodeFormateur - [ ] Implémenter la logique de validation de présence formateur - [ ] Gérer la détection automatique de la date du jour ### Phase 3 : Tests locaux - [ ] Tester la génération du QR code formateur - [ ] Tester le scan et la validation de signature - [ ] Vérifier l'enregistrement en base de données - [ ] Tester les cas d'erreur (date invalide, doublon, etc.) ### Phase 4 : Déploiement - [ ] Créer un checkpoint de la version testée - [ ] Déployer sur le VPS - [ ] Tester en production - [ ] Valider avec l'utilisateur ## Affichage des signatures formateurs sur la page d'émargement numérique - [x] Créer une procédure backend pour récupérer les signatures formateurs d'une séquence - [x] Ajouter un encart dédié sur la page d'émargement numérique pour afficher les signatures formateurs - [x] Afficher les signatures formateurs avec date/heure et période (matin/après-midi) - [x] Déployer sur recette et production ## Amélioration ergonomie signatures formateurs - [x] Modifier l'affichage pour regrouper les signatures par date (au lieu d'une signature par ligne) - [x] Afficher une zone par date avec les signatures matin et après-midi à l'intérieur - [x] Ergonomie identique à celle des apprenants ## Modifier le format d'affichage des signatures formateurs - [x] Analyser le format d'affichage des apprenants (zone par date avec lignes matin/après-midi) - [x] Reproduire exactement le même format pour les formateurs - [x] Afficher le nom du formateur, la date/heure de signature et une case verte par ligne - [x] Supprimer l'affichage actuel avec les grandes images de signature ## Intégrer les signatures formateurs dans la feuille de présence PDF - [x] Analyser le code de génération de la feuille de présence PDF actuelle - [x] Modifier le backend pour récupérer les signatures formateurs en plus des signatures apprenants - [x] Ajouter une section "Signature Formateur" dans le PDF avec les signatures matin et après-midi - [x] Tester la génération PDF avec les signatures formateurs - [x] Déployer sur recette et production ## Afficher les images de signature directement dans la page d'émargement - [x] Analyser le code actuel de la page FormateurEmargement.tsx pour identifier où ajouter les images - [x] Modifier l'affichage des lignes de présence apprenants pour inclure les images de signature matin et après-midi - [x] Modifier l'affichage des lignes de présence formateurs pour inclure les images de signature matin et après-midi - [x] Ajuster le layout pour que les images s'affichent correctement à côté des informations existantes - [x] Déployer sur le serveur de test (recette) uniquement ## Ajouter un cadre bleu autour des images de signature - [x] Modifier les classes CSS des images de signature pour ajouter une bordure bleue - [x] Appliquer le cadre bleu aux signatures apprenants - [x] Appliquer le cadre bleu aux signatures formateurs - [x] Déployer sur production (recette indisponible temporairement) ## Corriger l'erreur "inscription requise pour un apprenant" lors de la signature formateur - [ ] Analyser le code de validation dans presenceDb.ts (fonction validerPresenceFormateur) - [ ] Identifier pourquoi la vérification d'inscription apprenant est appliquée aux formateurs - [ ] Corriger la logique pour permettre la signature formateur sans inscription apprenant - [ ] Déployer sur recette et production - [ ] Tester avec l'email marianne.tarrieu@gmail.com sur la séquence 1 du 03/02/26 ## Correction bug émargement formateur - Erreur "inscription requise pour un apprenant" - [x] Analyser le code de validation dans EmargementFormateurScan.tsx - [x] Identifier que le paramètre typeUtilisateur n'était pas passé dans l'appel à validerPresence - [x] Ajouter le paramètre typeUtilisateur: "formateur" dans l'appel à la mutation - [x] Déployer sur recette et production - [ ] Tester avec l'email marianne.tarrieu@gmail.com sur la séquence 1 du 03/02/26 ## Correction bug "Aucune date de formation ne correspond à aujourd'hui" - Émargement formateur - [x] Analyser le code de validation de la date dans routers.ts (procédure presences.valider) - [x] Identifier pourquoi la logique cherche automatiquement la date du jour au lieu d'utiliser dateFormationId - [x] Corriger la logique pour utiliser la date sélectionnée par le formateur - [x] Déployer sur le serveur de recette et production - [ ] Tester avec une date passée ou future ## Correction définitive stockage local signatures formateur - [x] Remplacer storagePut() par fs.writeFileSync() dans le code de validation formateur - [x] Déployer sur production - [ ] Tester la validation formateur (doit fonctionner sans fetch failed) - [ ] Vérifier que la signature est bien enregistrée localement ## CRITIQUE - Perte de signatures lors de l'ajout d'une date dans une séquence - [x] Analyser le code qui gère l'ajout de dates dans une séquence (procédure sequences.update) - [x] Identifier pourquoi les signatures des dates précédentes sont supprimées (suppression en cascade via deleteDatesBySequence) - [x] Vérifier si c'est un problème de suppression en cascade ou de réinitialisation (confirmé : suppression en cascade) - [x] Corriger le bug pour préserver toutes les signatures existantes (logique de mise à jour intelligente) - [x] Déployer sur le VPS de TEST (108.143.67.56) - [ ] Tester en ajoutant une nouvelle date et vérifier que les signatures précédentes sont toujours présentes ## URGENT - Les signatures sont toujours perdues sur TEST malgré la correction - [x] Vérifier les logs du serveur TEST lors d'une modification de séquence (toutes les dates traitées comme nouvelles) - [x] Vérifier si le frontend envoie bien les IDs des dates existantes dans la requête (NON, les IDs n'étaient pas envoyés) - [x] Analyser le code frontend qui gère la modification de séquence (AdminSequences.tsx ligne 203-207) - [x] Identifier pourquoi la logique de mise à jour intelligente ne fonctionne pas (frontend n'incluait pas les IDs) - [x] Corriger définitivement le problème (ajout de id: d.id dans le mapping des dates) - [x] Déployer et tester sur TEST - [ ] Valider que les signatures sont bien préservées lors de l'ajout d'une date ## CORRECTION DÉFINITIVE - Schéma Zod manquant le champ id - [x] Identifier que le schéma Zod de sequences.update ne contenait pas le champ id (ligne 509-513) - [x] Ajouter id: z.number().optional() dans le schéma Zod - [x] Déployer sur le serveur TEST (108.143.67.56) - [x] Tester en ajoutant une nouvelle date et vérifier que les signatures sont préservées - [x] Déployer sur PROD (98.71.216.234) - Version V1.17 ## BUG - Erreur "(void 0) is not a function" et doublons de dates - [x] Analyser l'erreur (problème de closure React) - [x] Nettoyer les doublons dans la table datesFormation (séquence 20) - [x] Implémenter correction robuste avec useCallback pour stabiliser la référence - [x] Déployer sur TEST et PROD - [ ] Tester la suppression de date sur PROD ## Affichage URL complète du QR code apprenant - [x] Analyser le code existant du QR code apprenant - [x] Ajouter l'URL dans le retour de la procédure generateQRCode - [x] Afficher l'URL sous le QR code (texte cliquable) - [x] Déployer sur TEST pour validation - [x] Déployer sur PROD ## Envoi d'attestations par groupe - [x] Analyser la page des attestations pour identifier l'emplacement du bouton - [x] Modifier le bouton existant pour permettre l'envoi/renvoi de toutes les attestations du groupe - [x] Adapter la logique pour gérer les attestations déjà envoyées (renvoi) - [x] Déployer sur TEST (recette) - [x] Déployer sur sandbox (dev local) - déjà actif ## Implémenter notificationsActives pour les notifications formateur - [x] Identifier tous les endroits où les notifications formateur sont envoyées (inscription, annulation) - [x] Ajouter la vérification du paramètre notificationsActives avant chaque envoi (3 endroits) - [x] Mettre à jour la description du paramètre dans l'interface admin pour clarifier son rôle - [x] Déployer sur TEST pour validation - [x] Déployer sur PROD ## BUG - Invitations Outlook (ICS) ne s'ouvrent pas - [x] Analyser le fichier ICS fourni (encodage incorrect) - [x] Corriger l'encodage UTF-8 et les en-têtes dans emailService.ts - [x] Tester avec Outlook pour valider l'importation - [x] Déployer sur TEST - [x] Déployer sur PROD ## BUG - Seulement 2 invitations sur 3 envoyées lors de l'inscription - [x] Diagnostiquer pourquoi seulement 2 invitations ICS sont envoyées alors qu'il y a 3 dates - [x] Corriger le code d'envoi des invitations (conversion Buffer vers base64 UTF-8) - [x] Tester sur TEST - [x] Déployer sur PROD