import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart'; import 'package:aitrainer_app/library/custom_icon_icons.dart'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/dialog_html.dart'; import 'package:aitrainer_app/widgets/number_picker.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:modal_progress_hud/modal_progress_hud.dart'; class ExerciseControlPage extends StatefulWidget { _ExerciseControlPage createState() => _ExerciseControlPage(); } class _ExerciseControlPage extends State with Trans { final ScrollController _controller = ScrollController(); double offset = 0; @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { LinkedHashMap arguments = ModalRoute.of(context).settings.arguments; final ExerciseRepository exerciseRepository = arguments['exerciseRepository']; final double percent = arguments['percent']; final bool readonly = arguments['readonly']; setContext(context); return BlocProvider( create: (context) => ExerciseControlBloc(exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly) ..add(ExerciseControlLoad()), child: BlocConsumer(listener: (context, state) { if (state is ExerciseControlError) { Scaffold.of(context).showSnackBar( SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } }, builder: (context, state) { final exerciseBloc = BlocProvider.of(context); if (state is ExerciseControlReady) { _controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn); } return ModalProgressHUD( child: getControlForm(exerciseBloc), inAsyncCall: state is ExerciseControlLoading, opacity: 0.5, color: Colors.black54, progressIndicator: CircularProgressIndicator(), ); })); } Form getControlForm(ExerciseControlBloc exerciseBloc) { this.offset = exerciseBloc.scrollOffset; String exerciseName = AppLanguage().appLocal == Locale("en") ? exerciseBloc.exerciseRepository.exerciseType.name : exerciseBloc.exerciseRepository.exerciseType.nameTranslation; return Form( child: Scaffold( resizeToAvoidBottomInset: true, appBar: AppBarNav(depth: 1), body: Container( height: double.infinity, width: double.infinity, alignment: Alignment.center, decoration: BoxDecoration( image: DecorationImage( image: Cache().userLoggedIn.sex == "m" ? AssetImage("asset/image/WT_Results_for_men.png") : AssetImage("asset/image/WT_Results_for_female.png"), fit: BoxFit.cover, alignment: Alignment.topCenter, ), ), child: Container( padding: const EdgeInsets.only(top: 10, left: 25, right: 25), child: SingleChildScrollView( scrollDirection: Axis.vertical, controller: _controller, child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( exerciseName, style: GoogleFonts.archivoBlack( fontWeight: FontWeight.bold, fontSize: 24, color: Colors.white, shadows: [ Shadow( offset: Offset(2.0, 2.0), blurRadius: 6.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], ), overflow: TextOverflow.fade, textAlign: TextAlign.center, maxLines: 2, softWrap: true, ), Divider( color: Colors.transparent, ), Divider( color: Colors.transparent, ), Divider( color: Colors.transparent, ), Divider( color: Colors.transparent, ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Text(t("Your 1RM:"), style: GoogleFonts.inter( color: Colors.yellow[300], fontSize: 18, shadows: [ Shadow( offset: Offset(-2.0, -2.0), blurRadius: 12.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], )), Text( " " + exerciseBloc.initialRM.toStringAsFixed(0) + " " + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit, style: GoogleFonts.inter( color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold, shadows: [ Shadow( offset: Offset(-2.0, -2.0), blurRadius: 6.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 6.0, color: Colors.black54, ), ], ), ), SizedBox(width: 10), GestureDetector( onTap: () => { showDialog( context: context, builder: (BuildContext context) { return DialogHTML( title: t("OneRepMax"), htmlData: t("OneRepMax_desc"), ); }) }, child: Icon(CustomIcon.question, color: Colors.yellow[300])) ], ), Divider(), Row(mainAxisAlignment: MainAxisAlignment.start, children: [ Flexible( child: Text(t("Why do you need Exercise Control?"), style: GoogleFonts.inter( color: Colors.yellow[300], fontSize: 18, shadows: [ Shadow( offset: Offset(2.0, 2.0), blurRadius: 6.0, color: Colors.black54, ), Shadow( offset: Offset(-3.0, 3.0), blurRadius: 12.0, color: Colors.black54, ), ], ))), SizedBox(width: 10), GestureDetector( onTap: () => { showDialog( context: context, builder: (BuildContext context) { return DialogHTML( title: t("Control Exercise:"), htmlData: t("controlexercise_desc"), ); }) }, child: Icon(CustomIcon.question, color: Colors.yellow[300])) ]), Divider(), numberPickForm(exerciseBloc, 1), Divider(), numberPickForm(exerciseBloc, 2), Divider(), numberPickForm(exerciseBloc, 3), ]), ))), bottomNavigationBar: BottomNavigator(bottomNavIndex: 1), ), ); } List getButton(int step, ExerciseControlBloc exerciseBloc) { List widgets = List(); if (step < exerciseBloc.step) { widgets.add(Icon( CustomIcon.check_circle, color: Color(0xffb4f500), size: 36, )); } else { widgets.add(Icon( CustomIcon.question, color: Colors.grey[700], size: 36, )); } return widgets; } Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) { String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max."; String textInstruction = ""; textInstruction = t("Please repeat with ") + exerciseBloc.unitQuantity.toStringAsFixed(0) + " " + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + t("hu_with") + " " + strTimes + " " + t( "times!", ); String title = step.toString() + ". " + t("Control Exercise:"); LinkedHashMap args = LinkedHashMap(); List listWidgets = [ Text( title, style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold), ), Text( textInstruction, style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 16), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ NumberPickerWidget( minValue: 0, maxValue: 200, initalValue: exerciseBloc.quantity.toInt(), unit: t("reps"), color: Colors.yellow[50], onChange: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))}), FlatButton( padding: EdgeInsets.all(0), textColor: Colors.white, focusColor: Colors.blueAccent, onPressed: () => { exerciseBloc.add(ExerciseControlSubmit(step: step)), if (step == 3) { Navigator.of(context).pop(), args['exerciseRepository'] = exerciseBloc.exerciseRepository, Navigator.of(context).pushNamed('evaluationPage', arguments: args) } }, child: step == exerciseBloc.step ? Stack( alignment: Alignment.center, children: [ Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60), Text( t("Save"), style: TextStyle(fontSize: 16, color: Colors.white), ), ], ) : Stack( alignment: Alignment.center, children: getButton(step, exerciseBloc), )), ], ), ]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: listWidgets, ); } }