HydroNutrify_Ari_e41221567/lib/ui/shared/components/custom_button.dart

190 lines
5.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:mobile_monitoring/core/constants/colors.dart';
import 'package:mobile_monitoring/core/constants/app_settings.dart';
/// Custom Button - Berbagai jenis button yang reusable
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback? onPressed;
final bool isLoading;
final ButtonType type;
final ButtonSize size;
final IconData? icon;
final Color? backgroundColor;
final Color? textColor;
final double? width;
final double? height;
const CustomButton({
super.key,
required this.text,
this.onPressed,
this.isLoading = false,
this.type = ButtonType.primary,
this.size = ButtonSize.medium,
this.icon,
this.backgroundColor,
this.textColor,
this.width,
this.height,
});
@override
Widget build(BuildContext context) {
final isDisabled = onPressed == null || isLoading;
return SizedBox(
width: width,
height: height ?? _getHeight(),
child: _buildButton(context, isDisabled),
);
}
Widget _buildButton(BuildContext context, bool isDisabled) {
switch (type) {
case ButtonType.primary:
return ElevatedButton(
onPressed: isDisabled ? null : onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: backgroundColor ?? AppColors.primary,
foregroundColor: textColor ?? AppColors.white,
padding: _getPadding(),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius),
),
elevation: 2,
),
child: _buildContent(),
);
case ButtonType.secondary:
return OutlinedButton(
onPressed: isDisabled ? null : onPressed,
style: OutlinedButton.styleFrom(
foregroundColor: backgroundColor ?? AppColors.primary,
side: BorderSide(
color: backgroundColor ?? AppColors.primary,
width: 1.5,
),
padding: _getPadding(),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius),
),
),
child: _buildContent(),
);
case ButtonType.text:
return TextButton(
onPressed: isDisabled ? null : onPressed,
style: TextButton.styleFrom(
foregroundColor: backgroundColor ?? AppColors.primary,
padding: _getPadding(),
),
child: _buildContent(),
);
case ButtonType.danger:
return ElevatedButton(
onPressed: isDisabled ? null : onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.error,
foregroundColor: AppColors.white,
padding: _getPadding(),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppSettings.defaultBorderRadius),
),
elevation: 2,
),
child: _buildContent(),
);
}
}
Widget _buildContent() {
if (isLoading) {
return SizedBox(
height: _getIndicatorSize(),
width: _getIndicatorSize(),
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
type == ButtonType.primary || type == ButtonType.danger
? AppColors.white
: AppColors.primary,
),
),
);
}
if (icon != null) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: _getIconSize()),
const SizedBox(width: 8),
Text(text, style: TextStyle(fontSize: _getFontSize())),
],
);
}
return Text(text, style: TextStyle(fontSize: _getFontSize()));
}
double _getHeight() {
switch (size) {
case ButtonSize.small:
return 36;
case ButtonSize.medium:
return 48;
case ButtonSize.large:
return 56;
}
}
EdgeInsets _getPadding() {
switch (size) {
case ButtonSize.small:
return const EdgeInsets.symmetric(horizontal: 16, vertical: 8);
case ButtonSize.medium:
return const EdgeInsets.symmetric(horizontal: 24, vertical: 12);
case ButtonSize.large:
return const EdgeInsets.symmetric(horizontal: 32, vertical: 16);
}
}
double _getFontSize() {
switch (size) {
case ButtonSize.small:
return 14;
case ButtonSize.medium:
return 16;
case ButtonSize.large:
return 18;
}
}
double _getIconSize() {
switch (size) {
case ButtonSize.small:
return 18;
case ButtonSize.medium:
return 20;
case ButtonSize.large:
return 24;
}
}
double _getIndicatorSize() {
switch (size) {
case ButtonSize.small:
return 16;
case ButtonSize.medium:
return 20;
case ButtonSize.large:
return 24;
}
}
}
enum ButtonType { primary, secondary, text, danger }
enum ButtonSize { small, medium, large }