import 'package:flutter/material.dart'; import '../../core/theme/app_spacing.dart'; import '../../core/theme/app_theme.dart'; /// 現代彈窗模板 - 基於 modernization-v2.md 規範 /// /// 使用方法: /// ```dart /// ModernDialog.show( /// context: context, /// title: '確認操作', /// description: '確定要執行此操作嗎?', /// actions: [ /// ModernDialogAction(label: '取消', isDestructive: false), /// ModernDialogAction(label: '確認', isPrimary: true), /// ], /// ); /// ``` class ModernDialog extends StatelessWidget { final String? title; final Widget? titleWidget; final String? description; final Widget? content; final List? actions; final VoidCallback? onClose; const ModernDialog({ super.key, this.title, this.titleWidget, this.description, this.content, this.actions, this.onClose, }); /// 顯示現代彈窗 static Future show({ required BuildContext context, String? title, Widget? titleWidget, String? description, Widget? content, List? actions, bool barrierDismissible = true, }) { return showDialog( context: context, barrierDismissible: barrierDismissible, builder: (context) => ModernDialog( title: title, titleWidget: titleWidget, description: description, content: content, actions: actions, ), ); } /// 顯示確認彈窗 static Future confirm({ required BuildContext context, required String title, String? description, String confirmText = '確認', String cancelText = '取消', bool isDestructive = false, }) async { final result = await show( context: context, title: title, description: description, actions: [ ModernDialogAction(label: cancelText, returnValue: false), ModernDialogAction( label: confirmText, returnValue: true, isPrimary: true, isDestructive: isDestructive, ), ], ); return result ?? false; } /// 顯示信息彈窗 static Future info({ required BuildContext context, required String title, String? description, String buttonText = '知道了', }) { return show( context: context, title: title, description: description, actions: [ ModernDialogAction(label: buttonText, isPrimary: true), ], ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Dialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.xl), ), backgroundColor: theme.colorScheme.surfaceContainer, child: Container( padding: const EdgeInsets.all(AppSpacing.lg), constraints: const BoxConstraints(maxWidth: 400), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // 標題 if (titleWidget != null) titleWidget! else if (title != null) Text( title!, style: AppTextStyles.headlineSmall(context).copyWith( fontWeight: FontWeight.w600, ), ), if (title != null || titleWidget != null) const SizedBox(height: AppSpacing.md), // 描述 if (description != null) ...[ Text( description!, style: AppTextStyles.bodyMedium(context).copyWith(color: theme.colorScheme.onSurfaceVariant), ), const SizedBox(height: AppSpacing.md), ], // 自定義內容 if (content != null) ...[ content!, const SizedBox(height: AppSpacing.lg), ], // 按鈕 if (actions != null && actions!.isNotEmpty) Row( mainAxisAlignment: MainAxisAlignment.end, children: _buildActions(context), ), ], ), ), ); } List _buildActions(BuildContext context) { return actions!.asMap().entries.map((entry) { final index = entry.key; final action = entry.value; return Padding( padding: EdgeInsets.only(left: index > 0 ? AppSpacing.sm : 0), child: _buildActionButton(context, action), ); }).toList(); } Widget _buildActionButton(BuildContext context, ModernDialogAction action) { final theme = Theme.of(context); if (action.isPrimary) { return ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: action.isDestructive ? theme.colorScheme.error : theme.colorScheme.primary, ), onPressed: () { Navigator.of(context).pop(action.returnValue); action.onPressed?.call(); }, child: Text(action.label), ); } return OutlinedButton( onPressed: () { Navigator.of(context).pop(action.returnValue); action.onPressed?.call(); }, child: Text(action.label), ); } } /// 彈窗按鈕配置 class ModernDialogAction { final String label; final dynamic returnValue; final bool isPrimary; final bool isDestructive; final VoidCallback? onPressed; const ModernDialogAction({ required this.label, this.returnValue, this.isPrimary = false, this.isDestructive = false, this.onPressed, }); }