Files
unionflow-client-quarkus-pr…/unionflow-mobile-apps/lib/shared/widgets/buttons/primary_button.dart
2025-09-15 20:15:34 +00:00

292 lines
8.5 KiB
Dart

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<Color>(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<Color>(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<Color>(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,
);
}
}