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

274 lines
6.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:mobile_monitoring/core/constants/colors.dart';
/// Custom Switch - Switch widget yang reusable
class CustomSwitch extends StatelessWidget {
final bool value;
final ValueChanged<bool>? onChanged;
final Color? activeColor;
final Color? inactiveColor;
const CustomSwitch({
super.key,
required this.value,
this.onChanged,
this.activeColor,
this.inactiveColor,
});
@override
Widget build(BuildContext context) {
return Switch(
value: value,
onChanged: onChanged,
activeTrackColor: activeColor ?? AppColors.primary,
inactiveThumbColor: inactiveColor ?? AppColors.mediumGray,
);
}
}
/// Labeled Switch - Switch dengan label
class LabeledSwitch extends StatelessWidget {
final String label;
final bool value;
final ValueChanged<bool>? onChanged;
final String? description;
final IconData? icon;
const LabeledSwitch({
super.key,
required this.label,
required this.value,
this.onChanged,
this.description,
this.icon,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onChanged != null ? () => onChanged!(!value) : null,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: Row(
children: [
if (icon != null) ...[
Icon(
icon,
color: AppColors.textSecondary,
size: 24,
),
const SizedBox(width: 12),
],
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: AppColors.textPrimary,
),
),
if (description != null) ...[
const SizedBox(height: 4),
Text(
description!,
style: const TextStyle(
fontSize: 12,
color: AppColors.textSecondary,
),
),
],
],
),
),
CustomSwitch(
value: value,
onChanged: onChanged,
),
],
),
),
);
}
}
/// Custom Checkbox - Checkbox yang reusable
class CustomCheckbox extends StatelessWidget {
final bool value;
final ValueChanged<bool?>? onChanged;
final Color? activeColor;
const CustomCheckbox({
super.key,
required this.value,
this.onChanged,
this.activeColor,
});
@override
Widget build(BuildContext context) {
return Checkbox(
value: value,
onChanged: onChanged,
activeColor: activeColor ?? AppColors.primary,
);
}
}
/// Labeled Checkbox - Checkbox dengan label
class LabeledCheckbox extends StatelessWidget {
final String label;
final bool value;
final ValueChanged<bool?>? onChanged;
const LabeledCheckbox({
super.key,
required this.label,
required this.value,
this.onChanged,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onChanged != null ? () => onChanged!(!value) : null,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
CustomCheckbox(
value: value,
onChanged: onChanged,
),
const SizedBox(width: 8),
Expanded(
child: Text(
label,
style: const TextStyle(
fontSize: 14,
color: AppColors.textPrimary,
),
),
),
],
),
),
);
}
}
/// Custom Radio - Radio button yang reusable
class CustomRadio<T> extends StatefulWidget {
final T value;
final T initialGroupValue;
final ValueChanged<T>? onChanged;
final Color? activeColor;
const CustomRadio({
super.key,
required this.value,
required this.initialGroupValue,
this.onChanged,
this.activeColor,
});
@override
State<CustomRadio<T>> createState() => _CustomRadioState<T>();
}
class _CustomRadioState<T> extends State<CustomRadio<T>> {
late T _groupValue;
@override
void initState() {
super.initState();
_groupValue = widget.initialGroupValue;
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onChanged != null ? () {
setState(() {
_groupValue = widget.value;
});
widget.onChanged!(widget.value);
} : null,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: _groupValue == widget.value
? (widget.activeColor ?? AppColors.primary)
: AppColors.borderDark,
width: 2,
),
),
child: _groupValue == widget.value
? Center(
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: widget.activeColor ?? AppColors.primary,
),
),
)
: null,
),
);
}
}
/// Labeled Radio - Radio button dengan label
class LabeledRadio<T> extends StatelessWidget {
final String label;
final T value;
final T initialGroupValue;
final ValueChanged<T>? onChanged;
const LabeledRadio({
super.key,
required this.label,
required this.value,
required this.initialGroupValue,
this.onChanged,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onChanged != null ? () => onChanged!(value) : null,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
children: [
CustomRadio<T>(
value: value,
initialGroupValue: initialGroupValue,
onChanged: onChanged,
),
const SizedBox(width: 8),
Expanded(
child: Text(
label,
style: const TextStyle(
fontSize: 14,
color: AppColors.textPrimary,
),
),
),
],
),
),
);
}
}