From 5c2592f601d9fd8581e5a9f3c2bf684018f9b85f Mon Sep 17 00:00:00 2001 From: Andreas Fahrecker Date: Thu, 11 Feb 2021 23:38:02 +0100 Subject: [PATCH] Cleanup of Progress Detail Screen Signed-off-by: Andreas Fahrecker --- lib/screens/progress_detail_screen.dart | 191 +++++------------- lib/widgets/app_drawer_widget.dart | 129 ------------ lib/widgets/app_yes_no_dialog_widget.dart | 6 +- ...detail_screen_floating_action_buttons.dart | 87 ++++++++ ...ogress_detail_circular_percent_widget.dart | 21 -- ...progress_detail_edit_dates_row_widget.dart | 44 ---- ...rogress_detail_fab_editing_row_widget.dart | 35 ---- .../progress_detail_fab_row_widget.dart | 33 --- ...progress_detail_linear_percent_widget.dart | 24 --- ...rogress_detail_select_date_btn_widget.dart | 34 ---- 10 files changed, 139 insertions(+), 465 deletions(-) delete mode 100644 lib/widgets/app_drawer_widget.dart create mode 100644 lib/widgets/detail_screen_floating_action_buttons.dart delete mode 100644 lib/widgets/progress_detail_widgets/progress_detail_circular_percent_widget.dart delete mode 100644 lib/widgets/progress_detail_widgets/progress_detail_edit_dates_row_widget.dart delete mode 100644 lib/widgets/progress_detail_widgets/progress_detail_fab_editing_row_widget.dart delete mode 100644 lib/widgets/progress_detail_widgets/progress_detail_fab_row_widget.dart delete mode 100644 lib/widgets/progress_detail_widgets/progress_detail_linear_percent_widget.dart delete mode 100644 lib/widgets/progress_detail_widgets/progress_detail_select_date_btn_widget.dart diff --git a/lib/screens/progress_detail_screen.dart b/lib/screens/progress_detail_screen.dart index 20db694..2aafb43 100644 --- a/lib/screens/progress_detail_screen.dart +++ b/lib/screens/progress_detail_screen.dart @@ -6,9 +6,7 @@ import 'package:time_progress_tracker/models/app_state.dart'; import 'package:time_progress_tracker/models/time_progress.dart'; import 'package:time_progress_tracker/screens/home_screen.dart'; import 'package:time_progress_tracker/selectors/time_progress_selectors.dart'; -import 'package:time_progress_tracker/widgets/app_yes_no_dialog_widget.dart'; -import 'package:time_progress_tracker/widgets/progress_detail_widgets/progress_detail_fab_editing_row_widget.dart'; -import 'package:time_progress_tracker/widgets/progress_detail_widgets/progress_detail_fab_row_widget.dart'; +import 'package:time_progress_tracker/widgets/detail_screen_floating_action_buttons.dart'; import 'package:time_progress_tracker/widgets/progress_editor_widget.dart'; import 'package:time_progress_tracker/widgets/progress_view_widget.dart'; @@ -20,6 +18,7 @@ class ProgressDetailScreenArguments { class ProgressDetailScreen extends StatefulWidget { static const routeName = "/progress-detail"; + static const title = "Progress View"; @override State createState() { @@ -29,7 +28,7 @@ class ProgressDetailScreen extends StatefulWidget { class _ProgressDetailScreenState extends State { bool _editMode = false; - TimeProgress _editedProgress = TimeProgress.initialDefault(); + TimeProgress _editedProgress; void _onEditedProgressChanged(TimeProgress newProgress) { setState(() { @@ -37,162 +36,70 @@ class _ProgressDetailScreenState extends State { }); } - void _onSaveTimeProgress(Store store, id) { - if (!TimeProgress.isValid(_editedProgress)) return; - store.dispatch(UpdateTimeProgressAction(id, _editedProgress)); + void _switchEditMode(bool newMode) { setState(() { - _editMode = false; + _editMode = newMode; }); } - void _showCancelEditTimeProgressDialog(AppState state, id) { - TimeProgress originalTp = timeProgressByIdSelector(state, id); - if (originalTp != _editedProgress) { - String originalName = originalTp.name; - showDialog( - context: context, - builder: (_) => AppYesNoDialog( - titleText: "Cancel Editing of $originalName", - contentText: - "Are you sure that you want to discard the changes done to $originalName", - onYesPressed: () { - _cancelEditMode(); - Navigator.pop(context); - }, - onNoPressed: _onCloseDialog, - ), - ); - } else { - _cancelEditMode(); - } - } - - void _cancelEditMode() { - setState(() { - _editMode = false; - }); - } - - void _onEditTimeProgress(AppState state, id) { - setState(() { - _editMode = true; - _editedProgress = timeProgressByIdSelector(state, id); - }); - } - - void _showDeleteTimeProgressDialog(Store store, id) { - showDialog( - context: context, - builder: (_) => AppYesNoDialog( - titleText: "Delete ${timeProgressByIdSelector(store.state, id).name}", - contentText: "Are you sure you want to delete this time progress?", - onYesPressed: () => _onDeleteTimeProgress(store, id), - onNoPressed: _onCloseDialog, - ), - ); - } - - void _onDeleteTimeProgress(Store store, String id) { - store.dispatch(DeleteTimeProgressAction(id)); - Navigator.popUntil(context, ModalRoute.withName(HomeScreen.routeName)); - } - - void _onCloseDialog() { - Navigator.pop(context); - } - @override Widget build(BuildContext context) { final ProgressDetailScreenArguments args = ModalRoute.of(context).settings.arguments; final Store store = StoreProvider.of(context); - final ThemeData appTheme = Theme.of(context); + final TimeProgress _timeProgress = + timeProgressByIdSelector(store.state, args.id); + + if (_timeProgress == null) //+++++Time Progress Not Found Error+++++ + return Center( + child: Text("Error Invalid Time Progress"), + ); + if (_editedProgress == null) + _editedProgress = _timeProgress; // initialize _editedProgress + + void _saveEditedProgress() { + store.dispatch(UpdateTimeProgressAction(args.id, _editedProgress)); + _switchEditMode(false); + } + + void _deleteTimeProgress() { + store.dispatch(DeleteTimeProgressAction(args.id)); + Navigator.popUntil(context, ModalRoute.withName(HomeScreen.routeName)); + } + + List columnChildren = [ + Expanded( + child: ProgressViewWidget( + timeProgress: _editMode ? _editedProgress : _timeProgress), + ) + ]; + if (_editMode) + columnChildren.add(Expanded( + child: ProgressEditorWidget( + timeProgress: _editedProgress, + onTimeProgressChanged: _onEditedProgressChanged, + ), + )); return Scaffold( appBar: AppBar( - title: Text("Progress"), + title: Text(ProgressDetailScreen.title), ), body: Container( margin: EdgeInsets.all(8), - child: StoreConnector( - converter: (Store store) => - _ViewModel.fromStoreAndArg(store, args), - onInit: loadTimeProgressListIfUnloaded, - builder: (BuildContext context, _ViewModel vm) { - if (vm.timeProgress == null) - return Center( - child: Text("Error Invalid Time Progress"), - ); - List columnChildren = [ - Expanded( - child: ProgressViewWidget( - timeProgress: - _editMode ? _editedProgress : vm.timeProgress), - ) - ]; - if (_editMode) - columnChildren.add(Expanded( - child: ProgressEditorWidget( - timeProgress: _editedProgress, - onTimeProgressChanged: _onEditedProgressChanged, - ), - )); - return Column( - children: columnChildren, - ); - }, + child: Column( + children: columnChildren, ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, - floatingActionButton: Row( - children: [ - Expanded( - child: FloatingActionButton( - heroTag: _editMode - ? "saveEditedTimeProgressBTN" - : "editTimeProgressBTN", - child: _editMode ? Icon(Icons.save) : Icon(Icons.edit), - backgroundColor: _editMode ? Colors.green : appTheme.accentColor, - onPressed: _editMode - ? () { - _onSaveTimeProgress(store, args.id); - } - : () { - _onEditTimeProgress(store.state, args.id); - }, - ), - ), - Expanded( - child: FloatingActionButton( - heroTag: _editMode - ? "cancelEditTimeProgressBTN" - : "deleteTimeProgressBTN", - child: _editMode ? Icon(Icons.cancel) : Icon(Icons.delete), - backgroundColor: Colors.red, - onPressed: _editMode - ? () { - _showCancelEditTimeProgressDialog(store.state, args.id); - } - : () { - _showDeleteTimeProgressDialog(store, args.id); - }, - ), - ), - ], - ), - ); - } -} - -class _ViewModel { - final TimeProgress timeProgress; - - _ViewModel({@required this.timeProgress}); - - static _ViewModel fromStoreAndArg( - Store store, ProgressDetailScreenArguments args) { - return _ViewModel( - timeProgress: timeProgressByIdSelector(store.state, args.id), + floatingActionButton: DetailScreenFloatingActionButtons( + editMode: _editMode, + originalProgress: timeProgressByIdSelector(store.state, args.id), + editedProgress: _editedProgress, + onEditProgress: () => _switchEditMode(true), + onSaveEditedProgress: _saveEditedProgress, + onCancelEditProgress: () => _switchEditMode(false), + onDeleteProgress: _deleteTimeProgress), ); } } diff --git a/lib/widgets/app_drawer_widget.dart b/lib/widgets/app_drawer_widget.dart deleted file mode 100644 index 2bcda4f..0000000 --- a/lib/widgets/app_drawer_widget.dart +++ /dev/null @@ -1,129 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; -import 'package:flutter_redux/flutter_redux.dart'; -import 'package:percent_indicator/circular_percent_indicator.dart'; -import 'package:redux/redux.dart'; -import 'package:time_progress_tracker/actions/actions.dart'; -import 'package:time_progress_tracker/app.dart'; -import 'package:time_progress_tracker/models/app_state.dart'; -import 'package:time_progress_tracker/models/time_progress.dart'; -import 'package:time_progress_tracker/screens/home_screen.dart'; -import 'package:time_progress_tracker/screens/progress_detail_screen.dart'; -import 'package:time_progress_tracker/selectors/time_progress_selectors.dart'; - -class AppDrawer extends StatelessWidget { - final String appVersion; - - AppDrawer({ - Key key, - @required this.appVersion, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - ThemeData appTheme = Theme.of(context); - - return Drawer( - child: StoreConnector( - converter: _ViewModel.fromStore, - onInit: loadTimeProgressListIfUnloaded, - builder: (context, _ViewModel vm) { - if (!vm.hasLoaded) { - return Center( - child: CircularProgressIndicator(), - ); - } - List drawerTileList = List(); - drawerTileList.add(DrawerHeader( - child: Text(TimeProgressTrackerApp.name), - decoration: BoxDecoration(color: appTheme.primaryColor), - margin: EdgeInsets.zero, - )); - drawerTileList.add(Container( - color: appTheme.accentColor, - margin: EdgeInsets.only(bottom: 8), - child: ListTile( - title: Text(HomeScreen.title), - trailing: Icon(Icons.dashboard), - onTap: () { - Navigator.pop(context); - Navigator.pushNamed(context, HomeScreen.routeName); - }, - ), - )); - if (vm.currentTimeProgresses.length > 0) { - for (TimeProgress tp in vm.currentTimeProgresses) { - drawerTileList.add(ListTile( - title: Text(tp.name), - trailing: CircularPercentIndicator( - percent: tp.percentDone(), - radius: 40, - progressColor: Colors.green, - backgroundColor: Colors.red, - center: FittedBox( - fit: BoxFit.scaleDown, - child: - Text((tp.percentDone() * 100).floor().toString() + "%"), - ), - ), - onTap: () { - Navigator.pop(context); - Navigator.pushNamed( - context, - ProgressDetailScreen.routeName, - arguments: ProgressDetailScreenArguments(tp.id), - ); - }, - )); - if (vm.currentTimeProgresses.last != tp) { - drawerTileList.add(Divider( - color: Colors.black12, - )); - } - } - } else { - drawerTileList.add(ListTile( - title: Text("You don't have any tracked time progress."), - )); - } - drawerTileList.add(Divider( - color: Colors.black38, - )); - drawerTileList.add(Container( - margin: EdgeInsets.only(bottom: 8), - child: ListTile( - title: Text("About"), - onTap: () { - showAboutDialog( - context: context, - applicationName: TimeProgressTrackerApp.name, - applicationVersion: " Version $appVersion", - applicationLegalese: '\u00a9Andreas Fahrecker 2020-2021'); - }, - ), - )); - return ListView( - children: drawerTileList, - ); - }, - ), - ); - } -} - -class _ViewModel { - final List currentTimeProgresses; - final bool hasLoaded; - - _ViewModel({ - @required this.currentTimeProgresses, - @required this.hasLoaded, - }); - - static _ViewModel fromStore(Store store) { - return _ViewModel( - currentTimeProgresses: currentTimeProgressSelector(store.state), - hasLoaded: store.state.hasLoaded, - ); - } -} diff --git a/lib/widgets/app_yes_no_dialog_widget.dart b/lib/widgets/app_yes_no_dialog_widget.dart index 29b6d50..270752b 100644 --- a/lib/widgets/app_yes_no_dialog_widget.dart +++ b/lib/widgets/app_yes_no_dialog_widget.dart @@ -4,14 +4,12 @@ class AppYesNoDialog extends StatelessWidget { final String titleText; final String contentText; final void Function() onYesPressed; - final void Function() onNoPressed; AppYesNoDialog({ Key key, @required this.titleText, @required this.contentText, @required this.onYesPressed, - @required this.onNoPressed, }) : super(key: key); @override @@ -26,7 +24,9 @@ class AppYesNoDialog extends StatelessWidget { ), FlatButton( child: Text("No"), - onPressed: onNoPressed, + onPressed: () { + Navigator.pop(context); + }, ) ], ); diff --git a/lib/widgets/detail_screen_floating_action_buttons.dart b/lib/widgets/detail_screen_floating_action_buttons.dart new file mode 100644 index 0000000..e23b7e0 --- /dev/null +++ b/lib/widgets/detail_screen_floating_action_buttons.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:time_progress_tracker/models/time_progress.dart'; +import 'package:time_progress_tracker/widgets/app_yes_no_dialog_widget.dart'; + +class DetailScreenFloatingActionButtons extends StatelessWidget { + final bool editMode; + final TimeProgress originalProgress, editedProgress; + final void Function() onEditProgress, + onSaveEditedProgress, + onCancelEditProgress, + onDeleteProgress; + + DetailScreenFloatingActionButtons({ + @required this.editMode, + @required this.originalProgress, + @required this.editedProgress, + @required this.onEditProgress, + @required this.onSaveEditedProgress, + @required this.onCancelEditProgress, + @required this.onDeleteProgress, + }); + + @override + Widget build(BuildContext context) { + final ThemeData appTheme = Theme.of(context); + + void _onCancelEditTimeProgressBTN() { + if (originalProgress == editedProgress) + onCancelEditProgress(); + else { + showDialog( + context: context, + builder: (_) => AppYesNoDialog( + titleText: "Cancel Editing of ${originalProgress.name}", + contentText: + "Are you sure that you want to discard the changes done to ${originalProgress.name}", + onYesPressed: () { + onCancelEditProgress(); + Navigator.pop(context); + }, + ), + ); + } + } + + void _onDeleteTimeProgressBTN() { + showDialog( + context: context, + builder: (_) => AppYesNoDialog( + titleText: "Delete ${originalProgress.name}", + contentText: "Are you sure you want to delete this time progress?", + onYesPressed: onDeleteProgress, + ), + ); + } + + return Row( + children: [ + Expanded( + child: FloatingActionButton( + heroTag: + editMode ? "saveEditedTimeProgressBTN" : "editTimeProgressBTN", + child: editMode ? Icon(Icons.save) : Icon(Icons.edit), + backgroundColor: editMode ? Colors.green : appTheme.accentColor, + onPressed: editMode + ? TimeProgress.isValid(editedProgress) + ? onSaveEditedProgress + : null + : onEditProgress, + ), + ), + Expanded( + child: FloatingActionButton( + heroTag: editMode + ? "cancelEditTimeProgressBTN" + : "deleteTimeProgressBTN", + child: editMode ? Icon(Icons.cancel) : Icon(Icons.delete), + backgroundColor: Colors.red, + onPressed: editMode + ? _onCancelEditTimeProgressBTN + : _onDeleteTimeProgressBTN, + ), + ), + ], + ); + } +} diff --git a/lib/widgets/progress_detail_widgets/progress_detail_circular_percent_widget.dart b/lib/widgets/progress_detail_widgets/progress_detail_circular_percent_widget.dart deleted file mode 100644 index d2b37eb..0000000 --- a/lib/widgets/progress_detail_widgets/progress_detail_circular_percent_widget.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:percent_indicator/circular_percent_indicator.dart'; - -class ProgressDetailCircularPercent extends StatelessWidget { - final double percentDone; - - ProgressDetailCircularPercent({Key key, @required this.percentDone}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return CircularPercentIndicator( - radius: 100, - lineWidth: 10, - percent: percentDone, - progressColor: Colors.green, - backgroundColor: Colors.red, - center: Text("${(percentDone * 100).floor()} %"), - ); - } -} diff --git a/lib/widgets/progress_detail_widgets/progress_detail_edit_dates_row_widget.dart b/lib/widgets/progress_detail_widgets/progress_detail_edit_dates_row_widget.dart deleted file mode 100644 index 4ee96ac..0000000 --- a/lib/widgets/progress_detail_widgets/progress_detail_edit_dates_row_widget.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:time_progress_tracker/widgets/progress_detail_widgets/progress_detail_select_date_btn_widget.dart'; - -class ProgressDetailEditDatesRow extends StatelessWidget { - final DateTime startTime; - final DateTime endTime; - final void Function(DateTime) onStartTimeChanged; - final void Function(DateTime) onEndTimeChanged; - - ProgressDetailEditDatesRow({ - Key key, - @required this.startTime, - @required this.endTime, - @required this.onStartTimeChanged, - @required this.onEndTimeChanged, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - flex: 5, - child: ProgressDetailSelectDateButton( - leadingString: "Start Date:", - selectedDate: startTime, - onDateSelected: onStartTimeChanged, - ), - ), - Spacer( - flex: 1, - ), - Expanded( - flex: 5, - child: ProgressDetailSelectDateButton( - leadingString: "End Date:", - selectedDate: endTime, - onDateSelected: onEndTimeChanged, - ), - ) - ], - ); - } -} diff --git a/lib/widgets/progress_detail_widgets/progress_detail_fab_editing_row_widget.dart b/lib/widgets/progress_detail_widgets/progress_detail_fab_editing_row_widget.dart deleted file mode 100644 index f6d774c..0000000 --- a/lib/widgets/progress_detail_widgets/progress_detail_fab_editing_row_widget.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:flutter/material.dart'; - -class ProgressDetailFabEditingRow extends StatelessWidget { - final void Function() onSave; - final void Function() onCancelEdit; - - ProgressDetailFabEditingRow({ - Key key, - @required this.onSave, - @required this.onCancelEdit, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FloatingActionButton( - heroTag: "saveEditedTimeProgressBTN", - child: Icon(Icons.save), - backgroundColor: Colors.green, - onPressed: this.onSave, - ), - ), - Expanded( - child: FloatingActionButton( - heroTag: "cancelEditTimeProgressBTN", - child: Icon(Icons.cancel), - backgroundColor: Colors.red, - onPressed: this.onCancelEdit, - )) - ], - ); - } -} diff --git a/lib/widgets/progress_detail_widgets/progress_detail_fab_row_widget.dart b/lib/widgets/progress_detail_widgets/progress_detail_fab_row_widget.dart deleted file mode 100644 index 0d1c1b6..0000000 --- a/lib/widgets/progress_detail_widgets/progress_detail_fab_row_widget.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; - -class ProgressDetailFabRow extends StatelessWidget { - final void Function() onEdit; - final void Function() onDelete; - - ProgressDetailFabRow( - {Key key, @required this.onEdit, @required this.onDelete}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Row( - children: [ - Expanded( - child: FloatingActionButton( - heroTag: "editTimeProgressBTN", - child: Icon(Icons.edit), - onPressed: onEdit, - ), - ), - Expanded( - child: FloatingActionButton( - heroTag: "deleteTimeProgressBTN", - child: Icon(Icons.delete), - backgroundColor: Colors.red, - onPressed: onDelete, - ), - ) - ], - ); - } -} diff --git a/lib/widgets/progress_detail_widgets/progress_detail_linear_percent_widget.dart b/lib/widgets/progress_detail_widgets/progress_detail_linear_percent_widget.dart deleted file mode 100644 index 62e1519..0000000 --- a/lib/widgets/progress_detail_widgets/progress_detail_linear_percent_widget.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:percent_indicator/linear_percent_indicator.dart'; -import 'package:time_progress_tracker/models/time_progress.dart'; - -class ProgressDetailLinearPercent extends StatelessWidget { - final TimeProgress timeProgress; - - ProgressDetailLinearPercent({Key key, @required this.timeProgress}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return LinearPercentIndicator( - padding: EdgeInsets.symmetric(horizontal: 15), - percent: this.timeProgress.percentDone(), - leading: Text("${this.timeProgress.daysBehind()} Days"), - center: Text("${(this.timeProgress.percentDone() * 100).floor()} %"), - trailing: Text("${this.timeProgress.daysLeft()} Days"), - progressColor: Colors.green, - backgroundColor: Colors.red, - lineHeight: 25, - ); - } -} diff --git a/lib/widgets/progress_detail_widgets/progress_detail_select_date_btn_widget.dart b/lib/widgets/progress_detail_widgets/progress_detail_select_date_btn_widget.dart deleted file mode 100644 index b0c8efb..0000000 --- a/lib/widgets/progress_detail_widgets/progress_detail_select_date_btn_widget.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; - -class ProgressDetailSelectDateButton extends StatelessWidget { - final String leadingString; - final DateTime selectedDate; - final void Function(DateTime) onDateSelected; - - ProgressDetailSelectDateButton({ - Key key, - @required this.leadingString, - @required this.selectedDate, - @required this.onDateSelected, - }) : super(key: key); - - @override - Widget build(BuildContext context) { - ThemeData appTheme = Theme.of(context); - - return FlatButton( - color: appTheme.accentColor, - child: Text( - "$leadingString ${selectedDate.toLocal().toString().split(" ")[0]}"), - onPressed: () async { - DateTime picked = await showDatePicker( - context: context, - initialDate: selectedDate, - firstDate: DateTime(selectedDate.year - 5), - lastDate: DateTime(selectedDate.year + 5), - ); - onDateSelected(picked); - }, - ); - } -}