Checkpoint: Correction du bug React #31 dans le calendrier - Erreur lors du survol des vignettes de séquences

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.
This commit is contained in:
Manus Sandbox
2025-11-24 09:29:03 -05:00
parent 7a737c0593
commit 14aa8c5f21
20 changed files with 3611 additions and 4 deletions

273
deployment-package/deploy.sh Executable file
View File

@@ -0,0 +1,273 @@
#!/bin/bash
###############################################################################
# Script de déploiement - Gestion des Formations Manager Itinova
# Version: 1.0.0
# Description: Script automatisé pour déployer l'application en production
###############################################################################
set -e # Arrêter en cas d'erreur
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Fonction pour afficher les messages
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Fonction pour vérifier les prérequis
check_prerequisites() {
log_info "Vérification des prérequis..."
# Vérifier Node.js
if ! command -v node &> /dev/null; then
log_error "Node.js n'est pas installé"
exit 1
fi
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
if [ "$NODE_VERSION" -lt 18 ]; then
log_error "Node.js version 18+ est requis (version actuelle: $(node -v))"
exit 1
fi
log_info "Node.js version: $(node -v)"
# Vérifier pnpm
if ! command -v pnpm &> /dev/null; then
log_warn "pnpm n'est pas installé. Installation..."
npm install -g pnpm
fi
log_info "pnpm version: $(pnpm -v)"
# Vérifier MySQL
if ! command -v mysql &> /dev/null; then
log_warn "MySQL client n'est pas installé"
else
log_info "MySQL client: ✓"
fi
}
# Fonction pour créer le fichier .env si nécessaire
setup_env() {
log_info "Configuration des variables d'environnement..."
if [ ! -f .env ]; then
log_warn "Fichier .env non trouvé. Création à partir du template..."
cat > .env << 'EOF'
# Base de données
DATABASE_URL=mysql://user:password@localhost:3306/formation_manager
# JWT Secret (IMPORTANT: Générer une clé aléatoire sécurisée)
JWT_SECRET=changez_cette_cle_secrete_par_une_valeur_aleatoire_tres_longue
# OAuth Manus
OAUTH_SERVER_URL=https://api.manus.im
VITE_OAUTH_PORTAL_URL=https://login.manus.im
VITE_APP_ID=
# Propriétaire
OWNER_OPEN_ID=
OWNER_NAME=
# Application
VITE_APP_TITLE=Gestion des Formations Manager Itinova
VITE_APP_LOGO=/logo.svg
# APIs Manus (optionnel)
BUILT_IN_FORGE_API_URL=https://forge.manus.im
BUILT_IN_FORGE_API_KEY=
VITE_FRONTEND_FORGE_API_KEY=
VITE_FRONTEND_FORGE_API_URL=https://forge.manus.im
# Analytics (optionnel)
VITE_ANALYTICS_ENDPOINT=
VITE_ANALYTICS_WEBSITE_ID=
# Environnement
NODE_ENV=production
EOF
log_warn "Fichier .env créé. IMPORTANT: Modifiez les valeurs avant de continuer!"
log_warn "Éditez le fichier .env avec vos paramètres de production"
read -p "Appuyez sur Entrée après avoir configuré le fichier .env..."
else
log_info "Fichier .env trouvé ✓"
fi
}
# Fonction pour installer les dépendances
install_dependencies() {
log_info "Installation des dépendances..."
pnpm install --frozen-lockfile
log_info "Dépendances installées ✓"
}
# Fonction pour sauvegarder la base de données
backup_database() {
if [ -z "$DATABASE_URL" ]; then
log_warn "DATABASE_URL non définie, sauvegarde de la base de données ignorée"
return
fi
log_info "Sauvegarde de la base de données..."
BACKUP_DIR="./backups"
mkdir -p $BACKUP_DIR
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/db_backup_$TIMESTAMP.sql"
# Extraire les informations de connexion de DATABASE_URL
# Format: mysql://user:password@host:port/database
DB_USER=$(echo $DATABASE_URL | sed -n 's/.*:\/\/\([^:]*\):.*/\1/p')
DB_PASS=$(echo $DATABASE_URL | sed -n 's/.*:\/\/[^:]*:\([^@]*\)@.*/\1/p')
DB_HOST=$(echo $DATABASE_URL | sed -n 's/.*@\([^:]*\):.*/\1/p')
DB_PORT=$(echo $DATABASE_URL | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
DB_NAME=$(echo $DATABASE_URL | sed -n 's/.*\/\([^?]*\).*/\1/p')
if command -v mysqldump &> /dev/null; then
mysqldump -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_FILE 2>/dev/null || {
log_warn "Impossible de créer la sauvegarde de la base de données"
return
}
gzip $BACKUP_FILE
log_info "Sauvegarde créée: $BACKUP_FILE.gz ✓"
# Supprimer les sauvegardes de plus de 30 jours
find $BACKUP_DIR -name "db_backup_*.sql.gz" -mtime +30 -delete
else
log_warn "mysqldump non disponible, sauvegarde ignorée"
fi
}
# Fonction pour appliquer les migrations
run_migrations() {
log_info "Application des migrations de base de données..."
pnpm db:push
log_info "Migrations appliquées ✓"
}
# Fonction pour build l'application
build_app() {
log_info "Build de l'application..."
pnpm build
log_info "Build terminé ✓"
}
# Fonction pour redémarrer le service
restart_service() {
if command -v systemctl &> /dev/null; then
SERVICE_NAME="formation-manager"
if systemctl is-active --quiet $SERVICE_NAME; then
log_info "Redémarrage du service $SERVICE_NAME..."
sudo systemctl restart $SERVICE_NAME
# Attendre que le service soit actif
sleep 3
if systemctl is-active --quiet $SERVICE_NAME; then
log_info "Service redémarré avec succès ✓"
else
log_error "Échec du redémarrage du service"
sudo systemctl status $SERVICE_NAME
exit 1
fi
else
log_warn "Le service $SERVICE_NAME n'est pas actif"
log_info "Démarrage du service..."
sudo systemctl start $SERVICE_NAME
fi
else
log_warn "systemctl non disponible. Redémarrage manuel requis."
fi
}
# Fonction pour vérifier le déploiement
verify_deployment() {
log_info "Vérification du déploiement..."
# Vérifier que le serveur répond
if command -v curl &> /dev/null; then
sleep 2
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 || echo "000")
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ]; then
log_info "Application accessible ✓"
else
log_warn "L'application ne répond pas correctement (HTTP $HTTP_CODE)"
fi
fi
}
# Fonction principale
main() {
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Déploiement - Gestion des Formations Manager Itinova ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
# Vérifier que nous sommes dans le bon répertoire
if [ ! -f "package.json" ]; then
log_error "Ce script doit être exécuté depuis la racine du projet"
exit 1
fi
# Étapes de déploiement
check_prerequisites
setup_env
# Charger les variables d'environnement
if [ -f .env ]; then
export $(cat .env | grep -v '^#' | xargs)
fi
# Demander confirmation avant de continuer
echo ""
log_warn "Le déploiement va:"
echo " 1. Sauvegarder la base de données"
echo " 2. Installer les dépendances"
echo " 3. Appliquer les migrations"
echo " 4. Builder l'application"
echo " 5. Redémarrer le service"
echo ""
read -p "Continuer? (y/N) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
log_info "Déploiement annulé"
exit 0
fi
backup_database
install_dependencies
run_migrations
build_app
restart_service
verify_deployment
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ Déploiement terminé avec succès! ✓ ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
log_info "L'application est maintenant accessible"
log_info "Vérifiez les logs avec: sudo journalctl -u formation-manager -f"
}
# Exécuter le script
main "$@"