import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; enum SnackbarType { success, error, warning, info, } class SnackbarUtil { /// Show a success snackbar static void showSuccess( String message, { String? title, Duration? duration, }) { _showSnackbar( title: title ?? 'Success', message: message, type: SnackbarType.success, duration: duration, ); } /// Show an error snackbar static void showError( String message, { String? title, Duration? duration, }) { _showSnackbar( title: title ?? 'Error', message: message, type: SnackbarType.error, duration: duration, ); } /// Show a warning snackbar static void showWarning( String message, { String? title, Duration? duration, }) { _showSnackbar( title: title ?? 'Warning', message: message, type: SnackbarType.warning, duration: duration, ); } /// Show an info snackbar static void showInfo( String message, { String? title, Duration? duration, }) { _showSnackbar( title: title ?? 'Info', message: message, type: SnackbarType.info, duration: duration, ); } /// Internal method to show snackbar with custom styling static void _showSnackbar({ required String title, required String message, required SnackbarType type, Duration? duration, }) { final config = _getSnackbarConfig(type); Get.snackbar( title, message, snackPosition: SnackPosition.TOP, backgroundColor: config.backgroundColor, colorText: config.textColor, icon: Icon( config.icon, color: config.iconColor, size: 28.w, ), shouldIconPulse: true, borderRadius: 12.r, margin: EdgeInsets.all(16.w), padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h), duration: duration ?? const Duration(seconds: 3), isDismissible: true, dismissDirection: DismissDirection.horizontal, forwardAnimationCurve: Curves.easeOutBack, reverseAnimationCurve: Curves.easeInBack, animationDuration: const Duration(milliseconds: 500), boxShadows: [ BoxShadow( color: config.backgroundColor.withOpacity(0.3), blurRadius: 12, offset: const Offset(0, 4), ), ], titleText: Text( title, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: config.textColor, ), ), messageText: Text( message, style: TextStyle( fontSize: 14.sp, color: config.textColor.withOpacity(0.9), ), ), ); } /// Get configuration based on snackbar type static _SnackbarConfig _getSnackbarConfig(SnackbarType type) { switch (type) { case SnackbarType.success: return _SnackbarConfig( backgroundColor: const Color(0xFF2E7D32), // Green textColor: Colors.white, iconColor: Colors.white, icon: Icons.check_circle_rounded, ); case SnackbarType.error: return _SnackbarConfig( backgroundColor: const Color(0xFFD32F2F), // Red textColor: Colors.white, iconColor: Colors.white, icon: Icons.error_rounded, ); case SnackbarType.warning: return _SnackbarConfig( backgroundColor: const Color(0xFFF57C00), // Orange textColor: Colors.white, iconColor: Colors.white, icon: Icons.warning_rounded, ); case SnackbarType.info: return _SnackbarConfig( backgroundColor: const Color(0xFF1976D2), // Blue textColor: Colors.white, iconColor: Colors.white, icon: Icons.info_rounded, ); } } /// Show a loading snackbar that can be dismissed programmatically static void showLoading(String message) { Get.snackbar( 'Loading', message, snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.grey.shade800, colorText: Colors.white, icon: SizedBox( width: 24.w, height: 24.h, child: const CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ), shouldIconPulse: false, borderRadius: 12.r, margin: EdgeInsets.all(16.w), padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h), duration: const Duration(days: 1), // Long duration isDismissible: false, showProgressIndicator: false, ); } /// Dismiss the current snackbar static void dismiss() { if (Get.isSnackbarOpen) { Get.closeCurrentSnackbar(); } } /// Show a custom snackbar with action button static void showWithAction({ required String title, required String message, required String actionLabel, required VoidCallback onAction, SnackbarType type = SnackbarType.info, Duration? duration, }) { final config = _getSnackbarConfig(type); Get.snackbar( title, message, snackPosition: SnackPosition.TOP, backgroundColor: config.backgroundColor, colorText: config.textColor, icon: Icon( config.icon, color: config.iconColor, size: 28.w, ), shouldIconPulse: true, borderRadius: 12.r, margin: EdgeInsets.all(16.w), padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h), duration: duration ?? const Duration(seconds: 5), isDismissible: true, mainButton: TextButton( onPressed: () { Get.closeCurrentSnackbar(); onAction(); }, style: TextButton.styleFrom( foregroundColor: Colors.white, backgroundColor: Colors.white.withOpacity(0.2), padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r), ), ), child: Text( actionLabel, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, ), ), ), titleText: Text( title, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.bold, color: config.textColor, ), ), messageText: Text( message, style: TextStyle( fontSize: 14.sp, color: config.textColor.withOpacity(0.9), ), ), ); } } /// Internal configuration class for snackbar styling class _SnackbarConfig { final Color backgroundColor; final Color textColor; final Color iconColor; final IconData icon; _SnackbarConfig({ required this.backgroundColor, required this.textColor, required this.iconColor, required this.icon, }); }