/// Centralized helper for showing consistent Snackbar messages library snackbar_helper; import 'package:flutter/material.dart'; import '../../core/error/failures.dart'; import '../design_system/tokens/app_colors.dart'; /// Helper class for showing consistent Snackbar messages throughout the app class SnackbarHelper { /// Show success message static void showSuccess( BuildContext context, String message, { Duration duration = const Duration(seconds: 3), SnackBarAction? action, }) { final snackBar = SnackBar( content: Row( children: [ const Icon(Icons.check_circle, color: AppColors.onPrimary), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.success, behavior: SnackBarBehavior.floating, duration: duration, action: action, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } /// Show error message static void showError( BuildContext context, String message, { Duration duration = const Duration(seconds: 4), VoidCallback? onRetry, }) { final snackBar = SnackBar( content: Row( children: [ const Icon(Icons.error_outline, color: AppColors.onPrimary), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.error, behavior: SnackBarBehavior.floating, duration: duration, action: onRetry != null ? SnackBarAction( label: 'Réessayer', textColor: AppColors.onPrimary, onPressed: onRetry, ) : null, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } /// Show warning message static void showWarning( BuildContext context, String message, { Duration duration = const Duration(seconds: 4), }) { final snackBar = SnackBar( content: Row( children: [ const Icon(Icons.warning_amber, color: AppColors.onPrimary), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.warning, behavior: SnackBarBehavior.floating, duration: duration, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } /// Show info message static void showInfo( BuildContext context, String message, { Duration duration = const Duration(seconds: 3), }) { final snackBar = SnackBar( content: Row( children: [ const Icon(Icons.info_outline, color: AppColors.onPrimary), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.info, behavior: SnackBarBehavior.floating, duration: duration, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } /// Show "not implemented" message with appropriate styling static void showNotImplemented( BuildContext context, String? featureName, ) { final message = featureName != null ? '$featureName sera bientôt disponible !' : 'Cette fonctionnalité sera bientôt disponible !'; final snackBar = SnackBar( content: Row( children: [ const Icon(Icons.construction, color: AppColors.onPrimary), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.info, behavior: SnackBarBehavior.floating, duration: const Duration(seconds: 4), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } /// Show failure with appropriate styling based on failure type static void showFailure( BuildContext context, Failure failure, { VoidCallback? onRetry, }) { // Handle NotImplementedFailure specially if (failure is NotImplementedFailure) { showNotImplemented(context, null); return; } Color backgroundColor; IconData icon; if (failure is NetworkFailure) { backgroundColor = AppColors.warning; icon = Icons.wifi_off; } else if (failure is UnauthorizedFailure) { backgroundColor = AppColors.error; icon = Icons.lock_outline; } else if (failure is ForbiddenFailure) { backgroundColor = AppColors.warning; icon = Icons.block; } else if (failure is ValidationFailure) { backgroundColor = AppColors.warningUI; icon = Icons.error_outline; } else { backgroundColor = AppColors.error; icon = Icons.error_outline; } final snackBar = SnackBar( content: Row( children: [ Icon(icon, color: AppColors.onPrimary), const SizedBox(width: 12), Expanded(child: Text(failure.getUserMessage())), ], ), backgroundColor: backgroundColor, behavior: SnackBarBehavior.floating, duration: Duration(seconds: failure.isRetryable ? 6 : 4), action: failure.isRetryable && onRetry != null ? SnackBarAction( label: 'Réessayer', textColor: AppColors.onPrimary, onPressed: onRetry, ) : null, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } /// Show loading message (use with caution - prefer progress indicators) static void showLoading( BuildContext context, String message, { Duration duration = const Duration(seconds: 2), }) { final snackBar = SnackBar( content: Row( children: [ const SizedBox( width: 16, height: 16, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(AppColors.onPrimary), ), ), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.surfaceDark, behavior: SnackBarBehavior.floating, duration: duration, ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } /// Dismiss current Snackbar static void dismiss(BuildContext context) { ScaffoldMessenger.of(context).hideCurrentSnackBar(); } }