habitrack/app/lib/function_widgets/compound_widgets/compound_widget_water.dart
2024-08-26 00:34:20 +02:00

491 lines
18 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:habitrack_app/function_widgets/widget_settings_menu/setting_entry.dart';
import 'package:habitrack_app/function_widgets/widget_settings_menu/widget_settings.dart';
import 'package:habitrack_app/infrastructure/widget_wall/items_controller.dart';
import 'package:habitrack_app/infrastructure/widget_wall/items_state.dart';
import 'package:habitrack_app/main.dart';
import 'package:habitrack_app/sembast/hydration.dart';
import 'package:liquid_progress_indicator_v2/liquid_progress_indicator.dart';
// ignore: must_be_immutable
class CompoundWidgetWater extends ConsumerStatefulWidget {
CompoundWidgetWater({required this.item, super.key});
late Hydration item;
double getProgress() {
return item.current / item.goal;
}
@override
ConsumerState<CompoundWidgetWater> createState() =>
_CompoundWidgetWaterState();
}
class _CompoundWidgetWaterState extends ConsumerState<CompoundWidgetWater> {
void _toggleExpansion() {
setState(() {
widget.item = widget.item.copyWith(isExpanded: !widget.item.isExpanded);
ref.watch(homeControllerProvider).edit(widget.item);
});
}
void _addQuantity(int toAdd) {
setState(() {
final controller = ref.watch(homeControllerProvider);
final oldval = widget.item.current;
logger.i('Old item: ${widget.item}');
widget.item = widget.item.copyWith(current: oldval + toAdd);
logger.i('New item: ${widget.item}');
controller.edit(widget.item);
});
}
@override
Widget build(BuildContext context) {
ref.watch(itemsProvider);
return Container(
margin: const EdgeInsets.only(left: 10, top: 10, right: 10, bottom: 10),
padding: const EdgeInsets.only(left: 10, top: 15, right: 10, bottom: 15),
//height: 100,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary,
borderRadius: const BorderRadius.all(Radius.circular(7)),
boxShadow: [
BoxShadow(
color: const Color(0x00000000).withOpacity(0.25),
spreadRadius: 2,
blurRadius: 5,
// changes position of shadow
),
],
),
width: double.infinity,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
if (!widget.item.isExpanded) ...[
Icon(
Icons.local_drink,
size: 20,
color: Theme.of(context).colorScheme.onPrimary,
),
Expanded(
flex: 2,
child: Container(
margin: const EdgeInsets.only(left: 10, right: 10),
// Width of the progress bar
height: 30, // Height of the progress bar
child: ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(5),
), // Rounded corners
child: LinearProgressIndicator(
value:
widget.getProgress(), // Progress value (0.0 - 1.0)
backgroundColor:
Colors.grey.withOpacity(0.5), // Background color
valueColor: const AlwaysStoppedAnimation<Color>(
Color(0xffA4E8FD),
), // Progress color
),
),
),
),
Expanded(
child: Text(
widget.item.name,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
],
if (widget.item.isExpanded) ...[
Expanded(
child: Text(
widget.item.name,
textScaler: const TextScaler.linear(2),
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
Expanded(
flex: 0,
child: IconButton(
icon: Icon(
Icons.settings,
color: Theme.of(context).colorScheme.onPrimary,
),
onPressed: () => _showSettingsMenu(ref),
),
//child: Icon(Icons.arrow_drop_down_circle_outlined),
),
],
Expanded(
flex: 0,
child: IconButton(
icon: Icon(
widget.item.isExpanded
? Icons.arrow_drop_up_outlined
: Icons.arrow_drop_down_circle_outlined,
color: Theme.of(context).colorScheme.onPrimary,
),
onPressed: _toggleExpansion,
),
//child: Icon(Icons.arrow_drop_down_circle_outlined),
),
],
),
if (widget.item.isExpanded) ...[
// Additional child elements when expanded
SizedBox(
height: 300,
width: MediaQuery.of(context).size.width,
child: Column(
children: [
//INSERT WIDGET SPECIFIC STUFF HERE
SizedBox(
height: 300,
width: MediaQuery.of(context).size.width,
child: Row(
children: [
Expanded(
child: OvershootLiquidLinearProgressIndicator(
current: widget.item.current,
goal: widget.item.goal,
),
),
Expanded(
child: Column(
children: [
Text(
'${widget.item.current / 1000} / ${widget.item.goal / 1000} L',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: Theme.of(context)
.colorScheme
.onPrimary,
),
),
Expanded(
child: OutlinedButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
Theme.of(context).colorScheme.secondary,
),
),
onPressed: () => {
_addQuantity(
widget.item.button1Amount,
),
},
child: Text(
'${widget.item.button1Amount} mL',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: Theme.of(context)
.colorScheme
.onSecondary,
),
),
),
),
Expanded(
child: OutlinedButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
Theme.of(context).colorScheme.secondary,
),
),
onPressed: () => {
_addQuantity(
widget.item.button2Amount,
),
},
child: Text(
'${widget.item.button2Amount} mL',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: Theme.of(context)
.colorScheme
.onPrimary,
),
),
),
),
Expanded(
child: OutlinedButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(
Theme.of(context).colorScheme.secondary,
),
),
onPressed: _showPopupCustomAmount,
child: Text(
AppLocalizations.of(context)!
.waterWidget_customAmountButton,
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(
color: Theme.of(context)
.colorScheme
.onPrimary,
),
),
),
),
],
),
),
],
),
),
],
),
),
// Add more widgets here as needed
],
],
),
);
}
Future<void> _showSettingsMenu(WidgetRef ref) async {
final settingEntries = WidgetSettingsData(
entries: {
'name': SettingEntryText(
name: AppLocalizations.of(context)!.widgetSettings_name,
defaultValue: widget.item.name,
),
'button1Amount': SettingEntryNumeric(
name: AppLocalizations.of(context)!.waterWidgetSettings_button1,
defaultValue: widget.item.button1Amount,
),
'button2Amount': SettingEntryNumeric(
name: AppLocalizations.of(context)!.waterWidgetSettings_button2,
defaultValue: widget.item.button2Amount,
),
'targetGoal': SettingEntrySlider(
name: AppLocalizations.of(context)!.waterWidgetSettings_goal,
defaultValue: double.parse(widget.item.goal.toString()),
divisions: 80,
topValue: 4000,
),
'currentAmount': SettingEntryNumeric(
name: AppLocalizations.of(context)!.waterWidgetSettings_current,
defaultValue: widget.item.current,
),
},
);
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
content: WidgetSettings(
entries: settingEntries,
),
actions: [
OutlinedButton(
style: OutlinedButton.styleFrom(
backgroundColor: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: () {
//widget.parent.delete(ref);
ref.watch(itemsProvider);
final controller = ref.watch(homeControllerProvider);
widget.item = widget.item.copyWith(isVisible: false);
controller.edit(widget.item);
logger.i('Attempting delete');
// ignore: use_build_context_synchronously
Navigator.of(context).pop();
},
child: Text(
AppLocalizations.of(context)!.widgetSettings_deleteButton,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
fontWeight: FontWeight.bold,
),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.onPrimary,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: () {
final controller = ref.watch(homeControllerProvider);
logger.i('Attempting edit of water widget stuff');
// widget.settingEntries.notify();
final name = settingEntries.getValue('name') as String;
final currentAmount =
settingEntries.getValue('currentAmount') as int;
final targetGoal =
(settingEntries.getValue('targetGoal') as double).round();
final button1Amount =
settingEntries.getValue('button1Amount') as int;
final button2Amount =
settingEntries.getValue('button2Amount') as int;
widget.item = widget.item.copyWith(
name: name,
current: currentAmount,
goal: targetGoal,
button1Amount: button1Amount,
button2Amount: button2Amount,
);
controller.edit(widget.item);
Navigator.of(context).pop();
},
child: Text(
AppLocalizations.of(context)!.widgetSettings_saveButton,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.bold,
),
),
),
],
);
},
);
}
Future<void> _showPopupCustomAmount() async {
final customFieldController = TextEditingController();
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
scrollable: true,
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
title: Text(
AppLocalizations.of(context)!.waterWidget_customAmountMessage,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimaryContainer,
),
),
content: Column(
children: <Widget>[
TextField(
controller: customFieldController,
keyboardType: TextInputType.number,
autofocus: true,
),
],
),
actions: <Widget>[
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
backgroundColor: Theme.of(context).colorScheme.primary,
),
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
AppLocalizations.of(context)!.widgetSettings_cancelButton,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primary,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: () {
Navigator.of(context).pop();
final result = int.tryParse(customFieldController.text) ?? 0;
_addQuantity(result);
},
child: Text(
AppLocalizations.of(context)!.widgetSettings_saveButton,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
],
);
},
);
}
}
class OvershootLiquidLinearProgressIndicator extends StatelessWidget {
const OvershootLiquidLinearProgressIndicator({
required this.current,
required this.goal,
super.key,
});
final int current;
final int goal;
@override
Widget build(BuildContext context) {
var mainColor = Colors.blue;
var backColor = Colors.white;
var value = 0.0;
if (current < goal) {
mainColor = Colors.blue;
backColor = Colors.white;
value = (current - goal * 0) / goal;
} else if (current < goal * 2) {
mainColor = Colors.orange;
backColor = Colors.blue;
value = (current - goal * 1) / goal;
} else {
mainColor = Colors.red;
backColor = Colors.orange;
value = (current - goal * 2) / goal;
}
return LiquidLinearProgressIndicator(
value: value,
valueColor: AlwaysStoppedAnimation(
mainColor,
),
backgroundColor: backColor,
borderColor: Colors.black,
borderWidth: 3,
borderRadius: 12,
direction: Axis.vertical,
);
}
}