import 'dart:collection'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; import 'package:aitrainer_app/library/tree_view.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/training_plan.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/util/app_language.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/dialog_common.dart'; import 'package:aitrainer_app/widgets/menu_image.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_html/style.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; // ignore: must_be_immutable class TrainingPlanActivatePage extends StatelessWidget with Trans { late String parentName; TrainingPlanActivatePage(); @override Widget build(BuildContext context) { setContext(context); final HashMap args = ModalRoute.of(context)!.settings.arguments as HashMap; parentName = args['parentName']; return Scaffold( appBar: AppBarNav(depth: 1), body: Container( padding: EdgeInsets.all(20), decoration: BoxDecoration( image: DecorationImage( image: AssetImage('asset/image/WT_black_background.jpg'), fit: BoxFit.cover, alignment: Alignment.center, ), ), child: BlocConsumer( listener: (context, state) { if (state is TrainingPlanError) { showDialog( context: context, builder: (BuildContext context) { return DialogCommon( warning: true, title: t("Warning"), descriptions: t(state.message), text: "OK", onTap: () => Navigator.of(context).pushNamed("login"), onCancel: () => { Navigator.of(context).pop(), }, ); }); } else if (state is TrainingPlanFinished) { Navigator.of(context).pop(); Navigator.of(context).pushNamed("myTrainingPlanExecute"); } }, builder: (context, state) { final TrainingPlanBloc bloc = BlocProvider.of(context); return ModalProgressHUD( child: getPlans(bloc), inAsyncCall: state is TrainingPlanLoading, opacity: 0.5, color: Colors.black54, progressIndicator: CircularProgressIndicator(), ); }, ), ), ); } Widget getPlans(TrainingPlanBloc bloc) { return TreeView( startExpanded: false, children: _getTreeChildren(bloc), ); } List _getTreeChildren(TrainingPlanBloc bloc) { final List plans = bloc.trainingPlanRepository.getPlansByParent(parentName); final String parentTitle = bloc.trainingPlanRepository.parentTree != null ? bloc.trainingPlanRepository.parentTree!.nameTranslation : ""; final String parentDescription = bloc.trainingPlanRepository.parentTree != null && bloc.trainingPlanRepository.parentTree!.descriptionTranslation != null ? bloc.trainingPlanRepository.parentTree!.descriptionTranslation! : ""; 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(" "), Flexible( child: Text( parentTitle, maxLines: 2, style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), )), ], ), Divider( color: Colors.transparent, ), Html( data: parentDescription, //Optional parameters: style: { "p": Style( color: Colors.black, fontSize: FontSize(12), padding: const EdgeInsets.only(left: 20, right: 8, bottom: 4), ), "strong": Style( color: Colors.indigo, fontWeight: FontWeight.bold, fontSize: FontSize(14), ), "h3": Style( color: Colors.yellow[600], fontSize: FontSize(16), textAlign: TextAlign.center, padding: const EdgeInsets.all(12), ), "li": Style( color: Colors.white, fontSize: FontSize(14), padding: const EdgeInsets.only(left: 20, bottom: 10, right: 8), //before: "*", display: Display.LIST_ITEM), "h2": Style( color: Colors.yellow[600], fontWeight: FontWeight.bold, fontSize: FontSize(24), textAlign: TextAlign.center, //padding: const EdgeInsets.all(4), ), "h1": Style( color: Colors.yellow[400], fontWeight: FontWeight.bold, fontSize: FontSize.larger, alignment: Alignment.center, padding: const EdgeInsets.all(4), ), }, ), // ], ))); listWidget.add(explanation); plans.forEach((element) { listWidget.add(Container( margin: const EdgeInsets.only(left: 4.0), child: TreeViewChild( startExpanded: false, parent: TreeviewParentWidget( text: element.nameTranslations[AppLanguage().appLocal.toString()] != null ? element.nameTranslations[AppLanguage().appLocal.toString()]! : element.name, fontSize: 18, icon: Icon(Icons.list_sharp), color: Colors.blue[800], ), children: _getChildList(element, bloc), ))); }); return listWidget; } List _getChildList(TrainingPlan plan, TrainingPlanBloc bloc) { List list = []; list.add(Card( margin: EdgeInsets.only(left: 10, top: 5), color: Colors.white60, child: Container( padding: EdgeInsets.only(left: 10, right: 10), child: Column(children: [ Html( data: plan.descriptionTranslations[AppLanguage().appLocal.toString()] != null ? plan.descriptionTranslations[AppLanguage().appLocal.toString()]! : plan.description, //Optional parameters: style: { "p": Style( color: Colors.black, padding: const EdgeInsets.all(4), ), "li": Style( color: Colors.white, //padding: const EdgeInsets.all(4), ), "h2": Style( color: Colors.black, fontWeight: FontWeight.bold, fontSize: FontSize.larger, //padding: const EdgeInsets.all(4), ), "h1": Style( color: Colors.black, fontWeight: FontWeight.bold, fontSize: FontSize.larger, alignment: Alignment.center, padding: const EdgeInsets.all(4), ), }, ), getPlanDetails(plan, bloc), ElevatedButton( style: ElevatedButton.styleFrom( onPrimary: Colors.white, primary: Colors.orange, ), child: Text(t("Start")), onPressed: () { if (Cache().myTrainingPlan != null) { showCupertinoDialog( useRootNavigator: true, context: context, builder: (_) => CupertinoAlertDialog( title: Text(t("You have an active Training Plan")), content: Column(children: [ Divider(), Text( t("Do you want to override it with"), style: (TextStyle(color: Colors.blue)), ), Text( plan.nameTranslations[AppLanguage().appLocal.toString()]! + "?", style: (TextStyle(color: Colors.blue[800], fontWeight: FontWeight.bold)), ), ]), actions: [ TextButton( child: Text(t("No")), onPressed: () => Navigator.pop(context), ), TextButton( child: Text(t("Yes")), onPressed: () { Navigator.pop(context); bloc.add(TrainingPlanActivate(trainingPlanId: plan.trainingPlanId)); }, ) ], )); } else { bloc.add(TrainingPlanActivate(trainingPlanId: plan.trainingPlanId)); } }, ) ]), ))); return list; } Widget getPlanDetails(TrainingPlan plan, TrainingPlanBloc bloc) { return SfDataGrid( headerRowHeight: 30, rowHeight: 45, source: TrainingPlanDetailSource( plan: plan, menuBloc: bloc.menuBloc, onWeightTap: () => { showDialog( context: context, builder: (BuildContext context) { return DialogCommon( title: t("Calculated Weight"), descriptions: t("The weight is based on your previuos tests - if they exist."), description2: t("If it does not exist, your very first exercise will be a test."), text: "OK", onTap: () => { Navigator.of(context).pop(), }, onCancel: () => { Navigator.of(context).pop(), }, ); }) }, onRepeatTap: () => { print("Reps"), }), headerGridLinesVisibility: GridLinesVisibility.both, gridLinesVisibility: GridLinesVisibility.both, columns: [ GridTextColumn( //columnWidthMode: ColumnWidthMode.lastColumnFill, maximumWidth: 120, columnName: 'exerciseImage', label: Container( color: Colors.green[50], padding: EdgeInsets.only(left: 8.0), alignment: Alignment.centerLeft, child: Text( t('Exercise'), textAlign: TextAlign.start, overflow: TextOverflow.ellipsis, ))), GridTextColumn( visible: false, columnName: 'exerciseName', label: Container( color: Colors.green[50], padding: EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.centerLeft, child: Text( t('Exercise'), textAlign: TextAlign.start, overflow: TextOverflow.ellipsis, ))), GridTextColumn( maximumWidth: 40, columnName: 'set', label: Container( color: Colors.green[50], padding: EdgeInsets.symmetric(horizontal: 2.0), alignment: Alignment.centerLeft, child: Text( t('Set'), overflow: TextOverflow.ellipsis, ))), GridTextColumn( maximumWidth: 50, columnName: 'repeats', label: Container( color: Colors.green[50], padding: EdgeInsets.symmetric(horizontal: 2.0), alignment: Alignment.centerLeft, child: Text( t('Reps'), overflow: TextOverflow.ellipsis, ))), GridTextColumn( maximumWidth: 60, columnName: 'weight', label: Container( color: Colors.green[50], padding: EdgeInsets.symmetric(horizontal: 2.0), alignment: Alignment.centerLeft, child: Text( t('Weight'), overflow: TextOverflow.ellipsis, ))), GridTextColumn( maximumWidth: 50, columnName: 'day', label: Container( color: Colors.green[50], padding: EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.centerLeft, child: Text( t('Day'), overflow: TextOverflow.ellipsis, ))), ], ); } } class TrainingPlanDetailSource extends DataGridSource { final TrainingPlan plan; final MenuBloc menuBloc; final VoidCallback onWeightTap; final VoidCallback onRepeatTap; TrainingPlanDetailSource({ required this.plan, required this.menuBloc, required this.onWeightTap, required this.onRepeatTap, }) { if (plan.details != null) { dataGridRows = plan.details!.map((dataGridRow) { WorkoutMenuTree? menuTree = menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(dataGridRow.exerciseTypeId); if (menuTree == null) { return DataGridRow(cells: []); } return DataGridRow(cells: [ DataGridCell( columnName: 'exerciseImage', value: MenuImage( imageName: menuTree.imageName, workoutTreeId: menuTree.id, radius: 8, )), DataGridCell(columnName: 'exerciseName', value: menuTree.name), DataGridCell(columnName: 'set', value: dataGridRow.set), DataGridCell(columnName: 'reps', value: dataGridRow.repeats), DataGridCell(columnName: 'weight', value: dataGridRow.weight), DataGridCell(columnName: 'day', value: dataGridRow.day), ]); }).toList(); } } List dataGridRows = []; @override List get rows => dataGridRows; @override DataGridRowAdapter? buildRow(DataGridRow row) { if (row.getCells().isEmpty) { return null; } String name = row.getCells()[1].value; return DataGridRowAdapter( color: Colors.white60, cells: row.getCells().map((dataGridCell) { return Container( alignment: dataGridCell.columnName == "exerciseImage" ? Alignment.centerLeft : Alignment.centerLeft, padding: EdgeInsets.only(top: 2, bottom: 2, left: 4, right: 4), child: dataGridCell.columnName == "exerciseImage" ? Stack(alignment: AlignmentDirectional.bottomStart, children: [ dataGridCell.value, Container( padding: EdgeInsets.only(left: 4, right: 8, bottom: 3), child: Text( name, maxLines: 3, overflow: TextOverflow.ellipsis, style: GoogleFonts.inter(fontSize: 10, color: Colors.yellow[600], fontWeight: FontWeight.bold, shadows: [ Shadow( offset: Offset(2.0, 2.0), blurRadius: 6.0, color: Colors.black, ), ]), )) ]) : dataGridCell.columnName == "weight" && dataGridCell.value == -1 ? GestureDetector( onTap: () { onWeightTap(); }, child: Icon( CustomIcon.question_circle, color: Colors.indigo[300], )) : dataGridCell.columnName == "reps" && dataGridCell.value == -1 ? GestureDetector( onTap: () { onRepeatTap(); }, child: Icon( CustomIcon.question_circle, color: Colors.indigo[600], )) : Text(dataGridCell.value.toString(), style: GoogleFonts.inter( fontSize: 14, color: Colors.indigo, fontWeight: FontWeight.bold, ))); }).toList()); } }