From c6ceab66bc334110e49ab29c09ed5fcbefe1303e Mon Sep 17 00:00:00 2001 From: Momshad Dinury Date: Mon, 12 Sep 2022 18:01:55 +0600 Subject: [PATCH 1/3] chore: alert dialog implementation --- .../alert_dialogs/alert_dialog_impl.dart | 64 +++++++++++++++++ .../widgets/alert_dialogs/alert_dialogs.dart | 72 +++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 lib/src/widgets/alert_dialogs/alert_dialog_impl.dart create mode 100644 lib/src/widgets/alert_dialogs/alert_dialogs.dart diff --git a/lib/src/widgets/alert_dialogs/alert_dialog_impl.dart b/lib/src/widgets/alert_dialogs/alert_dialog_impl.dart new file mode 100644 index 0000000..26d7809 --- /dev/null +++ b/lib/src/widgets/alert_dialogs/alert_dialog_impl.dart @@ -0,0 +1,64 @@ +import 'package:exerlog/src/core/theme/app_theme.dart'; +import 'package:exerlog/src/widgets/theme/theme_provider.dart'; +import 'package:flutter/material.dart'; + +@immutable +class AlertDialogModel { + const AlertDialogModel({ + required this.title, + this.subtitle, + this.content, + required this.buttons, + }); + + final String title; + final String? subtitle; + final Widget? content; + final Map buttons; +} + +extension Present on AlertDialogModel { + Future present(BuildContext context, {bool barrierDismissible = true}) { + return showDialog( + context: context, + barrierDismissible: barrierDismissible, + builder: (context) { + return ThemeProvider(builder: (context, AppTheme theme) { + return AlertDialog( + backgroundColor: theme.colorTheme.backgroundColorVariation, + titleTextStyle: Theme.of(context) + .textTheme + .headline6 + ?.copyWith(color: theme.colorTheme.white), + contentTextStyle: Theme.of(context) + .textTheme + .subtitle1 + ?.copyWith(color: theme.colorTheme.white.withOpacity(0.5)), + title: Text(title), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (subtitle != null) Text(subtitle!), + if (content != null) content!, + ], + ), + actions: buttons.entries.map( + (entry) { + return TextButton( + style: TextButton.styleFrom( + primary: theme.colorTheme.white, + ), + child: Text(entry.key), + onPressed: () { + Navigator.of(context).pop(entry.value); + }, + ); + }, + ).toList(), + ); + }); + }, + ); + } +} diff --git a/lib/src/widgets/alert_dialogs/alert_dialogs.dart b/lib/src/widgets/alert_dialogs/alert_dialogs.dart new file mode 100644 index 0000000..2d35688 --- /dev/null +++ b/lib/src/widgets/alert_dialogs/alert_dialogs.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +import 'alert_dialog_impl.dart'; + +/// Delete workout dialog +@immutable +class _DeleteDialog extends AlertDialogModel { + const _DeleteDialog({required String objName}) + : super( + title: 'Delete $objName', + subtitle: 'Are you sure you want to delete this $objName?', + buttons: const { + 'CANCEL': false, + 'DELETE': true, + }, + ); +} + +Future showDeleteWorkoutDialog(BuildContext context) { + return const _DeleteDialog(objName: 'workout').present(context).then( + (value) => value ?? false, + ); +} + +/// Add new exercise dialog +@immutable +class _AddNewExerciseDialog extends AlertDialogModel { + _AddNewExerciseDialog({required String objName, Widget? content}) + : super( + title: 'New $objName', + subtitle: + 'You can add a new exercise name or select from a existing one', + content: content, + buttons: const { + 'CANCEL': false, + 'ADD': true, + }, + ); +} + +Future showAddNewExerciseDialog(BuildContext context, Widget? content) { + return _AddNewExerciseDialog( + objName: 'Exercise', + content: content, + ).present(context, barrierDismissible: false).then( + (value) => value ?? false, + ); +} + +/// View or Redo Exercise +@immutable +class _ViewOrRedoExerciseDialog extends AlertDialogModel { + _ViewOrRedoExerciseDialog({required String objName}) + : super( + title: 'Previous $objName', + subtitle: 'Do you want to view or redo?', + buttons: const { + 'VIEW': false, + 'REDO': true, + }, + ); +} + +Future showViewOrRedoAlertDialog(BuildContext context) { + return _ViewOrRedoExerciseDialog( + objName: 'workout', + ).present(context, barrierDismissible: false).then( + (value) => value ?? false, + ); +} + + From 061f2936786a2b9aeafae3e90deb0e532621680a Mon Sep 17 00:00:00 2001 From: Momshad Dinury Date: Mon, 12 Sep 2022 18:07:38 +0600 Subject: [PATCH 2/3] chore: alert dialog widget implementation used, unused code removed, organised --- lib/UI/exercise/add_exercise_widget.dart | 92 +++++---- lib/UI/exercise/add_new_exercise_alert.dart | 3 +- lib/UI/prev_workout/prev_workout_page.dart | 198 +++----------------- lib/UI/workout/workout_page.dart | 44 ++--- 4 files changed, 80 insertions(+), 257 deletions(-) diff --git a/lib/UI/exercise/add_exercise_widget.dart b/lib/UI/exercise/add_exercise_widget.dart index 6347be2..11aa789 100644 --- a/lib/UI/exercise/add_exercise_widget.dart +++ b/lib/UI/exercise/add_exercise_widget.dart @@ -4,73 +4,71 @@ import 'package:exerlog/src/widgets/theme/theme_provider.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -class ExerciseNameSelectionWidget extends StatefulWidget { - Function(String) setExercisename; +class ExerciseInputField extends StatefulWidget { + ExerciseInputField({ + required this.setExerciseName, + }); + + final Function(String) setExerciseName; - ExerciseNameSelectionWidget({ - required this.setExercisename, - }) { - setExercisename = this.setExercisename; - } @override - _ExerciseNameSelectionWidgetState createState() => _ExerciseNameSelectionWidgetState(); + _ExerciseInputFieldState createState() => _ExerciseInputFieldState(); } -class _ExerciseNameSelectionWidgetState extends State { +class _ExerciseInputFieldState extends State { @override Widget build(BuildContext context) { return ThemeProvider( builder: (context, theme) { return FutureBuilder>( future: getExerciseNames(), - builder: (BuildContext context, AsyncSnapshot> snapshot) { + builder: + (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { - return Center( - child: CircularProgressIndicator(), - ); + return Center(child: CircularProgressIndicator()); } else { if (snapshot.hasError) { - return Center( - child: Text("Error"), - ); + return Center(child: Text("Error")); } else { return Center( - child: Theme( - data: ThemeData( - inputDecorationTheme: new InputDecorationTheme( - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: theme.colorTheme.primaryColor, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Theme( + data: ThemeData( + inputDecorationTheme: InputDecorationTheme( + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: theme.colorTheme.primaryColor, + ), ), - // when the TextFormField in unfocused - ), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: theme.colorTheme.primaryColor, + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: theme.colorTheme.primaryColor, + ), + ), + border: UnderlineInputBorder( + borderSide: BorderSide( + color: theme.colorTheme.primaryColor, + ), ), - // when the TextFormField in focused - ), - border: UnderlineInputBorder( - borderSide: BorderSide(color: theme.colorTheme.primaryColor), ), + textTheme: TextTheme(subtitle1: setStyle), + ), + child: Autocomplete( + optionsMaxHeight: 100, + onSelected: widget.setExerciseName, + optionsBuilder: (TextEditingValue textEditingValue) { + widget.setExerciseName(textEditingValue.text); + return snapshot.data!.where( + (String name) => name.toLowerCase().startsWith( + textEditingValue.text.toLowerCase(), + ), + ); + }, ), - textTheme: TextTheme( - subtitle1: setStyle, - )), - child: Container( - child: Autocomplete( - optionsMaxHeight: 100, - onSelected: (value) { - widget.setExercisename(value); - }, - optionsBuilder: (TextEditingValue textEditingValue) { - widget.setExercisename(textEditingValue.text); - return snapshot.data!.where((String name) => name.toLowerCase().startsWith( - textEditingValue.text.toLowerCase(), - )); - }, ), - ), + ], ), ); } diff --git a/lib/UI/exercise/add_new_exercise_alert.dart b/lib/UI/exercise/add_new_exercise_alert.dart index 3c0e889..e69e5cd 100644 --- a/lib/UI/exercise/add_new_exercise_alert.dart +++ b/lib/UI/exercise/add_new_exercise_alert.dart @@ -4,8 +4,9 @@ import 'package:exerlog/src/widgets/gradient_button.dart'; import 'package:exerlog/src/widgets/theme/theme_provider.dart'; import 'package:flutter/material.dart'; +@Deprecated('This is going to be removed soon') class AddExerciseAlert extends StatelessWidget { - final ExerciseNameSelectionWidget nameWidget; + final ExerciseInputField nameWidget; final RaisedGradientButton addExercise; const AddExerciseAlert( diff --git a/lib/UI/prev_workout/prev_workout_page.dart b/lib/UI/prev_workout/prev_workout_page.dart index b218ee6..5af7fe1 100644 --- a/lib/UI/prev_workout/prev_workout_page.dart +++ b/lib/UI/prev_workout/prev_workout_page.dart @@ -1,17 +1,10 @@ import 'package:exerlog/Bloc/workout_bloc.dart'; -import 'package:exerlog/Models/exercise.dart'; import 'package:exerlog/Models/prev_workout_data.dart'; import 'package:exerlog/Models/workout.dart'; -import 'package:exerlog/UI/exercise/add_exercise_widget.dart'; -import 'package:exerlog/UI/exercise/add_new_exercise_alert.dart'; import 'package:exerlog/UI/global.dart'; -import 'package:exerlog/UI/gradient_border_button.dart'; -import 'package:exerlog/UI/prev_workout/delete_prev_workout_dialog.dart'; -import 'package:exerlog/UI/workout/redo_workout_alert.dart'; -import 'package:exerlog/UI/workout/save_workout_dialog.dart'; import 'package:exerlog/UI/workout/workout_page.dart'; import 'package:exerlog/UI/workout/workout_toatals_widget.dart'; -import 'package:exerlog/src/widgets/gradient_button.dart'; +import 'package:exerlog/src/widgets/alert_dialogs/alert_dialogs.dart'; import 'package:exerlog/src/widgets/theme/theme_provider.dart'; import 'package:flutter/material.dart'; @@ -27,13 +20,11 @@ class PrevWorkoutPage extends StatefulWidget { class _PrevWorkoutPageState extends State { late WorkoutTotalsWidget workoutTotalsWidget; late PrevWorkoutData workoutData; - String exerciseName = ''; late bool firstLoad; late Workout newWorkout; @override void initState() { - print("init"); firstLoad = true; newWorkout = new Workout( [], @@ -50,7 +41,6 @@ class _PrevWorkoutPageState extends State { newWorkout.id = widget.workout.id; - // TODO: implement initState workoutData = new PrevWorkoutData( newWorkout, new WorkoutTotals(0, 0, 0, 0, 0), @@ -64,11 +54,10 @@ class _PrevWorkoutPageState extends State { @override Widget build(BuildContext context) { if (firstLoad) { - Future.delayed(Duration.zero, () => showAlertDialogWorkout(context)); + Future.delayed(Duration.zero, () => _showViewOrRedoAlertDialog(context)); } screenHeight = MediaQuery.of(context).size.height; screenWidth = MediaQuery.of(context).size.width; - //workoutData.workout = workout; workoutTotalsWidget = new WorkoutTotalsWidget(totals: workoutData.totals); return ThemeProvider( builder: (context, theme) { @@ -84,7 +73,7 @@ class _PrevWorkoutPageState extends State { actions: [ TextButton( onPressed: () { - showDeleteWorkoutAlertDialog(context); + _showDeleteWorkoutDialog(context); }, child: Icon( Icons.delete, @@ -108,7 +97,6 @@ class _PrevWorkoutPageState extends State { ), Expanded( child: Container( - //height: screenHeight * 0.5, child: ListView( addAutomaticKeepAlives: true, children: workoutData.exerciseWidgets, @@ -126,134 +114,24 @@ class _PrevWorkoutPageState extends State { ); } - setExercisename(name) { - exerciseName = name; - } - - setWorkout(name, template) { - workoutData.workout.name = name; - workoutData.workout.template = template; - } - - updateTotals(newWorkout) { + void updateTotals(newWorkout) { setState(() { firstLoad = false; - //workoutData.workout = new_workout; - //workout = new_workout; - //print(workoutData.exerciseWidgets[0].setList.length); }); } - showAlertDialogExercise(BuildContext context) { - ExerciseNameSelectionWidget exerciseNameSelectionWidget = - new ExerciseNameSelectionWidget( - setExercisename: setExercisename, - ); - // set up the button - RaisedGradientButton okButton = RaisedGradientButton( - radius: 30, - child: Text( - "ADD", - style: buttonTextSmall, - ), - onPressed: () { - if (exerciseName != '') { - setState(() { - workoutData - .addExercise(new Exercise(exerciseName, [], [], 0, 0, 0.0)); - workoutData.setExerciseWidgets(); - }); - Navigator.pop(context); - } - }, - ); - - // set up the AlertDialog - AddExerciseAlert alert = - AddExerciseAlert(okButton, exerciseNameSelectionWidget); - - // show the dialog - showDialog( - context: context, - builder: (BuildContext context) { - return alert; - }, - ); - } - - addNewSet(exercise, newSet, id) { + void addNewSet(exercise, newSet, id) { workoutData.addSet(exercise, newSet, id); } - createNewSet(sets, id) {} - - showSaveWorkoutAlertDialog(BuildContext context) { - RaisedGradientButton okButton = RaisedGradientButton( - radius: 30, - child: Text( - "SAVE", - style: buttonTextSmall, - ), - onPressed: () { - saveWorkout(workoutData.workout); - setState(() { - firstLoad = true; - workoutData = new PrevWorkoutData( - new Workout([], '', '', 0, '', '', false, 0, 0.0, 0), - new WorkoutTotals(0, 0, 0, 0, 0), - updateTotals, - addNewSet, - ); - }); - }, - ); - - // set up the AlertDialog - SaveWorkoutAlert alert = SaveWorkoutAlert(okButton, setWorkout); - - // show the dialog - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return alert; - }, - ); - } - - showDeleteWorkoutAlertDialog(BuildContext context) { - RaisedGradientButton okButton = RaisedGradientButton( - radius: 30, - child: Text( - "DELETE", - style: buttonTextSmall, - ), - onPressed: () { - deleteWorkout(workoutData.workout); - Navigator.of(context) - ..pop() - ..pop(); - }, - ); - - // set up the AlertDialog - DeleteWorkoutAlert alert = DeleteWorkoutAlert(okButton); - - // show the dialog - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return alert; - }, - ); - } - - setWorkoutName(name) { - workoutData.workout.name = name; + void _showDeleteWorkoutDialog(BuildContext context) async { + if (await showDeleteWorkoutDialog(context)) { + deleteWorkout(workoutData.workout); + Navigator.of(context).pop(); + } } - addExercises(newWorkout) { + void addExercises(newWorkout) { setState(() { PrevWorkoutData newWorkoutData = new PrevWorkoutData( newWorkout, @@ -264,52 +142,18 @@ class _PrevWorkoutPageState extends State { firstLoad = false; workoutData = newWorkoutData; newWorkout = newWorkoutData.workout; - //print(workoutData.workout.exercises[0]); }); } - showAlertDialogWorkout(BuildContext context) { - RaisedGradientButton viewButton = RaisedGradientButton( - radius: 30, - child: Text( - "VIEW", - style: buttonTextSmall, - ), - onPressed: () { - addExercises(widget.workout); - Navigator.pop(context); - }, - ); - - GradientBorderButton redoButton = GradientBorderButton( - addButton: false, - borderSize: 2, - radius: 30, - child: Text( - "REDO", - style: whiteTextStyleSmall, - ), - onPressed: () { - Navigator.of(context) - ..pop() - ..pushReplacement( - MaterialPageRoute( - builder: (context) => WorkoutPage(widget.workout), - ), - ); - }, - ); - - // set up the AlertDialog - RedoWorkoutAlert alert = RedoWorkoutAlert(viewButton, redoButton); - - // show the dialog - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return alert; - }, - ); + Future _showViewOrRedoAlertDialog(BuildContext context) async { + if (await showViewOrRedoAlertDialog(context)) { + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (context) => WorkoutPage(widget.workout), + ), + ); + } else { + addExercises(widget.workout); + } } } diff --git a/lib/UI/workout/workout_page.dart b/lib/UI/workout/workout_page.dart index 1f8e1ce..14d1b93 100644 --- a/lib/UI/workout/workout_page.dart +++ b/lib/UI/workout/workout_page.dart @@ -3,13 +3,13 @@ import 'package:exerlog/Models/exercise.dart'; import 'package:exerlog/Models/workout.dart'; import 'package:exerlog/Models/workout_data.dart'; import 'package:exerlog/UI/exercise/add_exercise_widget.dart'; -import 'package:exerlog/UI/exercise/add_new_exercise_alert.dart'; import 'package:exerlog/UI/global.dart'; import 'package:exerlog/UI/workout/add_new_workout_alert.dart'; import 'package:exerlog/UI/workout/save_workout_dialog.dart'; import 'package:exerlog/UI/workout/workout_name_selection_widget.dart'; import 'package:exerlog/UI/workout/workout_toatals_widget.dart'; import 'package:exerlog/src/core/theme/app_theme.dart'; +import 'package:exerlog/src/widgets/alert_dialogs/alert_dialogs.dart'; import 'package:exerlog/src/widgets/custom_floating_action_button.dart'; import 'package:exerlog/src/widgets/gradient_button.dart'; import 'package:exerlog/src/widgets/theme/theme_provider.dart'; @@ -83,7 +83,7 @@ class _WorkoutPageState extends State { backgroundColor: theme.colorTheme.backgroundColorVariation, floatingActionButton: CustomFloatingActionButton( icon: Icons.add, - onTap: () => showAlertDialogExercise(context), + onTap: () => _showAddNewExerciseDialog(context), ), resizeToAvoidBottomInset: true, appBar: AppBar( @@ -136,7 +136,7 @@ class _WorkoutPageState extends State { if (snapshot.data!.isEmpty) { firstLoad = false; Future.delayed(Duration.zero, - () => showAlertDialogExercise(context)); + () => _showAddNewExerciseDialog(context)); return getPage(theme); } else { firstLoad = false; @@ -198,6 +198,15 @@ class _WorkoutPageState extends State { setState(() {}); } + void _showAddNewExerciseDialog(BuildContext context) async { + ExerciseInputField exerciseNameSelectionWidget = + ExerciseInputField(setExerciseName: setExerciseName); + + if (await showAddNewExerciseDialog(context, exerciseNameSelectionWidget)) { + addExercise(); + } + } + void addExercise() { if (exerciseName != '') { workoutData.addExercise( @@ -210,38 +219,9 @@ class _WorkoutPageState extends State { 0.0, ), ); - Navigator.pop(context); } } - void showAlertDialogExercise(BuildContext context) { - ExerciseNameSelectionWidget exerciseNameSelectionWidget = - ExerciseNameSelectionWidget( - setExercisename: setExerciseName, - ); - // set up the button - RaisedGradientButton okButton = RaisedGradientButton( - child: Text( - "ADD", - style: buttonTextSmall, - ), - onPressed: addExercise, - ); - - /// Set up the AlertDialog - AddExerciseAlert alert = AddExerciseAlert( - okButton, - exerciseNameSelectionWidget, - ); - - showDialog( - context: context, - builder: (BuildContext context) { - return alert; - }, - ); - } - void showSaveWorkoutAlertDialog(BuildContext context) { RaisedGradientButton okButton = RaisedGradientButton( child: Text( From b2b873dae450420513cec584f933773d7e252168 Mon Sep 17 00:00:00 2001 From: Momshad Dinury Date: Mon, 12 Sep 2022 19:34:06 +0600 Subject: [PATCH 3/3] chore: unused widgets removed, refactored --- lib/UI/exercise/add_new_exercise_alert.dart | 50 ----- .../delete_prev_workout_dialog.dart | 52 ----- lib/UI/prev_workout/prev_workout_page.dart | 118 ++++++------ lib/UI/workout/save_workout_dialog.dart | 128 +++++-------- lib/UI/workout/workout_page.dart | 178 ++++++------------ .../widgets/alert_dialogs/alert_dialogs.dart | 46 +++-- 6 files changed, 202 insertions(+), 370 deletions(-) delete mode 100644 lib/UI/exercise/add_new_exercise_alert.dart delete mode 100644 lib/UI/prev_workout/delete_prev_workout_dialog.dart diff --git a/lib/UI/exercise/add_new_exercise_alert.dart b/lib/UI/exercise/add_new_exercise_alert.dart deleted file mode 100644 index e69e5cd..0000000 --- a/lib/UI/exercise/add_new_exercise_alert.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:exerlog/UI/exercise/add_exercise_widget.dart'; -import 'package:exerlog/UI/global.dart'; -import 'package:exerlog/src/widgets/gradient_button.dart'; -import 'package:exerlog/src/widgets/theme/theme_provider.dart'; -import 'package:flutter/material.dart'; - -@Deprecated('This is going to be removed soon') -class AddExerciseAlert extends StatelessWidget { - final ExerciseInputField nameWidget; - final RaisedGradientButton addExercise; - - const AddExerciseAlert( - this.addExercise, - this.nameWidget, - ); - @override - Widget build(BuildContext context) { - return ThemeProvider( - builder: (context, theme) { - return Dialog( - backgroundColor: theme.colorTheme.backgroundColorVariation, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), - child: Container( - padding: EdgeInsets.all(15), - height: screenHeight * 0.4, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "New Exercise", - style: mediumTitleStyleWhite, - textAlign: TextAlign.center, - ), - Container( - padding: EdgeInsets.only(left: 20, right: 20), - child: nameWidget, - ), - Container( - height: screenHeight * 0.05, - width: screenWidth * 0.5, - child: addExercise, - ), - ], - ), - ), - ); - }, - ); - } -} diff --git a/lib/UI/prev_workout/delete_prev_workout_dialog.dart b/lib/UI/prev_workout/delete_prev_workout_dialog.dart deleted file mode 100644 index db69319..0000000 --- a/lib/UI/prev_workout/delete_prev_workout_dialog.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:exerlog/UI/global.dart'; -import 'package:exerlog/src/widgets/gradient_button.dart'; -import 'package:exerlog/src/widgets/theme/theme_provider.dart'; -import 'package:flutter/material.dart'; - -class DeleteWorkoutAlert extends StatefulWidget { - final RaisedGradientButton deleteWorkoutButton; - - const DeleteWorkoutAlert(this.deleteWorkoutButton); - @override - _DeleteWorkoutAlertState createState() => _DeleteWorkoutAlertState(); -} - -class _DeleteWorkoutAlertState extends State { - String name = ''; - bool? template; - - @override - void initState() { - template = false; - super.initState(); - } - - @override - Widget build(BuildContext context) { - return ThemeProvider(builder: (context, theme) { - return Dialog( - backgroundColor: theme.colorTheme.backgroundColorVariation, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), - child: Container( - padding: EdgeInsets.all(15), - height: screenHeight * 0.4, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Are you sure you want to delete this workout?", - style: mediumTitleStyleWhite, - textAlign: TextAlign.center, - ), - Container( - height: screenHeight * 0.05, - width: screenWidth * 0.5, - child: widget.deleteWorkoutButton, - ), - ], - ), - ), - ); - }); - } -} diff --git a/lib/UI/prev_workout/prev_workout_page.dart b/lib/UI/prev_workout/prev_workout_page.dart index 5af7fe1..2ef6385 100644 --- a/lib/UI/prev_workout/prev_workout_page.dart +++ b/lib/UI/prev_workout/prev_workout_page.dart @@ -25,8 +25,13 @@ class _PrevWorkoutPageState extends State { @override void initState() { + _prefillWorkoutData(); + super.initState(); + } + + void _prefillWorkoutData() { firstLoad = true; - newWorkout = new Workout( + newWorkout = Workout( [], '', '', @@ -41,14 +46,12 @@ class _PrevWorkoutPageState extends State { newWorkout.id = widget.workout.id; - workoutData = new PrevWorkoutData( + workoutData = PrevWorkoutData( newWorkout, - new WorkoutTotals(0, 0, 0, 0, 0), + WorkoutTotals(0, 0, 0, 0, 0), updateTotals, addNewSet, ); - - super.initState(); } @override @@ -56,59 +59,52 @@ class _PrevWorkoutPageState extends State { if (firstLoad) { Future.delayed(Duration.zero, () => _showViewOrRedoAlertDialog(context)); } - screenHeight = MediaQuery.of(context).size.height; - screenWidth = MediaQuery.of(context).size.width; - workoutTotalsWidget = new WorkoutTotalsWidget(totals: workoutData.totals); return ThemeProvider( builder: (context, theme) { - return ThemeProvider( - builder: (context, theme) { - return Scaffold( - appBar: AppBar( - backgroundColor: theme.colorTheme.backgroundColorVariation, - leading: BackButton( - onPressed: Navigator.of(context).pop, + screenHeight = MediaQuery.of(context).size.height; + screenWidth = MediaQuery.of(context).size.width; + workoutTotalsWidget = WorkoutTotalsWidget(totals: workoutData.totals); + return Scaffold( + backgroundColor: theme.colorTheme.backgroundColorVariation, + appBar: AppBar( + backgroundColor: theme.colorTheme.backgroundColorVariation, + leading: BackButton( + onPressed: Navigator.of(context).pop, + color: theme.colorTheme.primaryColor, + ), + actions: [ + TextButton( + onPressed: () { + _showDeleteWorkoutDialog(context); + }, + child: Icon( + Icons.delete, color: theme.colorTheme.primaryColor, ), - actions: [ - TextButton( - onPressed: () { - _showDeleteWorkoutDialog(context); - }, - child: Icon( - Icons.delete, - color: theme.colorTheme.primaryColor, - ), - ) - ], - ), - body: firstLoad - ? Container( - color: theme.colorTheme.backgroundColorVariation, - ) - : GestureDetector( - child: Container( - color: theme.colorTheme.backgroundColorVariation, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - WorkoutTotalsWidget( - totals: workoutData.totals, - ), - Expanded( - child: Container( - child: ListView( - addAutomaticKeepAlives: true, - children: workoutData.exerciseWidgets, - ), - ), - ), - ], + ) + ], + ), + body: firstLoad + ? Container(color: theme.colorTheme.backgroundColorVariation) + : GestureDetector( + child: Container( + color: theme.colorTheme.backgroundColorVariation, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + WorkoutTotalsWidget( + totals: workoutData.totals, + ), + Expanded( + child: ListView( + addAutomaticKeepAlives: true, + children: workoutData.exerciseWidgets, + ), ), - ), + ], ), - ); - }, + ), + ), ); }, ); @@ -124,18 +120,11 @@ class _PrevWorkoutPageState extends State { workoutData.addSet(exercise, newSet, id); } - void _showDeleteWorkoutDialog(BuildContext context) async { - if (await showDeleteWorkoutDialog(context)) { - deleteWorkout(workoutData.workout); - Navigator.of(context).pop(); - } - } - void addExercises(newWorkout) { setState(() { - PrevWorkoutData newWorkoutData = new PrevWorkoutData( + PrevWorkoutData newWorkoutData = PrevWorkoutData( newWorkout, - new WorkoutTotals(0, 0, 0, 0, 0), + WorkoutTotals(0, 0, 0, 0, 0), updateTotals, addNewSet, ); @@ -156,4 +145,11 @@ class _PrevWorkoutPageState extends State { addExercises(widget.workout); } } + + Future _showDeleteWorkoutDialog(BuildContext context) async { + if (await showDeleteWorkoutDialog(context)) { + deleteWorkout(workoutData.workout); + Navigator.of(context).pop(); + } + } } diff --git a/lib/UI/workout/save_workout_dialog.dart b/lib/UI/workout/save_workout_dialog.dart index ffcbd7f..4e12199 100644 --- a/lib/UI/workout/save_workout_dialog.dart +++ b/lib/UI/workout/save_workout_dialog.dart @@ -1,104 +1,78 @@ import 'package:exerlog/UI/global.dart'; -import 'package:exerlog/src/widgets/gradient_button.dart'; import 'package:exerlog/src/widgets/theme/theme_provider.dart'; import 'package:flutter/material.dart'; -class SaveWorkoutAlert extends StatefulWidget { - final Function(String, bool) setWorkout; - final RaisedGradientButton saveWorkout; - - const SaveWorkoutAlert( - this.saveWorkout, +class SaveWorkoutContent extends StatefulWidget { + const SaveWorkoutContent( this.setWorkout, ); + + final Function(String, bool) setWorkout; + @override - _SaveWorkoutAlertState createState() => _SaveWorkoutAlertState(); + _SaveWorkoutContentState createState() => _SaveWorkoutContentState(); } -class _SaveWorkoutAlertState extends State { +class _SaveWorkoutContentState extends State { String name = ''; - bool? template; - - @override - void initState() { - template = false; - super.initState(); - } + bool template = false; @override Widget build(BuildContext context) { return ThemeProvider( builder: (context, theme) { - return Dialog( - backgroundColor: theme.colorTheme.backgroundColorVariation, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - child: Container( - padding: EdgeInsets.all(15), - height: screenHeight * 0.4, - child: Column( + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + style: setStyle, + onChanged: (value) { + name = value; + widget.setWorkout(name, template); + }, + decoration: InputDecoration( + hintText: 'Enter workout name', + hintStyle: setHintStyle, + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: theme.colorTheme.primaryColor, + ), + ), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: theme.colorTheme.primaryColor, + ), + ), + border: UnderlineInputBorder( + borderSide: BorderSide( + color: theme.colorTheme.primaryColor, + ), + ), + ), + ), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Save Workout", + 'Save as template', style: mediumTitleStyleWhite, - textAlign: TextAlign.center, ), - Container( - padding: EdgeInsets.only(left: 20, right: 20), - child: TextField( - style: setStyle, - onChanged: (value) { - name = value; - widget.setWorkout(name, template!); - }, - decoration: InputDecoration( - hintText: 'name your workout', - hintStyle: setHintStyle, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: theme.colorTheme.primaryColor), - // when the TextFormField in unfocused - ), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: theme.colorTheme.primaryColor), - // when the TextFormField in focused - ), - border: UnderlineInputBorder(borderSide: BorderSide(color: theme.colorTheme.primaryColor)), - ), - )), - Container( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - child: Text( - 'Save as template', - style: mediumTitleStyleWhite, - ), - ), - Checkbox( - fillColor: MaterialStateProperty.all(theme.colorTheme.primaryColor), - value: this.template, - onChanged: (bool? value) { - setState(() { - print(value); - template = value; - widget.setWorkout(name, template!); - }); - }, - ), - ], + Checkbox( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + fillColor: MaterialStateProperty.all( + theme.colorTheme.primaryColor, ), - ), - Container( - height: screenHeight * 0.05, - width: screenWidth * 0.5, - child: widget.saveWorkout, + value: this.template, + onChanged: (bool? value) { + setState(() { + template = value!; + widget.setWorkout(name, template); + }); + }, ), ], ), - ), + ], ); }, ); diff --git a/lib/UI/workout/workout_page.dart b/lib/UI/workout/workout_page.dart index 14d1b93..87fdc96 100644 --- a/lib/UI/workout/workout_page.dart +++ b/lib/UI/workout/workout_page.dart @@ -4,14 +4,11 @@ import 'package:exerlog/Models/workout.dart'; import 'package:exerlog/Models/workout_data.dart'; import 'package:exerlog/UI/exercise/add_exercise_widget.dart'; import 'package:exerlog/UI/global.dart'; -import 'package:exerlog/UI/workout/add_new_workout_alert.dart'; import 'package:exerlog/UI/workout/save_workout_dialog.dart'; -import 'package:exerlog/UI/workout/workout_name_selection_widget.dart'; import 'package:exerlog/UI/workout/workout_toatals_widget.dart'; import 'package:exerlog/src/core/theme/app_theme.dart'; import 'package:exerlog/src/widgets/alert_dialogs/alert_dialogs.dart'; import 'package:exerlog/src/widgets/custom_floating_action_button.dart'; -import 'package:exerlog/src/widgets/gradient_button.dart'; import 'package:exerlog/src/widgets/theme/theme_provider.dart'; import 'package:flutter/material.dart'; @@ -34,7 +31,6 @@ class _WorkoutPageState extends State { @override void initState() { _preFillWorkoutData(); - super.initState(); } @@ -93,27 +89,31 @@ class _WorkoutPageState extends State { color: theme.colorTheme.primaryColor, ), actions: [ - Container( - margin: EdgeInsets.only(right: 5), - height: 30, - width: 30, - child: CustomFloatingActionButton( - icon: Icons.done, - onTap: () { - for (Exercise exercise in workoutData.workout.exercises) { - for (int i = 0; i < exercise.sets.length; i++) { - if (exercise.sets[i].reps == 0) { - exercise.sets.remove(exercise.sets[i]); + Padding( + padding: const EdgeInsets.only(right: 16.0), + child: CircleAvatar( + backgroundColor: theme.colorTheme.primaryColor, + child: IconButton( + icon: Icon( + Icons.done, + color: Colors.black, + ), + onPressed: () { + for (Exercise exercise in workoutData.workout.exercises) { + for (int i = 0; i < exercise.sets.length; i++) { + if (exercise.sets[i].reps == 0) { + exercise.sets.remove(exercise.sets[i]); + } + } + if (exercise.sets.length == 0) { + workoutData.workout.exercises.remove(exercise); } } - if (exercise.sets.length == 0) { - workoutData.workout.exercises.remove(exercise); + if (workoutData.workout.exercises.length > 0) { + _showSaveWorkoutDialog(context); } - } - if (workoutData.workout.exercises.length > 0) { - showSaveWorkoutAlertDialog(context); - } - }, + }, + ), ), ), ], @@ -121,33 +121,31 @@ class _WorkoutPageState extends State { body: firstLoad ? FutureBuilder( future: getWorkoutTemplates(), - builder: (BuildContext context, - AsyncSnapshot> snapshot) { + builder: ( + BuildContext context, + AsyncSnapshot> snapshot, + ) { + /// Loading if (snapshot.connectionState == ConnectionState.waiting) { - return Center( - child: CircularProgressIndicator(), - ); - } else { - if (snapshot.hasError) { - return Center( - child: Text("Something went wrong"), - ); - } else { - if (snapshot.data!.isEmpty) { - firstLoad = false; - Future.delayed(Duration.zero, - () => _showAddNewExerciseDialog(context)); - return getPage(theme); - } else { - firstLoad = false; - workoutList = snapshot.data!; - Future.delayed(Duration.zero, - () => showAlertDialogWorkout(context)); - return getPage(theme); - } - } + return Center(child: CircularProgressIndicator()); + } + + /// Error + if (snapshot.hasError) { + return Center(child: Text("Something went wrong")); } - }) + + firstLoad = false; + if (snapshot.data!.isNotEmpty) workoutList = snapshot.data!; + Future.delayed( + Duration.zero, + () { + _showAddNewExerciseDialog(context); + }, + ); + return getPage(theme); + }, + ) : getPage(theme), ); }, @@ -157,12 +155,10 @@ class _WorkoutPageState extends State { Widget getPage(AppTheme theme) { return GestureDetector( onTap: () { - FocusScope.of(context).requestFocus(new FocusNode()); + FocusScope.of(context).requestFocus(FocusNode()); }, child: firstLoad - ? Container( - color: theme.colorTheme.backgroundColorVariation, - ) + ? Container(color: theme.colorTheme.backgroundColorVariation) : GestureDetector( child: Container( color: theme.colorTheme.backgroundColorVariation, @@ -198,15 +194,6 @@ class _WorkoutPageState extends State { setState(() {}); } - void _showAddNewExerciseDialog(BuildContext context) async { - ExerciseInputField exerciseNameSelectionWidget = - ExerciseInputField(setExerciseName: setExerciseName); - - if (await showAddNewExerciseDialog(context, exerciseNameSelectionWidget)) { - addExercise(); - } - } - void addExercise() { if (exerciseName != '') { workoutData.addExercise( @@ -222,35 +209,6 @@ class _WorkoutPageState extends State { } } - void showSaveWorkoutAlertDialog(BuildContext context) { - RaisedGradientButton okButton = RaisedGradientButton( - child: Text( - "SAVE", - style: buttonTextSmall, - ), - onPressed: () { - saveWorkout(workoutData.workout); - Navigator.of(context) - ..pop() - ..pop(); - }, - ); - - SaveWorkoutAlert alert = SaveWorkoutAlert(okButton, setWorkout); - - showDialog( - barrierDismissible: true, - context: context, - builder: (BuildContext context) { - return alert; - }, - ); - } - - void setWorkoutName(name) { - workoutData.workout.name = name; - } - void addExercises(newWorkout) { setState(() { WorkoutData newWorkoutData = WorkoutData( @@ -264,36 +222,20 @@ class _WorkoutPageState extends State { }); } - void showAlertDialogWorkout(BuildContext context) { - WorkoutTemplateSelectionWidget workoutTemplateSelectionWidget = - WorkoutTemplateSelectionWidget( - setWorkout: addExercises, - workoutList: workoutList, - ); - RaisedGradientButton okButton = RaisedGradientButton( - child: Text( - "START", - style: buttonTextSmall, - ), - onPressed: () { - setState(() { - firstLoad = false; - }); - Navigator.pop(context); - }, - ); + /// Alert Dialogs + void _showAddNewExerciseDialog(BuildContext context) async { + ExerciseInputField exerciseNameSelectionWidget = + ExerciseInputField(setExerciseName: setExerciseName); - AddWorkoutAlert alert = AddWorkoutAlert( - okButton, - workoutTemplateSelectionWidget, - ); + if (await showAddNewExerciseDialog(context, exerciseNameSelectionWidget)) { + addExercise(); + } + } - showDialog( - barrierDismissible: false, - context: context, - builder: (BuildContext context) { - return alert; - }, - ); + void _showSaveWorkoutDialog(BuildContext context) async { + if (await showSaveWorkoutDialog(context, SaveWorkoutContent(setWorkout))) { + saveWorkout(workoutData.workout); + Navigator.of(context).pop(); + } } } diff --git a/lib/src/widgets/alert_dialogs/alert_dialogs.dart b/lib/src/widgets/alert_dialogs/alert_dialogs.dart index 2d35688..57bcdbe 100644 --- a/lib/src/widgets/alert_dialogs/alert_dialogs.dart +++ b/lib/src/widgets/alert_dialogs/alert_dialogs.dart @@ -18,8 +18,8 @@ class _DeleteDialog extends AlertDialogModel { Future showDeleteWorkoutDialog(BuildContext context) { return const _DeleteDialog(objName: 'workout').present(context).then( - (value) => value ?? false, - ); + (value) => value ?? false, + ); } /// Add new exercise dialog @@ -43,8 +43,8 @@ Future showAddNewExerciseDialog(BuildContext context, Widget? content) { objName: 'Exercise', content: content, ).present(context, barrierDismissible: false).then( - (value) => value ?? false, - ); + (value) => value ?? false, + ); } /// View or Redo Exercise @@ -52,13 +52,13 @@ Future showAddNewExerciseDialog(BuildContext context, Widget? content) { class _ViewOrRedoExerciseDialog extends AlertDialogModel { _ViewOrRedoExerciseDialog({required String objName}) : super( - title: 'Previous $objName', - subtitle: 'Do you want to view or redo?', - buttons: const { - 'VIEW': false, - 'REDO': true, - }, - ); + title: 'Previous $objName', + subtitle: 'Do you want to view or redo?', + buttons: const { + 'VIEW': false, + 'REDO': true, + }, + ); } Future showViewOrRedoAlertDialog(BuildContext context) { @@ -66,7 +66,29 @@ Future showViewOrRedoAlertDialog(BuildContext context) { objName: 'workout', ).present(context, barrierDismissible: false).then( (value) => value ?? false, - ); + ); } +/// Save workout dialog +@immutable +class _SaveWorkoutDialog extends AlertDialogModel { + _SaveWorkoutDialog({required String objName, Widget? content}) + : super( + title: 'Save $objName', + subtitle: 'Save a workout by adding a name', + content: content, + buttons: const { + 'CANCEL': false, + 'SAVE': true, + }, + ); +} +Future showSaveWorkoutDialog(BuildContext context, Widget? content) { + return _SaveWorkoutDialog( + objName: 'workout', + content: content, + ).present(context, barrierDismissible: false).then( + (value) => value ?? false, + ); +}