**Modification apportée :**
- Alternance de fond entre lignes paires (blanc) et impaires (gris très clair bg-gray-50/50)
- Améliore la lisibilité et facilite le suivi visuel des lignes
- Effet subtil et élégant grâce à l'opacité réduite
**Résultat :**
Tableau plus lisible et professionnel, conforme aux standards modernes d'interface utilisateur.
**Modifications apportées :**
1. Badge "Non" en rouge (bg-red-50, text-red-700, border-red-200) pour un meilleur contraste visuel avec le vert
2. Tooltip informatif au survol du badge "Oui" affichant le nom du fichier et sa taille en Ko
3. Badge "Oui" cliquable pour télécharger directement la pièce jointe sans ouvrir la fenêtre de modification
4. Effet hover vert clair (hover:bg-green-100) pour indiquer l'interactivité
**Résultat :**
Interface plus intuitive et fonctionnelle avec code couleur cohérent (vert = présent/actif, rouge = absent/inactif) et actions directes pour améliorer l'expérience utilisateur.
**Modification apportée :**
- Remplacement de l'affichage texte simple par des badges avec icônes SVG
- Badge vert avec icône check-circle (✓) pour "Oui" (pièce jointe présente)
- Badge gris avec icône x-circle (✗) pour "Non" (pas de pièce jointe)
- Alignement cohérent avec flex et gap pour une meilleure lisibilité
**Résultat :**
Interface plus moderne et visuelle, conforme aux préférences d'UI avec utilisation accrue de la couleur et des icônes de taille appropriée.
1. Ajout de l'enregistrement dans l'historique lors de l'envoi d'attestations (backend + frontend)
2. Correction du bouton Renvoyer inactif (selectedSequenceId -> apprenant.sequence.id)
3. Gestion des erreurs avec enregistrement dans l'historique en cas d'échec
4. Support des chemins locaux et URLs pour les fichiers PDF
- Modification de l'interface AdminGestionAttestations.tsx
- Le bouton d'envoi reste maintenant toujours visible (suppression de la condition !isSent)
- Le libellé du bouton change dynamiquement : "Envoyer" si jamais envoyée, "Renvoyer" si déjà envoyée
- Permet de renvoyer une attestation après remplacement ou suppression
- Le backend marque simplement l'attestation comme envoyée à chaque appel
- Déployé sur le VPS de production (https://formations.itinova.org)
- Les utilisateurs peuvent maintenant renvoyer une attestation à tout moment
- Modification de la fonction handleSendAttestation pour vérifier à la fois documentUrl et urlPdf
- Les attestations uploadées manuellement sont stockées dans documentUrl
- Les attestations générées automatiquement sont stockées dans urlPdf
- La fonction vérifie maintenant les deux champs (documentUrl en priorité, puis urlPdf en fallback)
- Déployé sur le VPS de production (https://formations.itinova.org)
- L'envoi manuel d'attestations uploadées fonctionne maintenant correctement
- Remplacement de refetchInscrits() par refetchApprenants() dans AdminGestionAttestations.tsx ligne 489
- La fonction refetchApprenants() est la bonne fonction définie dans le composant (ligne 157)
- Déployé sur le VPS de production (https://formations.itinova.org)
- L'upload d'attestation manuelle fonctionne maintenant correctement sans erreur JavaScript
- Upload de fichiers avec fallback automatique vers stockage local
- Configuration Nginx pour uploads jusqu'à 10 Mo
- Colonne "Pièce jointe" dans le tableau de gestion des rappels
- Support des fichiers locaux et S3 dans l'envoi d'emails
- Correction de l'encoding base64 pour SMTP/Nodemailer
- Table logsrappels créée dans la base de données MySQL du VPS
**Fonctionnalités ajoutées :**
1. **Procédure tRPC `viderHistoriqueRappels`** (server/routers.ts) :
- Mutation admin protégée pour supprimer tous les logs de la table logsRappels
- Retourne le nombre de logs supprimés
- Utilise une requête SQL directe pour optimiser les performances
2. **Bouton de vidage dans l'interface** (client/src/pages/admin/AdminRappelsHistorique.tsx) :
- Bouton rouge "Vider l'historique" avec icône de corbeille
- Dialogue de confirmation AlertDialog avec message d'avertissement
- Invalidation automatique de la requête historique après suppression
- Toast de succès avec le nombre de logs supprimés
3. **Correction d'une erreur TypeScript** :
- Ajout d'une parenthèse fermante manquante dans le router gestionAttestations
- Correction de l'erreur TS1135: Argument expression expected
**Fichiers modifiés :**
- server/routers.ts : Ajout de la procédure viderHistoriqueRappels
- client/src/pages/admin/AdminRappelsHistorique.tsx : Ajout du bouton avec dialogue
Déployé sur le VPS de production (https://formations.itinova.org)
**Améliorations apportées :**
1. **Colonne "Type d'envoi" avec badge coloré** :
- Ajout d'une nouvelle colonne dans l'interface d'historique des rappels
- Badge bleu pour les tests ("Test")
- Badge vert pour les envois automatiques ("Automatique")
- Permet de distinguer visuellement les envois de test des envois réels
2. **Correction des filtres** :
- Correction de l'enum du statut : "succes"/"echec" au lieu de "success"/"failed"
- Correction des noms de colonnes : "email" au lieu de "emailDestinataire", "type" au lieu de "typeRappel"
3. **Nettoyage des anciens logs** :
- Ajout d'une procédure tRPC `nettoyerLogsErrones` pour supprimer les logs sans email
- Exécution de la requête SQL sur le VPS pour nettoyer les données erronées
- Tous les logs créés avant la correction du schéma ont été supprimés
**Fichiers modifiés :**
- client/src/pages/admin/AdminRappelsHistorique.tsx : Ajout de la colonne Type d'envoi avec badges colorés
- server/routers.ts : Ajout de la procédure nettoyerLogsErrones + correction des enums
**Résultat :**
- L'historique des rappels affiche maintenant clairement si un envoi est un test ou automatique
- Les anciens logs erronés ont été supprimés de la base de données
- Les statistiques sont maintenant plus fiables et précises
Déployé sur le VPS de production (https://formations.itinova.org)
- Suppression de 4 boutons : "Aperçu rappel J-7", "Envoyer rappel J-7", "Aperçu rappel J-1", "Envoyer rappel J-1"
- Ces boutons sont maintenant remplacés par le bouton "Tester le rappel" qui envoie automatiquement le bon template configuré
- Fichier modifié : client/src/pages/AdminSequenceInscrits.tsx
- Déployé sur le VPS de production (https://formations.itinova.org)
- Mise à jour du fichier todo.md
- Page AdminSequences : ouvre en vue réduite par défaut
- DashboardLayout : seule la section "Gestion" est ouverte par défaut à la connexion
- Déployé sur le VPS de production
- Ajout de la page /forgot-password pour demander un lien de réinitialisation
- Ajout de la page /reset-password pour définir un nouveau mot de passe
- Ajout du lien "Mot de passe oublié ?" sur la page de connexion
- Installation du module bcrypt dans le sandbox
- Les procédures backend (requestPasswordReset, resetPassword) sont déjà implémentées
- Note: bcrypt temporairement désactivé sur le VPS en attendant la résolution du problème de store pnpm
- Modification de la procédure testerRappel pour détecter automatiquement le premier rappel actif configuré pour la séquence
- Suppression du paramètre typeRappel (n'est plus nécessaire)
- Création de la fonction sendRappelEmail générique qui utilise le templateType du rappel configuré
- Le bouton frontend envoie maintenant le bon template (rappel 1, 3, 4, 5, 6, etc.) selon la configuration de la séquence
- Gestion des pièces jointes configurées dans le rappel
- Mise à jour du fichier todo.md pour marquer la tâche comme terminée
- Ajout du paramètre typeRappel: 'rappel' dans l'appel à testerRappelMutation
- Le backend attendait ce paramètre avec les valeurs 'rappel' ou 'rappelJ1'
- Le bouton envoie maintenant un rappel J-7 par défaut lors du test
- Mise à jour du fichier todo.md pour marquer la tâche comme terminée
- Ajout de la mutation testerRappelMutation connectée à la procédure tRPC rappels.testerRappel
- Ajout de l'icône Send dans les imports
- Ajout du bouton dans la colonne Actions du tableau des séquences (entre Edit et Delete)
- Le bouton envoie un email de test à l'administrateur avec les données de la séquence sélectionnée
- Validation : le bouton est désactivé si la séquence n'a pas de dates configurées
- Feedback utilisateur : toast de succès ou d'erreur après l'envoi
- Mise à jour du fichier todo.md pour marquer la tâche comme terminée
**Ajouts :**
- Template "Réinitialisation de mot de passe" (reset_password) ajouté à l'enum et au système
**Corrections de bugs :**
- Bug de mise à jour du type de template (ajout de key={selectedType} pour forcer remontage)
- Erreur SQL configuration SMTP (correction schéma emailConfig avec champs active, domainVerified, apiKey)
- Erreur de type formateurId (conversion string → number dans AdminSequences.tsx)
- Date de blocage non sauvegardée (ajout champ dateBlocage au schéma sequences)
- Table logsRappels incohérente (suppression colonnes obsolètes, correction enum statut)
**Schémas Drizzle mis à jour :**
- emailTemplates : ajout reset_password à l'enum type
- emailConfig : ajout active, domainVerified, correction apiKey
- sequences : ajout dateBlocage (datetime)
- logsRappels : structure nettoyée et conforme
**Déploiement VPS :**
- Toutes les migrations SQL exécutées avec succès
- Application redémarrée et fonctionnelle
- Historique des rappels prêt à fonctionner (table logsRappels corrigée)
- Ajout de "reset_password" à l'enum du schéma Drizzle (table emailTemplates)
- Migration SQL pour modifier l'enum dans la base de données
- Création du template dans la base de données avec un contenu par défaut approprié
- Mise à jour de la procédure tRPC emailTemplates.upsert pour utiliser les noms de colonnes français (titre, couleurPrincipale, couleurSecondaire, piedDePage)
- Mise à jour de la fonction upsertEmailTemplate dans server/db.ts pour utiliser les noms de colonnes français
- Réécriture complète de AdminEmailTemplates.tsx pour utiliser les noms de colonnes français
- Test complet de l'interface : le template s'affiche correctement, peut être modifié et prévisualisé
- Le template contient les variables {{prenom}}, {{nom}}, {{lienReinitialisation}} pour la réinitialisation de mot de passe
- Total de 9 templates d'emails maintenant disponibles (inscription, teaser, rappel, rappelJ1, rappel3-6, reset_password)
- Renommage questionnaire.nom → questionnaire.titre dans QuestionnaireReponse.tsx, AdminQuestionnaireEdit.tsx, questionnaireScheduler.ts, questionnaireExport.ts
- Correction des requêtes SQL dans questionnaireDb.ts (suppression de la condition complete inexistante)
- Ajout des colonnes valeurMin et valeurMax dans la table questions
- Renommage de la colonne nom en titre dans la table questionnaires
- Changement du champ 'nom' en 'titre' pour les questionnaires (backend et frontend)
- Suppression de la propriété 'complete' inexistante dans reponsesQuestionnaires
- Correction du type 'provider' dans la configuration email
- Gestion des valeurs null pour le champ 'fonction' des apprenants
- Résolution de l'erreur logsRappels.email après redémarrage du serveur
Nouvelle fonctionnalité complète pour gérer les attestations :
- Schéma de base de données : colonnes modeAttestation et modeEnvoi dans formations, colonnes documentUrl, documentS3Key, uploadedBy, uploadedAt dans attestations
- Backend : fichier gestionAttestationsDb.ts, procédures tRPC, fonction sendAttestationEmail
- Interface : page AdminGestionAttestations avec sélection de formation, configuration des modes, tableau des apprenants, boutons upload/prévisualisation/envoi/suppression
- Navigation : lien dans menu Gestion, route /admin/gestion-attestations
- Ajout du paramètre d'envoi automatique des attestations dans la page Paramètres
- Ajout de la prévisualisation du modèle d'attestation avec génération PDF
- Création de la page Historique des attestations dans la section Traçabilité
- Création de la table historiqueAttestations pour tracer les envois
- Ajout des procédures tRPC pour l'historique et la prévisualisation
- Ajout du composant DashboardLayout à la page FormateurDashboard
- Le menu de navigation latéral s'affiche maintenant correctement pour les utilisateurs avec le rôle formateur
- Navigation cohérente entre toutes les pages de l'espace formateur (Dashboard et Émargement)
- Ajout de 3 nouveaux paramètres globaux : délai d'expiration QR codes (minutes), durée de validité tokens (heures), notifications actives (boolean)
- Création de la table historiqueParametres pour tracer toutes les modifications avec userId, userName, champModifié, ancienneValeur, nouvelleValeur et dateModification
- Ajout d'un bouton "Tester l'URL" avec indicateur visuel de statut (vert si accessible, rouge si erreur)
- Affichage de l'historique des modifications dans un tableau avec toutes les informations de traçabilité
- Mise à jour automatique de l'historique lors de chaque modification de paramètre
Modifications :
- Ajout de DashboardLayout dans client/src/pages/AdminParametres.tsx
- Ajout de DashboardLayout dans client/src/pages/FormateurEmargement.tsx
Le menu de navigation s'affiche maintenant correctement dans toutes les pages de l'application.
Modifications apportées :
- Création de la table parametres dans la base de données
- Création du fichier server/parametresDb.ts avec les fonctions getParametres et updateUrlPublique
- Ajout du router parametres dans server/routers.ts avec les procédures get et updateUrlPublique
- Création de la page client/src/pages/AdminParametres.tsx avec formulaire de modification
- Ajout de la route /admin/parametres dans App.tsx
- Ajout du lien "Paramètres" dans le menu après "Configuration SMTP" dans DashboardLayout
- Modification de server/qrCodeGenerator.ts pour utiliser l'URL de la BDD au lieu de getAppBaseUrl
- URL par défaut définie : https://formations.itinova.org
Fonctionnalités :
- Interface graphique pour modifier l'URL publique de l'application
- Les QR codes d'émargement utilisent maintenant l'URL configurée dans la base de données
- Validation de l'URL avant enregistrement
- Message d'information sur l'impact des modifications
Corrections apportées :
- Correction des références à heureDebut/heureFin dans AdminRappels.tsx (utilisation de dateDebut/dateFin)
- Correction de l'accès à la propriété dates dans EmargementScan.tsx (cast de type)
- Ajout de l'import manquant de QrCode dans DashboardLayout.tsx
- Correction des erreurs TypeScript dans DashboardLayout.tsx (gestion de subItems)
- Ajout de downlevelIteration dans tsconfig.json
- Correction de l'utilisation de Set dans DateFormationMultiSelect.tsx (Array.from)
- Correction de l'appel à createAttestation (utilisation de enregistrerAttestation)
L'application fonctionne maintenant correctement sans erreurs TypeScript.
## Base de données
- ✅ Table `presences` créée (inscriptionId, dateFormationId, heurePresence, modeValidation, validateurId)
- ✅ Colonne `qrCodeToken` ajoutée à la table `sequences`
## Backend
- ✅ Génération de QR code unique par séquence (qrCodeGenerator.ts)
- ✅ Procédures tRPC pour l'émargement (presences.generateQRCode, presences.valider, presences.listBySequence)
- ✅ Fonctions de base de données (presenceDb.ts) pour gérer les présences
- ✅ Génération automatique d'attestation après validation de toutes les présences
- ✅ Intégration avec le service d'attestations existant
## Interface formateur (/formateur/emargement)
- ✅ Sélection de la séquence
- ✅ Génération et affichage du QR code en modal
- ✅ Liste des inscrits avec statut de présence par date
- ✅ Validation manuelle de présence possible
- ✅ Actualisation en temps réel des présences
- ✅ Entrée de menu "Émargement" dans DashboardLayout
## Interface publique (/emargement/:token)
- ✅ Page de scan QR code accessible sans authentification
- ✅ Recherche de l'apprenant par email
- ✅ Sélection de la formation et de la date
- ✅ Validation automatique de la présence via QR code
- ✅ Écrans de confirmation (succès/erreur)
- ✅ Gestion des erreurs (QR invalide, déjà émargé, etc.)
## Génération automatique d'attestations
- ✅ Vérification automatique après chaque validation de présence
- ✅ Génération du PDF d'attestation si toutes les présences sont validées
- ✅ Enregistrement en base de données
- ✅ Upload automatique sur S3
## Dépendances installées
- qrcode (génération de QR codes)
- @types/qrcode (types TypeScript)
Le système est entièrement fonctionnel et prêt à être utilisé par les formateurs et apprenants.
- Ajout du champ formateur (number | null) dans le type FormData de AdminSequences.tsx
- Ajout du type "tous" dans publicCible pour supporter toutes les valeurs possibles
- Correction de FormateurCombobox pour accepter number | null au lieu de string
- Correction des erreurs null dans QuestionnaireReponse.tsx avec optional chaining
- Correction du type previewType dans AdminSequenceInscrits.tsx pour inclure "rappel_j1"
- Build de production testé et fonctionnel (✓ built in 14.69s)
Les quelques avertissements TypeScript restants (11) ne bloquent pas le build de production. L'application peut maintenant être publiée.
Fonctionnalités ajoutées :
- Table de liaison rappelSequences pour associer rappels et séquences
- Composant SequenceMultiSelect avec recherche et multi-sélection
- Gestion des associations dans les procédures create/update
- Modification du scheduler pour filtrer les séquences selon les associations
- Si aucune séquence n'est sélectionnée, le rappel s'applique à toutes les séquences (comportement par défaut)
Le système permet maintenant de configurer des rappels spécifiques pour certaines dates/séquences particulières, offrant une flexibilité complète dans la gestion des rappels automatiques.
Problème résolu :
- Les rappels post-formation affichaient "J-X" au lieu de "J+X" dans la colonne Délai
Modification apportée :
- Mise à jour de l'affichage dans AdminRappels.tsx pour vérifier le champ "timing"
- Si timing = "post_formation" : affiche "J+X"
- Si timing = "pre_formation" : affiche "J-X"
Résultat : L'affichage est maintenant cohérent avec le type de rappel configuré
Modifications apportées :
- Ajout des colonnes nomFichier, urlFichier, s3Key, typeFichier, tailleFichier dans la table rappels
- Création du composant FileUpload pour l'upload de fichiers vers S3 (max 10 Mo)
- Création de l'endpoint API /api/upload-file pour gérer l'upload
- Intégration du composant FileUpload dans les formulaires de création et modification de rappels
- Mise à jour des procédures tRPC create et update pour gérer les informations de fichier
- Modification des fonctions sendRappelJ7Email et sendRappelJ1Email pour inclure les pièces jointes
- Mise à jour du scheduler de rappels pour passer les informations de fichier lors de l'envoi
- Les fichiers sont téléchargés depuis S3 et convertis en base64 pour être attachés aux emails