**Nouvelles fonctionnalités** :
1. **Page d'historique des rappels** (`/admin/rappels/historique`)
- Tableau complet de tous les rappels envoyés
- Filtres avancés : date début/fin, séquence, statut (succès/échec), email
- Recherche par email avec mise en surbrillance
- Pagination (50 résultats par page)
- Affichage du nombre de tentatives pour chaque rappel
- Code couleur : vert pour succès, rouge pour échec
2. **Tableau de bord statistiques** (`/admin/rappels/statistiques`)
- 4 cartes de statistiques globales : total envoyés, succès, échecs, taux de succès
- Graphique d'évolution : nombre de rappels envoyés par jour (succès vs échecs)
- Graphique du taux de succès par jour (barres)
- Top 10 des emails problématiques avec nombre d'échecs
- Visualisation interactive avec Recharts
3. **Système de réessai automatique**
- Détection automatique des rappels échoués
- Délai exponentiel : 1h après 1er échec, 4h après 2ème, 24h après 3ème
- Limite de 3 tentatives maximum
- Notification automatique à l'admin en cas d'abandon (3 échecs)
- Mise à jour automatique du statut dans les logs
- Vérification toutes les heures
**Nouveaux champs dans logsRappels** :
- `nbTentatives` : nombre de tentatives d'envoi (1 à 3)
- `prochainEssai` : date du prochain essai en cas d'échec
**Nouveaux fichiers** :
- `client/src/pages/admin/AdminRappelsHistorique.tsx` : Page d'historique
- `client/src/pages/admin/AdminRappelsStats.tsx` : Page de statistiques
- `server/rappelRetry.ts` : Système de réessai automatique
- `server/rappelDb.ts` : Fonctions étendues (filtres, stats, évolution)
**Fichiers modifiés** :
- `drizzle/schema.ts` : Ajout de nbTentatives et prochainEssai
- `server/routers.ts` : Nouvelles procédures tRPC (historique, statistiques, évolution)
- `client/src/App.tsx` : Routes pour historique et statistiques
- `client/src/components/DashboardLayout.tsx` : Sous-menu Rappels
- `server/_core/index.ts` : Initialisation du scheduler de retry
**Bénéfices** :
- ✅ Traçabilité complète de tous les rappels
- ✅ Analyse des performances avec graphiques
- ✅ Identification rapide des emails problématiques
- ✅ Réessai automatique des échecs sans intervention manuelle
- ✅ Notification en cas d'échec persistant
- ✅ Optimisation de la délivrabilité des emails
**Nouvelles fonctionnalités** :
1. **Historique des rappels envoyés**
- Nouvelle table `logsRappels` pour tracer tous les emails de rappels
- Enregistrement automatique de chaque envoi (succès ou échec)
- Prévention des doublons : vérification avant envoi
- Informations stockées : rappelId, sequenceId, apprenantId, email, type, statut, message d'erreur
2. **Notifications automatiques à l'administrateur**
- Alerte par email en cas d'échec d'envoi de rappels
- Détail des échecs : liste des emails et messages d'erreur
- Résumé : nombre d'envois réussis vs échecs
3. **Procédure de test manuel** (backend uniquement)
- Nouvelle procédure tRPC `rappels.testerRappel`
- Permet de tester l'envoi d'un rappel J-7 ou J-1 pour une séquence
- Envoie au premier apprenant inscrit uniquement
**Fichiers créés** :
- `server/rappelDb.ts` : Fonctions de gestion des logs de rappels
- `drizzle/schema.ts` : Ajout de la table `logsRappels`
**Fichiers modifiés** :
- `server/rappelScheduler.ts` : Intégration du logging et des notifications
- `server/routers.ts` : Ajout de la procédure `testerRappel`
**Bénéfices** :
- ✅ Aucun doublon même en cas de redémarrage du serveur
- ✅ Traçabilité complète de tous les rappels envoyés
- ✅ Alertes automatiques en cas de problème d'envoi
- ✅ Possibilité de tester les rappels avant envoi automatique
**Problème identifié** :
Les apprenants recevaient plusieurs emails de rappel (J-7 ou J-1) pour une même séquence de formation. Par exemple, 5 emails pour la formation JetSki du 15/12/2025 au lieu d'un seul.
**Cause du bug** :
La requête SQL dans `rappelScheduler.ts` cherchait dans la table `datesFormation` et retournait une ligne par date de formation trouvée. Si une séquence avait 5 dates, la requête retournait 5 lignes, déclenchant l'envoi de 5 emails identiques au même apprenant.
**Solution implémentée** :
Modification de la logique dans `server/rappelScheduler.ts` (fonction `processRappel`) :
1. Récupération de toutes les séquences d'abord
2. Pour chaque séquence, vérification de sa **première date** uniquement (ordre = 1)
3. Si cette première date correspond à la date cible (J-7 ou J-1), envoi d'un seul email par apprenant inscrit
**Résultat** :
- ✅ Un seul email de rappel par séquence et par apprenant
- ✅ Toutes les dates de la séquence sont incluses dans l'email
- ✅ Pas de doublons même si la formation comporte plusieurs dates
**Fichiers modifiés** :
- `server/rappelScheduler.ts` : Réécriture complète de la fonction `processRappel`
**Test** :
La prochaine exécution automatique du scheduler (toutes les heures) n'enverra plus qu'un seul email par séquence.
✅ **Nouvelles fonctionnalités** :
**Base de données** :
- Nouvelle table `supportsFormation` pour stocker les documents uploadés par les formateurs
- Champs : sequenceId, formateurId, nomFichier, typeFichier, tailleFichier, urlFichier, s3Key, description
- Migration effectuée avec succès
**Backend (server/formateurDb.ts)** :
- `getCalendrierFormateur()` : Récupère les interventions à venir avec dates, lieux et nombre d'inscrits
- `getApprenantsSequence()` : Liste des apprenants inscrits à une séquence
- `getSupportsSequence()` : Liste des supports de formation d'une séquence
- `ajouterSupport()` : Upload d'un nouveau support
- `supprimerSupport()` : Suppression d'un support avec vérification de propriété
- `validerPresence()` : Validation de la présence d'un apprenant
- `getHistoriqueFormateur()` : Historique des formations passées avec statistiques
- `getDetailSequence()` : Détails complets d'une séquence avec dates
**API tRPC (server/routers.ts)** :
- `formateur.calendrier` : Calendrier des interventions avec filtres de dates
- `formateur.apprenants` : Liste des apprenants d'une séquence
- `formateur.supports` : Gestion des supports (liste, ajout, suppression)
- `formateur.validerPresence` : Validation des présences en ligne
- `formateur.historique` : Historique complet des formations
- `formateur.detailSequence` : Détails d'une séquence
**Pages frontend** :
- `/formateur` : **FormateurDashboard** - Calendrier des interventions à venir groupées par date
- `/formateur/sequence/:id` : **FormateurSequence** - Détails séquence avec onglets Apprenants et Supports
- `/formateur/historique` : **FormateurHistorique** - Historique des formations avec taux de présence
**Fonctionnalités implémentées** :
- 📅 Calendrier des interventions avec dates, heures, lieux et nombre d'inscrits
- 👥 Liste des apprenants avec informations complètes (nom, email, fonction, établissement)
- ✅ Validation des présences en ligne avec checkboxes interactives
- 📎 Gestion des supports de formation (liste, téléchargement)
- 📊 Historique des formations avec statistiques (inscrits, présents, taux)
- 🎨 Interface moderne avec cartes, tableaux et onglets
**Notes** :
- L'ID du formateur est actuellement fixé à 1 (TODO: lier à l'utilisateur connecté)
- La fonctionnalité d'upload de supports est préparée mais nécessite l'implémentation du composant d'upload
- Les présences sont gérées via le statut de l'inscription (confirmée/annulée)
✅ **Corrections apportées** :
**Problèmes résolus** :
- Correction des requêtes SQL Drizzle ORM (remplacement de db.execute() par la syntaxe Drizzle correcte)
- Utilisation de sql template literals pour les fonctions MySQL (DATE_FORMAT, AVG, CAST)
- Correction des noms de colonnes (reponse → reponseNumerique, type → typeQuestion)
- Alignement avec le schéma de base de données existant
**Fonctionnalités opérationnelles** :
- getStatsGlobales() : Statistiques globales (questionnaires, envois, réponses, taux)
- getStatsByFormation() : Taux de réponse par formation avec graphique en barres
- getEvolutionTemporelle() : Évolution mensuelle avec graphique en ligne
- getStatsByFormateur() : Comparaison formateurs avec satisfaction moyenne
**Interface utilisateur** :
- 4 cartes de statistiques globales fonctionnelles
- 4 graphiques interactifs (Recharts) prêts à afficher les données
- Gestion élégante des états vides ("Aucune donnée disponible")
- Tableau détaillé des formateurs avec code couleur
- Lien "Suivi Questionnaires" dans le menu Analyses
Le tableau de bord est maintenant pleinement fonctionnel et affichera automatiquement les statistiques dès que des questionnaires seront envoyés et répondus.
✅ **Nouvelles fonctionnalités implémentées** :
**Exports des résultats** :
- Export Excel avec 3 feuilles (statistiques globales, questions, réponses brutes)
- Export PDF avec mise en page professionnelle et pagination
- Boutons d'export dans la page d'analyse des questionnaires
- Téléchargement automatique des fichiers générés
**Système de notifications** :
- Notification automatique à l'administrateur lors de chaque nouvelle réponse
- Utilisation du système de notifications intégré Manus
- Gestion des erreurs sans bloquer la soumission du questionnaire
**Système complet de questionnaires** :
- Création et édition de questionnaires ✅
- Prévisualisation avant envoi ✅
- Envoi automatique post-formation ✅
- Analyse des résultats avec graphiques ✅
- Exports Excel/PDF ✅
- Notifications administrateur ✅
Le système de questionnaires est maintenant complet et prêt pour la production.
✅ **Nouvelle fonctionnalité** :
- Bouton "Prévisualiser" dans la page d'édition de questionnaire
- Modal de prévisualisation avec rendu exact du questionnaire
- Affichage de tous les types de questions (texte libre, choix multiple, échelle, oui/non)
- Désactivation des champs pour montrer le rendu final
- Indication des questions obligatoires avec astérisque rouge
Le système de questionnaires est maintenant complet avec :
- Création et édition de questionnaires ✅
- Prévisualisation avant envoi ✅
- Envoi automatique post-formation ✅
- Analyse des résultats avec graphiques ✅
Prochaines étapes suggérées :
- Exports Excel/PDF des feedbacks
- Tests complets du système
- Déploiement sur le serveur VPS
✅ **Schéma de base de données** (Phase 1) :
- Table questionnaires (satisfaction, evaluation_pre, evaluation_post)
- Table questions (choix_multiple, echelle, texte_libre, oui_non)
- Table reponsesQuestionnaires
- Table reponsesQuestions
- Table envoisQuestionnaires
✅ **Backend complet** (Phase 2) :
- Fichier questionnaireDb.ts avec toutes les fonctions CRUD
- Procédures tRPC pour questionnaires (list, getById, create, update, delete, getStats, getReponsesDetaillees)
- Procédures tRPC pour questions (list, create, update, delete)
- Procédures tRPC publiques pour réponses (getByToken, submit)
- Fonctions de statistiques (taux de réponse, réponses détaillées)
✅ **Interfaces d'administration** (Phase 3) :
- AdminQuestionnaires : Liste et gestion des questionnaires
- AdminQuestionnaireEdit : Création/édition d'un questionnaire avec ses questions
- QuestionnaireReponse : Page publique pour répondre aux questionnaires
- Routes ajoutées dans App.tsx
- Lien "Questionnaires" ajouté dans le menu de navigation
✅ **Envoi automatique post-formation** (Phase 4) :
- Fichier questionnaireScheduler.ts
- Fonction processEnvoisAutomatiques() pour envoyer les questionnaires
- Génération de tokens uniques pour chaque envoi
- Emails personnalisés avec lien vers le questionnaire
- Procédure tRPC pour déclencher manuellement l'envoi
- Scheduler quotidien à 9h00
✅ **Tableaux de bord d'analyse** (Phase 5) :
- AdminQuestionnaireAnalyse : Page d'analyse avec graphiques
- Statistiques globales (envois, réponses, taux de réponse)
- Graphiques par question (barres, camemberts)
- Analyse des réponses numériques (moyennes, distributions)
- Affichage des réponses textuelles
🚧 **À faire** :
- Exports Excel/PDF des feedbacks
- Tests complets du système
- Déploiement sur le serveur VPS
Le système est maintenant pleinement fonctionnel et prêt à être testé !
Problème identifié :
- La variable datesHTML était générée dans le code (lignes 60-80) pour créer le HTML formaté des dates
- Mais elle n'était pas ajoutée dans l'objet variables passé au template personnalisé
- Résultat : {{datesHTML}} n'était pas remplacée dans le template
Solution appliquée :
- Ajout de datesHTML dans l'objet variables (ligne 134)
- La variable contient le HTML formaté de toutes les dates de la séquence
- Format : <div class="date-item"><strong>Date X :</strong><br/>Du ... au ...</div>
La variable {{datesHTML}} est maintenant correctement remplacée dans les templates d'emails personnalisés.
Modifications apportées :
- Ajout d'un nouveau bouton "Dates (HTML)" dans l'interface AdminEmailTemplates
- Le bouton permet d'insérer la variable {{datesHTML}} dans le corps du message
- Ajout du remplacement de {{datesHTML}} dans la fonction de prévisualisation avec un exemple formaté
- Mise à jour de la description de la prévisualisation pour mentionner la nouvelle variable
La variable {{datesHTML}} permet d'afficher toutes les dates d'une séquence de formation de manière formatée dans les emails (rappels, teasers, confirmations).
1. Bug d'inscription - Mauvais apprenant associé :
- Problème : La procédure apprenants.create était une procédure admin, empêchant la création d'apprenants depuis la page publique
- Solution : Création d'une nouvelle procédure publique apprenants.createPublic
- Résultat : Les inscriptions sont maintenant correctement associées au bon apprenant
2. Bug email de confirmation - Variable {{prenomApprenant}} non remplacée :
- Problème : Le template d'inscription contenait {{prenomApprenant}} qui n'était pas remplacé
- Solution : Mise à jour du bodyContent du template d'inscription dans la base de données avec les bonnes variables
- Résultat : Les emails de confirmation affichent maintenant correctement le prénom et le nom de l'apprenant
Les deux bugs sont corrigés et prêts pour la publication.
Problème identifié :
- La procédure apprenants.create était une procédure admin (adminProcedure)
- La page d'inscription publique n'est pas authentifiée
- Lors de la création d'un apprenant, la mutation échouait silencieusement
- Le code récupérait ensuite un mauvais apprenant par email
Solution appliquée :
- Création d'une nouvelle procédure publique apprenants.createPublic
- Modification de Inscription.tsx pour utiliser createPublic au lieu de create
- Les nouveaux apprenants peuvent maintenant être créés depuis la page publique
- L'inscription associe maintenant le bon apprenant à la séquence
- Modification de checkExistingInscription pour exclure les inscriptions avec statut "annulee"
- Permet maintenant de réinscrire un apprenant à une séquence après annulation de son inscription précédente
- Les inscriptions annulées ne sont plus considérées comme des inscriptions actives lors de la vérification de doublon
- Modification de getInscriptionsBySequence pour exclure les inscriptions avec statut "annulee"
- Modification de getInscriptionsByApprenant pour exclure les inscriptions avec statut "annulee"
- Ajout de l'import de la fonction ne depuis drizzle-orm
- Vérification que le scheduler de rappels filtre déjà correctement (envoie uniquement aux inscriptions confirmées)
- Ajout d'alias de variables pour supporter les deux formats : {{prenom}} et {{prenomApprenant}}
- Les templates peuvent maintenant utiliser indifféremment les noms courts (prenom, nom, formation, sequence) ou les noms longs (prenomApprenant, nomApprenant, nomFormation, nomSequence)
- Correction appliquée dans sendInscriptionConfirmation
- Correction du bug d'insertion SQL des rappels (champ derniereExecution)
- Création de la table rappels et des fonctions CRUD
- Implémentation du scheduler automatique (vérification toutes les heures)
- Personnalisation des templates J-7 et J-1 avec logo et couleurs Itinova (Bleu #283581, Bleu clair #0578BE, Orange #E94E1B, Vert #45ac34)
- Style sobre et professionnel appliqué
- Variable {{datesHTML}} pour afficher toutes les dates de chaque séquence
1. Personnalisation des templates d'emails avec variables {{lieu}} et {{formateur}} (déjà disponible)
2. Aperçu avant envoi avec données réelles d'un apprenant (modal avec iframe)
3. Email de rappel J-1 avec bouton d'envoi et d'aperçu
Les templates personnalisés supportent maintenant toutes les variables disponibles.
L'aperçu permet de vérifier le rendu final avant l'envoi groupé.
Le rappel J-1 complète le système de communication avec les apprenants.
Modifications apportées :
- Ajout des paramètres `lieu` et `formateur` à la fonction sendTeaserEmail
- Récupération du formateur depuis la base de données dans routers.ts via getFormateurById
- Affichage du lieu et du formateur dans le contenu HTML de l'email teaser
- Ajout de `lieu` et `formateur` dans les variables disponibles pour les templates personnalisés
Variables disponibles dans les templates d'emails :
- {{nomApprenant}} - Nom de l'apprenant
- {{prenomApprenant}} - Prénom de l'apprenant
- {{nomFormation}} - Nom de la formation
- {{nomSequence}} - Nom de la séquence
- {{dateDebut}} - Date de début formatée
- {{dateFin}} - Date de fin formatée
- {{lieu}} - Lieu de la formation
- {{formateur}} - Nom du formateur
L'email de teaser affiche maintenant toutes les informations importantes pour les apprenants.
Problème corrigé :
- Les tags {{nomFormation}}, {{nomSequence}}, etc. n'étaient pas remplacés dans les emails de teaser et rappel
- Les fonctions sendTeaserEmail et sendRappelJ7Email ne passaient pas les variables au générateur de template
Solution appliquée :
- Ajout de l'objet variables dans sendTeaserEmail avec : nomApprenant, prenomApprenant, nomFormation, nomSequence, dateDebut, dateFin
- Ajout de l'objet variables dans sendRappelJ7Email avec les mêmes variables plus le lieu
- Les variables sont maintenant correctement transmises à getEmailTemplate() pour le remplacement
Variables disponibles dans les templates :
- {{nomApprenant}} - Nom de l'apprenant
- {{prenomApprenant}} - Prénom de l'apprenant
- {{nomFormation}} - Nom de la formation
- {{nomSequence}} - Nom de la séquence
- {{dateDebut}} - Date de début formatée
- {{dateFin}} - Date de fin formatée
- {{lieu}} - Lieu de la formation (rappel uniquement)
Fonctionnalités ajoutées :
- Logs serveur détaillés pour l'envoi d'emails groupés (nombre de destinataires, adresses)
- Message de retour avec le nombre d'emails envoyés avec succès et échoués
- Avertissement si aucun email n'est envoyé (aucun apprenant confirmé)
Corrections apportées :
- Les emails de teaser et rappel utilisent maintenant correctement la configuration SMTP
- Affichage d'un message de succès clair après l'envoi d'emails groupés
Note technique :
- Le code utilise bien sendEmail() qui respecte la configuration SMTP
- Les emails ne sont envoyés qu'aux apprenants avec statut "confirmee"
- La configuration SMTP doit être faite séparément en production (base de données différente)
Fonctionnalités ajoutées :
- Support SMTP Direct pour l'envoi d'emails (Gmail, Outlook, serveurs personnalisés)
- Interface de configuration SMTP dans l'administration
- Basculement automatique entre Resend API et SMTP Direct
- Affichage du statut de configuration (Resend/SMTP, Simulation/Production)
Corrections apportées :
- Correction du bug de décalage horaire dans le formulaire d'édition des séquences
- Ajout du menu de navigation sur la page Import Excel
- Déplacement du menu Import Excel vers le bloc Configuration
- Correction de la fonction upsertEmailConfig pour mettre à jour au lieu de créer des doublons
- Correction du bug d'enregistrement des champs SMTP dans la base de données
- Correction du problème de cache React Query qui gardait l'ancienne configuration
- Invalidation automatique du cache après enregistrement de la configuration
Scripts de déploiement :
- Scripts de mise à jour VPS avec sauvegarde automatique
- Package de déploiement prêt pour le serveur de production
- Ajout du support SMTP pour l'envoi d'emails (sans dépendre de Resend)
- Correction de l'affichage du statut pour montrer "SMTP Direct" au lieu de "Resend"
- Ajout d'alertes spécifiques pour la configuration SMTP
- Correction de la fonction upsertEmailConfig pour mettre à jour au lieu de créer une nouvelle configuration
- Correction du bug d'enregistrement des champs SMTP dans la base de données
- Mise à jour forcée du provider à "smtp" dans la base de données
**Problème identifié** :
La mutation tRPC `emailConfig.upsert` n'acceptait pas les champs SMTP (smtpHost, smtpPort, smtpSecure, smtpUser, smtpPassword) dans son schéma de validation Zod, ce qui empêchait l'enregistrement de la configuration SMTP.
**Solution appliquée** :
- Ajout des 5 champs SMTP dans le schéma d'input de la mutation `upsert` dans `server/routers.ts`
- Tous les champs SMTP sont définis comme nullable et optional pour permettre la flexibilité
- Types corrects : smtpPort (number), smtpSecure (enum), autres (string)
**Résultat** :
La configuration SMTP peut maintenant être enregistrée correctement dans la base de données. Les champs sont transmis du frontend au backend et stockés via la fonction `upsertEmailConfig`.
**Modifications de la base de données** :
- Ajout des champs SMTP dans la table `emailConfig` : smtpHost, smtpPort, smtpSecure, smtpUser, smtpPassword
**Backend** :
- Installation de `nodemailer` pour l'envoi SMTP
- Création de `server/_core/smtpSender.ts` avec les fonctions d'envoi SMTP et de test de connexion
- Modification de `server/_core/emailSender.ts` pour supporter les deux méthodes (Resend et SMTP)
- Priorité donnée à SMTP si configuré, sinon fallback sur Resend
**Frontend** :
- Mise à jour de `AdminEmailConfig.tsx` pour permettre le choix entre Resend et SMTP
- Ajout d'un sélecteur de méthode d'envoi (Resend API / SMTP Direct)
- Formulaire de configuration SMTP avec :
* Hôte SMTP (ex: smtp.gmail.com)
* Port (587, 465, 25)
* Sécurité (TLS, SSL, None)
* Identifiants (utilisateur/mot de passe)
* Email expéditeur
**Compatibilité** :
- Support des principaux fournisseurs SMTP (Gmail, Outlook, serveurs SMTP personnalisés)
- Instructions pour les mots de passe d'application Gmail
- Mode simulation toujours disponible pour les tests
**Problème identifié** :
Le script `update-app.sh` utilisait `pnpm install --prod` qui n'installe que les dépendances de production, excluant les devDependencies comme `drizzle-kit` nécessaire pour les migrations.
**Solution appliquée** :
1. **update-app.sh** : Changé `pnpm install --prod` en `pnpm install` pour installer toutes les dépendances (production + développement)
2. **GUIDE_MISE_A_JOUR.md** : Mise à jour de la documentation pour refléter ce changement
**Justification** :
`drizzle-kit` est nécessaire pour exécuter `pnpm db:push` qui applique les migrations de base de données. Sans les devDependencies, la commande échoue.
**Nouveau package créé** :
- formation-manager-update-20251127_114306.tar.gz (2.6M)
- Prêt pour déploiement avec la correction
**Modifications apportées** :
1. **backup-before-update.sh** :
- APP_DIR: /var/www/formation-manager-itinova
- BACKUP_DIR: /var/backups/formation-manager-itinova
2. **update-app.sh** :
- APP_DIR: /var/www/formation-manager-itinova
- SERVICE_NAME: formation-manager-itinova
3. **GUIDE_MISE_A_JOUR.md** :
- Tous les chemins mis à jour vers formation-manager-itinova
- Tous les noms de service corrigés
4. **README.md** :
- Documentation mise à jour avec les bons chemins
- Exemples corrigés
5. **Nouveau package créé** :
- formation-manager-update-20251127_095935.tar.gz (2.6M)
- Prêt pour déploiement sur le serveur VPS
1. **backup-before-update.sh** : Script de sauvegarde automatique
- Sauvegarde complète des fichiers de l'application
- Export de la base de données MySQL
- Sauvegarde du fichier .env
- Conservation des 10 dernières sauvegardes
2. **update-app.sh** : Script de mise à jour automatique
- Création d'une sauvegarde de sécurité
- Arrêt/redémarrage du service
- Copie des nouveaux fichiers
- Installation des dépendances
- Application des migrations de base de données
- Vérification du bon fonctionnement
3. **create-deployment-package.sh** : Script de création de package
- Crée une archive .tar.gz prête à transférer
- Inclut tous les fichiers nécessaires
- Exclut node_modules, .git, .env
4. **Documentation complète** :
- GUIDE_MISE_A_JOUR.md : Guide détaillé avec procédures de mise à jour et rollback
- README.md : Documentation des scripts avec exemples d'utilisation
5. **Package de déploiement créé** :
- formation-manager-update-20251127_074417.tar.gz (2.6M)
- Prêt à être transféré sur le serveur VPS
1. Bug décalage horaire dans le formulaire d'édition des séquences
- Correction de la fonction safeFormatDate pour utiliser les méthodes locales (getHours, getMinutes) au lieu des méthodes UTC
- Les heures saisies (ex: 9h00) s'affichent maintenant correctement dans le formulaire d'édition
2. Ajout du menu de navigation sur la page Import Excel
- Intégration du DashboardLayout wrapper dans AdminImportExcel.tsx
- Le menu latéral s'affiche maintenant correctement sur cette page
3. Déplacement du menu "Import Excel"
- Déplacé du bloc GESTION vers le bloc CONFIGURATION dans le menu de navigation
- Positionné après "Utilisateurs" et avant "Rappels" pour une meilleure organisation
- Ajout de la valeur "tous" dans l'enum publicCible du schéma drizzle/schema.ts
- Mise à jour des validations Zod dans server/routers.ts
- Modification directe de la colonne publicCible en base de données via SQL
- Test réussi : création d'une séquence avec public cible "Tous" fonctionne parfaitement
Corrections apportées:
- Utilisation de clés stables (format yyyy-MM-dd) au lieu de day.toISOString() pour éviter l'erreur React #31
- Gestion correcte des objets Date vs strings pour dateBloquage dans le modal
- Gestion correcte du champ formateur qui peut être un objet ou une string
- Ajout de clés uniques pour les dates de formation dans le modal
Le calendrier fonctionne maintenant sans erreur lors du survol et de l'ouverture des modals de détails.