import 'package:flutter/material.dart'; import '../../core/constants/colors.dart'; import '../../core/constants/design_system.dart'; /// Widget de badge affichant le nombre de notifications non lues. /// /// Utilisé dans l'AppBar, BottomNavigationBar, ou partout où un compteur /// de notifications est nécessaire. /// /// **Usage:** /// ```dart /// NotificationBadge( /// count: 5, /// child: Icon(Icons.notifications), /// ) /// ``` class NotificationBadge extends StatelessWidget { const NotificationBadge({ required this.count, required this.child, this.showZero = false, this.maxCount = 99, super.key, }); /// Nombre de notifications non lues final int count; /// Widget enfant sur lequel afficher le badge final Widget child; /// Afficher le badge même si count == 0 final bool showZero; /// Nombre maximum à afficher (au-delà, affiche "99+") final int maxCount; @override Widget build(BuildContext context) { final theme = Theme.of(context); final shouldShow = count > 0 || showZero; return Stack( clipBehavior: Clip.none, children: [ child, if (shouldShow) Positioned( right: -6, top: -6, child: Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2, ), decoration: BoxDecoration( color: Colors.red, borderRadius: BorderRadius.circular(12), border: Border.all( color: theme.scaffoldBackgroundColor, width: 2, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.15), blurRadius: 4, offset: const Offset(0, 2), ), ], ), constraints: const BoxConstraints( minWidth: 20, minHeight: 20, ), child: Center( child: Text( count > maxCount ? '$maxCount+' : count.toString(), style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold, height: 1.2, ), textAlign: TextAlign.center, ), ), ), ), ], ); } } /// Widget de point rouge simple pour indiquer des notifications non lues. /// /// Plus discret que [NotificationBadge], affiche juste un point rouge /// sans compter le nombre. /// /// **Usage:** /// ```dart /// NotificationDot( /// show: hasUnreadNotifications, /// child: Icon(Icons.notifications), /// ) /// ``` class NotificationDot extends StatelessWidget { const NotificationDot({ required this.show, required this.child, super.key, }); /// Afficher ou non le point rouge final bool show; /// Widget enfant sur lequel afficher le dot final Widget child; @override Widget build(BuildContext context) { final theme = Theme.of(context); return Stack( clipBehavior: Clip.none, children: [ child, if (show) Positioned( right: -2, top: -2, child: Container( width: 10, height: 10, decoration: BoxDecoration( color: Colors.red, shape: BoxShape.circle, border: Border.all( color: theme.scaffoldBackgroundColor, width: 2, ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.15), blurRadius: 3, offset: const Offset(0, 1), ), ], ), ), ), ], ); } }