WT1.1.10 compact test, paralell test

This commit is contained in:
bossanyit
2021-03-25 21:54:18 +01:00
parent 2e0d7fc37d
commit f724737ea3
65 changed files with 5250 additions and 749 deletions
+1 -3
View File
@@ -36,15 +36,13 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
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);
// ignore: close_sinks
TimerBloc timerBloc = BlocProvider.of<TimerBloc>(context);
return BlocProvider(
create: (context) => ExerciseControlBloc(
exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly, timerBloc: timerBloc)
create: (context) => ExerciseControlBloc(exerciseRepository: exerciseRepository, readonly: readonly, timerBloc: timerBloc)
..add(ExerciseControlLoad()),
child: BlocConsumer<ExerciseControlBloc, ExerciseControlState>(listener: (context, state) {
if (state is ExerciseControlError) {
+59 -390
View File
@@ -2,8 +2,7 @@ import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_ability.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
@@ -14,95 +13,20 @@ import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bmi_widget.dart';
import 'package:aitrainer_app/widgets/bmr_widget.dart';
import 'package:aitrainer_app/widgets/bottom_bar_multiple_exercises.dart';
import 'package:aitrainer_app/widgets/exercise_save.dart';
import 'package:aitrainer_app/widgets/size_widget.dart';
import 'package:aitrainer_app/widgets/time_picker.dart';
import 'package:flutter/scheduler.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:keyboard_actions/keyboard_actions.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'package:stop_watch_timer/stop_watch_timer.dart';
import 'package:wakelock/wakelock.dart';
class ExerciseNewPage extends StatefulWidget {
_ExerciseNewPageState createState() => _ExerciseNewPageState();
}
class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
final FocusNode _nodeText1 = FocusNode();
final FocusNode _nodeText2 = FocusNode();
final _controller1 = TextEditingController();
final _controller2 = TextEditingController();
initState() {
super.initState();
_controller1.text = "30";
_nodeText1.addListener(() {
if (_nodeText1.hasFocus) {
_controller1.selection = TextSelection(baseOffset: 0, extentOffset: _controller1.text.length);
}
});
SchedulerBinding.instance.addPostFrameCallback((_) {
// ignore: close_sinks
final menuBloc = BlocProvider.of<MenuBloc>(context);
_controller2.text = menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString() ? "12" : "20";
_nodeText2.addListener(() {
if (_nodeText2.hasFocus) {
_controller2.selection = TextSelection(baseOffset: 0, extentOffset: _controller2.text.length);
}
});
});
}
KeyboardActionsConfig _buildConfig(BuildContext context) {
return KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Colors.grey[200],
keyboardSeparatorColor: Colors.black26,
nextFocus: true,
actions: [
KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [
(node) {
return GestureDetector(
onTap: () => node.unfocus(),
child: Container(
padding: EdgeInsets.all(8.0),
color: Colors.orange[500],
child: Text(
t("Done"),
style: TextStyle(color: Colors.white),
),
),
);
}
]),
KeyboardActionsItem(
focusNode: _nodeText1,
toolbarButtons: [
//button 2
(node) {
return GestureDetector(
onTap: () => node.unfocus(),
child: Container(
color: Colors.orange,
padding: EdgeInsets.all(8.0),
child: Text(
t("Done"),
style: TextStyle(color: Colors.white),
),
),
);
}
],
),
],
);
}
@override
Widget build(BuildContext context) {
final ExerciseType exerciseType = ModalRoute.of(context).settings.arguments;
@@ -122,12 +46,33 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
if (state is ExerciseNewError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is ExerciseNewSaved) {
final LinkedHashMap args = LinkedHashMap();
// ignore: close_sinks
final TestSetExecuteBloc executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
print("Execute paralell $exerciseType paralell: ${executeBloc.paralellTest}");
if (executeBloc != null && executeBloc.existsActivePlan() == true) {
Navigator.of(context).pushNamed("testSetExecute");
} else {
// ignore: close_sinks
final bloc = BlocProvider.of<ExerciseNewBloc>(context);
if (bloc.exerciseRepository.exerciseType.unitQuantityUnit == null) {
args['exerciseRepository'] = bloc.exerciseRepository;
Navigator.of(context).pushNamed('evaluationPage', arguments: args);
} else if (menuBloc.ability.equalsTo(ExerciseAbility.oneRepMax)) {
args['exerciseRepository'] = bloc.exerciseRepository;
args['percent'] = 0.75;
args['readonly'] = false;
Navigator.of(context).pushNamed('exerciseControlPage', arguments: args);
}
}
}
},
builder: (context, state) {
final exerciseBloc = BlocProvider.of<ExerciseNewBloc>(context);
return ModalProgressHUD(
child: getExerciseWidget(exerciseBloc, exerciseType, menuBloc),
child: getExerciseSaveWidget(exerciseBloc, exerciseType, menuBloc),
inAsyncCall: state is ExerciseNewLoading,
opacity: 0.5,
color: Colors.black54,
@@ -137,21 +82,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
));
}
Widget getExerciseWidget(ExerciseNewBloc exerciseBloc, ExerciseType exerciseType, MenuBloc menuBloc) {
exerciseBloc.exerciseRepository.setExerciseType(exerciseType);
final String exerciseName = AppLanguage().appLocal == Locale("en")
? exerciseBloc.exerciseRepository.exerciseType.name
: exerciseBloc.exerciseRepository.exerciseType.nameTranslation;
String exerciseDescription = AppLanguage().appLocal == Locale("en")
? exerciseBloc.exerciseRepository.exerciseType.description
: exerciseBloc.exerciseRepository.exerciseType.descriptionTranslation;
if (exerciseDescription == null) {
exerciseDescription = "";
}
//log(exerciseBloc.exerciseRepository.exerciseType.name);
Widget getExerciseSaveWidget(ExerciseNewBloc exerciseBloc, ExerciseType exerciseType, MenuBloc menuBloc) {
if (exerciseBloc.exerciseRepository.exerciseType.name == "BMR") {
return BMR(exerciseBloc: exerciseBloc);
}
@@ -162,288 +93,40 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
return SizeWidget(exerciseBloc: exerciseBloc);
}
final String exerciseTask = exerciseBloc.setExerciseTask();
return Form(
child: Scaffold(
resizeToAvoidBottomInset: true,
return Scaffold(
appBar: AppBarNav(depth: 1),
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('asset/image/WT_black_background.jpg'),
fit: BoxFit.fill,
alignment: Alignment.center,
),
),
child: KeyboardActions(
config: _buildConfig(context),
child: Container(
padding: const EdgeInsets.only(top: 25, left: 55, right: 55),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
exerciseName,
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
fontSize: 24,
color: Colors.white,
shadows: <Shadow>[
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,
),
],
),
overflow: TextOverflow.fade,
maxLines: 4,
softWrap: true,
textAlign: TextAlign.center,
),
SizedBox(
height: 15,
),
Text(
exerciseDescription,
style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[300]),
maxLines: 1,
overflow: TextOverflow.fade,
softWrap: true,
),
InkWell(
child: Text(
t("More »"),
style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[200]),
),
onTap: () => {
Navigator.of(context).pushNamed('exerciseTypeDescription', arguments: exerciseBloc.exerciseRepository),
},
),
Divider(
color: Colors.transparent,
),
Text(
t(exerciseTask),
style: GoogleFonts.inter(
fontSize: 14,
color: Colors.orange,
fontWeight: FontWeight.bold,
),
maxLines: 3,
textAlign: TextAlign.center,
overflow: TextOverflow.fade,
softWrap: true,
),
Divider(
color: Colors.transparent,
),
columnQuantityUnit(exerciseBloc),
Divider(
color: Colors.transparent,
),
columnQuantity(exerciseBloc),
Divider(
color: Colors.transparent,
),
exerciseBloc.exerciseRepository.exerciseType.unitQuantity == "1"
? Text(
t("Step") + ": " + "1/4",
style: GoogleFonts.inter(
fontSize: 22,
color: Colors.white,
fontWeight: FontWeight.bold,
),
maxLines: 3,
textAlign: TextAlign.center,
overflow: TextOverflow.fade,
softWrap: true,
)
: Offstage(),
Divider(
color: Colors.transparent,
),
Divider(
color: Colors.transparent,
),
FlatButton(
onPressed: () => {
confirmationDialog(exerciseBloc, menuBloc),
},
child: 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),
),
],
)),
]),
))),
),
));
}
Column columnQuantityUnit(ExerciseNewBloc bloc) {
Column row = Column();
if (bloc.exerciseRepository.exerciseType != null && bloc.exerciseRepository.exerciseType.unitQuantity == "1") {
row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
TextFormField(
focusNode: _nodeText1,
controller: _controller1,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5),
labelText: t(bloc.exerciseRepository.exerciseType.unitQuantityUnit),
labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]),
fillColor: Colors.black38,
filled: true,
border: OutlineInputBorder(
gapPadding: 8.0,
borderRadius: BorderRadius.circular(12.0),
borderSide: BorderSide(color: Colors.white12, width: 0.4),
),
padding: EdgeInsets.only(top: 10, left: 20, right: 20),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('asset/image/WT_black_background.jpg'),
fit: BoxFit.cover,
alignment: Alignment.center,
),
//initialValue: "30",
keyboardType: TextInputType.numberWithOptions(decimal: true),
textInputAction: TextInputAction.done,
style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.yellow[300]),
onChanged: (value) => {bloc.add(ExerciseNewQuantityUnitChange(quantity: double.parse(value)))}),
//] ),
]);
}
return row;
}
Column columnQuantity(ExerciseNewBloc bloc) {
if (bloc.exerciseRepository.exerciseType.unit == "second") {
return Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
Padding(
padding: const EdgeInsets.only(bottom: 0),
child: StreamBuilder<int>(
stream: bloc.stopWatchTimer.rawTime,
initialData: bloc.stopWatchTimer.rawTime.value,
builder: (context, snap) {
final value = snap.data;
final displayTime = StopWatchTimer.getDisplayTime(value, hours: false);
return Column(children: <Widget>[
Padding(
padding: const EdgeInsets.all(8),
child: Text(
displayTime,
style: const TextStyle(fontSize: 40, fontFamily: 'Helvetica', fontWeight: FontWeight.bold, color: Colors.white),
),
),
]);
})),
Padding(
padding: const EdgeInsets.all(2),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: IconButton(
padding: const EdgeInsets.all(2),
color: Colors.white70,
//shape: const StadiumBorder(),
onPressed: () async {
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.start);
Wakelock.enable(); // prevent sleep the phone
},
icon: Icon(CustomIcon.play_1),
iconSize: 40,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: IconButton(
padding: const EdgeInsets.all(2),
iconSize: 40,
color: Colors.white70,
//shape: const StadiumBorder(),
onPressed: () async {
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.stop);
Wakelock.disable();
},
icon: Icon(CustomIcon.stop),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: IconButton(
padding: const EdgeInsets.all(2),
iconSize: 40,
color: Colors.white70,
onPressed: () async {
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.reset);
},
icon: Icon(CustomIcon.creative_commons_zero),
),
),
],
),
),
],
),
),
Divider(),
Divider(),
Text(t("Or type the time manually:"), style: GoogleFonts.inter(color: Colors.white)),
TimePickerWidget(
onChange: (value) => {print("timer"), bloc.add(ExerciseNewQuantityChange(quantity: value))},
)
]);
}
Column row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
TextFormField(
focusNode: _nodeText2,
controller: _controller2,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5),
labelText: t(bloc.exerciseRepository.exerciseType.unit),
labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.orange[50], decorationColor: Colors.black12),
fillColor: Colors.black38,
filled: true,
border: OutlineInputBorder(
gapPadding: 8.0,
borderRadius: BorderRadius.circular(12.0),
borderSide: BorderSide(color: Colors.black26, width: 0.4),
),
),
//initialValue: bloc.quantity.toStringAsFixed(0),
keyboardType: TextInputType.number,
textInputAction: TextInputAction.next,
style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.orange[200]),
onChanged: (value) => {bloc.add(ExerciseNewQuantityChange(quantity: double.parse(value)))},
child: ExerciseSave(
exerciseName: exerciseBloc.exerciseRepository.exerciseType.nameTranslation,
exerciseDescription: exerciseBloc.exerciseRepository.exerciseType.descriptionTranslation,
exerciseTask: t("Please take a relative bigger weight and repeat 12-20 times"),
unit: exerciseBloc.exerciseRepository.exerciseType.unit,
unitQuantityUnit: exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit,
hasUnitQuantity: exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit != null,
onQuantityChanged: (value) {
exerciseBloc.add(ExerciseNewQuantityChange(quantity: double.parse(value)));
},
onUnitQuantityChanged: (value) => exerciseBloc.add(ExerciseNewQuantityUnitChange(quantity: double.parse(value))),
onSubmit: () => confirmationDialog(exerciseBloc, menuBloc),
exerciseTypeId: exerciseType.exerciseTypeId,
)),
bottomNavigationBar: BottomBarMultipleExercises(
isSet: false,
exerciseTypeId: exerciseType.exerciseTypeId,
),
]);
return row;
);
}
void confirmationDialog(ExerciseNewBloc bloc, MenuBloc menuBloc) {
LinkedHashMap args = LinkedHashMap();
print("quantity: " + bloc.quantity.toString());
if (bloc.exerciseRepository.exercise.quantity == null) {
print("Repository quantity modify");
//bloc.exerciseRepository.exercise.quantity = bloc.quantity;
return;
}
@@ -458,6 +141,9 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
: bloc.exerciseRepository.exercise.unitQuantity.toString();
}
// ignore: close_sinks
final TestSetExecuteBloc executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
showCupertinoDialog(
useRootNavigator: true,
context: context,
@@ -491,29 +177,12 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
bloc.exerciseRepository.setCustomer(Cache().userLoggedIn),
bloc.add(ExerciseNewSubmit()),
Navigator.pop(context),
Navigator.pop(context),
log("Ability " +
menuBloc.ability.toString() +
" exerciseType 1rm " +
bloc.exerciseRepository.exerciseType.is1RM().toString()),
if (bloc.exerciseRepository.exerciseType.unitQuantityUnit == null)
if (executeBloc.existsActivePlan() == true)
{
args['exerciseRepository'] = bloc.exerciseRepository,
Navigator.of(context).pushNamed('evaluationPage', arguments: args)
}
else if (menuBloc.ability.equalsTo(ExerciseAbility.oneRepMax))
{
args['exerciseRepository'] = bloc.exerciseRepository,
args['percent'] = 0.75,
args['readonly'] = false,
Navigator.of(context).pushNamed('exerciseControlPage', arguments: args)
}
else if (menuBloc.ability.equalsTo(ExerciseAbility.endurance))
{
args['exerciseRepository'] = bloc.exerciseRepository,
args['percent'] = 0.50,
args['readonly'] = false,
Navigator.of(context).pushNamed('exerciseControlPage', arguments: args)
executeBloc.add(TestSetExecuteExerciseFinished(
exerciseTypeId: bloc.exerciseRepository.exerciseType.exerciseTypeId,
quantity: bloc.exerciseRepository.exercise.quantity,
unitQuantity: bloc.exerciseRepository.exercise.unitQuantity)),
}
},
)
+2 -1
View File
@@ -137,7 +137,8 @@ class _ExercisePlanCustomPage extends State<ExercisePlanCustomPage> with Trans {
List<Widget> _getChildList(List<WorkoutMenuTree> listWorkoutTree, ExercisePlanBloc bloc) {
List<Widget> list = List();
listWorkoutTree.forEach((element) {
final String unitQuantityUnit = element.exerciseType.unitQuantityUnit != null ? element.exerciseType.unitQuantityUnit : "";
final String unitQuantityUnit =
element.exerciseType != null && element.exerciseType.unitQuantityUnit != null ? element.exerciseType.unitQuantityUnit : "";
list.add(TreeViewChild(
startExpanded: false,
parent: Card(
+3
View File
@@ -4,6 +4,8 @@ import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/util/app_language.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.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';
@@ -71,6 +73,7 @@ class SettingsPage extends StatelessWidget with Trans {
}).toList(),
onChanged: (String lang) => {
settingsBloc.add(SettingsChangeLanguage(language: lang)),
Track().track(TrackingEvent.settings_lang, eventValue: lang)
})),
getServer(settingsBloc),
//getDevice(settingsBloc),
+194
View File
@@ -0,0 +1,194 @@
import 'dart:collection';
import 'package:aitrainer_app/bloc/test_set_control/test_set_control_bloc.dart';
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
import 'package:aitrainer_app/bloc/test_set_new/test_set_new_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_bar_multiple_exercises.dart';
import 'package:aitrainer_app/widgets/number_picker.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/modal_progress_hud.dart';
// ignore: must_be_immutable
class TestSetControl extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
final HashMap args = ModalRoute.of(context).settings.arguments;
final ExerciseType exerciseType = args['exerciseType'];
final ExercisePlanDetail exercisePlanDetail = args['exercisePlanDetail'];
// ignore: close_sinks
TestSetExecuteBloc executeBloc = args['testSetExecuteBloc'];
setContext(context);
return Scaffold(
appBar: AppBarNav(depth: 1),
body: Container(
height: double.infinity,
width: double.infinity,
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
image: DecorationImage(
image: Cache().userLoggedIn.sex == "m"
? AssetImage("asset/image/WT_Results_for_men.jpg")
: AssetImage("asset/image/WT_Results_for_female.jpg"),
fit: BoxFit.cover,
alignment: Alignment.center,
),
),
child: BlocProvider(
create: (context) =>
TestSetControlBloc(exercisePlanDetail: exercisePlanDetail, executeBloc: executeBloc, exerciseType: exerciseType),
child: BlocConsumer<TestSetControlBloc, TestSetControlState>(listener: (context, state) {
if (state is TestSetControlError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
}
}, builder: (context, state) {
final bloc = BlocProvider.of<TestSetControlBloc>(context);
return ModalProgressHUD(
child: getExercisForm(bloc, exercisePlanDetail),
inAsyncCall: state is TestSetNewLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
}),
)),
bottomNavigationBar: BottomBarMultipleExercises(
isSet: executeBloc.miniTestSet == true,
exerciseTypeId: exerciseType.exerciseTypeId,
),
);
}
Widget getExercisForm(TestSetControlBloc bloc, ExercisePlanDetail exercisePlanDetail) {
return Container(
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Text(
exercisePlanDetail.exerciseType.nameTranslation,
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
fontSize: 24,
color: Colors.white,
shadows: <Shadow>[
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(),
numberPickForm(bloc),
],
)));
}
Widget numberPickForm(TestSetControlBloc bloc) {
final String strTimes = bloc.step == 2 ? bloc.initQuantity.toStringAsFixed(0) : "maximum";
String title = (bloc.step + 1).toString() + "/4 " + t("Control Exercise:");
List<Widget> listWidgets = [
Text(
title,
style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold),
),
GestureDetector(
onTap: () => {},
child: RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.yellow[300],
),
children: [
TextSpan(text: t("Please repeat with ")),
TextSpan(
text: bloc.initUnitQuantity.toStringAsFixed(0) + " " + bloc.exercisePlanDetail.exerciseType.unitQuantityUnit,
style: GoogleFonts.inter(
decoration: TextDecoration.underline,
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.yellow[100],
),
),
TextSpan(text: t("hu_with") + " "),
TextSpan(
text: strTimes + " ",
style: GoogleFonts.inter(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.yellow[100],
)),
TextSpan(
text: t(
"times!",
)),
]),
)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
NumberPickerWidget(
minValue: 0,
maxValue: 200,
initalValue: bloc.initQuantity.round(),
unit: t("reps"),
color: Colors.yellow[50],
onChange: (value) => {bloc.add(TestSetControlQuantityChange(quantity: value.toDouble()))}),
FlatButton(
padding: EdgeInsets.all(0),
textColor: Colors.white,
focusColor: Colors.blueAccent,
onPressed: () => {
bloc.add(TestSetControlSubmit()),
{
Navigator.of(context).pop(),
}
},
child: 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),
),
],
)),
],
),
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: listWidgets,
);
}
}
+77 -84
View File
@@ -1,32 +1,36 @@
import 'dart:convert';
import 'dart:collection';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/bloc/test_set_edit/test_set_edit_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/model/workout_menu_tree.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:carousel_slider/carousel_slider.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/modal_progress_hud.dart';
import 'package:transparent_image/transparent_image.dart';
import 'package:aitrainer_app/library/image_cache.dart' as wt;
// ignore: must_be_immutable
class TestSetEdit extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
final String templateName = ModalRoute.of(context).settings.arguments;
HashMap args = ModalRoute.of(context).settings.arguments;
final String templateName = args['templateName'];
final String templateNameTranslation = args['templateNameTranslation'];
// ignore: close_sinks
final MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
TestSetEditBloc bloc;
setContext(context);
return Scaffold(
appBar: AppBarNav(depth: 1),
appBar: AppBarNav(
depth: 0,
),
body: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
@@ -37,19 +41,23 @@ class TestSetEdit extends StatelessWidget with Trans {
),
),
child: BlocProvider(
create: (context) =>
TestSetEditBloc(templateName: templateName, workoutTreeRepository: menuBloc.menuTreeRepository, menuBloc: menuBloc),
create: (context) => TestSetEditBloc(
templateName: templateName,
templateNameTranslation: templateNameTranslation,
workoutTreeRepository: menuBloc.menuTreeRepository,
menuBloc: menuBloc),
child: BlocConsumer<TestSetEditBloc, TestSetEditState>(listener: (context, state) {
if (state is TestSetEditError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is TestSetEditSaved) {
Navigator.of(context).pushNamed("home");
Navigator.of(context).pop();
Navigator.of(context).pushNamed("testSetExecute");
}
}, builder: (context, state) {
bloc = BlocProvider.of<TestSetEditBloc>(context);
return ModalProgressHUD(
child: getTestSetWidget(bloc, templateName),
child: getTestSetWidget(bloc, templateNameTranslation),
inAsyncCall: state is TestSetEditLoading,
opacity: 0.5,
color: Colors.black54,
@@ -63,7 +71,7 @@ class TestSetEdit extends StatelessWidget with Trans {
builder: (BuildContext context) {
return DialogCommon(
title: "Start!",
descriptions: "GO",
descriptions: t("Enjoy the exercises, good luck with the testing!"),
text: "OK",
onTap: () => {
Navigator.of(context).pop(),
@@ -78,7 +86,7 @@ class TestSetEdit extends StatelessWidget with Trans {
backgroundColor: Colors.orange[800],
icon: Icon(CustomIcon.clock),
label: Text(
"Start training",
t("Start training"),
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
),
),
@@ -147,42 +155,70 @@ class TestSetEdit extends StatelessWidget with Trans {
]));
}
List<Widget> imageSliders(List<WorkoutMenuTree> alternatives, MenuBloc menuBloc) {
List<Widget> imageSliders(List<WorkoutMenuTree> alternatives, MenuBloc menuBloc, WorkoutMenuTree workoutTree, TestSetEditBloc bloc) {
final List<Widget> list = List();
alternatives.forEach((element) {
list.add(getImageStack(element, menuBloc));
});
list.add(Container(
padding: EdgeInsets.only(top: 25, bottom: 25),
child: ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: Container(
color: Colors.red[600],
child: Center(
child: Text(
"X",
style: GoogleFonts.archivoBlack(
color: Colors.white,
fontSize: 80,
if (bloc.exercisePlanDetails[workoutTree.exerciseTypeId] == null) {
list.add(Container(
padding: EdgeInsets.only(top: 25, bottom: 25),
child: ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: Container(
color: Colors.red[600],
child: Center(
child: Text(
"X",
style: GoogleFonts.archivoBlack(
color: Colors.white,
fontSize: 80,
),
),
),
)))));
)))));
list.add(getImageStack(workoutTree, menuBloc, bloc));
} else {
ExerciseType exerciseType = bloc.exercisePlanDetails[workoutTree.exerciseTypeId];
final WorkoutMenuTree actualWorkoutTree = bloc.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(exerciseType.exerciseTypeId);
list.add(getImageStack(actualWorkoutTree, menuBloc, bloc));
}
alternatives.forEach((element) {
list.add(getImageStack(element, menuBloc, bloc));
});
return list;
}
Stack getImageStack(WorkoutMenuTree element, MenuBloc menuBloc) {
print(element.toJson());
return Stack(alignment: Alignment.bottomLeft, children: [
_getButtonImage(element, menuBloc),
Container(
padding: EdgeInsets.only(left: 15, bottom: 15, right: 15),
child: Text(
element.name,
maxLines: 4,
style: GoogleFonts.archivoBlack(color: element.color, fontSize: 16, height: 1.1),
Stack getImageStack(WorkoutMenuTree element, MenuBloc menuBloc, TestSetEditBloc bloc) {
return Stack(alignment: Alignment.topRight, children: [
Stack(alignment: Alignment.bottomLeft, children: [
MenuImage(imageName: element.imageName, workoutTreeId: element.id),
Container(
padding: EdgeInsets.only(left: 15, bottom: 15, right: 15),
child: Text(
element.name,
maxLines: 4,
style: GoogleFonts.archivoBlack(color: element.color, fontSize: 16, height: 1.1),
),
),
),
]),
Container(
width: 40,
height: 40,
child: ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: GestureDetector(
onTap: () => bloc.add(TestSetEditDeleteExerciseType(exerciseTypeId: element.exerciseTypeId)),
child: Container(
color: Colors.red[600],
child: Center(
child: Text(
"X",
style: GoogleFonts.archivoBlack(
color: Colors.white,
fontSize: 28,
),
),
)))))
]);
}
@@ -204,54 +240,11 @@ class TestSetEdit extends StatelessWidget with Trans {
onPageChanged: (index, reason) =>
bloc.add(TestSetEditChangeExerciseType(index: index, exerciseTypeId: element.exerciseTypeId)),
enlargeStrategy: CenterPageEnlargeStrategy.scale),
items: imageSliders(alternativeMenuItems, bloc.menuBloc),
items: imageSliders(alternativeMenuItems, bloc.menuBloc, workoutTree, bloc),
);
widgets.add(widget);
}
});
return widgets;
}
Widget _getButtonImage(WorkoutMenuTree workoutTree, MenuBloc menuBloc) {
if (workoutTree == null) {
return Offstage();
}
String imageString = menuBloc.getImage(workoutTree.id, workoutTree.imageName);
Widget widget;
if (imageString != null) {
widget = ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: Container(
color: Colors.transparent,
child: FadeInImage(
fadeInDuration: Duration(milliseconds: 100),
image: MemoryImage(base64Decode(imageString)),
placeholder: MemoryImage(kTransparentImage),
),
));
} else {
if (workoutTree.imageName.contains("https")) {
if (!wt.ImageCache().existsImageInMap(workoutTree.id, workoutTree.imageName)) {
widget = ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: Container(
color: Colors.transparent,
child: FadeInImage(
fadeInDuration: Duration(milliseconds: 500),
image: NetworkImage(workoutTree.imageName),
placeholder: MemoryImage(kTransparentImage),
),
));
}
} else {
widget = ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: Container(
color: Colors.transparent,
child: Image.asset(workoutTree.imageName),
));
}
}
return widget;
}
}
+473
View File
@@ -0,0 +1,473 @@
import 'dart:collection';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.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/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/modal_progress_hud.dart';
import 'package:timeline_tile/timeline_tile.dart';
// ignore: must_be_immutable
class TestSetExecute extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
// ignore: close_sinks
final MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
// ignore: close_sinks
TestSetExecuteBloc executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
executeBloc.menuBloc = menuBloc;
executeBloc.add(TestSetExecuteLoad());
setContext(context);
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<TestSetExecuteBloc, TestSetExecuteState>(listener: (context, state) {
if (state is TestSetExecuteError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is TestSetExecuteFinished) {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return Victory(
victory: true,
);
});
}
}, builder: (context, state) {
executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
return ModalProgressHUD(
child: getExercises(executeBloc, context),
inAsyncCall: state is TestSetExecuteLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
}),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => executeExercise(executeBloc, executeBloc.getNext(), context),
backgroundColor: Colors.orange[800],
icon: Icon(CustomIcon.weight_hanging),
label: Text(
t("Next"),
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
),
),
);
}
Widget getExercises(TestSetExecuteBloc bloc, BuildContext context) {
return CustomScrollView(slivers: [
SliverList(delegate: SliverChildListDelegate(getTiles(bloc, context))),
]);
}
List<Widget> getTiles(TestSetExecuteBloc bloc, BuildContext context) {
List<Widget> tiles = List();
tiles.add(getStartTile(bloc));
tiles.addAll(getExerciseTiles(bloc, context));
tiles.add(getEndTile());
/* if (bloc.isDone100Percent()) {
tiles.add(Victory(
victory: true,
));
} */
return tiles;
}
Widget getStartTile(TestSetExecuteBloc bloc) {
return TimelineTile(
alignment: TimelineAlign.manual,
lineXY: 0.1,
isFirst: true,
afterLineStyle: const LineStyle(
color: Colors.orange,
thickness: 6,
),
indicatorStyle: IndicatorStyle(
width: 40,
color: Colors.orange,
padding: const EdgeInsets.all(8),
iconStyle: IconStyle(
color: Colors.white,
iconData: Icons.insert_emoticon,
),
),
endChild: Container(
padding: EdgeInsets.only(top: 30),
constraints: const BoxConstraints(
minHeight: 120,
),
color: Colors.transparent,
child: RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.white,
),
children: [
TextSpan(
text: bloc.isFirst() ? t("Start") : t("Continue"),
style: GoogleFonts.inter(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.yellow[400],
shadows: <Shadow>[
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: t(" your ") + t(bloc.testType),
style: GoogleFonts.inter(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.yellow[400],
shadows: <Shadow>[
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",
style: GoogleFonts.inter(
fontSize: 16,
color: Colors.white,
)),
TextSpan(
text: bloc.testName == null ? "" : bloc.testName,
style: GoogleFonts.inter(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
)),
TextSpan(
text: t("\nyour plan is available for 24 hours"),
style: GoogleFonts.inter(
fontSize: 16,
color: Colors.white,
))
])),
),
);
}
Widget getEndTile() {
return Container(
color: Colors.transparent,
child: TimelineTile(
alignment: TimelineAlign.manual,
lineXY: 0.1,
isLast: true,
beforeLineStyle: const LineStyle(
color: Colors.orange,
thickness: 6,
),
indicatorStyle: IndicatorStyle(
width: 40,
color: Colors.orange,
padding: const EdgeInsets.all(8),
iconStyle: IconStyle(
color: Colors.white,
iconData: Icons.thumb_up,
),
),
endChild: Container(
padding: EdgeInsets.only(top: 50),
constraints: const BoxConstraints(
minHeight: 120,
),
color: Colors.transparent,
child: RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.white,
),
children: [
TextSpan(
text: "Finish!",
style: GoogleFonts.inter(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.yellow[400],
shadows: <Shadow>[
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<Widget> getExerciseTiles(TestSetExecuteBloc bloc, BuildContext context) {
List<Widget> tiles = List();
if (bloc.exercisePlanDetails != null) {
bloc.exercisePlanDetails.forEach((element) {
if (element != null && element.exerciseTypeId != null) {
tiles.add(GestureDetector(
onDoubleTap: () => print("Execute ${element.exerciseType.nameTranslation}"),
onTap: () => executeExercise(bloc, element, context),
child: ExerciseTile(
bloc: bloc,
exercisePlanDetail: element,
)));
}
});
}
return tiles;
}
void executeExercise(TestSetExecuteBloc bloc, ExercisePlanDetail exercisePlanDetail, BuildContext context) {
ExercisePlanDetail next = bloc.getNext();
print("Detail: $next");
if (next != null) {
final HashMap args = HashMap();
args['exerciseType'] = exercisePlanDetail.exerciseType;
args['exercisePlanDetailId'] = exercisePlanDetail.exercisePlanDetailId;
args['testSetExecuteBloc'] = bloc;
String title = "";
String description = "";
String description2 = "";
if (next.exerciseTypeId != exercisePlanDetail.exerciseTypeId) {
title = t("Stop!");
description = t("Please continue with the next exercise in the queue:") + next.exerciseType.nameTranslation;
description2 = t("Or, you can redifine this exercise queue in the Compact Test menu");
} else {
if (exercisePlanDetail.state.equalsTo(ExercisePlanDetailState.inProgress)) {
final HashMap args = HashMap();
args['exerciseType'] = exercisePlanDetail.exerciseType;
args['exercisePlanDetail'] = exercisePlanDetail;
args['testSetExecuteBloc'] = bloc;
Navigator.of(context).pushNamed('testSetControl', arguments: args);
} else {
Navigator.of(context).pushNamed('testSetNew', arguments: args);
}
return;
}
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return DialogCommon(
title: title,
descriptions: description,
description2: description2,
text: "OK",
onTap: () => {Navigator.of(context).pop()},
onCancel: () => {Navigator.of(context).pop()},
);
});
} else {
Navigator.of(context).pushNamed('home');
}
}
}
// ignore: must_be_immutable
class ExerciseTile extends StatelessWidget with Trans {
final TestSetExecuteBloc bloc;
final ExercisePlanDetail exercisePlanDetail;
ExerciseTile({this.bloc, this.exercisePlanDetail});
Widget getIndicator(ExercisePlanDetailState state) {
ExercisePlanDetail next = bloc.getNext();
bool actual = false;
if (next != null) {
if (next.exerciseTypeId == exercisePlanDetail.exerciseTypeId) {
actual = true;
}
}
if (state.equalsTo(ExercisePlanDetailState.inProgress)) {
return ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: Container(
color: actual ? Colors.green : Colors.orange,
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 {
return Image.asset(
"asset/image/pict_reps_volumen_db.png",
);
}
}
@override
Widget build(BuildContext context) {
final ExercisePlanDetailState state = exercisePlanDetail.state;
final bool done = state.equalsTo(ExercisePlanDetailState.finished);
final String countSerie = exercisePlanDetail.exercises == null ? "1" : (exercisePlanDetail.exercises.length).toString();
final String serie = exercisePlanDetail.exerciseType.unitQuantityUnit == null ? "/1" : "/4";
setContext(context);
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(state),
),
endChild: Container(
padding: EdgeInsets.only(left: 10),
child: Row(children: [
Container(
width: 120,
height: 80,
child: MenuImage(
imageName: bloc.getActualImageName(exercisePlanDetail.exerciseType.exerciseTypeId),
workoutTreeId: bloc.getActualWorkoutTreeId(exercisePlanDetail.exerciseType.exerciseTypeId),
)),
SizedBox(
width: 10,
),
Expanded(
child: RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.bold,
color: done ? Colors.grey[400] : Colors.white,
),
children: [
TextSpan(
text: exercisePlanDetail.exerciseType.nameTranslation,
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.bold,
color: done ? Colors.grey[400] : Colors.orange[500],
shadows: <Shadow>[
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,
),
],
)),
exercisePlanDetail.exerciseType.unitQuantityUnit != null
? TextSpan(
text: "\n",
)
: TextSpan(),
exercisePlanDetail.exerciseType.unitQuantityUnit != null
? TextSpan(
text: t(exercisePlanDetail.exerciseType.unitQuantityUnit) + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
: TextSpan(),
exercisePlanDetail.exerciseType.unitQuantityUnit != null
? TextSpan(
text: t(bloc.getExerciseWeight(exercisePlanDetail)),
style: GoogleFonts.inter(
fontSize: 12,
))
: TextSpan(),
TextSpan(
text: "\n",
),
TextSpan(
text: t(exercisePlanDetail.exerciseType.unit) + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
TextSpan(
text: bloc.repeatTimesText(exercisePlanDetail),
style: GoogleFonts.inter(
fontSize: 12,
)),
TextSpan(
text: "\n",
),
TextSpan(
text: t("Set") + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
TextSpan(
text: countSerie + serie,
style: GoogleFonts.inter(
fontSize: 12,
)),
]),
)),
]),
),
),
);
}
}
+95
View File
@@ -0,0 +1,95 @@
import 'dart:collection';
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
import 'package:aitrainer_app/bloc/test_set_new/test_set_new_bloc.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:aitrainer_app/model/exercise_type.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_bar_multiple_exercises.dart';
import 'package:aitrainer_app/widgets/exercise_save.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
// ignore: must_be_immutable
class TestSetNew extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
final HashMap args = ModalRoute.of(context).settings.arguments;
final ExerciseType exerciseType = args['exerciseType'];
final int exercisePlanDetailId = args['exercisePlanDetailId'];
// ignore: close_sinks
final TestSetExecuteBloc executeBloc = args['testSetExecuteBloc'];
TestSetNewBloc bloc;
setContext(context);
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: BlocProvider(
create: (context) => TestSetNewBloc(
exerciseRepository: ExerciseRepository(),
exerciseType: exerciseType,
exercisePlanDetailId: exercisePlanDetailId,
executeBloc: executeBloc),
child: BlocConsumer<TestSetNewBloc, TestSetNewState>(listener: (context, state) {
if (state is TestSetNewError) {
Scaffold.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is TestSetNewReady) {
print("Actual state: ${executeBloc.actualState(exerciseType.exerciseTypeId).toString()}");
if (executeBloc.actualState(exerciseType.exerciseTypeId).equalsTo(ExercisePlanDetailState.inProgress)) {
HashMap args = HashMap();
final ExercisePlanDetail actualExercisePlanDetail = executeBloc.actualExercisePlanDetail(exerciseType.exerciseTypeId);
args['exerciseType'] = exerciseType;
args['exercisePlanDetail'] = actualExercisePlanDetail;
args['testSetExecuteBloc'] = executeBloc;
Navigator.of(context).pushNamed("testSetControl", arguments: args);
}
}
}, builder: (context, state) {
bloc = BlocProvider.of<TestSetNewBloc>(context);
return ModalProgressHUD(
child: getExercises(bloc),
inAsyncCall: state is TestSetNewLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
}),
)),
bottomNavigationBar: BottomBarMultipleExercises(
isSet: executeBloc.miniTestSet == true,
exerciseTypeId: exerciseType.exerciseTypeId,
),
);
}
Widget getExercises(TestSetNewBloc bloc) {
return ExerciseSave(
exerciseName: bloc.exerciseType.nameTranslation,
exerciseDescription: bloc.exerciseType.descriptionTranslation,
exerciseTask: t("Please take a relative bigger weight and repeat 12-20 times"),
unit: bloc.exerciseType.unit,
unitQuantityUnit: bloc.exerciseType.unitQuantityUnit,
hasUnitQuantity: bloc.exerciseType.unitQuantityUnit != null,
onQuantityChanged: (value) {
bloc.add(TestSetNewChangeQuantity(quantity: double.parse(value)));
},
onUnitQuantityChanged: (value) => bloc.add(TestSetNewChangeQuantityUnit(quantity: double.parse(value))),
exerciseTypeId: bloc.exerciseType.exerciseTypeId,
onSubmit: () {
Navigator.of(context).pop();
bloc.add(TestSetNewSubmit());
});
}
}