Skip to content

Latest commit

 

History

History
278 lines (213 loc) · 9.24 KB

File metadata and controls

278 lines (213 loc) · 9.24 KB

🔧 Correction finale - Bouton qui se déclenche automatiquement

🎯 Problème identifié

Le bouton "Lancer l'évaluation" devient grisé automatiquement dès le passage à la dernière étape "Robustesse technique et sécurité".

Cause racine

Quand l'utilisateur passe à la dernière dimension (étape 6), React re-rend le composant et remplace le bouton "Suivant" par le bouton "Lancer l'évaluation". Pendant ce re-render, un événement résiduel ou un problème de timing peut déclencher automatiquement le onClick du nouveau bouton.

✅ Corrections appliquées

1. Protection multi-niveaux contre les soumissions automatiques

A. Utilisation de useRef pour un suivi fiable

const isSubmittingRef = useRef(false);
const lastStepChangeRef = useRef<number>(0);

Pourquoi ? Les refs ne déclenchent pas de re-render et sont plus fiables que les states pour suivre l'état de soumission.

B. Triple vérification dans handleFormSubmit

const handleFormSubmit = useCallback((event?: React.MouseEvent) => {
  // 1. Empêcher la propagation d'événements
  if (event) {
    event.preventDefault();
    event.stopPropagation();
  }
  
  // 2. Protection temporelle : pas de soumission dans les 500ms après un changement d'étape
  const timeSinceStepChange = Date.now() - lastStepChangeRef.current;
  if (timeSinceStepChange < 500) {
    console.warn(`⚠️ Step changed ${timeSinceStepChange}ms ago, ignoring premature submission`);
    return;
  }
  
  // 3. Vérification avec ref
  if (isSubmittingRef.current) {
    console.warn('⚠️ Assessment already in progress (ref check)');
    return;
  }
  
  // 4. Vérification avec state
  if (assessmentMutation.isPending) {
    console.warn('⚠️ Assessment already in progress (state check)');
    return;
  }
  
  // 5. Validation du formulaire
  if (!isFormValid()) {
    console.warn('⚠️ Form is not valid');
    return;
  }
  
  // ✅ Tout est OK, on peut soumettre
  assessmentMutation.mutate(formData);
}, [assessmentMutation, formData]);

2. Protection dans la mutation elle-même

const assessmentMutation = useMutation({
  retry: false,
  mutationFn: async (data: AssessmentFormData) => {
    // Double vérification au début de la mutation
    if (isSubmittingRef.current) {
      throw new Error('Submission already in progress');
    }
    
    isSubmittingRef.current = true; // Marquer comme en cours
    
    try {
      // ... logique d'évaluation
    } catch (error) {
      isSubmittingRef.current = false; // Reset en cas d'erreur
      throw error;
    }
  },
  onSuccess: (data) => {
    isSubmittingRef.current = false; // Reset en cas de succès
    // ...
  },
  onError: (error) => {
    isSubmittingRef.current = false; // Reset en cas d'erreur
    // ...
  }
});

3. Gestion sécurisée des changements d'étape

const handleStepChange = useCallback((newStep: number) => {
  console.log(`🔄 Changing step from ${currentStep} to ${newStep}`);
  lastStepChangeRef.current = Date.now(); // Enregistrer le moment du changement
  setCurrentStep(newStep);
}, [currentStep]);

Tous les appels à setCurrentStep ont été remplacés par handleStepChange :

  • Navigation par onglets (Tabs)
  • Bouton "Suivant"
  • Bouton "Précédent"
  • Nouvelle évaluation

4. Utilisation de useCallback pour stabiliser les fonctions

const handleFormSubmit = useCallback((event?: React.MouseEvent) => {
  // ...
}, [assessmentMutation, formData]);

const handleStepChange = useCallback((newStep: number) => {
  // ...
}, [currentStep]);

Pourquoi ? useCallback empêche la recréation de la fonction à chaque render, ce qui évite les appels intempestifs.

5. Logs de débogage détaillés

console.log('🔄 Assessment component rendering');
console.log('📊 Current state:', { isFormCompleted, currentStep, ... });
console.log('✅ assessmentMutation created, isPending:', assessmentMutation.isPending);
console.log('🔄 Changing step from X to Y');
console.log('✅ User clicked submit button, starting assessment...');

🧪 Comment tester

Étape 1 : Vider le cache

IMPORTANT : Les modifications ne seront visibles qu'après avoir vidé le cache !

  1. Appuyez sur Ctrl+Shift+Delete
  2. Cochez "Images et fichiers en cache"
  3. Cliquez sur "Effacer les données"

Étape 2 : Recharger la page

  1. Appuyez sur Ctrl+F5 (rechargement forcé)
  2. Ou fermez complètement le navigateur et rouvrez-le

Étape 3 : Ouvrir la console

  1. Appuyez sur F12
  2. Allez dans l'onglet "Console"
  3. Gardez la console ouverte pendant le test

Étape 4 : Tester l'évaluation

  1. Connectez-vous
  2. Allez sur "Évaluation des risques"
  3. Remplissez les informations de base
  4. Répondez aux questions des 6 premières dimensions
  5. Cliquez sur "Suivant" pour passer à la dernière dimension "Robustesse technique et sécurité"

⚠️ POINT DE VÉRIFICATION CRITIQUE :

  • Le bouton "Lancer l'évaluation" doit apparaître
  • Le bouton doit rester ACTIF (non grisé)
  • Aucun log 🚀 Starting assessment ne doit apparaître
  • Le bouton ne doit PAS se déclencher automatiquement
  1. Répondez aux questions de la dernière dimension
  2. Cliquez manuellement sur "Lancer l'évaluation"

✅ RÉSULTAT ATTENDU :

  • Vous voyez ✅ User clicked submit button dans la console
  • Puis 🚀 Starting assessment for system:
  • Le bouton devient grisé avec le texte "Évaluation en cours..."
  • L'évaluation se termine normalement

📊 Logs attendus

Au chargement de la page

🔄 Assessment component rendering
📊 Current state: {isFormCompleted: false, currentStep: 0, ...}
✅ assessmentMutation created, isPending: false

Lors du passage à la dernière étape

🔄 Changing step from 5 to 6
🔄 Assessment component rendering
📊 Current state: {isFormCompleted: false, currentStep: 6, ...}
✅ assessmentMutation created, isPending: false

⚠️ Vous ne devez PAS voir :

  • 🚀 Starting assessment for system: (sans avoir cliqué)
  • isPending: true (avant d'avoir cliqué)

Lors du clic manuel sur le bouton

✅ User clicked submit button, starting assessment...
📋 Form data: {...}
🚀 Starting assessment for system: [Nom du système]
📍 Stack trace: Error at mutationFn...

🛡️ Protections mises en place

Protection Description Efficacité
Délai de 500ms Empêche la soumission dans les 500ms après un changement d'étape ⭐⭐⭐⭐⭐
Ref isSubmitting Suivi fiable de l'état de soumission sans re-render ⭐⭐⭐⭐⭐
isPending check Vérification de l'état de la mutation TanStack Query ⭐⭐⭐⭐
event.preventDefault() Empêche la propagation d'événements ⭐⭐⭐⭐
event.stopPropagation() Empêche la propagation vers les parents ⭐⭐⭐⭐
isFormValid() Validation du formulaire avant soumission ⭐⭐⭐⭐
useCallback Stabilisation des fonctions pour éviter les re-créations ⭐⭐⭐⭐
retry: false Désactivation des tentatives automatiques ⭐⭐⭐
type="button" Empêche le comportement de soumission HTML ⭐⭐⭐

🔍 Si le problème persiste

Scénario 1 : Le bouton se déclenche toujours automatiquement

Vérifiez :

  1. Le cache est bien vidé (Ctrl+Shift+Delete)
  2. La page est rechargée (Ctrl+F5)
  3. Les logs apparaissent dans la console

Si les logs n'apparaissent pas :

  • Les modifications ne sont pas chargées
  • Redémarrez le serveur Docker
  • Vérifiez que le build est à jour

Scénario 2 : Les logs montrent un déclenchement automatique

Cherchez dans les logs :

  • ⚠️ Step changed Xms ago → Le délai de 500ms a bloqué la soumission (NORMAL)
  • 🚀 Starting assessment sans ✅ User clicked submit button → Problème plus profond

Partagez :

  • Tous les logs de la console
  • Le moment exact où le bouton devient grisé
  • Les actions effectuées juste avant

Scénario 3 : Le bouton reste grisé en permanence

Cause probable : isPending reste à true

Solution :

  1. Rafraîchir la page (F5)
  2. Vider le cache de TanStack Query
  3. Redémarrer le navigateur

📁 Fichiers modifiés

  • client/src/pages/assessment.tsx - Protections multi-niveaux + logs

🎯 Résumé

Avant Après
❌ Bouton se déclenche automatiquement ✅ Contrôle total par l'utilisateur
❌ Pas de protection temporelle ✅ Délai de 500ms après changement d'étape
❌ Un seul niveau de vérification ✅ 5 niveaux de protection
❌ Fonctions recréées à chaque render ✅ Fonctions stabilisées avec useCallback
❌ Pas de logs de débogage ✅ Logs détaillés à chaque étape

🎉 Avec ces 5 niveaux de protection, le bouton ne devrait PLUS se déclencher automatiquement !

🚀 Prochaines étapes

  1. Videz le cache (Ctrl+Shift+Delete)
  2. Rechargez la page (Ctrl+F5)
  3. Testez l'évaluation complète
  4. Vérifiez les logs dans la console
  5. Confirmez que le bouton ne se déclenche plus automatiquement

Si le problème persiste malgré ces corrections, partagez les logs complets de la console pour une analyse plus approfondie.