WT1.1.10 compact test, paralell test
This commit is contained in:
@@ -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
@@ -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)),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)),
|
||||
]),
|
||||
)),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user