import 'package:flutter/material.dart'; import '../../theme/app_theme.dart'; /// Widget bouton principal réutilisable class PrimaryButton extends StatelessWidget { final String text; final VoidCallback? onPressed; final bool isLoading; final bool isEnabled; final IconData? icon; final Color? backgroundColor; final Color? textColor; final double? width; final double height; final EdgeInsetsGeometry? padding; final BorderRadius? borderRadius; const PrimaryButton({ super.key, required this.text, this.onPressed, this.isLoading = false, this.isEnabled = true, this.icon, this.backgroundColor, this.textColor, this.width, this.height = 48.0, this.padding, this.borderRadius, }); @override Widget build(BuildContext context) { final effectiveBackgroundColor = backgroundColor ?? AppTheme.primaryColor; final effectiveTextColor = textColor ?? Colors.white; final isButtonEnabled = isEnabled && !isLoading && onPressed != null; return SizedBox( width: width, height: height, child: ElevatedButton( onPressed: isButtonEnabled ? onPressed : null, style: ElevatedButton.styleFrom( backgroundColor: effectiveBackgroundColor, foregroundColor: effectiveTextColor, disabledBackgroundColor: effectiveBackgroundColor.withOpacity(0.5), disabledForegroundColor: effectiveTextColor.withOpacity(0.5), elevation: isButtonEnabled ? 2 : 0, shadowColor: effectiveBackgroundColor.withOpacity(0.3), shape: RoundedRectangleBorder( borderRadius: borderRadius ?? BorderRadius.circular(8), ), padding: padding ?? const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ), child: isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(effectiveTextColor), ), ) : Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ if (icon != null) ...[ Icon(icon, size: 18), const SizedBox(width: 8), ], Text( text, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: effectiveTextColor, ), ), ], ), ), ); } } /// Widget bouton secondaire class SecondaryButton extends StatelessWidget { final String text; final VoidCallback? onPressed; final bool isLoading; final bool isEnabled; final IconData? icon; final Color? borderColor; final Color? textColor; final double? width; final double height; final EdgeInsetsGeometry? padding; final BorderRadius? borderRadius; const SecondaryButton({ super.key, required this.text, this.onPressed, this.isLoading = false, this.isEnabled = true, this.icon, this.borderColor, this.textColor, this.width, this.height = 48.0, this.padding, this.borderRadius, }); @override Widget build(BuildContext context) { final effectiveBorderColor = borderColor ?? AppTheme.primaryColor; final effectiveTextColor = textColor ?? AppTheme.primaryColor; final isButtonEnabled = isEnabled && !isLoading && onPressed != null; return SizedBox( width: width, height: height, child: OutlinedButton( onPressed: isButtonEnabled ? onPressed : null, style: OutlinedButton.styleFrom( foregroundColor: effectiveTextColor, disabledForegroundColor: effectiveTextColor.withOpacity(0.5), side: BorderSide( color: isButtonEnabled ? effectiveBorderColor : effectiveBorderColor.withOpacity(0.5), width: 1.5, ), shape: RoundedRectangleBorder( borderRadius: borderRadius ?? BorderRadius.circular(8), ), padding: padding ?? const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ), child: isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(effectiveTextColor), ), ) : Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ if (icon != null) ...[ Icon(icon, size: 18), const SizedBox(width: 8), ], Text( text, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: effectiveTextColor, ), ), ], ), ), ); } } /// Widget bouton texte class CustomTextButton extends StatelessWidget { final String text; final VoidCallback? onPressed; final bool isLoading; final bool isEnabled; final IconData? icon; final Color? textColor; final double? width; final double height; final EdgeInsetsGeometry? padding; const CustomTextButton({ super.key, required this.text, this.onPressed, this.isLoading = false, this.isEnabled = true, this.icon, this.textColor, this.width, this.height = 48.0, this.padding, }); @override Widget build(BuildContext context) { final effectiveTextColor = textColor ?? AppTheme.primaryColor; final isButtonEnabled = isEnabled && !isLoading && onPressed != null; return SizedBox( width: width, height: height, child: Material( color: Colors.transparent, child: InkWell( onTap: isButtonEnabled ? onPressed : null, borderRadius: BorderRadius.circular(8), child: Container( padding: padding ?? const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: isLoading ? SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(effectiveTextColor), ), ) : Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: [ if (icon != null) ...[ Icon( icon, size: 18, color: isButtonEnabled ? effectiveTextColor : effectiveTextColor.withOpacity(0.5), ), const SizedBox(width: 8), ], Text( text, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: isButtonEnabled ? effectiveTextColor : effectiveTextColor.withOpacity(0.5), ), ), ], ), ), ), ), ); } } /// Widget bouton destructeur (pour les actions dangereuses) class DestructiveButton extends StatelessWidget { final String text; final VoidCallback? onPressed; final bool isLoading; final bool isEnabled; final IconData? icon; final double? width; final double height; final EdgeInsetsGeometry? padding; final BorderRadius? borderRadius; const DestructiveButton({ super.key, required this.text, this.onPressed, this.isLoading = false, this.isEnabled = true, this.icon, this.width, this.height = 48.0, this.padding, this.borderRadius, }); @override Widget build(BuildContext context) { return PrimaryButton( text: text, onPressed: onPressed, isLoading: isLoading, isEnabled: isEnabled, icon: icon, backgroundColor: AppTheme.errorColor, textColor: Colors.white, width: width, height: height, padding: padding, borderRadius: borderRadius, ); } }