import 'package:flutter/material.dart'; import '../../../core/theme/colors.dart'; /// Widget to display error messages in a user-friendly way class ErrorDisplay extends StatelessWidget { final String? errorMessage; final VoidCallback? onRetry; final Widget? child; const ErrorDisplay({ super.key, required this.errorMessage, this.onRetry, this.child, }); @override Widget build(BuildContext context) { if (errorMessage == null) { return child ?? const SizedBox.shrink(); } return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: LinearGradient( colors: [ AppColors.error.withOpacity(0.1), AppColors.error.withOpacity(0.05), ], ), borderRadius: BorderRadius.circular(12), border: Border.all( color: AppColors.error.withOpacity(0.3), width: 1, ), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( children: [ Icon( Icons.error_outline, color: AppColors.error, size: 20, ), const SizedBox(width: 8), Expanded( child: Text( errorMessage!, style: const TextStyle( color: AppColors.textPrimary, fontSize: 14, fontWeight: FontWeight.w500, ), ), ), ], ), if (onRetry != null) ...[ const SizedBox(height: 12), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: onRetry, style: ElevatedButton.styleFrom( backgroundColor: AppColors.error, foregroundColor: AppColors.textInverted, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: const Text( 'Retry', style: TextStyle( fontWeight: FontWeight.w600, fontSize: 14, ), ), ), ), ], ], ), ); } } /// Small inline error message for compact spaces class InlineError extends StatelessWidget { final String message; final VoidCallback? onRetry; const InlineError({ super.key, required this.message, this.onRetry, }); @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.error_outline, color: AppColors.error, size: 16, ), const SizedBox(width: 6), Flexible( child: Text( message, style: const TextStyle( color: AppColors.error, fontSize: 12, fontWeight: FontWeight.w500, ), ), ), if (onRetry != null) ...[ const SizedBox(width: 8), GestureDetector( onTap: onRetry, child: Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: AppColors.error.withOpacity(0.1), borderRadius: BorderRadius.circular(4), border: Border.all( color: AppColors.error.withOpacity(0.3), width: 1, ), ), child: const Text( 'Retry', style: TextStyle( color: AppColors.error, fontSize: 11, fontWeight: FontWeight.w600, ), ), ), ), ], ], ); } } /// Snackbar helper to show error messages class ErrorSnackbar { static void show( BuildContext context, String message, { VoidCallback? action, String? actionLabel, Duration duration = const Duration(seconds: 4), }) { final snackBar = SnackBar( content: Row( children: [ const Icon(Icons.error_outline, color: Colors.white), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.error, duration: duration, action: action != null && actionLabel != null ? SnackBarAction( label: actionLabel, textColor: Colors.white, onPressed: action, ) : null, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), margin: const EdgeInsets.all(16), ); ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar(snackBar); } 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: Colors.white), const SizedBox(width: 12), Expanded(child: Text(message)), ], ), backgroundColor: AppColors.cyan, duration: duration, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), margin: const EdgeInsets.all(16), ); ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar(snackBar); } }