WT1.1.18+2 Training Plan days, skip
This commit is contained in:
@@ -234,7 +234,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
||||
onPrimary: Colors.white,
|
||||
primary: Colors.orange,
|
||||
),
|
||||
child: Text(t("Activate")),
|
||||
child: Text(t("Start")),
|
||||
onPressed: () {
|
||||
if (Cache().myTrainingPlan != null) {
|
||||
showCupertinoDialog(
|
||||
|
||||
@@ -4,11 +4,14 @@ import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
|
||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||
import 'package:aitrainer_app/model/customer_training_plan_details.dart';
|
||||
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||
import 'package:aitrainer_app/util/app_localization.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:extended_tabs/extended_tabs.dart';
|
||||
import 'package:ezanimation/ezanimation.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
@@ -16,10 +19,19 @@ import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
||||
import 'package:timeline_tile/timeline_tile.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
class TrainingPlanExecutePage extends StatefulWidget {
|
||||
@override
|
||||
_TrainingPlanExecutePageState createState() => _TrainingPlanExecutePageState();
|
||||
}
|
||||
|
||||
class _TrainingPlanExecutePageState extends State<TrainingPlanExecutePage> with Trans {
|
||||
final scrollController = ScrollController();
|
||||
TrainingPlanBloc? bloc;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final TrainingPlanBloc bloc = BlocProvider.of<TrainingPlanBloc>(context);
|
||||
bloc = BlocProvider.of<TrainingPlanBloc>(context);
|
||||
bloc!.activateDays();
|
||||
setContext(context);
|
||||
return Scaffold(
|
||||
appBar: AppBarNav(depth: 0),
|
||||
@@ -39,7 +51,7 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
} else if (state is TrainingPlanFinished) {}
|
||||
}, builder: (context, state) {
|
||||
return ModalProgressHUD(
|
||||
child: getExercises(bloc),
|
||||
child: ExerciseTabs(bloc: bloc!),
|
||||
inAsyncCall: state is TrainingPlanLoading,
|
||||
opacity: 0.5,
|
||||
color: Colors.black54,
|
||||
@@ -48,7 +60,9 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
}),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () => bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!) : Navigator.of(context).pushNamed('home'),
|
||||
onPressed: () => bloc!.getNext() != null
|
||||
? _ExerciseListState.executeExercise(bloc!, bloc!.getNext()!, context)
|
||||
: Navigator.of(context).pushNamed('home'),
|
||||
backgroundColor: Colors.orange[800],
|
||||
icon: Icon(CustomIcon.weight_hanging),
|
||||
label: Text(
|
||||
@@ -58,10 +72,171 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget getExercises(TrainingPlanBloc bloc) {
|
||||
return CustomScrollView(slivers: [
|
||||
SliverList(delegate: SliverChildListDelegate(getTiles(bloc))),
|
||||
class ExerciseTabs extends StatefulWidget {
|
||||
final TrainingPlanBloc bloc;
|
||||
ExerciseTabs({required this.bloc});
|
||||
@override
|
||||
_ExerciseTabs createState() => _ExerciseTabs();
|
||||
}
|
||||
|
||||
class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
|
||||
late TabController tabController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
tabController = TabController(length: widget.bloc.dayNames.length, vsync: this);
|
||||
tabController.animateTo(0, duration: Duration(milliseconds: 300));
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
tabController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return getTabs(widget.bloc);
|
||||
}
|
||||
|
||||
Widget getTabs(TrainingPlanBloc bloc) {
|
||||
return Column(children: [
|
||||
ExtendedTabBar(
|
||||
tabs: getTabNames(),
|
||||
controller: tabController,
|
||||
),
|
||||
Expanded(
|
||||
child: ExtendedTabBarView(
|
||||
children: getExerciseLists(),
|
||||
controller: tabController,
|
||||
|
||||
/// if link is true and current tabbarview over scroll,
|
||||
/// it will check and scroll ancestor or child tabbarView.
|
||||
link: true,
|
||||
|
||||
/// cache page count
|
||||
/// default is 0.
|
||||
/// if cacheExtent is 1, it has two pages in cache
|
||||
/// null is infinity, it will cache all pages
|
||||
cacheExtent: 0,
|
||||
)),
|
||||
]);
|
||||
}
|
||||
|
||||
List<Tab> getTabNames() {
|
||||
List<Tab> tabs = [];
|
||||
widget.bloc.dayNames.forEach((element) {
|
||||
final Widget widget = RichText(
|
||||
text: TextSpan(
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: AppLocalizations.of(context)!.translate("Training Day") + ": \n",
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
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,
|
||||
),
|
||||
],
|
||||
)),
|
||||
TextSpan(
|
||||
text: element,
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
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,
|
||||
),
|
||||
],
|
||||
)),
|
||||
]));
|
||||
|
||||
tabs.add(Tab(child: widget));
|
||||
});
|
||||
return tabs;
|
||||
}
|
||||
|
||||
List<Widget> getExerciseLists() {
|
||||
List<Widget> list = [];
|
||||
widget.bloc.dayNames.forEach((element) {
|
||||
list.add(ExerciseList(bloc: widget.bloc, dayName: element));
|
||||
});
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
class ExerciseList extends StatefulWidget {
|
||||
final TrainingPlanBloc bloc;
|
||||
final String dayName;
|
||||
ExerciseList({required this.bloc, required this.dayName});
|
||||
|
||||
@override
|
||||
_ExerciseListState createState() => _ExerciseListState();
|
||||
}
|
||||
|
||||
class _ExerciseListState extends State<ExerciseList> with Trans {
|
||||
final scrollController = ScrollController();
|
||||
double offset = 5;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) {
|
||||
animate();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ExerciseList page) {
|
||||
super.didUpdateWidget(page);
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) {
|
||||
animate();
|
||||
});
|
||||
}
|
||||
|
||||
void animate() {
|
||||
offset = widget.bloc.getOffset();
|
||||
if (scrollController.hasClients) {
|
||||
scrollController.animateTo(offset, duration: Duration(milliseconds: 300), curve: Curves.easeIn);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
setContext(context);
|
||||
return CustomScrollView(controller: scrollController, slivers: [
|
||||
SliverList(delegate: SliverChildListDelegate(getTiles(widget.bloc))),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -69,7 +244,7 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
List<Widget> tiles = [];
|
||||
tiles.add(getStartTile(bloc));
|
||||
tiles.addAll(getExerciseTiles(bloc, context));
|
||||
if (bloc.myPlan != null) tiles.add(getEndTile());
|
||||
if (bloc.getMyPlan() != null) tiles.add(getEndTile());
|
||||
return tiles;
|
||||
}
|
||||
|
||||
@@ -77,11 +252,12 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
String startText = "";
|
||||
String explainingText = "";
|
||||
if (null == bloc.getMyPlan()) {
|
||||
startText = "No Active Training Plan";
|
||||
explainingText = "Please select one in the Training menu, or create your custom plan";
|
||||
startText = t("No Active Training Plan");
|
||||
explainingText = t("Please select one in the Training menu, or create your custom plan");
|
||||
} else {
|
||||
startText = bloc.isStarted() ? "Continue your training" : "Start your training";
|
||||
startText = bloc.isStarted() ? t("Continue your training") : t("Start your training");
|
||||
explainingText = bloc.getMyPlan()!.name != null ? bloc.getMyPlan()!.name! : "";
|
||||
print(" *** Plan NAME ${bloc.getMyPlan()!.name}");
|
||||
}
|
||||
|
||||
return TimelineTile(
|
||||
@@ -212,10 +388,14 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
|
||||
List<Widget> getExerciseTiles(TrainingPlanBloc bloc, BuildContext context) {
|
||||
List<Widget> tiles = [];
|
||||
if (bloc.myPlan != null && bloc.myPlan!.details.isNotEmpty) {
|
||||
bloc.myPlan!.details.forEach((element) {
|
||||
if (bloc.getMyPlan() != null &&
|
||||
bloc.getMyPlan()!.details.isNotEmpty &&
|
||||
bloc.getMyPlan()!.days[widget.dayName] != null &&
|
||||
bloc.getMyPlan()!.days[widget.dayName]!.isNotEmpty) {
|
||||
bloc.getMyPlan()!.days[widget.dayName]!.forEach((element) {
|
||||
//bloc.getMyPlan()!.details.forEach((element) {
|
||||
tiles.add(GestureDetector(
|
||||
onTap: () => {},
|
||||
onTap: () => bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!, context) : Navigator.of(context).pushNamed('home'),
|
||||
child: ExerciseTile(
|
||||
bloc: bloc,
|
||||
detail: element,
|
||||
@@ -226,7 +406,7 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
return tiles;
|
||||
}
|
||||
|
||||
void executeExercise(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail) {
|
||||
static void executeExercise(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail, BuildContext context) {
|
||||
CustomerTrainingPlanDetails? next = bloc.getNext();
|
||||
|
||||
if (next != null) {
|
||||
@@ -234,9 +414,10 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
String description = "";
|
||||
String description2 = "";
|
||||
if (next.exerciseTypeId != detail.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");
|
||||
title = AppLocalizations.of(context)!.translate("Stop!");
|
||||
description = AppLocalizations.of(context)!.translate("Please continue with the next exercise in the queue:") +
|
||||
next.exerciseType!.nameTranslation;
|
||||
description2 = AppLocalizations.of(context)!.translate("Or, you can redifine this exercise queue in the Compact Test menu");
|
||||
} else {
|
||||
final HashMap args = HashMap();
|
||||
args['exerciseType'] = next.exerciseType;
|
||||
@@ -264,8 +445,7 @@ class TrainingPlanExecutePage extends StatelessWidget with Trans {
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ExerciseTile extends StatefulWidget with Trans {
|
||||
class ExerciseTile extends StatefulWidget {
|
||||
final TrainingPlanBloc bloc;
|
||||
final CustomerTrainingPlanDetails detail;
|
||||
|
||||
@@ -323,6 +503,16 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
||||
size: 40,
|
||||
color: Colors.green,
|
||||
)));
|
||||
} else if (state.equalsTo(ExercisePlanDetailState.skipped)) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(24.0),
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: Icon(
|
||||
CustomIcon.stop_1,
|
||||
size: 40,
|
||||
color: Colors.grey,
|
||||
)));
|
||||
} else {
|
||||
return Image.asset(
|
||||
"asset/image/pict_reps_volumen_db.png",
|
||||
@@ -334,7 +524,7 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
||||
Widget build(BuildContext context) {
|
||||
setContext(context);
|
||||
final ExercisePlanDetailState state = widget.detail.state;
|
||||
final bool done = state.equalsTo(ExercisePlanDetailState.finished);
|
||||
final bool done = state.equalsTo(ExercisePlanDetailState.finished) || state.equalsTo(ExercisePlanDetailState.skipped);
|
||||
final String countSerie = widget.detail.set.toString();
|
||||
final String step = (widget.detail.exercises.length).toString();
|
||||
String weight = widget.detail.weight!.toStringAsFixed(1);
|
||||
@@ -363,16 +553,38 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
||||
height: 40,
|
||||
indicator: getIndicator(state),
|
||||
),
|
||||
startChild: Container(
|
||||
child: Column(children: [
|
||||
SizedBox(
|
||||
height: 1,
|
||||
),
|
||||
SizedBox(
|
||||
height: 55,
|
||||
),
|
||||
done
|
||||
? Offstage()
|
||||
: IconButton(
|
||||
padding: EdgeInsets.zero,
|
||||
alignment: Alignment.centerLeft,
|
||||
icon: Icon(
|
||||
Icons.skip_next_sharp,
|
||||
size: 30,
|
||||
color: Colors.orange[300],
|
||||
),
|
||||
onPressed: () => skip()),
|
||||
]),
|
||||
),
|
||||
endChild: Container(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: Row(children: [
|
||||
Container(
|
||||
width: 120,
|
||||
height: 80,
|
||||
child: MenuImage(
|
||||
imageName: widget.bloc.getActualImageName(widget.detail.exerciseType!.exerciseTypeId),
|
||||
workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.detail.exerciseType!.exerciseTypeId)!,
|
||||
)),
|
||||
width: 120,
|
||||
height: 80,
|
||||
child: MenuImage(
|
||||
imageName: widget.bloc.getActualImageName(widget.detail.exerciseType!.exerciseTypeId),
|
||||
workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.detail.exerciseType!.exerciseTypeId)!,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
@@ -507,4 +719,30 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void skip() {
|
||||
showCupertinoDialog(
|
||||
useRootNavigator: true,
|
||||
context: context,
|
||||
builder: (_) => CupertinoAlertDialog(
|
||||
title: Text(t("You want to skip really this exercise?")),
|
||||
content: Column(children: [
|
||||
Divider(),
|
||||
]),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(t("No")),
|
||||
onPressed: () => {
|
||||
Navigator.pop(context),
|
||||
}),
|
||||
TextButton(
|
||||
child: Text(t("Yes")),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
widget.bloc.add(TrainingPlanSkipExercise(detail: widget.detail));
|
||||
},
|
||||
)
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ 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/exercise_save.dart';
|
||||
import 'package:aitrainer_app/widgets/number_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -25,7 +24,6 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final HashMap args = ModalRoute.of(context)!.settings.arguments as HashMap;
|
||||
final ExerciseType exerciseType = args['exerciseType'];
|
||||
final CustomerTrainingPlanDetails detail = args['customerTrainingPlanDetails'];
|
||||
// ignore: close_sinks
|
||||
final TrainingPlanBloc bloc = BlocProvider.of<TrainingPlanBloc>(context);
|
||||
@@ -73,10 +71,6 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
||||
),
|
||||
),
|
||||
/* bottomNavigationBar: BottomBarMultipleExercises(
|
||||
//isSet: executeBloc.miniTestSet == true,
|
||||
exerciseTypeId: exerciseType.exerciseTypeId,
|
||||
), */
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,6 +92,8 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
||||
hasUnitQuantity: detail.exerciseType!.unitQuantityUnit != null,
|
||||
weight: detail.weight == -1 ? 30 : detail.weight,
|
||||
repeats: detail.repeats == -1 ? 12 : detail.repeats,
|
||||
set: detail.set,
|
||||
exerciseNr: detail.exercises.length + 1,
|
||||
onUnitQuantityChanged: (value) => bloc.add(TrainingPlanWeightChange(weight: value, detail: detail)),
|
||||
onQuantityChanged: (value) => bloc.add(TrainingPlanRepeatsChange(repeats: value.toInt(), detail: detail)),
|
||||
exerciseTypeId: detail.exerciseType!.exerciseTypeId,
|
||||
|
||||
Reference in New Issue
Block a user