import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_log/exercise_log_bloc.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/dialog_premium.dart'; import 'package:badges/badges.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/library/tree_view.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/material.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; // ignore: must_be_immutable class ExerciseLogPage extends StatelessWidget with Trans, Common { @override Widget build(BuildContext context) { LinkedHashMap arguments = ModalRoute.of(context)!.settings.arguments as LinkedHashMap; final int customerId = arguments['customerId']; setContext(context); return BlocProvider( create: (context) => ExerciseLogBloc(exerciseRepository: ExerciseRepository())..add(ExerciseLogLoad()), child: BlocConsumer(listener: (context, state) { if (state is ExerciseLogError) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } }, builder: (context, state) { final exerciseBloc = BlocProvider.of(context); return ModalProgressHUD( child: getExerciseLog(customerId, exerciseBloc), inAsyncCall: state is ExerciseLogLoading, opacity: 0.5, color: Colors.black54, progressIndicator: CircularProgressIndicator(), ); })); } Widget getExerciseLog(int customerId, ExerciseLogBloc exerciseLogBloc) { return Scaffold( appBar: AppBarNav(depth: 1), body: Container( padding: EdgeInsets.all(20), decoration: BoxDecoration( image: DecorationImage( image: customerId == Cache().userLoggedIn!.customerId ? AssetImage('asset/image/WT_black_background.jpg') : AssetImage('asset/image/WT_light_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), ), child: exerciseWidget(exerciseLogBloc, customerId), ), bottomNavigationBar: BottomNavigator(bottomNavIndex: 1), ); } Widget exerciseWidget(ExerciseLogBloc exerciseLogBloc, int customerId) { return TreeView( startExpanded: false, children: _getTreeChildren(exerciseLogBloc, customerId), ); } List _getTreeChildren(ExerciseLogBloc exerciseLogBloc, int customerId) { final ExerciseRepository exerciseRepository = exerciseLogBloc.exerciseRepository; if (customerId == Cache().userLoggedIn!.customerId) { exerciseRepository.exerciseList = exerciseRepository.getExerciseList(); } else if (Cache().getTrainee() != null && customerId == Cache().getTrainee()!.customerId) { exerciseRepository.exerciseList = exerciseRepository.getExerciseListTrainee(); } //print("ExerciseList ${exerciseRepository.exerciseList}"); exerciseRepository.sortByDate(); List listWidget = []; Card explanation = Card( color: Colors.white60, child: Container( padding: EdgeInsets.only(left: 10, right: 5, top: 12, bottom: 8), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Row( children: [ Icon( Icons.info, color: Colors.orangeAccent, ), Text(" "), Text( t("My Exercise Logs"), style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), ], ), Divider( color: Colors.transparent, ), Text( t("In this list you will find all your executed exercises grouped by the date."), style: TextStyle(fontSize: 12, fontWeight: FontWeight.normal), ), ], ))); listWidget.add(explanation); List listExercises = []; String origDate = ""; exerciseRepository.exerciseLogList!.forEach((exercise) { String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!); if (origDate != exerciseDate) { if (origDate.length == 0) { listExercises.add(exercise); origDate = exerciseDate; } else { listWidget.add(Container( margin: const EdgeInsets.only(left: 4.0), child: TreeViewChild( startExpanded: false, parent: TreeviewParentWidget(text: origDate), children: _getChildList(listExercises, exerciseRepository, exerciseLogBloc), ))); listExercises = []; listExercises.add(exercise); origDate = exerciseDate; } } else { listExercises.add(exercise); origDate = exerciseDate; } }); //print("ListExerices $listExercises"); if (listExercises.length > 0) { listWidget.add(Container( margin: const EdgeInsets.only(left: 4.0), child: TreeViewChild( startExpanded: true, parent: TreeviewParentWidget(text: origDate), children: _getChildList(listExercises, exerciseRepository, exerciseLogBloc), ))); } return listWidget; } List _getChildList(List listExercises, ExerciseRepository exerciseRepository, ExerciseLogBloc exerciseLogBloc) { List list = []; bool isEnglish = AppLanguage().appLocal == Locale('en'); listExercises.forEach((exercise) { ExerciseType? exerciseType = exerciseRepository.getExerciseTypeById(exercise.exerciseTypeId!); String exerciseName = isEnglish ? exerciseType!.name : exerciseType!.nameTranslation; list.add( Card( margin: EdgeInsets.only(left: 10, top: 5), color: Colors.white54, child: Container( padding: const EdgeInsets.only(left: 15, top: 0, right: 5, bottom: 0), child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [ Flexible( fit: FlexFit.tight, flex: 20, child: Text( exerciseName, style: TextStyle(fontSize: 12, color: Colors.black), ), ), Flexible( fit: FlexFit.tight, child: SizedBox( width: 5, )), Flexible( fit: FlexFit.tight, flex: 20, child: Text( exercise.summary == null ? "" : exercise.summary!, style: TextStyle(fontSize: 12, color: Colors.blue[800]), )), GestureDetector( onTap: () => evaluation(exerciseRepository, exercise), child: Badge( elevation: 0, padding: EdgeInsets.all(0), position: BadgePosition.topStart(top: -5, start: -10), animationDuration: Duration(milliseconds: 1500), animationType: BadgeAnimationType.fade, badgeColor: Colors.transparent, showBadge: true, badgeContent: /* IconButton( iconSize: 36, onPressed: () => showDialog( context: context, builder: (BuildContext context) { return DialogCommon( title: t("Premium function"), descriptions: Cache().canTrial() ? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription") : t("This is a premium function, you can reach it only with a valid subscription"), onCancel: () => Navigator.of(context).pop(), onTap: () => Navigator.of(context).pop(), text: '', ); }), icon: */ Icon( Icons.star, size: 14, color: Colors.orange[400], ), child: Image.asset( "asset/image/kupa.png", width: 35, ))), Badge( elevation: 0, padding: EdgeInsets.all(0), position: BadgePosition.topStart(top: 2, start: 5), animationDuration: Duration(milliseconds: 1500), animationType: BadgeAnimationType.fade, badgeColor: Colors.transparent, showBadge: true, badgeContent: /* Icon( iconSize: 36, onPressed: () => showDialog( context: context, builder: (BuildContext context) { return DialogCommon( title: t("Premium function"), descriptions: Cache().canTrial() ? t("This is a premium function, you can reach it outside of the trial period only with a valid subscription") : t("This is a premium function, you can reach it only with a valid subscription"), onCancel: () => Navigator.of(context).pop(), onTap: () => Navigator.of(context).pop(), text: '', ); }), */ Icon( Icons.star, size: 14, color: Colors.orange[400], ), child: IconButton( icon: Icon(Icons.delete, color: Colors.black12), onPressed: () { confirmationDialog(exerciseLogBloc, exercise); }, )), ]), )), ); }); return list; } void evaluation(ExerciseRepository exerciseRepository, Exercise exercise) { if (Cache().userLoggedIn != null) { if (!Cache().hasPurchased) { showDialog( context: context, builder: (BuildContext context) { return DialogPremium( unlocked: Cache().hasPurchased, unlockRound: 1, unlockedText: t("Enjoy also this premium feature to show all old evaluation data of your successful exercises."), function: "My Exercise Logs", onTap: () => {Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop()}, ); }); } else { LinkedHashMap args = LinkedHashMap(); args['exerciseRepository'] = exerciseRepository; args['exercise'] = exercise; args['past'] = true; Navigator.of(context).pushNamed('evaluationPage', arguments: args); } } } void confirmationDialog(ExerciseLogBloc bloc, Exercise exercise) { ExerciseType? exerciseType = bloc.exerciseRepository.getExerciseTypeById(exercise.exerciseTypeId!); String exerciseName = AppLanguage().appLocal == Locale("en") ? exerciseType!.name : exerciseType!.nameTranslation; String strDate = AppLanguage().appLocal == Locale("en") ? "on the " + DateFormat(DateFormat.YEAR_MONTH_DAY, AppLanguage().appLocal.toString()).format(exercise.dateAdd!.toUtc()) : DateFormat(DateFormat.YEAR_MONTH_DAY, AppLanguage().appLocal.toString()).format(exercise.dateAdd!.toUtc()) + "-n"; final String unitQuantity = exercise.unitQuantity == null ? "" : "x" + exercise.unitQuantity!.toStringAsFixed(0); showCupertinoDialog( useRootNavigator: true, context: context, //barrierDismissible: false, builder: (_) => CupertinoAlertDialog( title: Text(t("Are you sure to delete this exercise?")), content: Column(children: [ Divider(), Text( t("Exercise") + ": " + exerciseName, style: (TextStyle(color: Colors.blue)), ), Text( exercise.quantity!.toStringAsFixed(0) + unitQuantity + " ", //+ //exerciseType.unitQuantityUnit == null // ? "" // : exerciseType.unitQuantityUnit, style: (TextStyle(color: Colors.deepOrange)), ), Text( strDate, style: (TextStyle(color: Colors.deepOrange)), ), ]), actions: [ TextButton( child: Text(t("No")), onPressed: () => Navigator.pop(context), ), TextButton( child: Text(t("Yes")), onPressed: () { Navigator.pop(context); if (!Cache().hasPurchased) { showDialog( context: context, builder: (BuildContext context) { return DialogPremium( unlocked: Cache().hasPurchased, unlockRound: 1, unlockedText: t("Enjoy also this premium fetaure to delete mistyped old exercises."), function: "Delete Exercise", onTap: () => {Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop()}, ); }); } else { bloc.add(ExerciseLogDelete(exercise: exercise)); } }, ) ], )); } }