import 'package:flutter/material.dart'; import '../../../theme/app_colors.dart'; /// 앱 전체에서 사용되는 통합 스낵바 /// 성공, 에러, 정보 등 다양한 타입의 메시지를 표시합니다. class AppSnackBar { /// 성공 메시지를 표시합니다. static void showSuccess({ required BuildContext context, required String message, IconData icon = Icons.check_circle_rounded, Duration duration = const Duration(seconds: 3), bool showAtTop = true, }) { _show( context: context, message: message, icon: icon, backgroundColor: AppColors.successColor, iconColor: AppColors.pureWhite, textColor: AppColors.pureWhite, duration: duration, showAtTop: showAtTop, ); } /// 에러 메시지를 표시합니다. static void showError({ required BuildContext context, required String message, IconData icon = Icons.error_rounded, Duration duration = const Duration(seconds: 4), bool showAtTop = true, }) { _show( context: context, message: message, icon: icon, backgroundColor: AppColors.dangerColor, iconColor: AppColors.pureWhite, textColor: AppColors.pureWhite, duration: duration, showAtTop: showAtTop, ); } /// 정보 메시지를 표시합니다. static void showInfo({ required BuildContext context, required String message, IconData icon = Icons.info_rounded, Duration duration = const Duration(seconds: 3), bool showAtTop = true, }) { _show( context: context, message: message, icon: icon, backgroundColor: AppColors.primaryColor, iconColor: AppColors.pureWhite, textColor: AppColors.pureWhite, duration: duration, showAtTop: showAtTop, ); } /// 경고 메시지를 표시합니다. static void showWarning({ required BuildContext context, required String message, IconData icon = Icons.warning_amber_rounded, Duration duration = const Duration(seconds: 3), bool showAtTop = true, }) { _show( context: context, message: message, icon: icon, backgroundColor: AppColors.warningColor, iconColor: AppColors.pureWhite, textColor: AppColors.pureWhite, duration: duration, showAtTop: showAtTop, ); } /// 커스텀 스낵바를 표시합니다. static void showCustom({ required BuildContext context, required String message, required IconData icon, required Color backgroundColor, Color iconColor = AppColors.pureWhite, Color textColor = AppColors.pureWhite, Duration duration = const Duration(seconds: 3), bool showAtTop = true, SnackBarAction? action, }) { _show( context: context, message: message, icon: icon, backgroundColor: backgroundColor, iconColor: iconColor, textColor: textColor, duration: duration, showAtTop: showAtTop, action: action, ); } /// 내부적으로 스낵바를 표시하는 메서드 static void _show({ required BuildContext context, required String message, required IconData icon, required Color backgroundColor, required Color iconColor, required Color textColor, required Duration duration, required bool showAtTop, SnackBarAction? action, }) { // 기존 스낵바 제거 ScaffoldMessenger.of(context).hideCurrentSnackBar(); // 새 스낵바 표시 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ // 아이콘 Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: iconColor.withValues(alpha: 0.2), shape: BoxShape.circle, ), child: Icon( icon, color: iconColor, size: 20, ), ), const SizedBox(width: 12), // 메시지 Expanded( child: Text( message, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: textColor, height: 1.3, ), ), ), ], ), backgroundColor: backgroundColor, behavior: SnackBarBehavior.floating, margin: showAtTop ? EdgeInsets.only( top: MediaQuery.of(context).padding.top + 16, left: 16, right: 16, bottom: MediaQuery.of(context).size.height - 120, ) : const EdgeInsets.all(16), padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 14, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 4, duration: duration, dismissDirection: DismissDirection.horizontal, action: action, ), ); } /// 로딩 스낵바를 표시합니다. (자동으로 사라지지 않음) static ScaffoldFeatureController showLoading({ required BuildContext context, required String message, bool showAtTop = true, }) { // 기존 스낵바 제거 ScaffoldMessenger.of(context).hideCurrentSnackBar(); return ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ // 로딩 인디케이터 Container( width: 24, height: 24, margin: const EdgeInsets.only(right: 12), child: CircularProgressIndicator( strokeWidth: 2.5, color: AppColors.pureWhite, ), ), // 메시지 Expanded( child: Text( message, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: AppColors.pureWhite, ), ), ), ], ), backgroundColor: AppColors.primaryColor, behavior: SnackBarBehavior.floating, margin: showAtTop ? EdgeInsets.only( top: MediaQuery.of(context).padding.top + 16, left: 16, right: 16, bottom: MediaQuery.of(context).size.height - 120, ) : const EdgeInsets.all(16), padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 14, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 4, duration: const Duration(days: 365), // 자동으로 사라지지 않음 dismissDirection: DismissDirection.none, // 스와이프로 닫을 수 없음 ), ); } /// 액션 버튼이 있는 스낵바를 표시합니다. static void showWithAction({ required BuildContext context, required String message, required String actionLabel, required VoidCallback onActionPressed, IconData icon = Icons.info_rounded, Color backgroundColor = AppColors.primaryColor, Duration duration = const Duration(seconds: 4), bool showAtTop = true, }) { _show( context: context, message: message, icon: icon, backgroundColor: backgroundColor, iconColor: AppColors.pureWhite, textColor: AppColors.pureWhite, duration: duration, showAtTop: showAtTop, action: SnackBarAction( label: actionLabel, textColor: AppColors.pureWhite, onPressed: onActionPressed, ), ); } }