WT 1.1.11+3 Evaluation, null-safe fixes

This commit is contained in:
bossanyit
2021-04-12 00:51:09 +02:00
parent 01148c6e39
commit 10c8a0a2d8
73 changed files with 3256 additions and 676 deletions
+7 -7
View File
@@ -52,9 +52,11 @@ class AccountPage extends StatelessWidget with Trans {
customerName = accountBloc.customerRepository.firstName! + " " + accountBloc.customerRepository.name!;
customerName = customerName.length < 3 ? t("Personal data") : customerName;
goal = accountBloc.customerRepository.customer.goal != null ? t(accountBloc.customerRepository.customer.goal!) : goal;
fitnessLevel = accountBloc.customerRepository.customer.fitnessLevel != null
? t(capitalize(accountBloc.customerRepository.customer.fitnessLevel!))
goal = accountBloc.customerRepository.customer != null && accountBloc.customerRepository.customer!.goal != null
? t(accountBloc.customerRepository.customer!.goal!)
: goal;
fitnessLevel = accountBloc.customerRepository.customer != null && accountBloc.customerRepository.customer!.fitnessLevel != null
? t(capitalize(accountBloc.customerRepository.customer!.fitnessLevel!))
: fitnessLevel;
bodyType = accountBloc.getAccurateBodyType();
@@ -166,8 +168,6 @@ class AccountPage extends StatelessWidget with Trans {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [Text(t("Available Devices"), style: TextStyle(color: Colors.orange)), Icon(Icons.arrow_forward_ios)]),
//textColor: Colors.orange,
//color: Colors.white,
onPressed: () => {
if (Cache().userLoggedIn != null)
{
@@ -185,7 +185,7 @@ class AccountPage extends StatelessWidget with Trans {
String text = "Logout";
Color buttonColor = Colors.orange;
if (accountBloc.customerRepository.customer.email == null) {
if (accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer!.email == null) {
text = "Login";
buttonColor = Colors.blue;
}
@@ -220,7 +220,7 @@ class AccountPage extends StatelessWidget with Trans {
}
Widget getMyTrainees(BuildContext context, AccountBloc accountBloc) {
if (accountBloc.customerRepository.customer.trainer == 0) {
if (accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer!.trainer == 0) {
return ListTile(
title: Container(),
);
+107 -15
View File
@@ -11,6 +11,10 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import '../bloc/customer_change/customer_change_bloc.dart';
import '../library/dropdown_search.dart';
// ignore: must_be_immutable
class CustomerFitnessPage extends StatefulWidget {
@@ -22,10 +26,8 @@ class CustomerFitnessPage extends StatefulWidget {
}
}
// dropbox for professional sport
class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
late String selected;
String? selected;
bool fulldata = false;
@override
@@ -41,8 +43,6 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
customerRepository = ModalRoute.of(context)!.settings.arguments as CustomerRepository;
}
selected = customerRepository.customer.fitnessLevel!;
PreferredSizeWidget _bar = AppBarMin(
back: true,
);
@@ -56,6 +56,10 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
child: Builder(builder: (context) {
// ignore: close_sinks
CustomerChangeBloc changeBloc = BlocProvider.of<CustomerChangeBloc>(context);
selected = changeBloc.selectedFitnessItem;
if (selected == null) {
selected = FitnessState.beginner;
}
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Container(
@@ -85,7 +89,7 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, FitnessState.beginner),
shape: getShape(changeBloc, FitnessState.beginner),
),
child: Container(
width: cWidth,
@@ -103,14 +107,14 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
onPressed: () => {
setState(() {
selected = FitnessState.beginner;
changeBloc.add(CustomerFitnessChange(fitness: selected));
changeBloc.add(CustomerFitnessChange(fitness: selected!));
}),
}),
Divider(),
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, FitnessState.intermediate),
shape: getShape(changeBloc, FitnessState.intermediate),
),
child: Container(
width: cWidth,
@@ -136,7 +140,7 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
onPressed: () => {
setState(() {
selected = FitnessState.intermediate;
changeBloc.add(CustomerFitnessChange(fitness: selected));
changeBloc.add(CustomerFitnessChange(fitness: selected!));
print(selected);
}),
}),
@@ -144,7 +148,7 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, FitnessState.advanced),
shape: getShape(changeBloc, FitnessState.advanced),
),
child: Container(
width: cWidth,
@@ -170,7 +174,7 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
onPressed: () => {
setState(() {
selected = FitnessState.advanced;
changeBloc.add(CustomerFitnessChange(fitness: selected));
changeBloc.add(CustomerFitnessChange(fitness: selected!));
print(selected);
}),
}),
@@ -178,7 +182,7 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.all(10.0),
shape: getShape(customerRepository, FitnessState.professional),
shape: getShape(changeBloc, FitnessState.professional),
),
child: Container(
width: cWidth,
@@ -204,11 +208,13 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
onPressed: () => {
setState(() {
selected = FitnessState.professional;
changeBloc.add(CustomerFitnessChange(fitness: selected));
changeBloc.add(CustomerFitnessChange(fitness: selected!));
print(selected);
}),
}),
Divider(),
selected == FitnessState.professional ? getSport(changeBloc) : Offstage(),
Divider(),
ElevatedButton(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white,
@@ -228,8 +234,8 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
})));
}
dynamic getShape(CustomerRepository customerRepository, String fitnessLevel) {
String selected = customerRepository.fitnessLevel!;
dynamic getShape(CustomerChangeBloc changeBloc, String fitnessLevel) {
String? selected = changeBloc.selectedFitnessItem;
dynamic returnCode = (selected == fitnessLevel)
? RoundedRectangleBorder(
side: BorderSide(width: 4, color: Colors.orange),
@@ -240,4 +246,90 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
//return
return returnCode;
}
Widget getSport(CustomerChangeBloc bloc) {
Sport? selected = bloc.getSelectedSport;
return Container(
padding: EdgeInsets.only(left: 65, right: 65),
child: DropdownSearch<Sport>(
dropdownSearchDecoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5),
labelText: t("Sport"),
labelStyle: GoogleFonts.inter(fontSize: 16, color: Colors.indigo),
//fillColor: Colors.black38,
filled: false,
border: OutlineInputBorder(
gapPadding: 2.0,
borderRadius: BorderRadius.circular(12.0),
borderSide: BorderSide(color: Colors.blue, width: 0.4),
),
),
mode: Mode.MENU,
compareFn: (Sport i, Sport s) => i.equalsTo(s),
showSelectedItem: true,
selectedItem: selected,
itemAsString: (data) => t(data.toStr()),
onChanged: (data) {
bloc.add(CustomerSportChange(sport: data));
},
dropdownBuilder: _customDropDownItem,
popupItemBuilder: _customMenuBuilder,
popupBarrierColor: Colors.white10,
//popupBackgroundColor: Colors.yellow,
items: Sport.values,
dropDownButton: Icon(
Icons.arrow_drop_down,
color: Colors.indigo,
),
));
//items: FitnessItem().toList()));
}
Widget _customMenuBuilder(BuildContext context, Sport sport, bool isSelected) {
//bool selected = bloc.getSelectedSport;
return Container(
decoration: !isSelected
? BoxDecoration(color: Colors.grey[300])
: BoxDecoration(
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(12),
color: Colors.grey[100],
),
child: ListTile(
selected: isSelected,
title: Text(
t(sport.toStr()),
style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.blue[600]),
),
subtitle: Text(
t(sport.description(sport)),
style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[600]),
),
),
);
}
Widget _customDropDownItem(BuildContext context, Sport? item, String itemDesignation) {
return Container(
child: (item == null)
? ListTile(
contentPadding: EdgeInsets.all(0),
title: Text(
t("No item selected"),
style: GoogleFonts.inter(fontSize: 14, color: Colors.blue[600]),
),
)
: ListTile(
contentPadding: EdgeInsets.all(0),
title: Text(
t(item.toStr()),
style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.blue[600]),
),
subtitle: Text(
t(item.description(item)),
style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[600]),
),
),
);
}
}
+4 -1
View File
@@ -9,6 +9,7 @@ import 'package:aitrainer_app/widgets/app_bar_progress.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';
class GoalsItem {
static String muscle = "gain_muscle";
@@ -70,7 +71,8 @@ class _CustomerGoalPage extends State<CustomerGoalPage> with Trans {
InkWell(
child: Text(
AppLocalizations.of(context)!.translate("Set Your Goals"),
style: TextStyle(color: Colors.orange, fontSize: 50, fontFamily: 'Arial', fontWeight: FontWeight.w900),
style:
GoogleFonts.archivoBlack(color: Colors.orange, fontSize: 30, fontWeight: FontWeight.w900),
),
highlightColor: Colors.white,
),
@@ -146,6 +148,7 @@ class _CustomerGoalPage extends State<CustomerGoalPage> with Trans {
}
dynamic getShape(CustomerChangeBloc customerBloc, String goal) {
if (customerBloc.customerRepository.goal == null) return null;
String selectedGoal = customerBloc.customerRepository.goal!;
dynamic returnCode = (selectedGoal == goal)
? RoundedRectangleBorder(
+88 -62
View File
@@ -26,12 +26,12 @@ class CustomerModifyPage extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
setContext(context);
dynamic arguments = ModalRoute.of(context)!.settings.arguments;
if (arguments is HashMap && arguments['personal_data'] != null) {
fulldata = arguments['personal_data'];
}
setContext(context);
// ignore: close_sinks
final accountBloc = BlocProvider.of<AccountBloc>(context);
@@ -88,7 +88,6 @@ class CustomerModifyPage extends StatelessWidget with Trans {
Widget loadForm(CustomerChangeBloc customerBloc) {
return Form(
key: _scaffoldKey,
autovalidateMode: AutovalidateMode.always,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
padding: EdgeInsets.only(top: 40, left: 25, right: 25, bottom: 250),
@@ -96,7 +95,7 @@ class CustomerModifyPage extends StatelessWidget with Trans {
alignment: Alignment.center,
child: Column(
children: [
Text(t("Edit Profile"), style: GoogleFonts.inter(color: Colors.indigo, fontSize: 16), textAlign: TextAlign.center),
Text(t("Edit Profile"), style: GoogleFonts.archivoBlack(color: Colors.indigo, fontSize: 20), textAlign: TextAlign.center),
Divider(
color: Colors.transparent,
),
@@ -114,7 +113,7 @@ class CustomerModifyPage extends StatelessWidget with Trans {
borderSide: BorderSide(color: Colors.green[50]!, width: 0.4),
),
),
initialValue: customerBloc.customerRepository.customer.email,
initialValue: customerBloc.customerRepository.customer!.email,
autovalidateMode: AutovalidateMode.always,
validator: (val) {
String? validator = customerBloc.emailValidation(val!);
@@ -147,8 +146,8 @@ class CustomerModifyPage extends StatelessWidget with Trans {
borderSide: BorderSide(color: Colors.green[50]!, width: 0.4),
),
),
initialValue: customerBloc.customerRepository.customer.password,
autovalidateMode: AutovalidateMode.always,
initialValue: customerBloc.customerRepository.customer!.password,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (val) {
String? validator = customerBloc.passwordValidation(val!);
return validator == null ? null : t(validator);
@@ -173,8 +172,8 @@ class CustomerModifyPage extends StatelessWidget with Trans {
borderSide: BorderSide(color: Colors.green[50]!, width: 0.4),
),
),
initialValue: customerBloc.customerRepository.customer.name,
autovalidateMode: AutovalidateMode.always,
initialValue: customerBloc.customerRepository.customer!.name,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (val) {
return customerBloc.nameValidation(val);
},
@@ -198,8 +197,8 @@ class CustomerModifyPage extends StatelessWidget with Trans {
borderSide: BorderSide(color: Colors.green[50]!, width: 0.4),
),
),
initialValue: customerBloc.customerRepository.customer.firstname,
autovalidateMode: AutovalidateMode.always,
initialValue: customerBloc.customerRepository.customer!.firstname,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (val) {
return customerBloc.nameValidation(val);
},
@@ -210,65 +209,92 @@ class CustomerModifyPage extends StatelessWidget with Trans {
Divider(
color: Colors.transparent,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 4,
child: Text(t("Birth Year"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)),
),
NumberPickerWidget(
minValue: 1930,
maxValue: 2100,
initalValue: customerBloc.year!.toInt(),
unit: " ",
color: Colors.indigo,
onChange: (value) => {customerBloc.add(CustomerBirthYearChange(year: value.toInt()))}),
SizedBox(width: 80),
],
Container(
padding: EdgeInsets.only(left: 15),
decoration: BoxDecoration(
color: Colors.white24,
border: Border.all(color: Colors.black, width: 0.4),
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 2,
child: Text(t("Birth Year"),
style: GoogleFonts.inter(
fontWeight: FontWeight.normal,
fontSize: 18,
))),
NumberPickerWidget(
minValue: 1930,
maxValue: DateTime.now().year,
initalValue: customerBloc.year!.toInt(),
unit: " ",
color: Colors.indigo,
onChange: (value) => {customerBloc.add(CustomerBirthYearChange(year: value.toInt()))}),
SizedBox(width: 30),
],
)),
Divider(
color: Colors.transparent,
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
flex: 4,
child: Text(t("Weight"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)),
),
NumberPickerWidget(
minValue: 0,
maxValue: 200,
initalValue: customerBloc.weight.toInt(),
unit: " ",
color: Colors.indigo,
onChange: (value) => {customerBloc.add(CustomerWeightChange(weight: value.toInt()))}),
SizedBox(width: 80),
],
Container(
padding: EdgeInsets.only(left: 15),
decoration: BoxDecoration(
color: Colors.white24,
border: Border.all(color: Colors.black, width: 0.4),
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
flex: 4,
child: Text(t("Weight"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)),
),
NumberPickerWidget(
minValue: 0,
maxValue: 200,
initalValue: customerBloc.weight.toInt(),
unit: " ",
color: Colors.indigo,
onChange: (value) => {customerBloc.add(CustomerWeightChange(weight: value.toInt()))}),
SizedBox(width: 30),
],
)),
Divider(
color: Colors.transparent,
),
Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
flex: 4,
child: Text(t("Height"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)),
),
NumberPickerWidget(
minValue: 0,
maxValue: 230,
initalValue: customerBloc.height.toInt(),
unit: " ",
color: Colors.indigo[300]!,
onChange: (value) => {customerBloc.add(CustomerHeightChange(height: value.toInt()))}),
SizedBox(width: 80),
],
Container(
padding: EdgeInsets.only(left: 15),
decoration: BoxDecoration(
color: Colors.white24,
border: Border.all(color: Colors.black, width: 0.4),
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
flex: 4,
child: Text(t("Height"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 18)),
),
NumberPickerWidget(
minValue: 0,
maxValue: 230,
initalValue: customerBloc.height.toInt(),
unit: " ",
color: Colors.indigo[300]!,
onChange: (value) => {customerBloc.add(CustomerHeightChange(height: value.toInt()))}),
SizedBox(width: 30),
],
)),
Divider(
color: Colors.transparent,
),
Divider(),
ToggleSwitch(
minWidth: 80.0,
minHeight: 50.0,
fontSize: 14.0,
initialLabelIndex: customerBloc.customerRepository.customer.sex == "m" ? 0 : 1,
initialLabelIndex: customerBloc.customerRepository.customer!.sex == "m" ? 0 : 1,
activeBgColor: Colors.indigo,
activeFgColor: Colors.white,
inactiveBgColor: Colors.white30,
@@ -1,5 +1,6 @@
import 'dart:collection';
import 'dart:ui';
import 'package:aitrainer_app/util/enums.dart';
import 'package:intl/intl.dart';
import 'package:aitrainer_app/bloc/result/result_bloc.dart';
import 'package:aitrainer_app/util/app_language.dart';
@@ -281,6 +282,7 @@ class EvaluationPage extends StatelessWidget with Trans {
}
Widget getSuggestionWidget(ResultBloc resultBloc, String title, String picture, String repeats, double percent, String restTime) {
double _opacity = 1;
String unitQuantityUnit = resultBloc.exerciseRepository.exerciseType!.unitQuantityUnit == null
? ""
: resultBloc.exerciseRepository.exerciseType!.unitQuantityUnit!;
@@ -325,7 +327,7 @@ class EvaluationPage extends StatelessWidget with Trans {
softWrap: true,
style: GoogleFonts.archivoBlack(
fontSize: 18,
color: Colors.orange,
color: Colors.orange.withOpacity(_opacity),
shadows: <Shadow>[
Shadow(
offset: Offset(5.0, 5.0),
@@ -398,7 +400,7 @@ class EvaluationPage extends StatelessWidget with Trans {
Widget getSummary(ResultBloc bloc) {
int index = 0;
List<Text> resultList = [];
List<Widget> resultList = [];
bloc.exerciseRepository.actualExerciseList!.forEach((actual) {
//final String unit = t(bloc.exerciseRepository.exerciseType.unit);
@@ -421,36 +423,248 @@ class EvaluationPage extends StatelessWidget with Trans {
exerciseElement = t("3rd Control") + ": ";
}
index++;
resultList.add(
Text(exerciseElement + exerciseRepeats + exerciseUnitQuantity + " " + t(unit),
textAlign: TextAlign.center,
maxLines: 2,
softWrap: true,
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 18,
fontSize: 20,
color: Colors.white,
shadows: <Shadow>[
Shadow(
offset: Offset(5.0, 5.0),
blurRadius: 12.0,
color: Colors.black54,
),
children: [
TextSpan(text: exerciseElement),
TextSpan(
text: exerciseRepeats + exerciseUnitQuantity + " " + t(unit),
style: GoogleFonts.archivoBlack(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.yellow[300]!,
),
Shadow(
offset: Offset(-3.0, 3.0),
blurRadius: 12.0,
color: Colors.black54,
),
],
)),
);
),
]),
));
});
return Column(children: resultList);
}
Widget getEvaluationWidget(ResultBloc bloc) {
List<Widget> resultList = [];
print("Act ${bloc.exerciseRepository.actualExerciseList}");
if (bloc.exerciseRepository.actualExerciseList == null || bloc.exerciseRepository.actualExerciseList!.isEmpty) {
return Offstage();
}
final int exerciseTypeId = bloc.exerciseRepository.actualExerciseList![0].exerciseTypeId!;
final double quantity = bloc.exerciseRepository.actualExerciseList![0].quantity!;
String eval = bloc.evaluationRepository.getEvaluationTextByExerciseType(exerciseTypeId, quantity);
Color color = bloc.evaluationRepository.getEvaluationColor(eval);
double compareBest = bloc.exerciseRepository.getBestExercisePercent(bloc.exerciseRepository.actualExerciseList![0]);
double compareLast = bloc.exerciseRepository.getLastExercisePercent(bloc.exerciseRepository.actualExerciseList![0]);
bool has1RM = bloc.exerciseRepository.actualExerciseList![0].unitQuantity != null;
double? bestCompared1RM;
double? lastCompared1RM;
if (has1RM) {
lastCompared1RM = bloc.exerciseRepository.getLast1RMPercent(bloc.exerciseRepository.actualExerciseList![0]);
bestCompared1RM = bloc.exerciseRepository.getBest1RMPercent(bloc.exerciseRepository.actualExerciseList![0]);
}
if (!EvaluationText.fair.equalsStringTo(eval)) {
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.white,
),
children: [
TextSpan(text: t("Your result is: ")),
TextSpan(
text: eval,
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
color: color,
),
),
]),
));
resultList.add(Divider(color: Colors.transparent));
}
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
color: Colors.white,
),
children: [
TextSpan(text: t("Compared with...")),
]),
));
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
color: Colors.white,
),
children: [
TextSpan(text: t("your best")),
TextSpan(text: " "),
TextSpan(text: has1RM ? t("volumen") : t("exercise")),
TextSpan(text: ": "),
TextSpan(
text: compareBest.toStringAsFixed(1) + "%",
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
color: compareBest >= 0 ? Colors.green : Colors.red[600],
),
),
]),
));
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
color: Colors.white,
),
children: [
TextSpan(text: t("your last")),
TextSpan(text: " "),
TextSpan(text: has1RM ? t("volumen") : t("exercise")),
TextSpan(text: ": "),
TextSpan(
text: compareLast.toStringAsFixed(1) + "%",
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
color: compareLast >= 0 ? Colors.green : Colors.red[600],
),
),
]),
));
resultList.add(Divider(color: Colors.transparent));
if (has1RM) {
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
color: Colors.white,
),
children: [
TextSpan(text: t("best")),
TextSpan(text: " "),
TextSpan(text: t("1RM")),
TextSpan(text: ": "),
TextSpan(
text: bestCompared1RM!.toStringAsFixed(1) + "%",
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
color: bestCompared1RM >= 0 ? Colors.green : Colors.red[600],
),
),
]),
));
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
color: Colors.white,
),
children: [
TextSpan(text: t("last")),
TextSpan(text: " "),
TextSpan(text: t("1RM")),
TextSpan(text: ": "),
TextSpan(
text: lastCompared1RM!.toStringAsFixed(1) + "%",
style: GoogleFonts.archivoBlack(
fontWeight: FontWeight.bold,
color: lastCompared1RM >= 0 ? Colors.green : Colors.red[600],
),
),
]),
));
}
if (!Cache().hasPurchased) {
resultList.add(Divider());
resultList.add(Divider());
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
fontWeight: FontWeight.normal,
color: Colors.white,
),
children: [
TextSpan(
text: t('How can serve you this result?'),
style: GoogleFonts.inter(
color: Colors.white,
),
),
]),
));
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
fontWeight: FontWeight.normal,
color: Colors.white,
),
children: [
TextSpan(
text: t('Get the Fastlane to your'),
style: GoogleFonts.inter(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
]),
));
resultList.add(RichText(
text: TextSpan(
style: GoogleFonts.inter(
fontSize: 20,
fontWeight: FontWeight.normal,
color: Colors.white,
),
children: [
TextSpan(
text: t('Development'),
style: GoogleFonts.inter(
fontWeight: FontWeight.bold,
color: Colors.yellow[300],
),
)
])));
resultList.add(TextButton(
onPressed: () => {Navigator.of(context).pushNamed("salesPage")},
child: Stack(
alignment: Alignment.center,
children: [
Image.asset('asset/icon/gomb_orange_a.png', width: 140, height: 60),
Text(
t("Go"),
style: GoogleFonts.inter(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
],
),
));
}
return Column(children: resultList);
}
Widget getResultSummary(ResultBloc resultBloc) {
return SliverList(
delegate: SliverChildListDelegate(
[Divider(color: Colors.transparent), getSummary(resultBloc)],
[Divider(color: Colors.transparent), getSummary(resultBloc), Divider(color: Colors.transparent), getEvaluationWidget(resultBloc)],
),
);
}
+9 -5
View File
@@ -45,7 +45,8 @@ class _ExerciseExecuteAddPage extends State<ExerciseExecutePlanAddPage> with Tra
exercisePlanRepository: planBloc.exercisePlanRepository,
customerId: customerId,
workoutTree: workoutTree,
planBloc: planBloc),
planBloc: planBloc)
..add(ExerciseExecutePlanAddLoad()),
child: BlocConsumer<ExerciseExecutePlanAddBloc, ExerciseExecutePlanAddState>(listener: (context, state) {
if (state is ExerciseExecutePlanAddError) {
ScaffoldMessenger.of(context).showSnackBar(
@@ -54,7 +55,7 @@ class _ExerciseExecuteAddPage extends State<ExerciseExecutePlanAddPage> with Tra
}, builder: (context, state) {
// ignore: close_sinks
final exerciseBloc = BlocProvider.of<ExerciseExecutePlanAddBloc>(context);
if (state is ExerciseExecutePlanAddReady) {
if (state is ExerciseExecutePlanAddReady && _controller.hasClients) {
_controller.animateTo(exerciseBloc.scrollOffset, duration: Duration(milliseconds: 300), curve: Curves.easeIn);
}
return ModalProgressHUD(
@@ -67,7 +68,10 @@ class _ExerciseExecuteAddPage extends State<ExerciseExecutePlanAddPage> with Tra
}));
}
Form getControlForm(ExerciseExecutePlanAddBloc exerciseBloc) {
Widget getControlForm(ExerciseExecutePlanAddBloc exerciseBloc) {
if (exerciseBloc.exerciseRepository.exerciseType == null || exerciseBloc.quantity == null) {
return Offstage();
}
String exerciseName = AppLanguage().appLocal == Locale("en")
? exerciseBloc.exerciseRepository.exerciseType!.name
: exerciseBloc.exerciseRepository.exerciseType!.nameTranslation;
@@ -186,7 +190,7 @@ class _ExerciseExecuteAddPage extends State<ExerciseExecutePlanAddPage> with Tra
minValue: 0,
maxValue: 1000,
fontSize: 16,
initalValue: exerciseBloc.unitQuantity.toInt(),
initalValue: exerciseBloc.unitQuantity!.toInt(),
unit: t(exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit!),
color: Colors.yellow[50]!,
onChange: (value) => {exerciseBloc.add(ExerciseExecutePlanAddChangeUnitQuantity(quantity: value.toDouble()))}),
@@ -194,7 +198,7 @@ class _ExerciseExecuteAddPage extends State<ExerciseExecutePlanAddPage> with Tra
minValue: 0,
maxValue: 200,
fontSize: 16,
initalValue: exerciseBloc.quantity.toInt(),
initalValue: exerciseBloc.quantity!.toInt(),
unit: t(exerciseBloc.exerciseRepository.exerciseType!.unit), //t("repeat"),
color: Colors.yellow[50]!,
onChange: (value) => {exerciseBloc.add(ExerciseExecutePlanAddChangeQuantity(quantity: value.toDouble()))}),
+6 -8
View File
@@ -1,6 +1,5 @@
import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_log/exercise_log_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/dialog_premium.dart';
@@ -196,13 +195,12 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
exercise.summary == null ? "" : exercise.summary!,
style: TextStyle(fontSize: 12, color: Colors.blue[800]),
)),
IconButton(
iconSize: 36,
icon: Icon(CustomIcon.heart_1, color: Colors.orange[800]),
onPressed: () {
evaluation(exerciseRepository, exercise);
},
),
GestureDetector(
onTap: () => evaluation(exerciseRepository, exercise),
child: Image.asset(
"asset/image/kupa.png",
width: 35,
)),
IconButton(
icon: Icon(Icons.delete, color: Colors.black12),
onPressed: () {
+13 -4
View File
@@ -107,7 +107,9 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
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"),
exerciseTask: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit != null
? t("Please take a relative bigger weight and repeat 12-20 times and do your best! MAXIMIZE it!")
: t("Please repeat as much times as you can! MAXIMIZE it!"),
unit: exerciseBloc.exerciseRepository.exerciseType!.unit,
unitQuantityUnit: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit,
hasUnitQuantity: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit != null,
@@ -121,10 +123,13 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
floatingActionButton: FloatingActionButton.extended(
onPressed: () => save(exerciseBloc, menuBloc),
backgroundColor: Colors.orange[800],
icon: Icon(CustomIcon.save),
icon: Icon(
CustomIcon.save,
size: 20,
),
label: Text(
t("Save"),
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 12),
),
),
bottomNavigationBar: BottomBarMultipleExercises(
@@ -164,11 +169,15 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
// ignore: close_sinks
final TestSetExecuteBloc executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
final question = bloc.exerciseRepository.exercise!.quantity! == 12.0
? "Did you try the MAXIMUM what you can do? Are you sure we save the exercise with ONLY 12 repeats?"
: "Do you save this exercise with these parameters?";
showCupertinoDialog(
useRootNavigator: true,
context: context,
builder: (_) => CupertinoAlertDialog(
title: Text(t("Do you save this exercise with these parameters?")),
title: Text(t(question)),
content: Column(children: [
Divider(),
Text(
+3 -3
View File
@@ -120,7 +120,7 @@ class LoginPage extends StatelessWidget with Trans {
initialValue: loginBloc.userRepository.user.email,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (val) {
String? validationText = loginBloc.emailValidation(val!);
String? validationText = loginBloc.emailValidation(val);
return validationText == null ? null : t(validationText);
},
onChanged: (value) => loginBloc.add(LoginEmailChange(email: value)),
@@ -150,9 +150,9 @@ class LoginPage extends StatelessWidget with Trans {
),
),
initialValue: loginBloc.userRepository.user.password,
autovalidateMode: AutovalidateMode.always,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (val) {
String? validationText = loginBloc.passwordValidation(val!);
String? validationText = loginBloc.passwordValidation(val);
return validationText == null ? null : t(validationText);
},
onChanged: (value) => loginBloc.add(LoginPasswordChange(password: value)),
+1 -1
View File
@@ -163,7 +163,7 @@ class RegistrationPage extends StatelessWidget with Trans {
),
),
initialValue: loginBloc.userRepository.user.password,
autovalidateMode: AutovalidateMode.always,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (val) {
final String? validator = loginBloc.passwordValidation(val!);
return validator == null ? null : t(validator);
+1 -1
View File
@@ -31,7 +31,7 @@ class ResetPasswordPage extends StatelessWidget with Trans {
if (state is PasswordResetError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(t(state.message), style: TextStyle(color: Colors.white))));
} else if (state is PasswordResetReady) {
} else if (state is PasswordResetFinished) {
Navigator.of(context).pop();
}
},
+1 -1
View File
@@ -150,7 +150,7 @@ class SalesPage extends StatelessWidget with Trans, Logging {
bloc.product2Display.forEach((element) {
final String title = element.sort == 3 ? t("Montly") : t("Annual");
final String desc4 = element.sort == 1 ? "" : t("Predictions with Artificial Intelligence");
late String badge;
String? badge;
if (element.sort == 2) {
badge = t("14% discount");
} else if (element.sort == 1) {
+82 -24
View File
@@ -3,12 +3,16 @@ 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/library/fade_in.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.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/dialog_common.dart';
import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:aitrainer_app/widgets/victory_widget.dart';
import 'package:ezanimation/ezanimation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
@@ -64,7 +68,9 @@ class TestSetExecute extends StatelessWidget with Trans {
}),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => executeExercise(executeBloc, executeBloc.getNext()!, context),
onPressed: () => executeBloc.getNext() != null
? executeExercise(executeBloc, executeBloc.getNext()!, context)
: Navigator.of(context).pushNamed('home'),
backgroundColor: Colors.orange[800],
icon: Icon(CustomIcon.weight_hanging),
label: Text(
@@ -86,11 +92,6 @@ class TestSetExecute extends StatelessWidget with Trans {
tiles.add(getStartTile(bloc));
tiles.addAll(getExerciseTiles(bloc, context));
tiles.add(getEndTile());
/* if (bloc.isDone100Percent()) {
tiles.add(Victory(
victory: true,
));
} */
return tiles;
}
@@ -254,7 +255,9 @@ class TestSetExecute extends StatelessWidget with Trans {
//if (element != null && element.exerciseTypeId != null) {
tiles.add(GestureDetector(
onDoubleTap: () => print("Execute ${element.exerciseType!.nameTranslation}"),
onTap: () => executeExercise(bloc, element, context),
onTap: () => element.state.equalsTo(ExercisePlanDetailState.finished)
? evaluation(bloc, element)
: executeExercise(bloc, element, context),
child: ExerciseTile(
bloc: bloc,
exercisePlanDetail: element,
@@ -266,12 +269,27 @@ class TestSetExecute extends StatelessWidget with Trans {
return tiles;
}
void evaluation(TestSetExecuteBloc bloc, ExercisePlanDetail planDetail) {
if (planDetail.exercises != null && planDetail.exercises!.isNotEmpty) {
ExerciseRepository exerciseRepository = ExerciseRepository();
exerciseRepository.start = planDetail.exercises![0].dateAdd;
exerciseRepository.exerciseList = Cache().getExercises();
exerciseRepository.actualExerciseList = planDetail.exercises!;
print("actualEx ${exerciseRepository.actualExerciseList}");
LinkedHashMap args = LinkedHashMap();
args['exerciseRepository'] = exerciseRepository;
args['exercise'] = planDetail.exercises![0];
args['past'] = true;
Navigator.of(context).pushNamed('evaluationPage', arguments: args);
}
}
void executeExercise(TestSetExecuteBloc bloc, ExercisePlanDetail exercisePlanDetail, BuildContext context) {
ExercisePlanDetail? next = bloc.getNext();
if (next != null) {
final HashMap args = HashMap();
args['exerciseType'] = exercisePlanDetail.exerciseType;
args['exerciseType'] = next.exerciseType;
args['exercisePlanDetailId'] = exercisePlanDetail.exercisePlanDetailId;
args['testSetExecuteBloc'] = bloc;
String title = "";
@@ -314,17 +332,43 @@ class TestSetExecute extends StatelessWidget with Trans {
}
// ignore: must_be_immutable
class ExerciseTile extends StatelessWidget with Trans {
class ExerciseTile extends StatefulWidget {
final TestSetExecuteBloc bloc;
final ExercisePlanDetail exercisePlanDetail;
ExerciseTile({required this.bloc, required this.exercisePlanDetail});
@override
_ExerciseTileState createState() => _ExerciseTileState();
}
class _ExerciseTileState extends State<ExerciseTile> with Trans {
final EzAnimation animation = EzAnimation(1.0, 30.0, Duration(seconds: 3), reverseCurve: Curves.easeIn);
@override
void initState() {
animation.start();
animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
setState(() {});
}
});
super.initState();
}
@override
bool didUpdateWidget(ExerciseTile oldWidget) {
super.didUpdateWidget(oldWidget);
animation.start();
return true;
}
Widget getIndicator(ExercisePlanDetailState state) {
ExercisePlanDetail? next = bloc.getNext();
ExercisePlanDetail? next = widget.bloc.getNext();
bool actual = false;
if (next != null) {
if (next.exerciseTypeId == exercisePlanDetail.exerciseTypeId) {
if (next.exerciseTypeId == widget.exercisePlanDetail.exerciseTypeId) {
actual = true;
}
}
@@ -357,10 +401,11 @@ class ExerciseTile extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
final ExercisePlanDetailState state = exercisePlanDetail.state;
final ExercisePlanDetailState state = widget.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";
final String countSerie = widget.exercisePlanDetail.exercises == null ? "1" : (widget.exercisePlanDetail.exercises!.length).toString();
final String serie = widget.exercisePlanDetail.exerciseType!.unitQuantityUnit == null ? "/1" : "/4";
setContext(context);
return Container(
color: Colors.transparent,
@@ -387,8 +432,8 @@ class ExerciseTile extends StatelessWidget with Trans {
width: 120,
height: 80,
child: MenuImage(
imageName: bloc.getActualImageName(exercisePlanDetail.exerciseType!.exerciseTypeId),
workoutTreeId: bloc.getActualWorkoutTreeId(exercisePlanDetail.exerciseType!.exerciseTypeId)!,
imageName: widget.bloc.getActualImageName(widget.exercisePlanDetail.exerciseType!.exerciseTypeId),
workoutTreeId: widget.bloc.getActualWorkoutTreeId(widget.exercisePlanDetail.exerciseType!.exerciseTypeId)!,
)),
SizedBox(
width: 10,
@@ -403,7 +448,7 @@ class ExerciseTile extends StatelessWidget with Trans {
),
children: [
TextSpan(
text: exercisePlanDetail.exerciseType!.nameTranslation,
text: widget.exercisePlanDetail.exerciseType!.nameTranslation,
style: GoogleFonts.inter(
fontSize: 14,
fontWeight: FontWeight.bold,
@@ -421,20 +466,20 @@ class ExerciseTile extends StatelessWidget with Trans {
),
],
)),
exercisePlanDetail.exerciseType!.unitQuantityUnit != null
widget.exercisePlanDetail.exerciseType!.unitQuantityUnit != null
? TextSpan(
text: "\n",
)
: TextSpan(),
exercisePlanDetail.exerciseType!.unitQuantityUnit != null
widget.exercisePlanDetail.exerciseType!.unitQuantityUnit != null
? TextSpan(
text: t(exercisePlanDetail.exerciseType!.unitQuantityUnit!) + ": ",
text: t(widget.exercisePlanDetail.exerciseType!.unitQuantityUnit!) + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold))
: TextSpan(),
exercisePlanDetail.exerciseType!.unitQuantityUnit != null
widget.exercisePlanDetail.exerciseType!.unitQuantityUnit != null
? TextSpan(
text: t(bloc.getExerciseWeight(exercisePlanDetail)),
text: t(widget.bloc.getExerciseWeight(widget.exercisePlanDetail)),
style: GoogleFonts.inter(
fontSize: 12,
))
@@ -443,11 +488,11 @@ class ExerciseTile extends StatelessWidget with Trans {
text: "\n",
),
TextSpan(
text: t(exercisePlanDetail.exerciseType!.unit) + ": ",
text: t(widget.exercisePlanDetail.exerciseType!.unit) + ": ",
style: GoogleFonts.inter(
fontSize: 12, color: done ? Colors.grey[100] : Colors.yellow[400], fontWeight: FontWeight.bold)),
TextSpan(
text: bloc.repeatTimesText(exercisePlanDetail),
text: widget.bloc.repeatTimesText(widget.exercisePlanDetail),
style: GoogleFonts.inter(
fontSize: 12,
)),
@@ -465,6 +510,19 @@ class ExerciseTile extends StatelessWidget with Trans {
)),
]),
)),
done
? AnimatedBuilder(
animation: animation,
builder: (context, snapshot) {
return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Image.asset(
"asset/image/kupa.png",
width: animation.value,
),
Text("Result", style: GoogleFonts.inter(fontSize: 10, color: Colors.white)),
]);
})
: Offstage()
]),
),
),
+4 -2
View File
@@ -92,9 +92,11 @@ class TestSetNew extends StatelessWidget with Trans {
return ExerciseSave(
exerciseName: bloc.exerciseType.nameTranslation,
exerciseDescription: bloc.exerciseType.descriptionTranslation,
exerciseTask: t("Please take a relative bigger weight and repeat 12-20 times"),
exerciseTask: bloc.exerciseType.unitQuantityUnit != null
? t("Please take a relative bigger weight and repeat 12-20 times and do your best! MAXIMIZE it!")
: t("Please repeat as much times as you can! MAXIMIZE it!"),
unit: bloc.exerciseType.unit,
unitQuantityUnit: bloc.exerciseType.unitQuantityUnit!,
unitQuantityUnit: bloc.exerciseType.unitQuantityUnit,
hasUnitQuantity: bloc.exerciseType.unitQuantityUnit != null,
onQuantityChanged: (value) {
bloc.add(TestSetNewChangeQuantity(quantity: double.parse(value)));