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

211 lines
5.3 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 Card - Card container yang reusable
class CustomCard extends StatelessWidget {
final Widget child;
final EdgeInsetsGeometry? padding;
final EdgeInsetsGeometry? margin;
final Color? backgroundColor;
final double? elevation;
final double? borderRadius;
final Border? border;
final VoidCallback? onTap;
final List<BoxShadow>? boxShadow;
const CustomCard({
super.key,
required this.child,
this.padding,
this.margin,
this.backgroundColor,
this.elevation,
this.borderRadius,
this.border,
this.onTap,
this.boxShadow,
});
@override
Widget build(BuildContext context) {
final cardContent = Container(
padding: padding ?? const EdgeInsets.all(16),
decoration: BoxDecoration(
color: backgroundColor ?? AppColors.white,
borderRadius: BorderRadius.circular(
borderRadius ?? AppSettings.defaultBorderRadius,
),
border: border,
boxShadow: boxShadow ?? [
if (elevation != null && elevation! > 0)
BoxShadow(
color: AppColors.shadow,
blurRadius: elevation! * 2,
spreadRadius: elevation! / 2,
offset: Offset(0, elevation! / 2),
),
],
),
child: child,
);
if (onTap != null) {
return Padding(
padding: margin ?? const EdgeInsets.all(8),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(
borderRadius ?? AppSettings.defaultBorderRadius,
),
child: cardContent,
),
),
);
}
return Padding(
padding: margin ?? const EdgeInsets.all(8),
child: cardContent,
);
}
}
/// Stat Card - Card untuk menampilkan statistik
class StatCard extends StatelessWidget {
final String title;
final String value;
final String? subtitle;
final IconData? icon;
final Color? iconColor;
final Color? backgroundColor;
final VoidCallback? onTap;
const StatCard({
super.key,
required this.title,
required this.value,
this.subtitle,
this.icon,
this.iconColor,
this.backgroundColor,
this.onTap,
});
@override
Widget build(BuildContext context) {
return CustomCard(
onTap: onTap,
backgroundColor: backgroundColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (icon != null)
Icon(
icon,
color: iconColor ?? AppColors.primary,
size: 32,
),
const SizedBox(height: 8),
Text(
title,
style: const TextStyle(
fontSize: 14,
color: AppColors.textSecondary,
),
),
const SizedBox(height: 4),
Text(
value,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: AppColors.textPrimary,
),
),
if (subtitle != null) ...[
const SizedBox(height: 4),
Text(
subtitle!,
style: const TextStyle(
fontSize: 12,
color: AppColors.textSecondary,
),
),
],
],
),
);
}
}
/// Info Card - Card untuk menampilkan informasi dengan icon
class InfoCard extends StatelessWidget {
final String title;
final String description;
final IconData icon;
final Color? iconColor;
final Color? backgroundColor;
final VoidCallback? onTap;
const InfoCard({
super.key,
required this.title,
required this.description,
required this.icon,
this.iconColor,
this.backgroundColor,
this.onTap,
});
@override
Widget build(BuildContext context) {
return CustomCard(
onTap: onTap,
backgroundColor: backgroundColor,
child: Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: (iconColor ?? AppColors.primary).withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
icon,
color: iconColor ?? AppColors.primary,
size: 24,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
),
),
const SizedBox(height: 4),
Text(
description,
style: const TextStyle(
fontSize: 14,
color: AppColors.textSecondary,
),
),
],
),
),
],
),
);
}
}