import 'package:flutter/material.dart'; import '../tokens/unionflow_colors.dart'; /// Badge de notification avec compteur class UnionNotificationBadge extends StatelessWidget { final int count; final Widget child; final Color? badgeColor; final bool showZero; const UnionNotificationBadge({ super.key, required this.count, required this.child, this.badgeColor, this.showZero = false, }); @override Widget build(BuildContext context) { final shouldShow = count > 0 || showZero; return Stack( clipBehavior: Clip.none, children: [ child, if (shouldShow) Positioned( right: -6, top: -6, child: AnimatedScale( duration: const Duration(milliseconds: 300), scale: 1.0, curve: Curves.elasticOut, child: Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2, ), decoration: BoxDecoration( color: badgeColor ?? UnionFlowColors.error, borderRadius: BorderRadius.circular(10), border: Border.all( color: UnionFlowColors.surface, width: 2, ), boxShadow: [ BoxShadow( color: (badgeColor ?? UnionFlowColors.error) .withOpacity(0.4), blurRadius: 8, offset: const Offset(0, 2), ), ], ), constraints: const BoxConstraints( minWidth: 18, minHeight: 18, ), child: Text( count > 99 ? '99+' : count.toString(), style: const TextStyle( color: Colors.white, fontSize: 10, fontWeight: FontWeight.w700, ), textAlign: TextAlign.center, ), ), ), ), ], ); } } /// Widget de notification en temps réel (toast) class UnionNotificationToast extends StatelessWidget { final String title; final String message; final IconData icon; final Color color; final VoidCallback? onTap; const UnionNotificationToast({ super.key, required this.title, required this.message, this.icon = Icons.notifications_active, this.color = UnionFlowColors.info, this.onTap, }); static void show( BuildContext context, { required String title, required String message, IconData icon = Icons.notifications_active, Color color = UnionFlowColors.info, VoidCallback? onTap, }) { final overlay = Overlay.of(context); late OverlayEntry entry; entry = OverlayEntry( builder: (context) => Positioned( top: 60, left: 16, right: 16, child: Material( color: Colors.transparent, child: TweenAnimationBuilder( tween: Tween(begin: 0.0, end: 1.0), duration: const Duration(milliseconds: 300), curve: Curves.easeOut, builder: (context, value, child) { return Transform.translate( offset: Offset(0, -20 * (1 - value)), child: Opacity( opacity: value, child: child, ), ); }, child: UnionNotificationToast( title: title, message: message, icon: icon, color: color, onTap: () { entry.remove(); onTap?.call(); }, ), ), ), ), ); overlay.insert(entry); // Auto-dismiss après 4 secondes Future.delayed(const Duration(seconds: 4), () { entry.remove(); }); } @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: UnionFlowColors.surface, borderRadius: BorderRadius.circular(16), boxShadow: UnionFlowColors.mediumShadow, border: Border( left: BorderSide( color: color, width: 4, ), ), ), child: Row( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: color, size: 24), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w700, color: UnionFlowColors.textPrimary, ), ), const SizedBox(height: 4), Text( message, style: const TextStyle( fontSize: 12, color: UnionFlowColors.textSecondary, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ), ), const SizedBox(width: 8), Icon( Icons.chevron_right, size: 18, color: UnionFlowColors.textTertiary, ), ], ), ), ); } }