WT 1.1.20 Training Plan improvements, InApp Messageing

This commit is contained in:
bossanyit
2021-06-25 17:30:14 +02:00
parent a595ffb358
commit 211307e63e
36 changed files with 693 additions and 300 deletions
+2 -2
View File
@@ -202,8 +202,8 @@ class RegistrationPage extends StatelessWidget with Trans {
Divider(
color: Colors.transparent,
),
getDataProtection(loginBloc),
loginBloc.emailCheckbox ? getEmailSubscription(loginBloc) : Offstage(),
// getDataProtection(loginBloc),
// loginBloc.emailCheckbox ? getEmailSubscription(loginBloc) : Offstage(),
Divider(
color: Colors.transparent,
),
+57 -17
View File
@@ -254,7 +254,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
ElevatedButton(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white,
primary: Colors.orange,
primary: restricted ? Colors.grey[600] : Colors.orange,
),
child: Text(t("Start")),
onPressed: () {
@@ -294,15 +294,25 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
}
},
),
restricted
/* restricted
? Container(
padding: EdgeInsets.only(bottom: 8),
child: Text(
t("This is a premium function"),
style: GoogleFonts.inter(color: Colors.blue[700]),
style: GoogleFonts.inter(
color: Colors.deepOrange[800],
fontWeight: FontWeight.bold,
shadows: <Shadow>[
Shadow(
offset: Offset(2.0, 2.0),
blurRadius: 4.0,
color: Colors.black54,
),
],
),
),
)
: Offstage(),
: Offstage(), */
]),
)));
@@ -352,7 +362,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
Widget getPlanDetails(TrainingPlan plan, TrainingPlanBloc bloc) {
return SfDataGrid(
headerRowHeight: 30,
rowHeight: 45,
rowHeight: 60,
source: TrainingPlanDetailSource(
plan: plan,
menuBloc: bloc.menuBloc,
@@ -390,14 +400,33 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
Navigator.of(context).pop(),
},
);
}),
},
onDropsetTap: () => {
showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
title: t("Dropset"),
descriptions: t("A drop set is an advanced resistance training technique "),
description2:
t(" in which you focus on completing a set until failure - or the inability to do another repetition."),
text: "OK",
onTap: () => {
Navigator.of(context).pop(),
},
onCancel: () => {
Navigator.of(context).pop(),
},
);
})
}),
headerGridLinesVisibility: GridLinesVisibility.both,
gridLinesVisibility: GridLinesVisibility.both,
columns: [
GridTextColumn(
//columnWidthMode: ColumnWidthMode.lastColumnFill,
maximumWidth: 120,
columnWidthMode: ColumnWidthMode.lastColumnFill,
maximumWidth: 160,
columnName: 'exerciseImage',
label: Container(
color: Colors.green[50],
@@ -472,11 +501,13 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
class TrainingPlanDetailSource extends DataGridSource {
final TrainingPlan plan;
final MenuBloc menuBloc;
final VoidCallback onDropsetTap;
final VoidCallback onWeightTap;
final VoidCallback onRepeatTap;
TrainingPlanDetailSource({
required this.plan,
required this.menuBloc,
required this.onDropsetTap,
required this.onWeightTap,
required this.onRepeatTap,
}) {
@@ -540,7 +571,7 @@ class TrainingPlanDetailSource extends DataGridSource {
]),
))
])
: dataGridCell.columnName == "weight" && dataGridCell.value == -1
: dataGridCell.columnName == "weight" && (dataGridCell.value == -1 || dataGridCell.value == -2)
? GestureDetector(
onTap: () {
onWeightTap();
@@ -549,21 +580,30 @@ class TrainingPlanDetailSource extends DataGridSource {
CustomIcon.question_circle,
color: Colors.indigo[300],
))
: dataGridCell.columnName == "reps" && dataGridCell.value == -1
: dataGridCell.columnName == "weight" && dataGridCell.value == -3
? GestureDetector(
onTap: () {
onRepeatTap();
onDropsetTap();
},
child: Icon(
CustomIcon.question_circle,
color: Colors.indigo[600],
color: Colors.orange[400],
))
: Text(dataGridCell.value.toString(),
style: GoogleFonts.inter(
fontSize: 14,
color: Colors.indigo,
fontWeight: FontWeight.bold,
)));
: dataGridCell.columnName == "reps" && dataGridCell.value == -1
? GestureDetector(
onTap: () {
onRepeatTap();
},
child: Icon(
CustomIcon.question_circle,
color: Colors.indigo[600],
))
: Text(dataGridCell.value.toString(),
style: GoogleFonts.inter(
fontSize: 14,
color: Colors.indigo,
fontWeight: FontWeight.bold,
)));
}).toList());
}
}
+192 -79
View File
@@ -8,8 +8,10 @@ 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/dialog_html.dart';
import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:aitrainer_app/widgets/victory_widget.dart';
import 'package:badges/badges.dart';
import 'package:extended_tabs/extended_tabs.dart';
import 'package:ezanimation/ezanimation.dart';
import 'package:flutter/cupertino.dart';
@@ -125,6 +127,7 @@ class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
@override
void initState() {
super.initState();
print("init TAB ${widget.bloc.dayNames.length} index ${widget.bloc.activeDayIndex}");
tabController = TabController(length: widget.bloc.dayNames.length, vsync: this);
tabController.animateTo(widget.bloc.activeDayIndex, duration: Duration(milliseconds: 300));
}
@@ -143,6 +146,13 @@ class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
Widget getTabs(TrainingPlanBloc bloc) {
return Column(children: [
ExtendedTabBar(
indicator: BoxDecoration(
color: Colors.black87,
border: Border(
bottom: BorderSide(width: 4.0, color: Colors.blue),
top: BorderSide(width: 4.0, color: Colors.blue),
)),
labelPadding: EdgeInsets.only(left: 5, right: 5),
tabs: getTabNames(),
controller: tabController,
onTap: (index) => bloc.activeDayIndex = index,
@@ -168,52 +178,57 @@ class _ExerciseTabs extends State<ExerciseTabs> with TickerProviderStateMixin {
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,
),
],
)),
]));
final Widget widget = Container(
//height: 50,
padding: EdgeInsets.only(top: 2, left: 5, right: 5, bottom: 2),
color: Colors.white24,
child: RichText(
textScaleFactor: 0.8,
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));
});
@@ -559,11 +574,17 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
@override
Widget build(BuildContext context) {
setContext(context);
print("detail ${widget.detail}");
final ExercisePlanDetailState state = widget.detail.state;
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 != null ? widget.detail.weight!.toStringAsFixed(1) : "-";
bool isDrop = false;
if (widget.detail.weight == -3) {
weight = t("DROP");
isDrop = true;
}
String restingTime = widget.detail.restingTime == null ? "" : widget.detail.restingTime!.toStringAsFixed(0);
bool isTest = false;
if (widget.detail.weight != null && widget.detail.weight! == -1) {
@@ -574,6 +595,9 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
if (widget.detail.repeats! == -1) {
repeats = t("MAX");
}
final bool extraExercise = widget.detail.exerciseType!.name == "Warming Up" || widget.detail.exerciseType!.name == "Stretching";
bool buddyWarning = widget.detail.exerciseType == null ? false : widget.detail.exerciseType!.buddyWarning;
setContext(context);
return Container(
color: Colors.transparent,
@@ -620,10 +644,58 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
Container(
width: 120,
height: 80,
child: MenuImage(
imageName: widget.bloc.getActualImageName(widget.detail.exerciseType!.exerciseTypeId),
workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.detail.exerciseType!.exerciseTypeId)!,
),
child: Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.bottomStart(start: -5),
animationDuration: Duration(milliseconds: 500),
animationType: BadgeAnimationType.slide,
badgeColor: Colors.transparent,
showBadge: true,
badgeContent: IconButton(
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogHTML(
title: widget.detail.exerciseType!.nameTranslation,
htmlData: '<p>' + widget.detail.exerciseType!.descriptionTranslation + '</p>');
}),
icon: Icon(
Icons.info_outline,
color: Colors.yellow[200],
)),
child: Badge(
elevation: 0,
padding: EdgeInsets.all(0),
position: BadgePosition.topEnd(end: -8),
animationDuration: Duration(milliseconds: 500),
animationType: BadgeAnimationType.slide,
badgeColor: Colors.transparent,
showBadge: buddyWarning,
badgeContent: IconButton(
onPressed: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
warning: true,
text: "Warning",
descriptions: t("Attention!"),
description2: t("The safe and exact execution of this exercise you need a training buddy or a trainer"),
description3: t("Execution at your own risk!"),
onTap: () => Navigator.of(context).pop(),
onCancel: () => Navigator.of(context).pop(),
title: t('Training Buddy'),
);
}),
icon: Icon(
CustomIcon.exclamation_circle,
color: Colors.red[800],
)),
child: MenuImage(
imageName: widget.bloc.getActualImageName(widget.detail.exerciseType!.exerciseTypeId),
workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.detail.exerciseType!.exerciseTypeId)!,
radius: 12,
))),
),
SizedBox(
width: 10,
@@ -656,18 +728,18 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
),
],
)),
widget.detail.exerciseType!.unitQuantityUnit != null
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise
? TextSpan(
text: "\n",
)
: TextSpan(),
widget.detail.exerciseType!.unitQuantityUnit != null
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise
? TextSpan(
text: t(widget.detail.exerciseType!.unitQuantityUnit!) + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
: TextSpan(),
widget.detail.exerciseType!.unitQuantityUnit != null
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise
? TextSpan(
text: weight,
style: GoogleFonts.inter(
@@ -677,37 +749,50 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
TextSpan(
text: "\n",
),
TextSpan(
text: t(widget.detail.exerciseType!.unit) + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
TextSpan(
text: repeats,
style: GoogleFonts.inter(
fontSize: 12,
)),
!extraExercise
? TextSpan(
text: t(widget.detail.exerciseType!.unit) + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
: TextSpan(),
!extraExercise
? TextSpan(
text: repeats,
style: GoogleFonts.inter(
fontSize: 12,
))
: TextSpan(),
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: step + "/" + countSerie,
style: GoogleFonts.inter(
fontSize: 12,
)),
!extraExercise
? TextSpan(
text: t("Set") + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
: TextSpan(),
!extraExercise
? TextSpan(
text: step + "/" + countSerie,
style: GoogleFonts.inter(
fontSize: 12,
))
: TextSpan(),
TextSpan(
text: "\n",
),
TextSpan(
text: t("Resting time") + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
TextSpan(
text: restingTime + " " + t("min(s)"),
style: GoogleFonts.inter(fontSize: 12, color: done ? Colors.grey[100] : Colors.white, fontWeight: FontWeight.bold)),
!extraExercise
? TextSpan(
text: t("Resting time") + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
: TextSpan(),
!extraExercise
? TextSpan(
text: restingTime + " " + t("min(s)"),
style:
GoogleFonts.inter(fontSize: 12, color: done ? Colors.grey[100] : Colors.white, fontWeight: FontWeight.bold))
: TextSpan(),
]),
)),
isTest
@@ -740,7 +825,35 @@ class _ExerciseTileState extends State<ExerciseTile> with Trans {
)),
]);
})
: Offstage()
: isDrop
? AnimatedBuilder(
animation: animation,
builder: (context, snapshot) {
return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
GestureDetector(
onTap: () => showDialog(
context: context,
builder: (BuildContext context) {
return DialogCommon(
warning: false,
title: t("Drop set"),
descriptions: t("Drop set"),
description2: t("Recommended method:"),
text: "OK",
onTap: () => Navigator.of(context).pop(),
onCancel: () => {
Navigator.of(context).pop(),
},
);
}),
child: Icon(
CustomIcon.question_circle,
color: Colors.orange[200],
size: 16,
)),
]);
})
: Offstage()
]),
),
),
+5 -4
View File
@@ -6,7 +6,6 @@ import 'package:aitrainer_app/model/customer_training_plan_details.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/exercise_save.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';
@@ -43,7 +42,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
}, builder: (context, state) {
return ModalProgressHUD(
child: getExercises(bloc, detail),
inAsyncCall: state is TrainingPlanLoading,
inAsyncCall: state is TrainingPlanExerciseLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
@@ -52,6 +51,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
),
floatingActionButton: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
FloatingActionButton.extended(
heroTag: "skipButton",
onPressed: () => {
Navigator.of(context).pop(),
bloc.add(TrainingPlanSkipExercise(detail: detail)),
@@ -67,6 +67,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
width: 20,
),
FloatingActionButton.extended(
heroTag: "saveButton",
onPressed: () => {
Navigator.of(context).pop(),
bloc.add(TrainingPlanSaveExercise(detail: detail)),
@@ -111,7 +112,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
);
}
Widget getExerciseForm(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail) {
/* Widget getExerciseForm(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail) {
return Container(
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
child: SingleChildScrollView(
@@ -224,5 +225,5 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
crossAxisAlignment: CrossAxisAlignment.start,
children: listWidgets,
);
}
} */
}
+1
View File
@@ -85,6 +85,7 @@ class MyTrainingPlans extends StatelessWidget with Trans, Logging {
getTrainingPlan(t("Training Plans for Women"), "asset/menu/training_plans_q_woman.jpg", "for_woman"),
getTrainingPlan(t("Training Plans of Celebrities"), "asset/menu/training_plans_q_celebrities.jpg", "celebrities"),
getTrainingPlan(t("Training Plans for Gain Strength"), "asset/menu/training_plans_q_gain_strength.jpg", "gain_strength"),
getTrainingPlan(t("Physical Prepare Program for Footgolfers"), "asset/menu/FG_2_edz.jpg", "footgolf"),
]),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,