Versione OK Pour l'onglet événements.
This commit is contained in:
@@ -30,6 +30,7 @@ class AppTheme {
|
||||
|
||||
// Bordures et dividers
|
||||
static const Color borderColor = Color(0xFFE0E0E0);
|
||||
static const Color borderLight = Color(0xFFF5F5F5);
|
||||
static const Color dividerColor = Color(0xFFBDBDBD);
|
||||
|
||||
// Thème clair
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user