All files / components/common Notification.tsx

71.42% Statements 15/21
33.33% Branches 6/18
57.14% Functions 4/7
71.42% Lines 15/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152                                                                1x 1x                                                                         1x         1x               1x                 1x   1x         1x         1x 1x 1x                     1x 1x   1x                   1x                                          
/**
 * @module components/common/Notification
 * Module de composant Notification pour l'affichage des messages utilisateur
 *
 * Ce module contient le composant Notification qui affiche des messages temporaires
 * à l'utilisateur avec différents types (succès, erreur, info). Il gère automatiquement
 * la fermeture après une durée configurable et offre une interface utilisateur cohérente.
 *
 * ## Fonctionnalités principales
 * - Affichage centré avec overlay modal
 * - Types de notification : error, success, info
 * - Fermeture automatique configurable
 * - Fermeture manuelle via bouton
 * - Animation d'entrée et barre de progression
 * - Spinner intégré pour les redirections
 *
 * ## Types de notification
 * - **error** : Messages d'erreur (rouge)
 * - **success** : Messages de succès (vert)
 * - **info** : Messages d'information (bleu)
 *
 * ## Utilisation courante
 * - Confirmation d'actions utilisateur
 * - Affichage d'erreurs de validation
 * - Messages de redirection
 * - Notifications de statut
 *
 * @group Components
 */
 
'use client';
 
import { useEffect, useCallback, useRef } from 'react';
import Spinner from "@/components/common/Spinner";
import {NotificationProps} from "@/type/common/notification";
 
/**
 * Composant Notification pour l'affichage de messages temporaires à l'utilisateur.
 * Voir la documentation du module ci-dessus pour les détails complets.
 *
 * Le composant se positionne au centre de l'écran avec un z-index élevé et disparaît
 * automatiquement après la durée spécifiée. Il gère différents types visuels selon
 * le contexte (erreur, succès, information).
 *
 * @param props - Les propriétés du composant
 * @param props.message - Le message à afficher à l'utilisateur
 * @param props.type - Le type de notification qui détermine l'apparence ('error' | 'success' | 'info')
 * @param props.onCloseAction - Fonction appelée lors de la fermeture de la notification
 * @param props.duration - Durée d'affichage en millisecondes avant fermeture automatique
 *
 * @returns Notification modale centrée avec message et contrôles de fermeture
 *
 * @example
 * ```tsx
 * // Notification d'erreur
 * <Notification
 *   message="Une erreur est survenue"
 *   type="error"
 *   onCloseAction={() => setShowNotif(false)}
 * />
 *
 * // Notification de succès avec durée personnalisée
 * <Notification
 *   message="Opération réussie"
 *   type="success"
 *   duration={5000}
 *   onCloseAction={handleClose}
 * />
 * ```
 */
export default function Notification({ message, type = 'error', onCloseAction = () => {}, duration = 3000 }: NotificationProps) {
  /**
   * Référence du timer pour la fermeture automatique.
   * Permet d'annuler le timer si le composant est détruit prématurément.
   */
  const timerRef = useRef<NodeJS.Timeout | null>(null);
 
  /**
   * Gestionnaire de fermeture de la notification.
   * Utilise useCallback pour éviter les re-renders inutiles.
   *
   * @returns void
   */
  const handleClose = useCallback(() => {
    onCloseAction();
  }, [onCloseAction]);
 
  /**
   * Effect pour gérer la fermeture automatique de la notification.
   * Configure un timer qui appelle onCloseAction après la durée spécifiée.
   * Nettoie automatiquement le timer précédent et lors de la destruction du composant.
   */
  useEffect(() => {
    // Nettoyer le timer précédent
    Iif (timerRef.current) {
      clearTimeout(timerRef.current);
    }
 
    // Créer un nouveau timer
    timerRef.current = setTimeout(() => {
      onCloseAction();
    }, duration);
 
    // Cleanup à la destruction du composant
    return () => {
      if (timerRef.current) {
        clearTimeout(timerRef.current);
      }
    };
  }, [duration, onCloseAction]);
 
  /**
   * Détermine les styles CSS selon le type de notification.
   * Utilise useCallback pour optimiser les performances.
   *
   * @returns Classes CSS pour le type de notification spécifié
   */
  const getTypeStyles = useCallback(() => {
    switch (type) {
      case 'error':
        return 'bg-red-500 border-red-600';
      case 'success':
        return 'bg-green-500 border-green-600';
      case 'info':
        return 'bg-blue-500 border-blue-600';
      default:
        return 'bg-red-500 border-red-600';
    }
  }, [type]);
 
  return (
    <div className={`fixed top-1/2 left-1/2 z-[60] transform -translate-x-1/2 -translate-y-1/2 ${getTypeStyles()} text-white px-4 py-3 rounded-lg shadow-lg border-l-4 min-w-[300px] max-w-[400px] animate-slide-in`}>
      {type === 'success' && message.includes('Redirection') && (
        <div className="flex items-center gap-2">
          <Spinner size="small" color="white"/>
        </div>
      )}
      <div className="flex items-center justify-between">
        <p className="text-sm font-medium">{message}</p>
        <button
          onClick={handleClose}
          className="ml-3 text-white hover:text-gray-200 font-bold text-lg"
          aria-label="Fermer"
        >
          ×
        </button>
      </div>
      <div className={`absolute bottom-0 left-0 h-1 ${type === 'error' ? 'bg-red-300' : type === 'success' ? 'bg-green-300' : 'bg-blue-300'} animate-progress${type === 'success' ? ' success' : ''}`}></div>
    </div>
  );
}