import 'dart:collection'; import 'package:aitrainer_app/bloc/training_evaluation/training_evaluation_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/model/cache.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; import 'package:aitrainer_app/model/training_evaluation_exercise.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/menu_image.dart'; import 'package:aitrainer_app/widgets/victory_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:timeline_tile/timeline_tile.dart'; // ignore: must_be_immutable class TrainingEvaluationPage extends StatelessWidget with Trans { TrainingEvaluationPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { setContext(context); String imageUrl = ""; if (Cache().userLoggedIn == null) { imageUrl = 'asset/image/WT_Results_for_men.jpg'; } else if (Cache().userLoggedIn!.sex == "m") { imageUrl = 'asset/image/WT_Results_for_men.jpg'; } else { imageUrl = 'asset/image/WT_Results_for_female.jpg'; } final HashMap args = ModalRoute.of(context)!.settings.arguments as HashMap; final TrainingPlanBloc trainingPlanBloc = args["bloc"]; final dayName = args["day"]; return Scaffold( appBar: AppBarMin( back: true, ), body: Container( height: double.infinity, width: double.infinity, alignment: Alignment.center, decoration: BoxDecoration( image: DecorationImage( image: AssetImage(imageUrl), fit: BoxFit.cover, alignment: Alignment.topCenter, ), ), child: BlocProvider( create: (context) => TrainingEvaluationBloc(trainingPlanBloc: trainingPlanBloc, day: dayName)..add(TrainingEvaluationLoad()), child: BlocConsumer(listener: (context, state) { if (state is TrainingEvaluationError) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } else if (state is TrainingEvaluationVictoryReady) { showDialog( context: context, barrierDismissible: true, builder: (BuildContext context) { return Victory( victory: true, ); }); } }, builder: (context, state) { final bloc = BlocProvider.of(context); return ModalProgressHUD( child: getEvaluationWidgets(bloc, dayName), inAsyncCall: state is TrainingEvaluationLoading, opacity: 0.5, color: Colors.black54, progressIndicator: CircularProgressIndicator(), ); }))), bottomNavigationBar: BottomNavigator(bottomNavIndex: 0)); } Widget getEvaluationWidgets(TrainingEvaluationBloc bloc, String dayName) { return Container( padding: EdgeInsets.only(left: 10, right: 10), child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [ SliverAppBar( pinned: true, backgroundColor: Colors.transparent, expandedHeight: 130.0, collapsedHeight: 130, toolbarHeight: 40, automaticallyImplyLeading: false, flexibleSpace: FlexibleSpaceBar( title: Column(children: [ Divider(), Text(bloc.trainingPlanBloc.getMyPlan()!.name!, textAlign: TextAlign.center, maxLines: 4, style: GoogleFonts.archivoBlack( fontSize: 24, color: Colors.orange[300], shadows: [ Shadow( offset: Offset(5.0, 5.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], )), Text(t("Training Summary"), textAlign: TextAlign.center, maxLines: 3, style: GoogleFonts.archivoBlack( fontSize: 20, color: Colors.white, shadows: [ Shadow( offset: Offset(5.0, 5.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], )), ]), ), ), //getResultSummary(resultBloc), SliverList( delegate: SliverChildListDelegate([ summaryRow("asset/image/pict_time_h.png", "Duration", bloc.duration + " " + t("mins")), Divider(color: Colors.transparent), summaryRow("asset/image/pict_weight_volumen_tonna.png", "Total Lift", bloc.totalLift + " " + t("kg")), Divider(color: Colors.transparent), summaryRow("asset/image/pict_hypertrophy.png", "Maximum Repeats", "${bloc.maxRepeats}" + " " + t("reps")), Divider(color: Colors.transparent), //summaryRow("asset/image/pict_reps_volumen_db.png", "Total Lift Ever", "100 kg"), //Divider(color: Colors.transparent), Text(t("Details"), textAlign: TextAlign.center, maxLines: 3, style: GoogleFonts.archivoBlack( fontSize: 20, color: Colors.white, shadows: [ Shadow( offset: Offset(5.0, 5.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], )), ])), SliverList( delegate: SliverChildListDelegate( getExerciseLists(bloc, dayName), )) ])); } Widget summaryRow(String imageUrl, String title, String data) { return Row( children: [ Image.asset( imageUrl, height: 40, ), SizedBox( width: 10, ), Flexible( fit: FlexFit.tight, flex: 1, child: Text(t(title), textAlign: TextAlign.start, maxLines: 2, softWrap: true, style: GoogleFonts.archivoBlack( fontSize: 18, color: Colors.orange[400], shadows: [ Shadow( offset: Offset(5.0, 5.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], ))), SizedBox( width: 10, ), Text(t(data), textAlign: TextAlign.center, maxLines: 2, softWrap: true, style: GoogleFonts.archivoBlack( fontSize: 20, color: Colors.white, shadows: [ Shadow( offset: Offset(5.0, 5.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], )) ], ); } List getExerciseLists(TrainingEvaluationBloc bloc, String dayName) { List list = []; bloc.evaluationList.forEach((element) { list.add(ExerciseTile(bloc: bloc, exercise: element)); }); return list; } } // ignore: must_be_immutable class ExerciseTile extends StatelessWidget with Trans { final TrainingEvaluationBloc bloc; final TrainingEvaluationExercise exercise; ExerciseTile({required this.bloc, required this.exercise}); Widget getIndicator(ExercisePlanDetailState state) { if (state.equalsTo(ExercisePlanDetailState.inProgress)) { return ClipRRect( borderRadius: BorderRadius.circular(24.0), child: Container( color: Colors.green, child: Icon( CustomIcon.calendar_2, size: 28, color: Colors.white, ))); } else if (state.equalsTo(ExercisePlanDetailState.finished)) { return ClipRRect( borderRadius: BorderRadius.circular(24.0), child: Container( color: Colors.white, child: Icon( CustomIcon.ok_circled, size: 40, color: Colors.green, ))); } else if (state.equalsTo(ExercisePlanDetailState.skipped)) { return ClipRRect( borderRadius: BorderRadius.circular(24.0), child: Container( color: Colors.white, child: Icon( CustomIcon.stop_1, size: 40, color: Colors.grey, ))); } else if (state.equalsTo(ExercisePlanDetailState.extra)) { return ClipRRect( borderRadius: BorderRadius.circular(24.0), child: Container( color: Colors.white, child: Icon( CustomIcon.stopwatch_20, size: 40, color: Colors.blue[800], ))); } else { return Image.asset( "asset/image/pict_reps_volumen_db.png", ); } } Widget build(BuildContext context) { setContext(context); bool hasWeight = exercise.type.equalsTo(TrainingEvaluationExerciseType.weightBased); bool skipped = exercise.state.equalsTo(ExercisePlanDetailState.skipped); bool extra = exercise.state.equalsTo(ExercisePlanDetailState.extra); return Container( color: Colors.transparent, child: TimelineTile( alignment: TimelineAlign.manual, lineXY: 0.1, beforeLineStyle: const LineStyle( color: Color(0xffb4f500), thickness: 6, ), afterLineStyle: const LineStyle( color: Color(0xffb4f500), thickness: 6, ), indicatorStyle: IndicatorStyle( width: 40, height: 40, indicator: getIndicator(exercise.state), ), endChild: Container( padding: EdgeInsets.only(left: 10), child: Row(children: [ Container( width: 120, height: 80, child: MenuImage( imageName: bloc.trainingPlanBloc.getActualImageName(exercise.exerciseTypeId), workoutTreeId: bloc.trainingPlanBloc.getActualWorkoutTreeId(exercise.exerciseTypeId)!, radius: 12, ), ), SizedBox( width: 10, ), Expanded( child: RichText( text: TextSpan( style: GoogleFonts.inter( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white, ), children: [ TextSpan( text: exercise.name, style: GoogleFonts.inter( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.orange[500], shadows: [ Shadow( offset: Offset(5.0, 5.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], )), TextSpan(text: "\n"), hasWeight ? skipped ? extra ? TextSpan( text: "-", style: GoogleFonts.inter(fontSize: 12, color: Colors.grey[400], fontWeight: FontWeight.bold)) : TextSpan( text: t("skipped") + "!", style: GoogleFonts.inter(fontSize: 12, color: Colors.grey[400], fontWeight: FontWeight.bold)) : TextSpan( text: t("One Rep Max") + ": ", style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[400], fontWeight: FontWeight.bold)) : TextSpan(), hasWeight ? skipped || extra ? TextSpan() : TextSpan( text: exercise.oneRepMax!.toStringAsFixed(0) + " " + t("kg") + " (Max: " + exercise.max1RM!.toStringAsFixed(0) + " " + t("kg") + ")", style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold)) : TextSpan(), TextSpan(text: "\n"), hasWeight ? skipped || extra ? TextSpan() : TextSpan( text: t("Total Lift") + ": ", style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[400], fontWeight: FontWeight.bold)) : TextSpan(), hasWeight ? skipped || extra ? TextSpan() : TextSpan( text: exercise.totalLift!.toStringAsFixed(0) + " " + t("kg") + " (Max: " + exercise.maxTotalLift!.toStringAsFixed(0) + " " + t("kg") + ")", style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold)) : skipped || extra ? TextSpan() : TextSpan( text: exercise.repeats!.toStringAsFixed(0) + " " + t("reps") + " (Max: " + exercise.maxRepeats!.toStringAsFixed(0) + " " + t("reps") + ")", style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold)), TextSpan(text: "\n"), skipped || extra ? TextSpan() : TextSpan( text: t("Trend") + ": ", style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[400], fontWeight: FontWeight.bold)), skipped || extra ? TextSpan() : TextSpan( text: t(exercise.trendText), style: GoogleFonts.inter(fontSize: 12, color: exercise.trendColor, fontWeight: FontWeight.bold)), ]), )), ]), ), ), ); } }