1.1.22+3 corrections
This commit is contained in:
parent
cebd83648b
commit
e34add8185
BIN
asset/menu/close_reverse_grip_pull_ups.jpg
Normal file
BIN
asset/menu/close_reverse_grip_pull_ups.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 94 KiB |
BIN
asset/menu/dumbbell_presses.jpg
Normal file
BIN
asset/menu/dumbbell_presses.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 88 KiB |
BIN
asset/menu/seated_leg_curls.jpg
Normal file
BIN
asset/menu/seated_leg_curls.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 92 KiB |
BIN
asset/menu/smith_machine_front_press.jpg
Normal file
BIN
asset/menu/smith_machine_front_press.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
BIN
asset/menu/straight_arm_pulldown.jpg
Normal file
BIN
asset/menu/straight_arm_pulldown.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 82 KiB |
39
i18n/en.json
39
i18n/en.json
@ -280,7 +280,10 @@
|
|||||||
"Unleash your potential with WorkoutTest Premium!": "Unleash your potential with WorkoutTest Premium!",
|
"Unleash your potential with WorkoutTest Premium!": "Unleash your potential with WorkoutTest Premium!",
|
||||||
"feature is reachable after you finished": "feature is reachable after you finished",
|
"feature is reachable after you finished": "feature is reachable after you finished",
|
||||||
"100% test circles": "100% test rounds",
|
"100% test circles": "100% test rounds",
|
||||||
"Keep testing": "Keep Testing",
|
"week": "week",
|
||||||
|
"100% completed training": "100% completed training",
|
||||||
|
"after": "after",
|
||||||
|
"Keep testing": "Keep Training",
|
||||||
"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.": "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.",
|
"Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.": "Enjoy also this premium fetaure to show all old evaluation data of your successful exercises.",
|
||||||
"Please define your Exercise Plan": "Please define your Exercise Plan",
|
"Please define your Exercise Plan": "Please define your Exercise Plan",
|
||||||
"Go to: 'Training Plan' - 'Edit My Custom Plan'": "Go to: 'Training Plan' - 'Edit My Custom Plan'",
|
"Go to: 'Training Plan' - 'Edit My Custom Plan'": "Go to: 'Training Plan' - 'Edit My Custom Plan'",
|
||||||
@ -463,8 +466,6 @@
|
|||||||
"because only that way can we show you your exercises, results and evaluations.": "because only that way can we show you your exercises, results and evaluations.",
|
"because only that way can we show you your exercises, results and evaluations.": "because only that way can we show you your exercises, results and evaluations.",
|
||||||
"because only that way can we show you the personalized development diagrams and analysises": "because only that way can we show you the personalized development diagrams and analysises",
|
"because only that way can we show you the personalized development diagrams and analysises": "because only that way can we show you the personalized development diagrams and analysises",
|
||||||
"because only in that way can you begin to execute a training plan": "because only in that way can you begin to execute a training plan",
|
"because only in that way can you begin to execute a training plan": "because only in that way can you begin to execute a training plan",
|
||||||
"Please try to execute this exercise with exact weight and repeats what is suggested": "Please try to execute this exercise with exact weight and repeats what is suggested",
|
|
||||||
"Please try to execute this exercise with exact repeats what is suggested": "Please try to execute this exercise with exact repeats what is suggested",
|
|
||||||
"Please take a relative bigger weight and at least 12 times and do your best! MAXIMIZE it!": "Please take a relative bigger weight and at least 12 times and do your best! MAXIMIZE it!",
|
"Please take a relative bigger weight and at least 12 times and do your best! MAXIMIZE it!": "Please take a relative bigger weight and at least 12 times and do your best! MAXIMIZE it!",
|
||||||
"During the exercise you should try your best:": "During the exercise you should try your best:",
|
"During the exercise you should try your best:": "During the exercise you should try your best:",
|
||||||
"do it with the possible maximum repeats.": "do it with the possible maximum repeats.",
|
"do it with the possible maximum repeats.": "do it with the possible maximum repeats.",
|
||||||
@ -509,5 +510,35 @@
|
|||||||
"optimized training plans, customized to your fitness state and strength:": "optimized training plans, customized to your fitness state and strength:",
|
"optimized training plans, customized to your fitness state and strength:": "optimized training plans, customized to your fitness state and strength:",
|
||||||
"Soon! Check back later for the plan details": "Soon! Check back later for the plan details",
|
"Soon! Check back later for the plan details": "Soon! Check back later for the plan details",
|
||||||
"mins": "mins",
|
"mins": "mins",
|
||||||
"set": "set"
|
"set": "set",
|
||||||
|
"Set / Reps / Weight": "Set / Reps / Weight",
|
||||||
|
"Weight_": "Weight",
|
||||||
|
"Got It": "Got It",
|
||||||
|
"Done!": "Done!",
|
||||||
|
"Show this tip no more": "Show this tip no more",
|
||||||
|
"Don't forget, the app can give you only the right values, if you execute the task regurarly and after the exact instructions.": "Don't forget, the app can give you only the right values, if you execute the task regurarly and after the exact instructions.",
|
||||||
|
"Please take a middle weight which you are able to do 8-20 times with.": "Please take a middle weight which you are able to do 8-20 times with.",
|
||||||
|
"Execute your MAXIMUM repeats with it!": "Execute your MAXIMUM repeats with it!",
|
||||||
|
"Type here your selected weight,": "Type here your selected weight,",
|
||||||
|
"then here, how many times could you repeat it!": "then here, how many times could you repeat it!",
|
||||||
|
"After you done, click to the OK button!": "After you done, click to the OK button!",
|
||||||
|
"If you executed less repeats than given, modify it, and click to OK!": "If you executed less repeats than given, modify it, and click to OK!",
|
||||||
|
"Please type in a real number!": "Please type in a real number!",
|
||||||
|
"Exception: Please type in a real number!": "Please type in a real number!",
|
||||||
|
"If you could do less, then modify and click to OK": "If you could do less, then modify and click to OK",
|
||||||
|
"Here is your tailored weight,": "Here is your tailored weight,",
|
||||||
|
"and executed with this number of repeats!": "and execute it with this number of repeats!",
|
||||||
|
"You can change the weight, if you could not set it in the training room": "You can change the weight, if you could not set it in the training room",
|
||||||
|
"Exception: Please type your repeats!": "Please type your maximum repeats!",
|
||||||
|
"For your optimal development we calculated a suitable weight and repeats": "For your optimal development we calculated a suitable weight and repeats",
|
||||||
|
"It is time to exhaust your muscles": "It is time to really exhaust your muscles",
|
||||||
|
"Next Exercise": "Next Exercise",
|
||||||
|
"and execute it with maximum repeats!": "and execute it with maximum repeats!",
|
||||||
|
"10 days Premium for free": "10 days Premium for free",
|
||||||
|
"Would you like to try all premium functions for 10 days, without any subscription or bank card data?": "Would you like to try all premium functions for 10 days, without any subscription or bank card data?",
|
||||||
|
"If you click to 'Yes', all premium functions will be available right now.": "If you click to 'Yes', all premium functions will be available right now.",
|
||||||
|
"If you click to 'No', you can use all basic functions, and you will loose the oppurtunity to try the premium functions for free.": "If you click to 'No', you can use all basic functions, and you will loose the oppurtunity to try the premium functions for free.",
|
||||||
|
"Based on your initial data, we will generate the personalized training plan for you.": "Based on your initial data, we will generate the personalized training plan for you.",
|
||||||
|
"No selected Training Plan": "No selected Training Plan",
|
||||||
|
"Min. 10 minutes": "Min. 10 minutes"
|
||||||
}
|
}
|
35
i18n/hu.json
35
i18n/hu.json
@ -278,6 +278,9 @@
|
|||||||
"Unleash your potential with WorkoutTest Premium!": "Bontakoztasd ki az erősségeidet WorkoutTest Prémiummal!",
|
"Unleash your potential with WorkoutTest Premium!": "Bontakoztasd ki az erősségeidet WorkoutTest Prémiummal!",
|
||||||
"feature is reachable after you finished": "funkció elérhető számodra, miután teljesítetted",
|
"feature is reachable after you finished": "funkció elérhető számodra, miután teljesítetted",
|
||||||
"100% test circles": "100%-os teszt-köröd",
|
"100% test circles": "100%-os teszt-köröd",
|
||||||
|
"week": "hét",
|
||||||
|
"100% completed training": "alatt 100%-osan végrehajtott edzést",
|
||||||
|
"after": "",
|
||||||
"Keep testing": "Folytasd a tesztelést",
|
"Keep testing": "Folytasd a tesztelést",
|
||||||
"Enjoy also this premium feature to show all old evaluation data of your successful exercises.": "Élvezd ezt a prémium funkciót is, amely megjeleníti a korábbi gyakorlatok teljes kiértékelését",
|
"Enjoy also this premium feature to show all old evaluation data of your successful exercises.": "Élvezd ezt a prémium funkciót is, amely megjeleníti a korábbi gyakorlatok teljes kiértékelését",
|
||||||
"Please define your Exercise Plan": "Kérlek készíts edzéstervet!",
|
"Please define your Exercise Plan": "Kérlek készíts edzéstervet!",
|
||||||
@ -507,5 +510,35 @@
|
|||||||
"optimized training plans, customized to your fitness state and strength:": "optiomalizált edzés terveket, amelyeket a te erő- és fitnesz állapododra szabunk:",
|
"optimized training plans, customized to your fitness state and strength:": "optiomalizált edzés terveket, amelyeket a te erő- és fitnesz állapododra szabunk:",
|
||||||
"Soon! Check back later for the plan details": "Nemsokára! Nézz vissza később, amikor már aktiváltuk az edzésterv részleteit",
|
"Soon! Check back later for the plan details": "Nemsokára! Nézz vissza később, amikor már aktiváltuk az edzésterv részleteit",
|
||||||
"mins": "perc",
|
"mins": "perc",
|
||||||
"set": "sorozat"
|
"set": "sorozat",
|
||||||
|
"Set / Reps / Weight": "Sorozat / Ismétlés / Súly",
|
||||||
|
"Weight_": "Súly",
|
||||||
|
"Got It": "Értettem!",
|
||||||
|
"Done!": "Kész!",
|
||||||
|
"Show this tip no more": "Ne mutasd többet ezt a tippet",
|
||||||
|
"Don't forget, the app can give you only the right values, if you execute the task regurarly and after the exact instructions.": "Ne felejtsd el, hogy a program csak akkor tud számodra megfelelő értéket adni, ha helyesen, és az utasítás szerint végzed el a feladatokat",
|
||||||
|
"Please take a middle weight which you are able to do 8-20 times with.": "Vegyél egy közepes súlyt, amivel 8-20 ismétlésre vagy képes.",
|
||||||
|
"Execute your MAXIMUM repeats with it!": "Végezz vele MAXIMUM ismétlést",
|
||||||
|
"Type here your selected weight,": "Írd be ide a kiválasztott súlyt,",
|
||||||
|
"then here, how many times could you repeat it!": "majd ide, hogy mennyi ismétlés sikerült belőle!",
|
||||||
|
"After you done, click to the OK button!": "Ha elvégezted a gyakorlatot, kattints az OK gombra!",
|
||||||
|
"If you executed less repeats than given, modify it, and click to OK!": "Ha kevesebb sikerült, akkor írd be és utána nyomj OK-t!",
|
||||||
|
"Please type in a real number!": "Kérlek írj be egy számot eredményként",
|
||||||
|
"Exception: Please type in a real number!": "Kérlek írj be egy számot eredményként",
|
||||||
|
"If you could do less, then modify and click to OK": "Ha kevesebb sikerült, írd be és kattints az OK-ra",
|
||||||
|
"Here is your tailored weight,": "Itt van a rádszabott súly,",
|
||||||
|
"and executed with this number of repeats!": "ennyi ismétlést végezz!",
|
||||||
|
"You can change the weight, if you could not set it in the training room": "Változtasd meg a súlyt, ha éppen nincs ennyi az edzőteremben",
|
||||||
|
"Exception: Please type your repeats!": "Kérlek írd be a maximum ismétlésed számát!",
|
||||||
|
"For your optimal development we calculated a suitable weight and repeats": "A fejlődésed érdekében meghatároztuk Neked a megfelelő súlyt és ismétlésszámot",
|
||||||
|
"It is time to exhaust your muscles": "Itt az idő, hogy igazán lemerítsd az izmaidat.",
|
||||||
|
"Next Exercise": "Következő",
|
||||||
|
"and execute it with maximum repeats!": "és hajtsd végre maximális ismétléssel!",
|
||||||
|
"10 days Premium for free": "10 nap Prémium előfizetés díjmentesen",
|
||||||
|
"Would you like to try all premium functions for 10 days, without any subscription or bank card data?": "Szeretnéd kipróbálni 10 napig az összes prémium funkciót, előfizetés és bankkártya-adatok megadása nélkül?",
|
||||||
|
"If you click to 'Yes', all premium functions will be available right now.": "Ha az 'Igen'-re kattintasz, azonnal eléred az összes prémium funkciót, edzést.",
|
||||||
|
"If you click to 'No', you can use all basic functions, and you will loose the oppurtunity to try the premium functions for free.": "Ha a 'Nem'-re kattintasz, használhatod az összes alapfunkciót, de elveszted a lehetőséget, hogy a prémium funkciókat ingyen kipróbáld.",
|
||||||
|
"Based on your initial data, we will generate the personalized training plan for you.": "A megadott adataid alapján most személyre szabott edzéstervet generálunk neked.",
|
||||||
|
"No selected Training Plan": "Nincs kiválasztott edzésterved",
|
||||||
|
"Min. 10 minutes": "Minimum 10 perc"
|
||||||
}
|
}
|
@ -388,7 +388,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@ -531,7 +531,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
@ -566,7 +566,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 3;
|
||||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
@ -93,5 +93,5 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:async';
|
|||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/sport.dart';
|
import 'package:aitrainer_app/model/sport.dart';
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/mautic_repository.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
@ -29,8 +30,8 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
|||||||
weight = this.customerRepository.getWeight() == 0 ? 60 : this.customerRepository.getWeight();
|
weight = this.customerRepository.getWeight() == 0 ? 60 : this.customerRepository.getWeight();
|
||||||
height = this.customerRepository.getHeight() == 0 ? 170 : this.customerRepository.getHeight();
|
height = this.customerRepository.getHeight() == 0 ? 170 : this.customerRepository.getHeight();
|
||||||
|
|
||||||
// selectedSport = customerRepository.getSport();
|
selectedFitnessItem = customerRepository.fitnessLevel;
|
||||||
//print("selected: $selectedFitnessItem sport: $selectedSport " + customerRepository.customer!.fitnessLevel.toString());
|
selectedSport = customerRepository.getSport();
|
||||||
}
|
}
|
||||||
|
|
||||||
Sport? selectedSport;
|
Sport? selectedSport;
|
||||||
@ -95,6 +96,7 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
|||||||
} else if (event is CustomerSportChange) {
|
} else if (event is CustomerSportChange) {
|
||||||
yield CustomerChangeLoading();
|
yield CustomerChangeLoading();
|
||||||
selectedSport = event.sport;
|
selectedSport = event.sport;
|
||||||
|
print("Selected Sport $selectedSport");
|
||||||
yield CustomerDataChanged();
|
yield CustomerDataChanged();
|
||||||
} else if (event is CustomerSaveFitness) {
|
} else if (event is CustomerSaveFitness) {
|
||||||
yield CustomerChangeLoading();
|
yield CustomerChangeLoading();
|
||||||
@ -137,6 +139,8 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
|||||||
}
|
}
|
||||||
|
|
||||||
await customerRepository.saveCustomer();
|
await customerRepository.saveCustomer();
|
||||||
|
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);
|
||||||
|
await mauticRepository.sendMauticDataChange();
|
||||||
Cache().initBadges();
|
Cache().initBadges();
|
||||||
yield CustomerSaveSuccess();
|
yield CustomerSaveSuccess();
|
||||||
} else {
|
} else {
|
||||||
@ -151,10 +155,6 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
|||||||
bool validation() {
|
bool validation() {
|
||||||
if (customerRepository.customer == null) throw Exception("Customer object not defined");
|
if (customerRepository.customer == null) throw Exception("Customer object not defined");
|
||||||
return true;
|
return true;
|
||||||
/* return (emailValidation(customerRepository.customer!.email) == null) &&
|
|
||||||
(passwordValidation(customerRepository.customer!.password) == null) &&
|
|
||||||
(nameValidation(customerRepository.customer!.firstname) == null) &&
|
|
||||||
(nameValidation(customerRepository.customer!.name) == null); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String? emailValidation(String? email) {
|
String? emailValidation(String? email) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
@ -26,7 +27,6 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
late double initialRM;
|
late double initialRM;
|
||||||
late double unitQuantity;
|
late double unitQuantity;
|
||||||
late double quantity;
|
late double quantity;
|
||||||
late double origQuantity;
|
|
||||||
late double oneRepQuantity;
|
late double oneRepQuantity;
|
||||||
late double oneRepUnitQuantity;
|
late double oneRepUnitQuantity;
|
||||||
|
|
||||||
@ -36,6 +36,8 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
double scrollOffset = 0;
|
double scrollOffset = 0;
|
||||||
late ExerciseTypeLocal exerciseTypeLocal;
|
late ExerciseTypeLocal exerciseTypeLocal;
|
||||||
|
|
||||||
|
List<Exercise> controlList = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExerciseControlBloc({required this.exerciseRepository, required this.readonly, required this.timerBloc})
|
ExerciseControlBloc({required this.exerciseRepository, required this.readonly, required this.timerBloc})
|
||||||
: super(ExerciseControlInitial()) {
|
: super(ExerciseControlInitial()) {
|
||||||
@ -53,29 +55,29 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
if (oneRepQuantity > 25) {
|
if (oneRepQuantity > 25) {
|
||||||
quantity = 35;
|
quantity = 35;
|
||||||
}
|
}
|
||||||
origQuantity = quantity;
|
|
||||||
|
|
||||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
Exercise exercise = Exercise();
|
||||||
|
exercise.quantity = quantity;
|
||||||
|
exercise.unitQuantity = unitQuantity;
|
||||||
|
controlList.add(exercise);
|
||||||
|
}
|
||||||
|
|
||||||
timerBloc.add(TimerStart(duration: 300));
|
timerBloc.add(TimerStart(duration: 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<ExerciseControlState> mapEventToState(ExerciseControlEvent event) async* {
|
Stream<ExerciseControlState> mapEventToState(ExerciseControlEvent event) async* {
|
||||||
try {
|
try {
|
||||||
/* if (event is ExerciseControlLoad) {
|
|
||||||
yield ExerciseControlLoading();
|
|
||||||
step = 1;
|
|
||||||
yield ExerciseControlReady();
|
|
||||||
} else */
|
|
||||||
if (event is ExerciseControlQuantityChange) {
|
if (event is ExerciseControlQuantityChange) {
|
||||||
//yield ExerciseControlLoading();
|
|
||||||
if (event.step == step) {
|
if (event.step == step) {
|
||||||
exerciseRepository.setQuantity(event.quantity);
|
exerciseRepository.setQuantity(event.quantity);
|
||||||
quantity = event.quantity;
|
quantity = event.quantity;
|
||||||
|
controlList[step - 1].quantity = quantity;
|
||||||
}
|
}
|
||||||
//yield ExerciseControlReady();
|
|
||||||
} else if (event is ExerciseControlUnitQuantityChange) {
|
} else if (event is ExerciseControlUnitQuantityChange) {
|
||||||
yield ExerciseControlLoading();
|
yield ExerciseControlLoading();
|
||||||
print("event step ${event.step} quantity ${event.quantity}");
|
print("event step ${event.step} quantity ${event.quantity}");
|
||||||
@ -85,7 +87,8 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
unitQuantity = event.quantity;
|
unitQuantity = event.quantity;
|
||||||
quantity = calculateQuantityByUnitQuantity().toDouble();
|
quantity = calculateQuantityByUnitQuantity().toDouble();
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
origQuantity = quantity;
|
controlList[step - 1].unitQuantity = event.quantity;
|
||||||
|
controlList[step - 1].quantity = quantity;
|
||||||
}
|
}
|
||||||
yield ExerciseControlReady();
|
yield ExerciseControlReady();
|
||||||
} else if (event is ExerciseControlSubmit) {
|
} else if (event is ExerciseControlSubmit) {
|
||||||
@ -94,13 +97,11 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
step++;
|
step++;
|
||||||
scrollOffset = step * 400.0;
|
scrollOffset = step * 400.0;
|
||||||
|
|
||||||
quantity = origQuantity;
|
|
||||||
if (exerciseRepository.exercise!.quantity == null) {
|
if (exerciseRepository.exercise!.quantity == null) {
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
}
|
}
|
||||||
exerciseRepository.end = DateTime.now();
|
exerciseRepository.end = DateTime.now();
|
||||||
await exerciseRepository.addExercise();
|
await exerciseRepository.addExercise();
|
||||||
//exerciseRepository.initExercise();
|
|
||||||
|
|
||||||
step <= 3 ? timerBloc.add(TimerStart(duration: 300)) : timerBloc.add(TimerEnd(duration: 300));
|
step <= 3 ? timerBloc.add(TimerStart(duration: 300)) : timerBloc.add(TimerEnd(duration: 300));
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
final CustomerRepository customerRepository;
|
final CustomerRepository customerRepository;
|
||||||
final MenuBloc menuBloc;
|
final MenuBloc menuBloc;
|
||||||
late AnimationController bmiAnimationController;
|
late AnimationController bmiAnimationController;
|
||||||
double quantity = 12;
|
double quantity = -1;
|
||||||
double unitQuantity = 30;
|
double unitQuantity = -1;
|
||||||
double bmi = 0;
|
double bmi = 0;
|
||||||
double bmr = 0;
|
double bmr = 0;
|
||||||
double goalBMI = 0;
|
double goalBMI = 0;
|
||||||
@ -148,6 +148,10 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
yield ExerciseNewReady();
|
yield ExerciseNewReady();
|
||||||
} else if (event is ExerciseNewSubmit) {
|
} else if (event is ExerciseNewSubmit) {
|
||||||
yield ExerciseNewLoading();
|
yield ExerciseNewLoading();
|
||||||
|
if (quantity == -1 || unitQuantity == -1) {
|
||||||
|
yield ExerciseNewReady();
|
||||||
|
throw Exception("Please type in a real number");
|
||||||
|
}
|
||||||
exerciseRepository.end = DateTime.now();
|
exerciseRepository.end = DateTime.now();
|
||||||
await exerciseRepository.addExercise();
|
await exerciseRepository.addExercise();
|
||||||
// exerciseRepository.initExercise();
|
// exerciseRepository.initExercise();
|
||||||
|
@ -2,8 +2,11 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/mautic_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/split_test_respository.dart';
|
import 'package:aitrainer_app/repository/split_test_respository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/user_repository.dart';
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
@ -19,7 +22,7 @@ part 'login_state.dart';
|
|||||||
class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
||||||
final AccountBloc accountBloc;
|
final AccountBloc accountBloc;
|
||||||
final UserRepository userRepository;
|
final UserRepository userRepository;
|
||||||
final CustomerRepository customerRepository = CustomerRepository();
|
late CustomerRepository? customerRepository;
|
||||||
final SplitTestRepository splitTestRepository = SplitTestRepository();
|
final SplitTestRepository splitTestRepository = SplitTestRepository();
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final bool isRegistration;
|
final bool isRegistration;
|
||||||
@ -30,7 +33,12 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
Color testColor = Colors.green[800]!;
|
Color testColor = Colors.green[800]!;
|
||||||
bool emailCheckbox = true;
|
bool emailCheckbox = true;
|
||||||
|
|
||||||
LoginBloc({required this.accountBloc, required this.userRepository, required this.context, required this.isRegistration})
|
LoginBloc(
|
||||||
|
{required this.accountBloc,
|
||||||
|
required this.userRepository,
|
||||||
|
required this.context,
|
||||||
|
required this.isRegistration,
|
||||||
|
this.customerRepository})
|
||||||
: super(LoginInitial()) {
|
: super(LoginInitial()) {
|
||||||
String colorString = splitTestRepository.getSplitTestValue("registration_skip");
|
String colorString = splitTestRepository.getSplitTestValue("registration_skip");
|
||||||
if (colorString == "red") {
|
if (colorString == "red") {
|
||||||
@ -40,6 +48,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
if (emailCheckboxString == "0") {
|
if (emailCheckboxString == "0") {
|
||||||
emailCheckbox = false;
|
emailCheckbox = false;
|
||||||
}
|
}
|
||||||
|
if (customerRepository == null) {
|
||||||
|
customerRepository = CustomerRepository();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -87,56 +98,44 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationSubmit) {
|
} else if (event is RegistrationSubmit) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
/* if (!this.dataPolicyAllowed) {
|
|
||||||
throw Exception("Please accept our data policy");
|
|
||||||
} */
|
|
||||||
final String? validationError = validate();
|
final String? validationError = validate();
|
||||||
if (validationError != null) {
|
if (validationError != null) {
|
||||||
yield LoginError(message: validationError);
|
yield LoginError(message: validationError);
|
||||||
} else {
|
} else {
|
||||||
await userRepository.addUser();
|
await userRepository.addUser();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||||
await saveCustomer();
|
await afterRegistration("email");
|
||||||
Track().track(TrackingEvent.registration, eventValue: "email");
|
|
||||||
Cache().setLoginType(LoginType.email);
|
Cache().setLoginType(LoginType.email);
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
}
|
}
|
||||||
} else if (event is RegistrationFB) {
|
} else if (event is RegistrationFB) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
/* if (!this.dataPolicyAllowed) {
|
|
||||||
throw Exception("Please accept our data policy");
|
|
||||||
} */
|
|
||||||
Cache().setLoginType(LoginType.fb);
|
Cache().setLoginType(LoginType.fb);
|
||||||
await userRepository.addUserFB();
|
await userRepository.addUserFB();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||||
await saveCustomer();
|
await afterRegistration("FB");
|
||||||
Track().track(TrackingEvent.registration, eventValue: "FB");
|
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationGoogle) {
|
} else if (event is RegistrationGoogle) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
/* if (!this.dataPolicyAllowed) {
|
|
||||||
throw Exception("Please accept our data policy");
|
|
||||||
} */
|
|
||||||
Cache().setLoginType(LoginType.google);
|
Cache().setLoginType(LoginType.google);
|
||||||
await userRepository.addUserGoogle();
|
await userRepository.addUserGoogle();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||||
await saveCustomer();
|
await afterRegistration("Google");
|
||||||
Track().track(TrackingEvent.registration, eventValue: "Google");
|
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationApple) {
|
} else if (event is RegistrationApple) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
/* if (!this.dataPolicyAllowed) {
|
|
||||||
throw Exception("Please accept our data policy");
|
|
||||||
} */
|
|
||||||
Cache().setLoginType(LoginType.apple);
|
Cache().setLoginType(LoginType.apple);
|
||||||
await userRepository.addUserApple();
|
await userRepository.addUserApple();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||||
await saveCustomer();
|
await afterRegistration("Apple");
|
||||||
Track().track(TrackingEvent.registration, eventValue: "Apple");
|
|
||||||
|
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is DataProtectionClicked) {
|
} else if (event is DataProtectionClicked) {
|
||||||
@ -162,10 +161,23 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveCustomer() async {
|
Future<void> afterRegistration(String event) async {
|
||||||
customerRepository.customer = Cache().userLoggedIn!;
|
Customer tempCustomer = customerRepository!.customer!;
|
||||||
customerRepository.customer!.dataPolicyAllowed = 1;
|
customerRepository!.customer = Cache().userLoggedIn!;
|
||||||
await customerRepository.saveCustomer();
|
customerRepository!.customer!.fitnessLevel = tempCustomer.fitnessLevel;
|
||||||
|
customerRepository!.customer!.goal = tempCustomer.goal;
|
||||||
|
customerRepository!.customer!.sex = tempCustomer.sex;
|
||||||
|
customerRepository!.customer!.dataPolicyAllowed = 1;
|
||||||
|
customerRepository!.customer!.emailSubscription = 1;
|
||||||
|
customerRepository!.customer!.syncedDate = DateTime.now();
|
||||||
|
customerRepository!.setCustomerProperty("Weight", tempCustomer.getProperty("Weight"));
|
||||||
|
customerRepository!.setCustomerProperty("Height", tempCustomer.getProperty("Height"));
|
||||||
|
await customerRepository!.saveCustomer();
|
||||||
|
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository!);
|
||||||
|
await mauticRepository.sendMauticSubscription();
|
||||||
|
TrainingPlanRepository trainingPlanRepository = TrainingPlanRepository();
|
||||||
|
trainingPlanRepository.generateTrainingPlan();
|
||||||
|
Track().track(TrackingEvent.registration, eventValue: event);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? emailValidation(String? email) {
|
String? emailValidation(String? email) {
|
||||||
|
@ -7,6 +7,8 @@ import 'package:aitrainer_app/model/customer_training_plan_details.dart';
|
|||||||
import 'package:aitrainer_app/model/exercise.dart';
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/model/training_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/training_plan_detail.dart';
|
||||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
||||||
import 'package:aitrainer_app/service/exercise_service.dart';
|
import 'package:aitrainer_app/service/exercise_service.dart';
|
||||||
@ -29,6 +31,9 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
CustomerTrainingPlan? _myPlan;
|
CustomerTrainingPlan? _myPlan;
|
||||||
CustomerTrainingPlanDetails? _myDetail;
|
CustomerTrainingPlanDetails? _myDetail;
|
||||||
|
|
||||||
|
TrainingPlan? _myTrainingPlan;
|
||||||
|
final List<String> trainingPlanDayNames = [];
|
||||||
|
|
||||||
bool started = false;
|
bool started = false;
|
||||||
final List<String> dayNames = [];
|
final List<String> dayNames = [];
|
||||||
bool restarting = false;
|
bool restarting = false;
|
||||||
@ -38,6 +43,9 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
CustomerTrainingPlan? getMyPlan() => this._myPlan;
|
CustomerTrainingPlan? getMyPlan() => this._myPlan;
|
||||||
setMyPlan(CustomerTrainingPlan? myPlan) => this._myPlan = myPlan;
|
setMyPlan(CustomerTrainingPlan? myPlan) => this._myPlan = myPlan;
|
||||||
|
|
||||||
|
TrainingPlan? getMyTrainingPlan() => this._myTrainingPlan;
|
||||||
|
setMyTrainingPlan(TrainingPlan? myTrainingPlan) => this._myTrainingPlan = myTrainingPlan;
|
||||||
|
|
||||||
CustomerTrainingPlanDetails? getMyDetail() => this._myDetail;
|
CustomerTrainingPlanDetails? getMyDetail() => this._myDetail;
|
||||||
setMyDetail(CustomerTrainingPlanDetails? value) => this._myDetail = value;
|
setMyDetail(CustomerTrainingPlanDetails? value) => this._myDetail = value;
|
||||||
|
|
||||||
@ -88,6 +96,10 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
yield TrainingPlanReady();
|
yield TrainingPlanReady();
|
||||||
} else if (event is TrainingPlanSaveExercise) {
|
} else if (event is TrainingPlanSaveExercise) {
|
||||||
yield TrainingPlanLoading();
|
yield TrainingPlanLoading();
|
||||||
|
if (event.detail.repeats == -1) {
|
||||||
|
yield TrainingPlanReady();
|
||||||
|
throw Exception("Please type your repeats!");
|
||||||
|
}
|
||||||
if (event.detail.weight == -3) {
|
if (event.detail.weight == -3) {
|
||||||
print("DropSet");
|
print("DropSet");
|
||||||
event.detail.state = ExercisePlanDetailState.finished;
|
event.detail.state = ExercisePlanDetailState.finished;
|
||||||
@ -293,6 +305,83 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
|||||||
getActiveDayIndex();
|
getActiveDayIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void activateTrainingPlanDays() {
|
||||||
|
if (_myTrainingPlan == null || _myTrainingPlan!.details == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trainingPlanDayNames.clear();
|
||||||
|
|
||||||
|
String dayName = ".";
|
||||||
|
_myTrainingPlan!.details!.forEach((element) {
|
||||||
|
if (element.day != null && element.day != dayName) {
|
||||||
|
trainingPlanDayNames.add(element.day!);
|
||||||
|
dayName = element.day!;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (trainingPlanDayNames.length == 0) {
|
||||||
|
dayName = "";
|
||||||
|
trainingPlanDayNames.add(dayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TrainingPlanDetail> trainingPlanDetailSummary(TrainingPlan plan, String dayName) {
|
||||||
|
List<TrainingPlanDetail> details = [];
|
||||||
|
TrainingPlanDetail? prev;
|
||||||
|
plan.details!.forEach((element) {
|
||||||
|
if (prev == null || element.exerciseTypeId != prev!.exerciseTypeId) {
|
||||||
|
if (element.day! == dayName) {
|
||||||
|
element.summary = getSummary(element);
|
||||||
|
details.add(element);
|
||||||
|
}
|
||||||
|
prev = element;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TrainingPlanDetail> getAllTrainingPlanDetailsSameExercise(TrainingPlanDetail detail) {
|
||||||
|
List<TrainingPlanDetail> list = [];
|
||||||
|
getMyTrainingPlan()!.details!.forEach((element) {
|
||||||
|
if (detail.exerciseTypeId == element.exerciseTypeId) {
|
||||||
|
list.add(element);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getSummary(TrainingPlanDetail detail) {
|
||||||
|
String summary = "";
|
||||||
|
String set = "1";
|
||||||
|
|
||||||
|
set = detail.set.toString() + "/ ";
|
||||||
|
List<TrainingPlanDetail> details = getAllTrainingPlanDetailsSameExercise(detail);
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
String quantities = "";
|
||||||
|
|
||||||
|
details.forEach((element) {
|
||||||
|
String delimiter = ", ";
|
||||||
|
if (index == 0) {
|
||||||
|
delimiter = "";
|
||||||
|
}
|
||||||
|
if (element.repeats == -1) {
|
||||||
|
quantities += delimiter + " MAX ";
|
||||||
|
} else {
|
||||||
|
quantities += delimiter + "${element.repeats}";
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
});
|
||||||
|
|
||||||
|
//quantities += " / ? kg";
|
||||||
|
|
||||||
|
summary = quantities;
|
||||||
|
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
void addExtraExerciseType(String name, String dayName) {
|
void addExtraExerciseType(String name, String dayName) {
|
||||||
if (Cache().getExerciseTypes() == null) {
|
if (Cache().getExerciseTypes() == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -307,6 +307,60 @@ class SuperTooltip {
|
|||||||
isOpen = true;
|
isOpen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showBox(BuildContext targetContext) {
|
||||||
|
final renderBox = targetContext.findRenderObject() as RenderBox;
|
||||||
|
var size = renderBox.size;
|
||||||
|
print("Size $size");
|
||||||
|
if (containsBackgroundOverlay) {
|
||||||
|
_backGroundOverlay = OverlayEntry(
|
||||||
|
builder: (context) => _AnimationWrapper(
|
||||||
|
builder: (context, opacity) => AnimatedOpacity(
|
||||||
|
opacity: opacity,
|
||||||
|
duration: const Duration(milliseconds: 600),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (dismissOnTapOutside) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: ShapeDecoration(
|
||||||
|
shape: _ShapeOverlay(
|
||||||
|
touchThrougArea, touchThroughAreaShape, touchThroughAreaCornerRadius, outsideBackgroundColor))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
_ballonOverlay = OverlayEntry(
|
||||||
|
builder: (context) => _AnimationWrapper(
|
||||||
|
builder: (context, opacity) => Positioned(
|
||||||
|
left: left, //offset.dx,
|
||||||
|
top: top,
|
||||||
|
width: size.width > maxWidth! ? maxWidth : size.width,
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
duration: Duration(
|
||||||
|
milliseconds: 300,
|
||||||
|
),
|
||||||
|
opacity: opacity,
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.passthrough,
|
||||||
|
children: [_buildPopUp(), _buildCloseButton()],
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
));
|
||||||
|
|
||||||
|
var overlays = <OverlayEntry>[];
|
||||||
|
|
||||||
|
if (containsBackgroundOverlay) {
|
||||||
|
overlays.add(_backGroundOverlay!);
|
||||||
|
}
|
||||||
|
overlays.add(_ballonOverlay!);
|
||||||
|
|
||||||
|
Overlay.of(targetContext)!.insertAll(overlays);
|
||||||
|
isOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildPopUp() {
|
Widget _buildPopUp() {
|
||||||
return Positioned(
|
return Positioned(
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -675,6 +729,122 @@ class _PopupBallonLayoutDelegate extends SingleChildLayoutDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _PopupBallonLayoutDelegateBox extends SingleChildLayoutDelegate {
|
||||||
|
final double? _minWidth;
|
||||||
|
final double? _maxWidth;
|
||||||
|
final double? _minHeight;
|
||||||
|
final double? _maxHeight;
|
||||||
|
final double? _top;
|
||||||
|
final double? _bottom;
|
||||||
|
final double? _left;
|
||||||
|
final double? _right;
|
||||||
|
final double? _outSidePadding;
|
||||||
|
|
||||||
|
_PopupBallonLayoutDelegateBox({
|
||||||
|
double? minWidth,
|
||||||
|
double? maxWidth,
|
||||||
|
double? minHeight,
|
||||||
|
double? maxHeight,
|
||||||
|
double? outSidePadding,
|
||||||
|
double? top,
|
||||||
|
double? bottom,
|
||||||
|
double? left,
|
||||||
|
double? right,
|
||||||
|
}) : _minWidth = minWidth,
|
||||||
|
_maxWidth = maxWidth,
|
||||||
|
_minHeight = minHeight,
|
||||||
|
_maxHeight = maxHeight,
|
||||||
|
_top = top,
|
||||||
|
_bottom = bottom,
|
||||||
|
_left = left,
|
||||||
|
_right = right,
|
||||||
|
_outSidePadding = outSidePadding;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Offset getPositionForChild(Size size, Size childSize) {
|
||||||
|
double? calcLeftMostXtoTarget() {
|
||||||
|
double? leftMostXtoTarget;
|
||||||
|
if (_left != null) {
|
||||||
|
leftMostXtoTarget = _left;
|
||||||
|
} else if (_right != null) {
|
||||||
|
leftMostXtoTarget = max(
|
||||||
|
size.topLeft(Offset.zero).dx + _outSidePadding!, size.topRight(Offset.zero).dx - _outSidePadding! - childSize.width - _right!);
|
||||||
|
}
|
||||||
|
return leftMostXtoTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
double? calcTopMostYtoTarget() {
|
||||||
|
double? topmostYtoTarget;
|
||||||
|
if (_top != null) {
|
||||||
|
topmostYtoTarget = _top!;
|
||||||
|
} else if (_bottom != null) {
|
||||||
|
topmostYtoTarget = max(size.topLeft(Offset.zero).dy + _outSidePadding!,
|
||||||
|
size.bottomRight(Offset.zero).dy - _outSidePadding! - childSize.height - _bottom!);
|
||||||
|
}
|
||||||
|
return topmostYtoTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Offset(calcLeftMostXtoTarget()!, _top!);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
||||||
|
// print("ParentConstraints: $constraints");
|
||||||
|
|
||||||
|
var calcMinWidth = _minWidth ?? 0.0;
|
||||||
|
var calcMaxWidth = _maxWidth ?? double.infinity;
|
||||||
|
var calcMinHeight = _minHeight ?? 0.0;
|
||||||
|
var calcMaxHeight = _maxHeight ?? double.infinity;
|
||||||
|
|
||||||
|
void calcMinMaxWidth() {
|
||||||
|
if (_left != null && _right != null) {
|
||||||
|
calcMaxWidth = constraints.maxWidth - (_left! + _right!);
|
||||||
|
} else if ((_left != null && _right == null) || (_left == null && _right != null)) {
|
||||||
|
// make sure that the sum of left, right + maxwidth isn't bigger than the screen width.
|
||||||
|
var sideDelta = (_left ?? 0.0) + (_right ?? 0.0) + _outSidePadding!;
|
||||||
|
if (calcMaxWidth > constraints.maxWidth - sideDelta) {
|
||||||
|
calcMaxWidth = constraints.maxWidth - sideDelta;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (calcMaxWidth > constraints.maxWidth - 2 * _outSidePadding!) {
|
||||||
|
calcMaxWidth = constraints.maxWidth - 2 * _outSidePadding!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcMinMaxHeight() {
|
||||||
|
if (_top != null && _bottom != null) {
|
||||||
|
calcMaxHeight = constraints.maxHeight - (_top! + _bottom!);
|
||||||
|
} else if ((_top != null && _bottom == null) || (_top == null && _bottom != null)) {
|
||||||
|
// make sure that the sum of top, bottom + maxHeight isn't bigger than the screen Height.
|
||||||
|
var sideDelta = (_top ?? 0.0) + (_bottom ?? 0.0) + _outSidePadding!;
|
||||||
|
if (calcMaxHeight > constraints.maxHeight - sideDelta) {
|
||||||
|
calcMaxHeight = constraints.maxHeight - sideDelta;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (calcMaxHeight > constraints.maxHeight - 2 * _outSidePadding!) {
|
||||||
|
calcMaxHeight = constraints.maxHeight - 2 * _outSidePadding!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var childConstraints = new BoxConstraints(
|
||||||
|
minWidth: calcMinWidth > calcMaxWidth ? calcMaxWidth : calcMinWidth,
|
||||||
|
maxWidth: calcMaxWidth,
|
||||||
|
minHeight: calcMinHeight > calcMaxHeight ? calcMaxHeight : calcMinHeight,
|
||||||
|
maxHeight: calcMaxHeight);
|
||||||
|
|
||||||
|
// print("Child constraints: $childConstraints");
|
||||||
|
|
||||||
|
return childConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class _BubbleShape extends ShapeBorder {
|
class _BubbleShape extends ShapeBorder {
|
||||||
|
@ -41,7 +41,6 @@ import 'package:aitrainer_app/view/test_set_edit.dart';
|
|||||||
import 'package:aitrainer_app/view/test_set_execute.dart';
|
import 'package:aitrainer_app/view/test_set_execute.dart';
|
||||||
import 'package:aitrainer_app/view/test_set_new.dart';
|
import 'package:aitrainer_app/view/test_set_new.dart';
|
||||||
import 'package:aitrainer_app/view/training_plan_activate_page.dart';
|
import 'package:aitrainer_app/view/training_plan_activate_page.dart';
|
||||||
import 'package:aitrainer_app/view/training_plan_execute_page.dart';
|
|
||||||
import 'package:aitrainer_app/view/training_plan_exercise.dart';
|
import 'package:aitrainer_app/view/training_plan_exercise.dart';
|
||||||
import 'package:aitrainer_app/widgets/home.dart';
|
import 'package:aitrainer_app/widgets/home.dart';
|
||||||
import 'package:aitrainer_app/library/facebook_app_events/facebook_app_events.dart';
|
import 'package:aitrainer_app/library/facebook_app_events/facebook_app_events.dart';
|
||||||
@ -180,8 +179,8 @@ Future<Null> main() async {
|
|||||||
BlocProvider<TestSetExecuteBloc>(
|
BlocProvider<TestSetExecuteBloc>(
|
||||||
create: (BuildContext context) => TestSetExecuteBloc(),
|
create: (BuildContext context) => TestSetExecuteBloc(),
|
||||||
),
|
),
|
||||||
/* BlocProvider<TutorialBloc>(
|
BlocProvider<TutorialBloc>(
|
||||||
create: (BuildContext context) => TutorialBloc(tutorialName: ActivityDone.tutorialExecuteFirstTest.toStr())), */
|
create: (BuildContext context) => TutorialBloc(tutorialName: ActivityDone.tutorialExecuteFirstTest.toStr())),
|
||||||
BlocProvider<TrainingPlanBloc>(create: (context) {
|
BlocProvider<TrainingPlanBloc>(create: (context) {
|
||||||
final MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
|
final MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||||
return TrainingPlanBloc(menuBloc: menuBloc, trainingPlanRepository: TrainingPlanRepository());
|
return TrainingPlanBloc(menuBloc: menuBloc, trainingPlanRepository: TrainingPlanRepository());
|
||||||
@ -283,7 +282,6 @@ class WorkoutTestApp extends StatelessWidget {
|
|||||||
'myTrainingPlanCustom': (context) => TrainingPlanCustomPage(),
|
'myTrainingPlanCustom': (context) => TrainingPlanCustomPage(),
|
||||||
'myTrainingPlanCustomAdd': (context) => TrainingPlanCustomAddPage(),
|
'myTrainingPlanCustomAdd': (context) => TrainingPlanCustomAddPage(),
|
||||||
'myTrainingPlanActivate': (context) => TrainingPlanActivatePage(),
|
'myTrainingPlanActivate': (context) => TrainingPlanActivatePage(),
|
||||||
'myTrainingPlanExecute2': (context) => TrainingPlanExecutePage(),
|
|
||||||
'myTrainingPlanExecute': (context) => TrainingPlanExecute(),
|
'myTrainingPlanExecute': (context) => TrainingPlanExecute(),
|
||||||
'myTrainingPlanExercise': (context) => TrainingPlanExercise(),
|
'myTrainingPlanExercise': (context) => TrainingPlanExercise(),
|
||||||
'myTrainingEvaluation': (context) => TrainingEvaluationPage(),
|
'myTrainingEvaluation': (context) => TrainingEvaluationPage(),
|
||||||
|
@ -71,7 +71,11 @@ enum ActivityDone {
|
|||||||
tutorialBasicLegPress,
|
tutorialBasicLegPress,
|
||||||
tutorialDevelopment,
|
tutorialDevelopment,
|
||||||
isExerciseLogSeen,
|
isExerciseLogSeen,
|
||||||
isMuscleDevelopmentSeen
|
isMuscleDevelopmentSeen,
|
||||||
|
isBodyTypeSeen,
|
||||||
|
exerciseSaveTestTip,
|
||||||
|
exerciseSaveTrainingTip,
|
||||||
|
exerciseSaveTestsetTip
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ActivityDoneExt on ActivityDone {
|
extension ActivityDoneExt on ActivityDone {
|
||||||
@ -641,8 +645,8 @@ class Cache with Logging {
|
|||||||
}
|
}
|
||||||
if (this._exercises == null || this._exercises!.isEmpty) {
|
if (this._exercises == null || this._exercises!.isEmpty) {
|
||||||
setBadge("home", true);
|
setBadge("home", true);
|
||||||
setBadge("Muscle Build / Shape Toning", true);
|
setBadge("Custom Tests", true);
|
||||||
setBadge("Cardio", true);
|
setBadge("Start Training", true);
|
||||||
}
|
}
|
||||||
if (customerRepository.getHeight() == 0) {
|
if (customerRepository.getHeight() == 0) {
|
||||||
setBadge("BMI", true);
|
setBadge("BMI", true);
|
||||||
@ -726,6 +730,8 @@ class Cache with Logging {
|
|||||||
sharedPreferences.setBool(activity.toStr(), true);
|
sharedPreferences.setBool(activity.toStr(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isActivityDone(ActivityDone activity) => activitiesDone[activity.toStr()] == true;
|
||||||
|
|
||||||
List<Evaluation>? get evaluations => this._evaluations;
|
List<Evaluation>? get evaluations => this._evaluations;
|
||||||
set evaluations(List<Evaluation>? value) => this._evaluations = value;
|
set evaluations(List<Evaluation>? value) => this._evaluations = value;
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ class Customer {
|
|||||||
DateTime? dateChange;
|
DateTime? dateChange;
|
||||||
int? emailSubscription;
|
int? emailSubscription;
|
||||||
int? sportId;
|
int? sportId;
|
||||||
|
DateTime? syncedDate;
|
||||||
DateTime? trialDate;
|
DateTime? trialDate;
|
||||||
|
|
||||||
LinkedHashMap<String, CustomerProperty> properties = LinkedHashMap();
|
LinkedHashMap<String, CustomerProperty> properties = LinkedHashMap();
|
||||||
@ -71,6 +72,7 @@ class Customer {
|
|||||||
this.dataPolicyAllowed = json['dataPolicyAllowed'];
|
this.dataPolicyAllowed = json['dataPolicyAllowed'];
|
||||||
this.emailSubscription = json['emailSubscription'];
|
this.emailSubscription = json['emailSubscription'];
|
||||||
this.sportId = json['sportId'];
|
this.sportId = json['sportId'];
|
||||||
|
this.syncedDate = json['syncedDate'] == null ? null : DateTime.parse(json['syncedDate']);
|
||||||
this.trialDate = json['trialDate'] == null ? null : DateTime.parse(json['trialDate']);
|
this.trialDate = json['trialDate'] == null ? null : DateTime.parse(json['trialDate']);
|
||||||
|
|
||||||
this.dateAdd = json['dateAdd'] == null ? DateTime.parse("0000-00-00") : DateTime.parse(json['dateAdd']);
|
this.dateAdd = json['dateAdd'] == null ? DateTime.parse("0000-00-00") : DateTime.parse(json['dateAdd']);
|
||||||
@ -96,9 +98,13 @@ class Customer {
|
|||||||
"dateChange": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateChange!),
|
"dateChange": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateChange!),
|
||||||
"emailSubscription": this.emailSubscription,
|
"emailSubscription": this.emailSubscription,
|
||||||
"sportId": this.sportId,
|
"sportId": this.sportId,
|
||||||
"trialDate": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.trialDate!),
|
"syncedDate": this.syncedDate == null ? null : DateFormat('yyyy-MM-dd HH:mm:ss').format(this.syncedDate!),
|
||||||
|
"trialDate": this.trialDate == null ? null : DateFormat('yyyy-MM-dd HH:mm:ss').format(this.trialDate!),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => this.toJson().toString();
|
||||||
|
|
||||||
double getProperty(String propertyName) {
|
double getProperty(String propertyName) {
|
||||||
if (this.properties[propertyName] == null) {
|
if (this.properties[propertyName] == null) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -59,7 +59,7 @@ class CustomerTrainingPlanDetails {
|
|||||||
this.exerciseTypeId = json['exerciseTypeId'];
|
this.exerciseTypeId = json['exerciseTypeId'];
|
||||||
this.set = json['set'];
|
this.set = json['set'];
|
||||||
this.repeats = json['repeats'] == "null" ? -1 : json['repeats'];
|
this.repeats = json['repeats'] == "null" ? -1 : json['repeats'];
|
||||||
this.weight = json['weight'];
|
this.weight = json['weight'] == "null" ? 0 : json['weight'];
|
||||||
this.restingTime = json['restingTime'];
|
this.restingTime = json['restingTime'];
|
||||||
this.parallel = json['parallel'] == "false"
|
this.parallel = json['parallel'] == "false"
|
||||||
? false
|
? false
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aitrainer_app/util/app_language.dart';
|
|
||||||
|
|
||||||
class Faq {
|
class Faq {
|
||||||
late int faqId;
|
late int faqId;
|
||||||
late String name;
|
late String name;
|
||||||
|
40
lib/model/mautic.dart
Normal file
40
lib/model/mautic.dart
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
class Mautic {
|
||||||
|
late int formId;
|
||||||
|
String? firstname;
|
||||||
|
String? lastname;
|
||||||
|
String? email;
|
||||||
|
String? fitnessLevel;
|
||||||
|
String? goal;
|
||||||
|
int? databaseId;
|
||||||
|
String? subscriptionDate;
|
||||||
|
String? language;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
"formId": this.formId,
|
||||||
|
"firstname": this.firstname,
|
||||||
|
"lastname": this.lastname,
|
||||||
|
"email": this.email,
|
||||||
|
"fitnessLevel": this.fitnessLevel,
|
||||||
|
"goal": this.goal,
|
||||||
|
"databaseId": this.databaseId,
|
||||||
|
"subscriptionDate": this.subscriptionDate,
|
||||||
|
"language": this.language
|
||||||
|
};
|
||||||
|
|
||||||
|
String toForm() {
|
||||||
|
String form = "mauticform[formId]=${this.formId}";
|
||||||
|
form += this.email == null ? "" : "&mauticform[email]=${this.email}";
|
||||||
|
form += this.lastname == null ? "" : "&mauticform[f_name]=${this.lastname}";
|
||||||
|
form += this.firstname == null ? "" : "&mauticform[firstname]=${this.firstname}";
|
||||||
|
form += this.fitnessLevel == null ? "" : "&mauticform[fitness_level]=${this.fitnessLevel}";
|
||||||
|
form += this.goal == null ? "" : "&mauticform[goal]=${this.goal}";
|
||||||
|
form += this.subscriptionDate == null ? "" : "&mauticform[subscribed]=${this.subscriptionDate}";
|
||||||
|
form += this.databaseId == null ? "" : "&mauticform[database_id]=${this.databaseId}";
|
||||||
|
form += this.language == null ? "" : "&mauticform[language]=${this.language}";
|
||||||
|
|
||||||
|
return form;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => this.toJson().toString();
|
||||||
|
}
|
@ -1,13 +1,21 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
class Sport {
|
class Sport {
|
||||||
late int sportId;
|
late int sportId;
|
||||||
late String name;
|
late String name;
|
||||||
late String sportNameTranslation;
|
|
||||||
|
HashMap<String, String> nameTranslations = HashMap();
|
||||||
|
|
||||||
Sport.fromJson(Map json) {
|
Sport.fromJson(Map json) {
|
||||||
this.sportId = json['sportId'];
|
this.sportId = json['sportId'];
|
||||||
this.name = json['name'];
|
this.name = json['name'];
|
||||||
this.sportNameTranslation =
|
|
||||||
json['translations'] != null && (json['translations']).length > 0 ? json['translations'][0]['sportName'] : this.name;
|
nameTranslations['en'] = name;
|
||||||
|
if (json['translations'] != null && json['translations'].length > 0) {
|
||||||
|
json['translations'].forEach((translation) {
|
||||||
|
nameTranslations[translation['languageCode']] = translation['sportName'];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
|
@ -10,6 +10,7 @@ class TrainingPlanDetail {
|
|||||||
bool? parallel;
|
bool? parallel;
|
||||||
int? dayId;
|
int? dayId;
|
||||||
String? day;
|
String? day;
|
||||||
|
String? summary;
|
||||||
|
|
||||||
TrainingPlanDetail.fromJson(Map<String, dynamic> json) {
|
TrainingPlanDetail.fromJson(Map<String, dynamic> json) {
|
||||||
this.trainingPlanDetailId = json['trainingPlanDetailId'];
|
this.trainingPlanDetailId = json['trainingPlanDetailId'];
|
||||||
@ -35,6 +36,7 @@ class TrainingPlanDetail {
|
|||||||
"parallel": this.parallel,
|
"parallel": this.parallel,
|
||||||
"dayId": this.dayId,
|
"dayId": this.dayId,
|
||||||
"day": this.day,
|
"day": this.day,
|
||||||
|
"summary": this.summary
|
||||||
};
|
};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
49
lib/repository/mautic_repository.dart
Normal file
49
lib/repository/mautic_repository.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/mautic.dart';
|
||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:aitrainer_app/service/mautic.dart';
|
||||||
|
import 'package:aitrainer_app/util/app_language.dart';
|
||||||
|
|
||||||
|
class MauticRepository {
|
||||||
|
final CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
const MauticRepository({required this.customerRepository});
|
||||||
|
|
||||||
|
Future<void> sendMauticSubscription() async {
|
||||||
|
Mautic mautic = Mautic();
|
||||||
|
mautic.formId = 2;
|
||||||
|
mautic.databaseId = Cache().userLoggedIn!.customerId!;
|
||||||
|
mautic.firstname = customerRepository.customer!.firstname == null ? "" : customerRepository.customer!.firstname!;
|
||||||
|
mautic.lastname = customerRepository.customer!.name == null ? "" : customerRepository.customer!.name!;
|
||||||
|
mautic.email = customerRepository.customer!.email == null ? "" : customerRepository.customer!.email!;
|
||||||
|
if (mautic.email == null || mautic.email!.contains("privaterelay.appleid.com")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mautic.fitnessLevel = customerRepository.customer!.fitnessLevel == null ? "" : customerRepository.customer!.fitnessLevel!;
|
||||||
|
mautic.goal = customerRepository.customer!.goal == null ? "" : customerRepository.customer!.goal!;
|
||||||
|
mautic.subscriptionDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
|
||||||
|
mautic.language = AppLanguage().appLocal.languageCode;
|
||||||
|
|
||||||
|
await MauticApi().sendMauticForm(mautic);
|
||||||
|
|
||||||
|
customerRepository.customer!.syncedDate = DateTime.now();
|
||||||
|
await customerRepository.saveCustomer();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> sendMauticDataChange() async {
|
||||||
|
Mautic mautic = Mautic();
|
||||||
|
mautic.formId = 3;
|
||||||
|
mautic.databaseId = Cache().userLoggedIn!.customerId!;
|
||||||
|
mautic.firstname = customerRepository.customer!.firstname == null ? "" : customerRepository.customer!.firstname!;
|
||||||
|
mautic.lastname = customerRepository.customer!.name == null ? "" : customerRepository.customer!.name!;
|
||||||
|
mautic.email = customerRepository.customer!.email == null ? "" : customerRepository.customer!.email!;
|
||||||
|
if (mautic.email == null || mautic.email!.contains("privaterelay.appleid.com")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mautic.fitnessLevel = customerRepository.customer!.fitnessLevel == null ? "" : customerRepository.customer!.fitnessLevel!;
|
||||||
|
mautic.goal = customerRepository.customer!.goal == null ? "" : customerRepository.customer!.goal!;
|
||||||
|
|
||||||
|
await MauticApi().sendMauticForm(mautic);
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,7 @@ class TrainingPlanRepository {
|
|||||||
|
|
||||||
TrainingPlan? trainingPlan = this.getTrainingPlanById(trainingPlanId);
|
TrainingPlan? trainingPlan = this.getTrainingPlanById(trainingPlanId);
|
||||||
if (trainingPlan == null || trainingPlan.details == null) {
|
if (trainingPlan == null || trainingPlan.details == null) {
|
||||||
|
print("trainingPlan null");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,14 +275,26 @@ class TrainingPlanRepository {
|
|||||||
|
|
||||||
bool isWoman = Cache().userLoggedIn!.sex == "w";
|
bool isWoman = Cache().userLoggedIn!.sex == "w";
|
||||||
|
|
||||||
|
if (Cache().userLoggedIn!.goal == "shape_forming") {
|
||||||
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
|
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
|
||||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner") : getTrainingPlanByInternalName("beginner_man");
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner") : getTrainingPlanByInternalName("man_routine1");
|
||||||
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
|
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
|
||||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner_split") : getTrainingPlanByInternalName("beginner_split");
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner_split") : getTrainingPlanByInternalName("man_routine3");
|
||||||
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
|
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
|
||||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_advanced") : getTrainingPlanByInternalName("man_routine4");
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_advanced") : getTrainingPlanByInternalName("man_routine4");
|
||||||
} else {
|
} else {
|
||||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("5day") : getTrainingPlanByInternalName("5day");
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_routine2") : getTrainingPlanByInternalName("man_routine2");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
|
||||||
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner") : getTrainingPlanByInternalName("beginner_man");
|
||||||
|
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
|
||||||
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner_split") : getTrainingPlanByInternalName("man_foundation");
|
||||||
|
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
|
||||||
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_advanced") : getTrainingPlanByInternalName("basic_mass_building");
|
||||||
|
} else {
|
||||||
|
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_routine2") : getTrainingPlanByInternalName("mass_building");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Generated plan $trainingPlanId fitness ${Cache().userLoggedIn!.fitnessLevel} - ${FitnessState.beginner}");
|
print("Generated plan $trainingPlanId fitness ${Cache().userLoggedIn!.fitnessLevel} - ${FitnessState.beginner}");
|
||||||
@ -290,6 +303,7 @@ class TrainingPlanRepository {
|
|||||||
CustomerTrainingPlan? customerTrainingPlan = activateTrainingPlan(trainingPlanId);
|
CustomerTrainingPlan? customerTrainingPlan = activateTrainingPlan(trainingPlanId);
|
||||||
if (customerTrainingPlan != null) {
|
if (customerTrainingPlan != null) {
|
||||||
Cache().myTrainingPlan = customerTrainingPlan;
|
Cache().myTrainingPlan = customerTrainingPlan;
|
||||||
|
Cache().saveMyTrainingPlan();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
29
lib/service/mautic.dart
Normal file
29
lib/service/mautic.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/model/mautic.dart';
|
||||||
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
|
|
||||||
|
class MauticApi with Logging {
|
||||||
|
final String mauticUrl = "https://mautic.aitrainer.app/form/submit?formId=";
|
||||||
|
|
||||||
|
Future<void> sendMauticForm(Mautic model) async {
|
||||||
|
final String body = model.toForm();
|
||||||
|
log(" ===== mautic subscription:" + body);
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
|
||||||
|
String url = mauticUrl + model.formId.toString();
|
||||||
|
|
||||||
|
var uri = Uri.parse(url);
|
||||||
|
final HttpClientRequest request = await client.postUrl(uri);
|
||||||
|
request.headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
|
request.headers.set('cache-control', 'no-cache');
|
||||||
|
|
||||||
|
request.write(body);
|
||||||
|
HttpClientResponse result = await request.close();
|
||||||
|
client.close();
|
||||||
|
if (!(result.statusCode == 200 || result.statusCode == 302)) {
|
||||||
|
trace("mautic response: ${result.statusCode}");
|
||||||
|
throw Exception("Network error, try again later!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -57,7 +57,8 @@ enum TrackingEvent {
|
|||||||
training_plan_execute,
|
training_plan_execute,
|
||||||
training_plan_finished,
|
training_plan_finished,
|
||||||
training_plan_custom,
|
training_plan_custom,
|
||||||
trial
|
trial,
|
||||||
|
feedback_email
|
||||||
}
|
}
|
||||||
|
|
||||||
T enumFromString<T>(Iterable<T> values, String value) {
|
T enumFromString<T>(Iterable<T> values, String value) {
|
||||||
@ -103,3 +104,11 @@ extension ExerciseTypeTrainingPlanStateExt on ExerciseTypeTrainingPlanState {
|
|||||||
bool equalsTo(ExerciseTypeTrainingPlanState state) => this.toString() == state.toString();
|
bool equalsTo(ExerciseTypeTrainingPlanState state) => this.toString() == state.toString();
|
||||||
bool equalsStringTo(String state) => this.toStr() == state;
|
bool equalsStringTo(String state) => this.toStr() == state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ExerciseSaveType { test, training, test_set }
|
||||||
|
|
||||||
|
extension ExerciseSaveTypeExt on ExerciseSaveType {
|
||||||
|
String toStr() => this.toString().split(".").last;
|
||||||
|
bool equalsTo(ExerciseSaveType type) => this.toString() == type.toString();
|
||||||
|
bool equalsStringTo(String type) => this.toStr() == type;
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'package:aitrainer_app/service/tracking_service.dart';
|
|||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/model/tracking.dart' as model;
|
import 'package:aitrainer_app/model/tracking.dart' as model;
|
||||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||||
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flurry_data/flurry_data.dart';
|
import 'package:flurry_data/flurry_data.dart';
|
||||||
import 'package:flutter_uxcam/flutter_uxcam.dart';
|
import 'package:flutter_uxcam/flutter_uxcam.dart';
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ class Track with Logging {
|
|||||||
void track(TrackingEvent event, {String eventValue = ""}) {
|
void track(TrackingEvent event, {String eventValue = ""}) {
|
||||||
analytics.logEvent(name: event.enumToString(), parameters: {"value": eventValue});
|
analytics.logEvent(name: event.enumToString(), parameters: {"value": eventValue});
|
||||||
if (!isInDebugMode) {
|
if (!isInDebugMode) {
|
||||||
FlurryData.logEvent(event.toString());
|
FlurryData.logEvent(event.enumToString());
|
||||||
// Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
|
// Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
|
||||||
FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
|
FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
|
||||||
model.Tracking tracking = model.Tracking();
|
model.Tracking tracking = model.Tracking();
|
||||||
@ -32,6 +33,7 @@ class Track with Logging {
|
|||||||
tracking.eventValue = eventValue;
|
tracking.eventValue = eventValue;
|
||||||
}
|
}
|
||||||
tracking.dateAdd = DateTime.now();
|
tracking.dateAdd = DateTime.now();
|
||||||
|
FirebaseMessaging.instance.subscribeToTopic(event.enumToString());
|
||||||
TrackingApi().saveTracking(tracking);
|
TrackingApi().saveTracking(tracking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ class AccountPage extends StatelessWidget with Trans {
|
|||||||
return ListView(padding: EdgeInsets.only(top: 35), children: <Widget>[
|
return ListView(padding: EdgeInsets.only(top: 35), children: <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Common.badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity),
|
leading: Common.badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity),
|
||||||
subtitle: Text(t("Profile")),
|
subtitle: Text(t("Profile") + " " + t("and") + " " + t("Sport")),
|
||||||
title: TextButton(
|
title: TextButton(
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
Text(customerName, style: TextStyle(color: Colors.blue)),
|
Text(customerName, style: TextStyle(color: Colors.blue)),
|
||||||
@ -108,7 +108,7 @@ class AccountPage extends StatelessWidget with Trans {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Common.badgedIcon(Colors.grey, Icons.perm_contact_cal, "FitnessLevel"), //Icon(Icons.perm_contact_cal),
|
leading: Common.badgedIcon(Colors.grey, Icons.perm_contact_cal, "FitnessLevel"), //Icon(Icons.perm_contact_cal),
|
||||||
subtitle: Text(t("Activity") + " " + t("and") + " " + t("Sport")),
|
subtitle: Text(t("Activity")),
|
||||||
title: TextButton(
|
title: TextButton(
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
Text(fitnessLevel, style: TextStyle(color: Colors.blue)),
|
Text(fitnessLevel, style: TextStyle(color: Colors.blue)),
|
||||||
|
@ -7,6 +7,7 @@ import 'package:aitrainer_app/repository/customer_repository.dart';
|
|||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
import 'package:aitrainer_app/widgets/dialog_html.dart';
|
import 'package:aitrainer_app/widgets/dialog_html.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -34,9 +35,13 @@ class _CustomerBodyTypeAnimationPageState extends State<CustomerBodyTypeAnimatio
|
|||||||
customerRepository = ModalRoute.of(context)!.settings.arguments as CustomerRepository;
|
customerRepository = ModalRoute.of(context)!.settings.arguments as CustomerRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreferredSizeWidget _bar = AppBarMin(
|
||||||
|
back: true,
|
||||||
|
);
|
||||||
|
|
||||||
setContext(context);
|
setContext(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBarNav(depth: 0),
|
appBar: _bar,
|
||||||
body: Container(
|
body: Container(
|
||||||
height: double.infinity,
|
height: double.infinity,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
|
@ -2,8 +2,6 @@ import 'dart:collection';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
|
||||||
import 'package:aitrainer_app/model/sport.dart';
|
|
||||||
import 'package:aitrainer_app/util/app_localization.dart';
|
import 'package:aitrainer_app/util/app_localization.dart';
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/model/fitness_state.dart';
|
import 'package:aitrainer_app/model/fitness_state.dart';
|
||||||
@ -18,7 +16,6 @@ import 'package:google_fonts/google_fonts.dart';
|
|||||||
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
||||||
|
|
||||||
import '../bloc/customer_change/customer_change_bloc.dart';
|
import '../bloc/customer_change/customer_change_bloc.dart';
|
||||||
import '../library/dropdown_search/dropdown_search.dart';
|
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class CustomerFitnessPage extends StatefulWidget {
|
class CustomerFitnessPage extends StatefulWidget {
|
||||||
@ -76,8 +73,11 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||||
} else if (state is CustomerSaveSuccess) {
|
} else if (state is CustomerSaveSuccess) {
|
||||||
|
if (fulldata) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Navigator.of(context).pushNamed("customerSexPage", arguments: changeBloc.customerRepository);
|
} else {
|
||||||
|
Navigator.of(context).popAndPushNamed("customerSexPage", arguments: changeBloc.customerRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -103,15 +103,15 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
|
|||||||
changeBloc.add(CustomerSave()),
|
changeBloc.add(CustomerSave()),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
backgroundColor: Color(0xffb4f500),
|
backgroundColor: Colors.orange[600],
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
CustomIcon.save,
|
CustomIcon.save,
|
||||||
color: Colors.black,
|
color: Colors.white,
|
||||||
size: 26,
|
size: 26,
|
||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
fulldata ? t("Save") : t("Next"),
|
fulldata ? t("Save") : t("Next"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -141,46 +141,19 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: h,
|
height: h,
|
||||||
),
|
),
|
||||||
|
|
||||||
getButton("Beginner", "I am beginner", FitnessState.beginner),
|
getButton("Beginner", "I am beginner", FitnessState.beginner),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: h,
|
height: h,
|
||||||
),
|
),
|
||||||
getButton("Intermediate", "I am intermediate", FitnessState.intermediate),
|
getButton("Intermediate", "I am intermediate", FitnessState.intermediate),
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: h,
|
height: h,
|
||||||
),
|
),
|
||||||
getButton("Advanced", "I am advanced", FitnessState.advanced),
|
getButton("Advanced", "I am advanced", FitnessState.advanced),
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: h,
|
height: h,
|
||||||
),
|
),
|
||||||
getButton("Professional", "I am professional", FitnessState.professional),
|
getButton("Professional", "I am professional", FitnessState.professional),
|
||||||
|
|
||||||
/* Divider(),
|
|
||||||
Text(
|
|
||||||
t("Your Primary Sport") + ":",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: GoogleFonts.archivoBlack(
|
|
||||||
color: Colors.orange,
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
), */
|
|
||||||
//getSport(changeBloc),
|
|
||||||
/* Divider(),
|
|
||||||
ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
onPrimary: Colors.white,
|
|
||||||
primary: Colors.orange,
|
|
||||||
),
|
|
||||||
child: Text(fulldata ? t("Save") : t("Next")),
|
|
||||||
onPressed: () => {
|
|
||||||
changeBloc.add(CustomerSave()),
|
|
||||||
Navigator.of(context).pop(),
|
|
||||||
if (!fulldata) {Navigator.of(context).pushNamed("customerBodyTypePage", arguments: customerRepository)}
|
|
||||||
},
|
|
||||||
) */
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -233,98 +206,6 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
|
|||||||
side: BorderSide(width: 4, color: Colors.white24),
|
side: BorderSide(width: 4, color: Colors.white24),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
);
|
);
|
||||||
//return
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getSport(CustomerChangeBloc bloc) {
|
|
||||||
Sport? selected = bloc.selectedSport;
|
|
||||||
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) {
|
|
||||||
if (i == null || s == null) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return i.sportId == s.sportId;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
showSelectedItem: true,
|
|
||||||
selectedItem: selected,
|
|
||||||
itemAsString: (data) => t(data!.sportNameTranslation),
|
|
||||||
onChanged: (data) {
|
|
||||||
bloc.add(CustomerSportChange(sport: data!));
|
|
||||||
},
|
|
||||||
dropdownBuilder: _customDropDownItem,
|
|
||||||
popupItemBuilder: _customMenuBuilder,
|
|
||||||
popupBarrierColor: Colors.white10,
|
|
||||||
//popupBackgroundColor: Colors.yellow,
|
|
||||||
items: Cache().getSports(),
|
|
||||||
dropDownButton: Icon(
|
|
||||||
Icons.arrow_drop_down,
|
|
||||||
color: Colors.indigo,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
//items: FitnessItem().toList()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _customMenuBuilder(BuildContext context, Sport? sport, bool isSelected) {
|
|
||||||
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!.sportNameTranslation),
|
|
||||||
style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.blue[600]),
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
t(sport.name),
|
|
||||||
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.sportNameTranslation),
|
|
||||||
style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.blue[600]),
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
t(item.name),
|
|
||||||
style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[600]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ class _CustomerGoalPage extends State<CustomerGoalPage> with Trans {
|
|||||||
customerRepository = CustomerRepository();
|
customerRepository = CustomerRepository();
|
||||||
}
|
}
|
||||||
PreferredSizeWidget _bar = AppBarMin(
|
PreferredSizeWidget _bar = AppBarMin(
|
||||||
back: false,
|
back: true,
|
||||||
);
|
);
|
||||||
if (!fulldata) {
|
if (!fulldata) {
|
||||||
_bar = AppBarProgress(max: 14, min: 0);
|
_bar = AppBarProgress(max: 14, min: 0);
|
||||||
@ -107,7 +107,11 @@ class _CustomerGoalPage extends State<CustomerGoalPage> with Trans {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||||
} else if (state is CustomerSaveSuccess) {
|
} else if (state is CustomerSaveSuccess) {
|
||||||
Navigator.of(context).pushNamed("customerFitnessPage", arguments: changeBloc.customerRepository);
|
if (fulldata) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).popAndPushNamed("customerFitnessPage", arguments: changeBloc.customerRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -136,15 +140,15 @@ class _CustomerGoalPage extends State<CustomerGoalPage> with Trans {
|
|||||||
changeBloc.add(CustomerSave()),
|
changeBloc.add(CustomerSave()),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
backgroundColor: Color(0xffb4f500),
|
backgroundColor: Colors.orange[600],
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
CustomIcon.save,
|
CustomIcon.save,
|
||||||
color: Colors.black,
|
color: Colors.white,
|
||||||
size: 26,
|
size: 26,
|
||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
fulldata ? t("Save") : t("Next"),
|
fulldata ? t("Save") : t("Next"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -64,8 +64,11 @@ class _CustomerHeightPageState extends State<CustomerHeightPage> with Trans {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||||
} else if (state is CustomerSaveSuccess) {
|
} else if (state is CustomerSaveSuccess) {
|
||||||
|
if (fulldata) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Navigator.of(context).pushNamed("registration", arguments: changeBloc.customerRepository);
|
} else {
|
||||||
|
Navigator.of(context).popAndPushNamed("registration", arguments: changeBloc.customerRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -76,15 +79,15 @@ class _CustomerHeightPageState extends State<CustomerHeightPage> with Trans {
|
|||||||
)),
|
)),
|
||||||
floatingActionButton: FloatingActionButton.extended(
|
floatingActionButton: FloatingActionButton.extended(
|
||||||
onPressed: () => changeBloc.add(CustomerSaveHeight()),
|
onPressed: () => changeBloc.add(CustomerSaveHeight()),
|
||||||
backgroundColor: Color(0xffb4f500),
|
backgroundColor: Colors.orange[600],
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
CustomIcon.save,
|
CustomIcon.save,
|
||||||
color: Colors.black,
|
color: Colors.white,
|
||||||
size: 26,
|
size: 26,
|
||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
fulldata ? t("Save") : t("Finish"),
|
fulldata ? t("Save") : t("Finish"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,10 @@ import 'dart:collection';
|
|||||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||||
|
import 'package:aitrainer_app/library/dropdown_search/dropdown_search.dart';
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/sport.dart';
|
||||||
|
import 'package:aitrainer_app/util/app_language.dart';
|
||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
@ -385,10 +388,119 @@ class CustomerModifyPage extends StatelessWidget with Trans {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
Divider(),
|
Divider(),
|
||||||
|
Divider(),
|
||||||
|
Text(
|
||||||
|
t("Your Primary Sport") + ":",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: GoogleFonts.archivoBlack(
|
||||||
|
color: Colors.orange,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
getSport(customerBloc),
|
||||||
|
Divider(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget getSport(CustomerChangeBloc bloc) {
|
||||||
|
Sport? selected = bloc.selectedSport;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (i == null || s == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return i.sportId == s.sportId;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showSelectedItem: true,
|
||||||
|
selectedItem: selected,
|
||||||
|
itemAsString: (data) => data!.nameTranslations[AppLanguage().appLocal.toString()] != null
|
||||||
|
? data.nameTranslations[AppLanguage().appLocal.toString()]!
|
||||||
|
: data.name,
|
||||||
|
onChanged: (data) {
|
||||||
|
bloc.add(CustomerSportChange(sport: data!));
|
||||||
|
},
|
||||||
|
dropdownBuilder: _customDropDownItem,
|
||||||
|
popupItemBuilder: _customMenuBuilder,
|
||||||
|
popupBarrierColor: Colors.white10,
|
||||||
|
//popupBackgroundColor: Colors.yellow,
|
||||||
|
items: Cache().getSports(),
|
||||||
|
dropDownButton: Icon(
|
||||||
|
Icons.arrow_drop_down,
|
||||||
|
color: Colors.indigo,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
//items: FitnessItem().toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _customMenuBuilder(BuildContext context, Sport? sport, bool isSelected) {
|
||||||
|
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(
|
||||||
|
sport!.nameTranslations[AppLanguage().appLocal.toString()] != null
|
||||||
|
? sport.nameTranslations[AppLanguage().appLocal.toString()]!
|
||||||
|
: sport.name,
|
||||||
|
style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.blue[600]),
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
sport.name,
|
||||||
|
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(
|
||||||
|
item.nameTranslations[AppLanguage().appLocal.toString()] != null
|
||||||
|
? item.nameTranslations[AppLanguage().appLocal.toString()]!
|
||||||
|
: item.name,
|
||||||
|
style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.blue[600]),
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
item.name,
|
||||||
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[600]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,11 @@ class _CustomerSexPageState extends State<CustomerSexPage> with Trans {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||||
} else if (state is CustomerSaveSuccess) {
|
} else if (state is CustomerSaveSuccess) {
|
||||||
|
if (fulldata) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Navigator.of(context).pushNamed("customerWeightPage", arguments: changeBloc.customerRepository);
|
} else {
|
||||||
|
Navigator.of(context).popAndPushNamed("customerWeightPage", arguments: changeBloc.customerRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -84,15 +87,15 @@ class _CustomerSexPageState extends State<CustomerSexPage> with Trans {
|
|||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
changeBloc.add(CustomerSaveSex()),
|
changeBloc.add(CustomerSaveSex()),
|
||||||
},
|
},
|
||||||
backgroundColor: Color(0xffb4f500),
|
backgroundColor: Colors.orange[600],
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
CustomIcon.save,
|
CustomIcon.save,
|
||||||
color: Colors.black,
|
color: Colors.white,
|
||||||
size: 26,
|
size: 26,
|
||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
fulldata ? t("Save") : t("Next"),
|
fulldata ? t("Save") : t("Next"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||||
|
|
||||||
import 'package:aitrainer_app/util/app_localization.dart';
|
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
@ -65,8 +64,11 @@ class _CustomerWeightPageState extends State<CustomerWeightPage> with Trans {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||||
} else if (state is CustomerSaveSuccess) {
|
} else if (state is CustomerSaveSuccess) {
|
||||||
|
if (fulldata) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
Navigator.of(context).pushNamed("customerHeightPage", arguments: changeBloc.customerRepository);
|
} else {
|
||||||
|
Navigator.of(context).popAndPushNamed("customerHeightPage", arguments: changeBloc.customerRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
@ -85,15 +87,15 @@ class _CustomerWeightPageState extends State<CustomerWeightPage> with Trans {
|
|||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
changeBloc.add(CustomerSaveWeight()),
|
changeBloc.add(CustomerSaveWeight()),
|
||||||
},
|
},
|
||||||
backgroundColor: Color(0xffb4f500),
|
backgroundColor: Colors.orange[600],
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
CustomIcon.save,
|
CustomIcon.save,
|
||||||
color: Colors.black,
|
color: Colors.white,
|
||||||
size: 26,
|
size: 26,
|
||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
fulldata ? t("Save") : t("Next"),
|
fulldata ? t("Save") : t("Next"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:aitrainer_app/library/button_animations.dart';
|
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -231,7 +231,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
Divider(),
|
Divider(),
|
||||||
numberPickForm(exerciseBloc, 3),
|
numberPickForm(exerciseBloc, 3),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 80,
|
height: 120,
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
)),
|
)),
|
||||||
@ -263,12 +263,10 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) {
|
Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) {
|
||||||
final String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max.";
|
final String strTimes = step == 2 ? exerciseBloc.controlList[step - 1].quantity!.toStringAsFixed(0) : "max.";
|
||||||
//print("step $step, quantity ${exerciseBloc.origQuantity}");
|
|
||||||
|
|
||||||
String title = (step + 1).toString() + "/4 " + t("Control Exercise:");
|
String title = (step + 1).toString() + "/4 " + t("Control Exercise:");
|
||||||
LinkedHashMap args = LinkedHashMap();
|
LinkedHashMap args = LinkedHashMap();
|
||||||
final TutorialBloc tutorialBloc = BlocProvider.of<TutorialBloc>(context);
|
|
||||||
|
|
||||||
List<Widget> listWidgets = [
|
List<Widget> listWidgets = [
|
||||||
Text(
|
Text(
|
||||||
@ -294,7 +292,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(text: t("Please repeat with ")),
|
TextSpan(text: t("Please repeat with ")),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: exerciseBloc.unitQuantity.toStringAsFixed(0) +
|
text: exerciseBloc.controlList[step - 1].unitQuantity!.toStringAsFixed(0) +
|
||||||
" " +
|
" " +
|
||||||
exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit!,
|
exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit!,
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
@ -324,7 +322,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
NumberPickerWidget(
|
NumberPickerWidget(
|
||||||
minValue: 0,
|
minValue: 0,
|
||||||
maxValue: 200,
|
maxValue: 200,
|
||||||
initalValue: exerciseBloc.origQuantity.round(),
|
initalValue: exerciseBloc.controlList[step - 1].quantity!.round(),
|
||||||
unit: t("reps"),
|
unit: t("reps"),
|
||||||
color: Colors.yellow[50]!,
|
color: Colors.yellow[50]!,
|
||||||
onChange: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))}),
|
onChange: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))}),
|
||||||
@ -335,12 +333,6 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
onSurface: Colors.blueAccent,
|
onSurface: Colors.blueAccent,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (tutorialBloc.isActive) {
|
|
||||||
if (!tutorialBloc.checkAction("Save")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exerciseBloc.add(ExerciseControlSubmit(step: step));
|
exerciseBloc.add(ExerciseControlSubmit(step: step));
|
||||||
if (step == 3) {
|
if (step == 3) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@ -354,7 +346,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
|||||||
children: [
|
children: [
|
||||||
Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60),
|
Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60),
|
||||||
Text(
|
Text(
|
||||||
t("Save"),
|
t("Done!"),
|
||||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -436,9 +428,9 @@ class _UnitQuantityControlState extends State<UnitQuantityControl> with Trans {
|
|||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
NumberPickerWidget(
|
NumberPickerWidget(
|
||||||
minValue: (widget.exerciseBloc.unitQuantity - 30).round(),
|
minValue: (widget.exerciseBloc.controlList[widget.step - 1].unitQuantity! - 30).round(),
|
||||||
maxValue: (widget.exerciseBloc.unitQuantity + 30).round(),
|
maxValue: (widget.exerciseBloc.controlList[widget.step - 1].unitQuantity! + 30).round(),
|
||||||
initalValue: widget.exerciseBloc.unitQuantity.round(),
|
initalValue: widget.exerciseBloc.controlList[widget.step - 1].unitQuantity!.round(),
|
||||||
unit: t("kg"),
|
unit: t("kg"),
|
||||||
color: Colors.yellow[50]!,
|
color: Colors.yellow[50]!,
|
||||||
onChange: (value) => {
|
onChange: (value) => {
|
||||||
@ -452,9 +444,9 @@ class _UnitQuantityControlState extends State<UnitQuantityControl> with Trans {
|
|||||||
onTap: () => {
|
onTap: () => {
|
||||||
if (changedValue == null)
|
if (changedValue == null)
|
||||||
{
|
{
|
||||||
changedValue = widget.exerciseBloc.unitQuantity,
|
changedValue = widget.exerciseBloc.controlList[widget.step - 1].unitQuantity,
|
||||||
},
|
},
|
||||||
//print("Changed new value $changedValue"),
|
print("Changed new value $changedValue, step ${widget.step}"),
|
||||||
widget.exerciseBloc.add(ExerciseControlUnitQuantityChange(quantity: changedValue!.toDouble(), step: widget.step)),
|
widget.exerciseBloc.add(ExerciseControlUnitQuantityChange(quantity: changedValue!.toDouble(), step: widget.step)),
|
||||||
Navigator.of(context).pop(),
|
Navigator.of(context).pop(),
|
||||||
},
|
},
|
||||||
|
@ -8,6 +8,7 @@ import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
|||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
@ -17,6 +18,7 @@ import 'package:aitrainer_app/widgets/bmi_widget.dart';
|
|||||||
import 'package:aitrainer_app/widgets/bmr_widget.dart';
|
import 'package:aitrainer_app/widgets/bmr_widget.dart';
|
||||||
import 'package:aitrainer_app/widgets/dialog_common.dart';
|
import 'package:aitrainer_app/widgets/dialog_common.dart';
|
||||||
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/menu_image.dart';
|
||||||
import 'package:aitrainer_app/widgets/size_widget.dart';
|
import 'package:aitrainer_app/widgets/size_widget.dart';
|
||||||
import 'package:aitrainer_app/widgets/tutorial_widget.dart';
|
import 'package:aitrainer_app/widgets/tutorial_widget.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -55,7 +57,9 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
|||||||
title: t("Warning"),
|
title: t("Warning"),
|
||||||
descriptions: t(state.message),
|
descriptions: t(state.message),
|
||||||
text: "OK",
|
text: "OK",
|
||||||
onTap: () => Navigator.of(context).pushNamed("login"),
|
onTap: () => {
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
},
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
Navigator.of(context).pop(),
|
Navigator.of(context).pop(),
|
||||||
},
|
},
|
||||||
@ -114,10 +118,12 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
|||||||
return SizeWidget(exerciseBloc: exerciseBloc);
|
return SizeWidget(exerciseBloc: exerciseBloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WorkoutMenuTree? workoutTree = menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(exerciseType.exerciseTypeId);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBarNav(depth: 1),
|
appBar: AppBarNav(depth: 1),
|
||||||
body: Container(
|
body: Container(
|
||||||
padding: EdgeInsets.only(top: 10, left: 20, right: 20),
|
padding: EdgeInsets.only(),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage('asset/image/WT_black_background.jpg'),
|
image: AssetImage('asset/image/WT_black_background.jpg'),
|
||||||
@ -140,23 +146,24 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
|||||||
onUnitQuantityChanged: (value) => exerciseBloc.add(ExerciseNewQuantityUnitChange(quantity: value)),
|
onUnitQuantityChanged: (value) => exerciseBloc.add(ExerciseNewQuantityUnitChange(quantity: value)),
|
||||||
//onSubmit: () => confirmationDialog(exerciseBloc, menuBloc),
|
//onSubmit: () => confirmationDialog(exerciseBloc, menuBloc),
|
||||||
exerciseTypeId: exerciseType.exerciseTypeId,
|
exerciseTypeId: exerciseType.exerciseTypeId,
|
||||||
)),
|
tip: ActivityDone.exerciseSaveTestTip,
|
||||||
|
menuImage: MenuImage(
|
||||||
|
imageName: workoutTree!.imageName,
|
||||||
|
workoutTreeId: workoutTree.id,
|
||||||
|
radius: 0,
|
||||||
|
))),
|
||||||
floatingActionButton: FloatingActionButton.extended(
|
floatingActionButton: FloatingActionButton.extended(
|
||||||
onPressed: () => save(exerciseBloc, menuBloc),
|
onPressed: () => save(exerciseBloc, menuBloc),
|
||||||
backgroundColor: Colors.orange[800],
|
backgroundColor: Colors.orange[600],
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
CustomIcon.save,
|
CustomIcon.ok_circled,
|
||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
t("Save"),
|
t("Done!"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 12),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
/* bottomNavigationBar: BottomBarMultipleExercises(
|
|
||||||
isSet: false,
|
|
||||||
exerciseTypeId: exerciseType.exerciseTypeId,
|
|
||||||
), */
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,6 +202,11 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bloc.quantity == -1 || bloc.unitQuantity == -1) {
|
||||||
|
bloc.add(ExerciseNewAddError(message: "Please type in a real number!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String quantity = bloc.exerciseRepository.exercise!.quantity! % 1 == 0
|
String quantity = bloc.exerciseRepository.exercise!.quantity! % 1 == 0
|
||||||
? bloc.exerciseRepository.exercise!.quantity!.round().toString()
|
? bloc.exerciseRepository.exercise!.quantity!.round().toString()
|
||||||
: bloc.exerciseRepository.exercise!.quantity!.toString();
|
: bloc.exerciseRepository.exercise!.quantity!.toString();
|
||||||
@ -209,9 +221,9 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
|||||||
// ignore: close_sinks
|
// ignore: close_sinks
|
||||||
final TestSetExecuteBloc executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
|
final TestSetExecuteBloc executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
|
||||||
|
|
||||||
final question = bloc.exerciseRepository.exercise!.quantity! == 12.0
|
/* 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?"
|
? "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?";
|
final question = "Do you save this exercise with these parameters?";
|
||||||
|
|
||||||
showCupertinoDialog(
|
showCupertinoDialog(
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
|
@ -37,7 +37,7 @@ class _MyDevelopmentBodyPage extends State<MyDevelopmentBodyPage> with Trans, Co
|
|||||||
setContext(context);
|
setContext(context);
|
||||||
return DialogPremium(
|
return DialogPremium(
|
||||||
unlocked: Cache().hasPurchased,
|
unlocked: Cache().hasPurchased,
|
||||||
unlockRound: 2,
|
unlockRound: 4,
|
||||||
function: "My Whole Body Development",
|
function: "My Whole Body Development",
|
||||||
unlockedText: null,
|
unlockedText: null,
|
||||||
onTap: () => {Navigator.of(context).pop(), Navigator.of(context).pop()},
|
onTap: () => {Navigator.of(context).pop(), Navigator.of(context).pop()},
|
||||||
|
@ -163,7 +163,7 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return DialogPremium(
|
return DialogPremium(
|
||||||
unlocked: Cache().hasPurchased,
|
unlocked: Cache().hasPurchased,
|
||||||
unlockRound: 3,
|
unlockRound: 12,
|
||||||
function: "Predictions",
|
function: "Predictions",
|
||||||
unlockedText: null,
|
unlockedText: null,
|
||||||
onTap: () => {Navigator.of(context).pop()},
|
onTap: () => {Navigator.of(context).pop()},
|
||||||
|
@ -2,6 +2,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/login/login_bloc.dart';
|
import 'package:aitrainer_app/bloc/login/login_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
import 'package:aitrainer_app/repository/training_plan_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/user_repository.dart';
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
@ -23,12 +24,23 @@ class RegistrationPage extends StatelessWidget with Trans {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final accountBloc = BlocProvider.of<AccountBloc>(context);
|
final accountBloc = BlocProvider.of<AccountBloc>(context);
|
||||||
|
|
||||||
|
CustomerRepository? customerRepository;
|
||||||
|
if (ModalRoute.of(context) != null && ModalRoute.of(context)!.settings.arguments != null) {
|
||||||
|
customerRepository = ModalRoute.of(context)!.settings.arguments as CustomerRepository;
|
||||||
|
print("CustomerFitness reg ${customerRepository.customer!.toJson()}");
|
||||||
|
}
|
||||||
|
|
||||||
setContext(context);
|
setContext(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBarMin(),
|
appBar: AppBarMin(),
|
||||||
body: BlocProvider(
|
body: BlocProvider(
|
||||||
create: (context) =>
|
create: (context) => LoginBloc(
|
||||||
LoginBloc(userRepository: UserRepository(), accountBloc: accountBloc, context: context, isRegistration: true),
|
userRepository: UserRepository(),
|
||||||
|
accountBloc: accountBloc,
|
||||||
|
context: context,
|
||||||
|
isRegistration: true,
|
||||||
|
customerRepository: customerRepository),
|
||||||
child: BlocConsumer<LoginBloc, LoginState>(listener: (context, state) {
|
child: BlocConsumer<LoginBloc, LoginState>(listener: (context, state) {
|
||||||
if (state is LoginError) {
|
if (state is LoginError) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@ -67,7 +79,9 @@ class RegistrationPage extends StatelessWidget with Trans {
|
|||||||
}
|
}
|
||||||
}, builder: (context, state) {
|
}, builder: (context, state) {
|
||||||
final loginBloc = BlocProvider.of<LoginBloc>(context);
|
final loginBloc = BlocProvider.of<LoginBloc>(context);
|
||||||
|
if (customerRepository != null) {
|
||||||
|
print("Customer data ${customerRepository.customer!.toJson()}");
|
||||||
|
}
|
||||||
return ModalProgressHUD(
|
return ModalProgressHUD(
|
||||||
child: loadForm(loginBloc, accountBloc),
|
child: loadForm(loginBloc, accountBloc),
|
||||||
inAsyncCall: state is LoginLoading,
|
inAsyncCall: state is LoginLoading,
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
||||||
import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
|
import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
|
||||||
@ -19,8 +17,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
||||||
import 'package:toggle_switch/toggle_switch.dart';
|
import 'package:toggle_switch/toggle_switch.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:mailto/mailto.dart';
|
||||||
import 'dart:async';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class SettingsPage extends StatelessWidget with Trans {
|
class SettingsPage extends StatelessWidget with Trans {
|
||||||
@ -87,7 +85,7 @@ class SettingsPage extends StatelessWidget with Trans {
|
|||||||
//getTuturialBasic(settingsBloc),
|
//getTuturialBasic(settingsBloc),
|
||||||
getTermsOfUse(),
|
getTermsOfUse(),
|
||||||
getPrivacy(),
|
getPrivacy(),
|
||||||
getFaq(),
|
mailTo(),
|
||||||
getVersion(),
|
getVersion(),
|
||||||
//getDevice(settingsBloc),
|
//getDevice(settingsBloc),
|
||||||
]);
|
]);
|
||||||
@ -264,25 +262,40 @@ class SettingsPage extends StatelessWidget with Trans {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _printAndCopy(String cmd) async {
|
ListTile mailTo() {
|
||||||
print(cmd);
|
return ListTile(
|
||||||
|
leading: Icon(CustomIcon.mail_1),
|
||||||
await Clipboard.setData(ClipboardData(text: cmd));
|
title: TextButton(
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
const SnackBar(content: Text('Copied to Clipboard')),
|
Text("Feedback email", style: TextStyle(color: Colors.indigo)),
|
||||||
|
Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: Colors.indigo,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: Colors.white70,
|
||||||
|
onSurface: Colors.grey,
|
||||||
|
),
|
||||||
|
onPressed: () => {
|
||||||
|
launchMailto(),
|
||||||
|
Track().track(TrackingEvent.feedback_email),
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void link1() {
|
launchMailto() async {
|
||||||
String? cmd;
|
String from = Cache().userLoggedIn == null ? "" : Cache().userLoggedIn!.customerId!.toStringAsFixed(0);
|
||||||
String cmdSuffix;
|
final mailtoLink = Mailto(
|
||||||
if (Platform.isIOS) {
|
to: ['service@workouttest.com'],
|
||||||
cmd = '/usr/bin/xcrun simctl openurl booted';
|
subject: 'Feedback from app: $from',
|
||||||
} else if (Platform.isAndroid) {
|
body: '',
|
||||||
cmd = '\$ANDROID_HOME/platform-tools/adb shell \'am start'
|
);
|
||||||
' -a android.intent.action.VIEW'
|
// Convert the Mailto instance into a string.
|
||||||
' -c android.intent.category.BROWSABLE -d';
|
// Use either Dart's string interpolation
|
||||||
cmdSuffix = "'";
|
// or the toString() method.
|
||||||
}
|
print("Mailto: $mailtoLink");
|
||||||
|
await launch('$mailtoLink');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,16 @@ import 'dart:collection';
|
|||||||
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_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/bloc/test_set_new/test_set_new_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||||
import 'package:aitrainer_app/widgets/bottom_bar_multiple_exercises.dart';
|
import 'package:aitrainer_app/widgets/bottom_bar_multiple_exercises.dart';
|
||||||
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/menu_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
@ -29,7 +32,6 @@ class TestSetNew extends StatelessWidget with Trans {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBarNav(depth: 1),
|
appBar: AppBarNav(depth: 1),
|
||||||
body: Container(
|
body: Container(
|
||||||
padding: EdgeInsets.all(20),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage('asset/image/WT_black_background.jpg'),
|
image: AssetImage('asset/image/WT_black_background.jpg'),
|
||||||
@ -77,7 +79,7 @@ class TestSetNew extends StatelessWidget with Trans {
|
|||||||
backgroundColor: Colors.orange[800],
|
backgroundColor: Colors.orange[800],
|
||||||
icon: Icon(CustomIcon.save),
|
icon: Icon(CustomIcon.save),
|
||||||
label: Text(
|
label: Text(
|
||||||
t("Save"),
|
t("Done"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -89,6 +91,8 @@ class TestSetNew extends StatelessWidget with Trans {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget getExercises(TestSetNewBloc bloc) {
|
Widget getExercises(TestSetNewBloc bloc) {
|
||||||
|
WorkoutMenuTree? workoutTree =
|
||||||
|
bloc.executeBloc.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(bloc.exerciseType.exerciseTypeId);
|
||||||
return ExerciseSave(
|
return ExerciseSave(
|
||||||
exerciseName: bloc.exerciseType.nameTranslation,
|
exerciseName: bloc.exerciseType.nameTranslation,
|
||||||
exerciseDescription: bloc.exerciseType.descriptionTranslation,
|
exerciseDescription: bloc.exerciseType.descriptionTranslation,
|
||||||
@ -103,6 +107,12 @@ class TestSetNew extends StatelessWidget with Trans {
|
|||||||
},
|
},
|
||||||
onUnitQuantityChanged: (value) => bloc.add(TestSetNewChangeQuantityUnit(quantity: value)),
|
onUnitQuantityChanged: (value) => bloc.add(TestSetNewChangeQuantityUnit(quantity: value)),
|
||||||
exerciseTypeId: bloc.exerciseType.exerciseTypeId,
|
exerciseTypeId: bloc.exerciseType.exerciseTypeId,
|
||||||
|
tip: ActivityDone.exerciseSaveTestsetTip,
|
||||||
|
menuImage: MenuImage(
|
||||||
|
imageName: workoutTree!.imageName,
|
||||||
|
workoutTreeId: workoutTree.id,
|
||||||
|
radius: 0,
|
||||||
|
),
|
||||||
/* onSubmit: () {
|
/* onSubmit: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
bloc.add(TestSetNewSubmit());
|
bloc.add(TestSetNewSubmit());
|
||||||
|
@ -6,6 +6,7 @@ import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
|||||||
import 'package:aitrainer_app/library/tree_view.dart';
|
import 'package:aitrainer_app/library/tree_view.dart';
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/training_plan.dart';
|
import 'package:aitrainer_app/model/training_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/training_plan_detail.dart';
|
||||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||||
import 'package:aitrainer_app/util/app_language.dart';
|
import 'package:aitrainer_app/util/app_language.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
@ -58,7 +59,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
title: t("Warning"),
|
title: t("Warning"),
|
||||||
descriptions: t(state.message),
|
descriptions: t(state.message),
|
||||||
text: "OK",
|
text: "OK",
|
||||||
onTap: () => Navigator.of(context).pushNamed("login"),
|
onTap: () => Navigator.of(context).pop(),
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
Navigator.of(context).pop(),
|
Navigator.of(context).pop(),
|
||||||
},
|
},
|
||||||
@ -197,21 +198,45 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
icon: Icon(Icons.list_sharp),
|
icon: Icon(Icons.list_sharp),
|
||||||
color: Colors.blue[800],
|
color: Colors.blue[800],
|
||||||
),
|
),
|
||||||
children: _getChildList(element, bloc),
|
children: _getDays(element, bloc),
|
||||||
)));
|
)));
|
||||||
});
|
});
|
||||||
|
|
||||||
return listWidget;
|
return listWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _getChildList(TrainingPlan plan, TrainingPlanBloc bloc) {
|
List<Widget> _getDays(TrainingPlan plan, TrainingPlanBloc bloc) {
|
||||||
|
List<Widget> listWidget = [];
|
||||||
|
|
||||||
|
bloc.setMyTrainingPlan(plan);
|
||||||
|
bloc.activateTrainingPlanDays();
|
||||||
|
bloc.trainingPlanDayNames.forEach((value) {
|
||||||
|
listWidget.add(Container(
|
||||||
|
margin: const EdgeInsets.only(left: 4.0),
|
||||||
|
child: TreeViewChild(
|
||||||
|
startExpanded: true,
|
||||||
|
parent: TreeviewParentWidget(
|
||||||
|
text: " * " + t("Training Day") + ": " + value,
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
icon: Icon(Icons.view_day),
|
||||||
|
backgroundColor: Colors.white24,
|
||||||
|
),
|
||||||
|
children: _getChildList(plan, bloc, value),
|
||||||
|
)));
|
||||||
|
});
|
||||||
|
|
||||||
|
return listWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _getChildList(TrainingPlan plan, TrainingPlanBloc bloc, String dayName) {
|
||||||
List<Widget> list = [];
|
List<Widget> list = [];
|
||||||
|
|
||||||
bool restricted = (!plan.free && !Cache().hasPurchased);
|
bool restricted = (!plan.free && !Cache().hasPurchased);
|
||||||
|
|
||||||
list.add(Card(
|
list.add(Card(
|
||||||
margin: EdgeInsets.only(left: 10, top: 5),
|
margin: EdgeInsets.only(left: 10, top: 5),
|
||||||
color: Colors.white60,
|
color: Colors.white24,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.only(left: 10, right: 10),
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
@ -262,7 +287,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
),
|
),
|
||||||
))
|
))
|
||||||
: Offstage(),
|
: Offstage(),
|
||||||
getPlanDetails(plan, bloc),
|
getPlanDetails(plan, bloc, dayName),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
onPrimary: Colors.white,
|
onPrimary: Colors.white,
|
||||||
@ -371,13 +396,17 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getPlanDetails(TrainingPlan plan, TrainingPlanBloc bloc) {
|
Widget getPlanDetails(TrainingPlan plan, TrainingPlanBloc bloc, String dayName) {
|
||||||
return SfDataGrid(
|
return SfDataGrid(
|
||||||
headerRowHeight: 30,
|
headerRowHeight: 30,
|
||||||
rowHeight: 60,
|
rowHeight: 70,
|
||||||
|
columnWidthMode: ColumnWidthMode.lastColumnFill,
|
||||||
|
defaultColumnWidth: 50,
|
||||||
source: TrainingPlanDetailSource(
|
source: TrainingPlanDetailSource(
|
||||||
plan: plan,
|
plan: plan,
|
||||||
menuBloc: bloc.menuBloc,
|
menuBloc: bloc.menuBloc,
|
||||||
|
bloc: bloc,
|
||||||
|
dayName: dayName,
|
||||||
onWeightTap: () => {
|
onWeightTap: () => {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@ -438,18 +467,23 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
columns: [
|
columns: [
|
||||||
GridTextColumn(
|
GridTextColumn(
|
||||||
columnWidthMode: ColumnWidthMode.lastColumnFill,
|
columnWidthMode: ColumnWidthMode.lastColumnFill,
|
||||||
maximumWidth: 160,
|
maximumWidth: 130,
|
||||||
columnName: 'exerciseImage',
|
columnName: 'exerciseImage',
|
||||||
label: Container(
|
label: Container(
|
||||||
color: Colors.green[50],
|
color: Colors.black38,
|
||||||
padding: EdgeInsets.only(left: 8.0),
|
padding: EdgeInsets.only(left: 8.0),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
t('Exercise'),
|
t('Exercise'),
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
))),
|
))),
|
||||||
GridTextColumn(
|
GridTextColumn(
|
||||||
|
maximumWidth: 0,
|
||||||
visible: false,
|
visible: false,
|
||||||
columnName: 'exerciseName',
|
columnName: 'exerciseName',
|
||||||
label: Container(
|
label: Container(
|
||||||
@ -462,47 +496,40 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
))),
|
))),
|
||||||
GridTextColumn(
|
GridTextColumn(
|
||||||
maximumWidth: 40,
|
maximumWidth: 60,
|
||||||
columnName: 'set',
|
columnName: 'Set',
|
||||||
label: Container(
|
label: Container(
|
||||||
color: Colors.green[50],
|
color: Colors.black38,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
t('Set'),
|
t('Set'),
|
||||||
|
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
))),
|
))),
|
||||||
GridTextColumn(
|
GridTextColumn(
|
||||||
maximumWidth: 50,
|
maximumWidth: 100,
|
||||||
columnName: 'repeats',
|
columnWidthMode: ColumnWidthMode.fill,
|
||||||
|
columnName: 'Repeats',
|
||||||
label: Container(
|
label: Container(
|
||||||
color: Colors.green[50],
|
color: Colors.black38,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
t('Reps'),
|
t('Repeats'),
|
||||||
|
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
))),
|
))),
|
||||||
GridTextColumn(
|
GridTextColumn(
|
||||||
maximumWidth: 60,
|
maximumWidth: 60,
|
||||||
columnName: 'weight',
|
columnName: 'Weight',
|
||||||
label: Container(
|
label: Container(
|
||||||
color: Colors.green[50],
|
color: Colors.black38,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
t('Weight'),
|
t('Weight_'),
|
||||||
overflow: TextOverflow.ellipsis,
|
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
|
||||||
))),
|
|
||||||
GridTextColumn(
|
|
||||||
maximumWidth: 50,
|
|
||||||
columnName: 'day',
|
|
||||||
label: Container(
|
|
||||||
color: Colors.green[50],
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
t('Day'),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
))),
|
))),
|
||||||
],
|
],
|
||||||
@ -512,19 +539,25 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
|||||||
|
|
||||||
class TrainingPlanDetailSource extends DataGridSource {
|
class TrainingPlanDetailSource extends DataGridSource {
|
||||||
final TrainingPlan plan;
|
final TrainingPlan plan;
|
||||||
|
final TrainingPlanBloc bloc;
|
||||||
final MenuBloc menuBloc;
|
final MenuBloc menuBloc;
|
||||||
|
final dayName;
|
||||||
final VoidCallback onDropsetTap;
|
final VoidCallback onDropsetTap;
|
||||||
final VoidCallback onWeightTap;
|
final VoidCallback onWeightTap;
|
||||||
final VoidCallback onRepeatTap;
|
final VoidCallback onRepeatTap;
|
||||||
TrainingPlanDetailSource({
|
TrainingPlanDetailSource({
|
||||||
required this.plan,
|
required this.plan,
|
||||||
required this.menuBloc,
|
required this.menuBloc,
|
||||||
|
required this.bloc,
|
||||||
|
required this.dayName,
|
||||||
required this.onDropsetTap,
|
required this.onDropsetTap,
|
||||||
required this.onWeightTap,
|
required this.onWeightTap,
|
||||||
required this.onRepeatTap,
|
required this.onRepeatTap,
|
||||||
}) {
|
}) {
|
||||||
if (plan.details != null) {
|
if (plan.details != null) {
|
||||||
dataGridRows = plan.details!.map((dataGridRow) {
|
List<TrainingPlanDetail> details = bloc.trainingPlanDetailSummary(plan, dayName);
|
||||||
|
|
||||||
|
dataGridRows = details.map((dataGridRow) {
|
||||||
WorkoutMenuTree? menuTree = menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(dataGridRow.exerciseTypeId);
|
WorkoutMenuTree? menuTree = menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(dataGridRow.exerciseTypeId);
|
||||||
if (menuTree == null) {
|
if (menuTree == null) {
|
||||||
return DataGridRow(cells: []);
|
return DataGridRow(cells: []);
|
||||||
@ -539,9 +572,8 @@ class TrainingPlanDetailSource extends DataGridSource {
|
|||||||
)),
|
)),
|
||||||
DataGridCell<String>(columnName: 'exerciseName', value: menuTree.name),
|
DataGridCell<String>(columnName: 'exerciseName', value: menuTree.name),
|
||||||
DataGridCell<int>(columnName: 'set', value: dataGridRow.set),
|
DataGridCell<int>(columnName: 'set', value: dataGridRow.set),
|
||||||
DataGridCell<int>(columnName: 'reps', value: dataGridRow.repeats),
|
DataGridCell<String>(columnName: 'reps', value: dataGridRow.summary!),
|
||||||
DataGridCell<double>(columnName: 'weight', value: dataGridRow.weight),
|
DataGridCell<double>(columnName: 'weight', value: dataGridRow.weight),
|
||||||
DataGridCell<String>(columnName: 'day', value: dataGridRow.day),
|
|
||||||
]);
|
]);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
@ -557,9 +589,9 @@ class TrainingPlanDetailSource extends DataGridSource {
|
|||||||
if (row.getCells().isEmpty) {
|
if (row.getCells().isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
String name = row.getCells()[1].value;
|
String name = row.getCells()[1].value.toString();
|
||||||
return DataGridRowAdapter(
|
return DataGridRowAdapter(
|
||||||
color: Colors.white60,
|
color: Colors.white12,
|
||||||
cells: row.getCells().map<Widget>((dataGridCell) {
|
cells: row.getCells().map<Widget>((dataGridCell) {
|
||||||
return Container(
|
return Container(
|
||||||
alignment: dataGridCell.columnName == "exerciseImage" ? Alignment.centerLeft : Alignment.centerLeft,
|
alignment: dataGridCell.columnName == "exerciseImage" ? Alignment.centerLeft : Alignment.centerLeft,
|
||||||
@ -573,8 +605,7 @@ class TrainingPlanDetailSource extends DataGridSource {
|
|||||||
name,
|
name,
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style:
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold, shadows: <Shadow>[
|
||||||
GoogleFonts.inter(fontSize: 10, color: Colors.yellow[600], fontWeight: FontWeight.bold, shadows: <Shadow>[
|
|
||||||
Shadow(
|
Shadow(
|
||||||
offset: Offset(2.0, 2.0),
|
offset: Offset(2.0, 2.0),
|
||||||
blurRadius: 6.0,
|
blurRadius: 6.0,
|
||||||
@ -590,7 +621,7 @@ class TrainingPlanDetailSource extends DataGridSource {
|
|||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
CustomIcon.question_circle,
|
CustomIcon.question_circle,
|
||||||
color: Colors.indigo[300],
|
color: Colors.white,
|
||||||
))
|
))
|
||||||
: dataGridCell.columnName == "weight" && dataGridCell.value == -3
|
: dataGridCell.columnName == "weight" && dataGridCell.value == -3
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
@ -608,12 +639,12 @@ class TrainingPlanDetailSource extends DataGridSource {
|
|||||||
},
|
},
|
||||||
child: Icon(
|
child: Icon(
|
||||||
CustomIcon.question_circle,
|
CustomIcon.question_circle,
|
||||||
color: Colors.indigo[600],
|
color: Colors.white,
|
||||||
))
|
))
|
||||||
: Text(dataGridCell.value.toString(),
|
: Text(dataGridCell.value.toString(),
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.indigo,
|
color: Colors.white,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
)));
|
)));
|
||||||
}).toList());
|
}).toList());
|
||||||
|
@ -45,8 +45,20 @@ class _TrainingPlanExecuteState extends State<TrainingPlanExecute> with Trans {
|
|||||||
),
|
),
|
||||||
child: BlocConsumer<TrainingPlanBloc, TrainingPlanState>(listener: (context, state) {
|
child: BlocConsumer<TrainingPlanBloc, TrainingPlanState>(listener: (context, state) {
|
||||||
if (state is TrainingPlanError) {
|
if (state is TrainingPlanError) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
showDialog(
|
||||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogCommon(
|
||||||
|
warning: true,
|
||||||
|
title: t("Warning"),
|
||||||
|
descriptions: t(state.message),
|
||||||
|
text: "OK",
|
||||||
|
onTap: () => Navigator.of(context).pop(),
|
||||||
|
onCancel: () => {
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
} else if (state is TrainingPlanDayFinished) {
|
} else if (state is TrainingPlanDayFinished) {
|
||||||
bloc.celebrating = false;
|
bloc.celebrating = false;
|
||||||
final HashMap args = HashMap();
|
final HashMap args = HashMap();
|
||||||
@ -368,7 +380,7 @@ class _ExerciseListState extends State<ExerciseList> with Trans {
|
|||||||
bloc.getMyPlan()!.days[widget.dayName] != null &&
|
bloc.getMyPlan()!.days[widget.dayName] != null &&
|
||||||
bloc.getMyPlan()!.days[widget.dayName]!.isNotEmpty) {
|
bloc.getMyPlan()!.days[widget.dayName]!.isNotEmpty) {
|
||||||
bloc.getMyPlan()!.days[widget.dayName]!.forEach((element) {
|
bloc.getMyPlan()!.days[widget.dayName]!.forEach((element) {
|
||||||
if (prev != null && prev!.exerciseTypeId != element.exerciseTypeId) {
|
if (prev == null || (prev != null && prev!.exerciseTypeId != element.exerciseTypeId)) {
|
||||||
tiles.add(GestureDetector(
|
tiles.add(GestureDetector(
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!, context) : Navigator.of(context).pushNamed('home'),
|
bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!, context) : Navigator.of(context).pushNamed('home'),
|
||||||
|
@ -1,914 +0,0 @@
|
|||||||
import 'dart:collection';
|
|
||||||
|
|
||||||
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/dialog_html.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/menu_image.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/weight_control.dart';
|
|
||||||
import 'package:badges/badges.dart';
|
|
||||||
import 'package:extended_tabs/extended_tabs.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/gestures.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_nsn/modal_progress_hud_nsn.dart';
|
|
||||||
import 'package:timeline_tile/timeline_tile.dart';
|
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
|
||||||
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 HashMap args = HashMap();
|
|
||||||
bloc = BlocProvider.of<TrainingPlanBloc>(context);
|
|
||||||
bloc!.activateDays();
|
|
||||||
setContext(context);
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBarNav(depth: 0),
|
|
||||||
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<TrainingPlanBloc, TrainingPlanState>(listener: (context, state) {
|
|
||||||
if (state is TrainingPlanError) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
|
||||||
} else if (state is TrainingPlanDayFinished) {
|
|
||||||
bloc!.celebrating = false;
|
|
||||||
args["bloc"] = bloc;
|
|
||||||
args["day"] = bloc!.dayNames[bloc!.activeDayIndex];
|
|
||||||
Navigator.of(context).pushNamed('myTrainingEvaluation', arguments: args);
|
|
||||||
} else if (state is TrainingPlanDayReadyToRestart) {
|
|
||||||
if (!bloc!.celebrating) {
|
|
||||||
showCupertinoDialog(
|
|
||||||
useRootNavigator: true,
|
|
||||||
context: context,
|
|
||||||
builder: (_) => CupertinoAlertDialog(
|
|
||||||
title: Text(t("The training is finished")),
|
|
||||||
content: Column(children: [Divider(), Text(t("Do you want to restart, or select a new Training Plan?"))]),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
child: Text(t("New Training Plan"), textAlign: TextAlign.center),
|
|
||||||
onPressed: () => {
|
|
||||||
Navigator.pop(context),
|
|
||||||
Navigator.of(context).popAndPushNamed('myTrainingPlans'),
|
|
||||||
bloc!.restarting = false,
|
|
||||||
}),
|
|
||||||
TextButton(
|
|
||||||
child: Text(t("Restart")),
|
|
||||||
onPressed: () {
|
|
||||||
bloc!.restart();
|
|
||||||
Navigator.pop(context);
|
|
||||||
Navigator.of(context).popAndPushNamed('home');
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, builder: (context, state) {
|
|
||||||
return ModalProgressHUD(
|
|
||||||
child: ExerciseTabs(bloc: bloc!),
|
|
||||||
inAsyncCall: state is TrainingPlanLoading,
|
|
||||||
opacity: 0.5,
|
|
||||||
color: Colors.black54,
|
|
||||||
progressIndicator: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton.extended(
|
|
||||||
onPressed: () => {
|
|
||||||
args["bloc"] = bloc,
|
|
||||||
args["day"] = bloc!.dayNames[bloc!.activeDayIndex],
|
|
||||||
bloc!.getNext() != null
|
|
||||||
? _ExerciseListState.executeExercise(bloc!, bloc!.getNext()!, context)
|
|
||||||
: Navigator.of(context).pushNamed('myTrainingEvaluation', arguments: args),
|
|
||||||
},
|
|
||||||
backgroundColor: Colors.orange[800],
|
|
||||||
icon: Icon(CustomIcon.weight_hanging),
|
|
||||||
label: Text(
|
|
||||||
t("Training") + "!",
|
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
tabController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return getTabs(widget.bloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
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 = 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));
|
|
||||||
});
|
|
||||||
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))),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Widget> getTiles(TrainingPlanBloc bloc) {
|
|
||||||
List<Widget> tiles = [];
|
|
||||||
tiles.add(getStartTile(bloc));
|
|
||||||
tiles.addAll(getExerciseTiles(bloc, context));
|
|
||||||
if (bloc.getMyPlan() != null) tiles.add(getEndTile());
|
|
||||||
return tiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget getStartTile(TrainingPlanBloc bloc) {
|
|
||||||
String startText = "";
|
|
||||||
String explainingText = "";
|
|
||||||
if (null == bloc.getMyPlan()) {
|
|
||||||
startText = t("No Active Training Plan");
|
|
||||||
explainingText = t("Please select one in the Training menu, or create your custom plan");
|
|
||||||
} else {
|
|
||||||
startText = bloc.isStarted() ? t("Continue your training") : t("Start your training");
|
|
||||||
explainingText = bloc.getMyPlan()!.name != null ? bloc.getMyPlan()!.name! : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
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.emoji_flags_rounded,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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: startText,
|
|
||||||
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: explainingText,
|
|
||||||
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(TrainingPlanBloc bloc, BuildContext context) {
|
|
||||||
List<Widget> tiles = [];
|
|
||||||
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) {
|
|
||||||
tiles.add(
|
|
||||||
/* GestureDetector(
|
|
||||||
onTap: () => bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!, context) : Navigator.of(context).pushNamed('home'),
|
|
||||||
child: */
|
|
||||||
ExerciseTile(
|
|
||||||
bloc: bloc,
|
|
||||||
detail: element,
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return tiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void executeExercise(TrainingPlanBloc bloc, CustomerTrainingPlanDetails detail, BuildContext context) {
|
|
||||||
CustomerTrainingPlanDetails? next = bloc.getNext();
|
|
||||||
|
|
||||||
if (next != null) {
|
|
||||||
String title = "";
|
|
||||||
String description = "";
|
|
||||||
String description2 = "";
|
|
||||||
if (next.exerciseTypeId != detail.exerciseTypeId) {
|
|
||||||
title = AppLocalizations.of(context)!.translate("Stop!");
|
|
||||||
description = AppLocalizations.of(context)!.translate("Please continue with the next exercise in the queue:") +
|
|
||||||
next.exerciseType!.nameTranslation;
|
|
||||||
} else {
|
|
||||||
final HashMap args = HashMap();
|
|
||||||
args['exerciseType'] = next.exerciseType;
|
|
||||||
args['customerTrainingPlanDetails'] = detail;
|
|
||||||
Navigator.of(context).pushNamed('myTrainingPlanExercise', 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');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExerciseTile extends StatefulWidget {
|
|
||||||
final TrainingPlanBloc bloc;
|
|
||||||
final CustomerTrainingPlanDetails detail;
|
|
||||||
|
|
||||||
ExerciseTile({required this.bloc, required this.detail});
|
|
||||||
|
|
||||||
@override
|
|
||||||
_ExerciseTileState createState() => _ExerciseTileState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ExerciseTileState extends State<ExerciseTile> with Trans {
|
|
||||||
GestureRecognizer? _tapRecognizer;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
_tapRecognizer = TapGestureRecognizer()..onTap = _onPlusMinusWeight;
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
if (_tapRecognizer != null) {
|
|
||||||
_tapRecognizer!.dispose();
|
|
||||||
}
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onPlusMinusWeight() {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return WeightControl(
|
|
||||||
initialValue: widget.detail.weight != null ? widget.detail.weight! : 30,
|
|
||||||
onTap: (value) => widget.bloc.add(TrainingPlanWeightChangeRecalculate(detail: widget.detail, weight: value)),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget getIndicator(ExercisePlanDetailState state) {
|
|
||||||
CustomerTrainingPlanDetails? next = widget.bloc.getNext();
|
|
||||||
bool actual = false;
|
|
||||||
if (next != null) {
|
|
||||||
if (next.exerciseTypeId == widget.detail.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 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 if (state.equalsTo(ExercisePlanDetailState.extra)) {
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(24.0),
|
|
||||||
child: Container(
|
|
||||||
color: Colors.white,
|
|
||||||
child: Icon(
|
|
||||||
CustomIcon.stopwatch_20,
|
|
||||||
size: 40,
|
|
||||||
color: Colors.blue[800],
|
|
||||||
)));
|
|
||||||
} else {
|
|
||||||
return Image.asset(
|
|
||||||
"asset/image/pict_reps_volumen_db.png",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
setContext(context);
|
|
||||||
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 = "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) {
|
|
||||||
weight = "TEST";
|
|
||||||
isTest = true;
|
|
||||||
}
|
|
||||||
String repeats = widget.detail.repeats!.toString();
|
|
||||||
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,
|
|
||||||
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),
|
|
||||||
),
|
|
||||||
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: 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,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
style: GoogleFonts.inter(
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: done ? Colors.grey[400] : Colors.white,
|
|
||||||
),
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text: widget.detail.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,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise
|
|
||||||
? TextSpan(
|
|
||||||
text: "\n",
|
|
||||||
)
|
|
||||||
: TextSpan(),
|
|
||||||
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 && !extraExercise
|
|
||||||
? TextSpan(
|
|
||||||
text: t(weight),
|
|
||||||
style: GoogleFonts.inter(
|
|
||||||
fontSize: 12,
|
|
||||||
))
|
|
||||||
: TextSpan(),
|
|
||||||
widget.detail.exerciseType!.unitQuantityUnit != null && !extraExercise && weight != "TEST" && weight != "DROP"
|
|
||||||
? TextSpan(
|
|
||||||
text: " - +",
|
|
||||||
style: GoogleFonts.archivoBlack(
|
|
||||||
color: Colors.blue,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
recognizer: _tapRecognizer,
|
|
||||||
mouseCursor: SystemMouseCursors.precise,
|
|
||||||
)
|
|
||||||
: TextSpan(),
|
|
||||||
TextSpan(
|
|
||||||
text: "\n",
|
|
||||||
),
|
|
||||||
!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",
|
|
||||||
),
|
|
||||||
!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",
|
|
||||||
),
|
|
||||||
!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
|
|
||||||
? Container(
|
|
||||||
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () => showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return DialogCommon(
|
|
||||||
warning: false,
|
|
||||||
title: t("Why Test?"),
|
|
||||||
descriptions: t("This is your first exercise after at least 3 weeks."),
|
|
||||||
description2:
|
|
||||||
t("The first exercise will be a test. The following sets will be recalculated base on your test."),
|
|
||||||
description3: t("This is the most optimal way for your development"),
|
|
||||||
text: "OK",
|
|
||||||
onTap: () => Navigator.of(context).pop(),
|
|
||||||
onCancel: () => {
|
|
||||||
Navigator.of(context).pop(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
child: Icon(
|
|
||||||
CustomIcon.question_circle,
|
|
||||||
color: Colors.yellowAccent[700],
|
|
||||||
size: 16,
|
|
||||||
)),
|
|
||||||
]))
|
|
||||||
: isDrop
|
|
||||||
? Container(
|
|
||||||
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
|
||||||
GestureDetector(
|
|
||||||
onTap: () => showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return DialogCommon(
|
|
||||||
warning: false,
|
|
||||||
title: t("Drop Set"),
|
|
||||||
descriptions: t(
|
|
||||||
"Execute at least 3 sets with maximum repeats, without resting time, with decreasing the weight."),
|
|
||||||
description2:
|
|
||||||
t("The goal is to completly exhaust your muscle without lifting a ridiculous weight end the end."),
|
|
||||||
text: "OK",
|
|
||||||
onTap: () => Navigator.of(context).pop(),
|
|
||||||
onCancel: () => {
|
|
||||||
Navigator.of(context).pop(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
child: Icon(
|
|
||||||
CustomIcon.question_circle,
|
|
||||||
color: Colors.orange[200],
|
|
||||||
size: 16,
|
|
||||||
)),
|
|
||||||
]))
|
|
||||||
: Offstage()
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,10 +2,12 @@ import 'dart:collection';
|
|||||||
|
|
||||||
import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
|
import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/customer_training_plan_details.dart';
|
import 'package:aitrainer_app/model/customer_training_plan_details.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||||
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/menu_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
@ -26,7 +28,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
body: Container(
|
body: Container(
|
||||||
height: double.infinity,
|
height: double.infinity,
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: EdgeInsets.all(20),
|
//padding: EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage("asset/image/WT_black_background.jpg"),
|
image: AssetImage("asset/image/WT_black_background.jpg"),
|
||||||
@ -75,7 +77,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
backgroundColor: Colors.orange[800],
|
backgroundColor: Colors.orange[800],
|
||||||
icon: Icon(CustomIcon.save),
|
icon: Icon(CustomIcon.save),
|
||||||
label: Text(
|
label: Text(
|
||||||
isDropSet ? t("Done") : t("Save"),
|
t("Done"),
|
||||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -92,7 +94,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
unit: detail.exerciseType!.unit,
|
unit: detail.exerciseType!.unit,
|
||||||
unitQuantityUnit: detail.exerciseType!.unitQuantityUnit,
|
unitQuantityUnit: detail.exerciseType!.unitQuantityUnit,
|
||||||
hasUnitQuantity: detail.exerciseType!.unitQuantityUnit != null,
|
hasUnitQuantity: detail.exerciseType!.unitQuantityUnit != null,
|
||||||
weight: detail.weight == -1 ? 0 : detail.weight,
|
weight: detail.weight,
|
||||||
repeats: detail.repeats == -1 ? 99 : detail.repeats,
|
repeats: detail.repeats == -1 ? 99 : detail.repeats,
|
||||||
set: detail.set,
|
set: detail.set,
|
||||||
exerciseNr: detail.exercises.length + 1,
|
exerciseNr: detail.exercises.length + 1,
|
||||||
@ -100,6 +102,13 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
|||||||
onQuantityChanged: (value) => bloc.add(TrainingPlanRepeatsChange(repeats: value.toInt(), detail: detail)),
|
onQuantityChanged: (value) => bloc.add(TrainingPlanRepeatsChange(repeats: value.toInt(), detail: detail)),
|
||||||
exerciseTypeId: detail.exerciseType!.exerciseTypeId,
|
exerciseTypeId: detail.exerciseType!.exerciseTypeId,
|
||||||
originalQuantity: originalQuantity,
|
originalQuantity: originalQuantity,
|
||||||
|
tip: ActivityDone.exerciseSaveTrainingTip,
|
||||||
|
menuImage: MenuImage(
|
||||||
|
imageName: bloc.getActualImageName(detail.exerciseType!.exerciseTypeId),
|
||||||
|
workoutTreeId: bloc.getActualWorkoutTreeId(detail.exerciseType!.exerciseTypeId)!,
|
||||||
|
radius: 0,
|
||||||
|
filter: false,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return getDropSet(bloc, detail);
|
return getDropSet(bloc, detail);
|
||||||
|
@ -44,7 +44,7 @@ class MyTrainingPlans extends StatelessWidget with Trans, Logging {
|
|||||||
title: t("Warning"),
|
title: t("Warning"),
|
||||||
descriptions: t(state.message),
|
descriptions: t(state.message),
|
||||||
text: "OK",
|
text: "OK",
|
||||||
onTap: () => Navigator.of(context).pushNamed("login"),
|
onTap: () => Navigator.of(context).pop(),
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
Navigator.of(context).pop(),
|
Navigator.of(context).pop(),
|
||||||
},
|
},
|
||||||
|
@ -286,7 +286,7 @@ class _BMRState extends State<BMR> with Trans {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
mode: Mode.MENU,
|
mode: Mode.MENU,
|
||||||
compareFn: (FitnessState i, FitnessState s) => i.isEqual(s),
|
compareFn: (FitnessState? i, FitnessState? s) => i!.isEqual(s),
|
||||||
showSelectedItem: true,
|
showSelectedItem: true,
|
||||||
selectedItem: FitnessItem().getItem(fitnessLevel),
|
selectedItem: FitnessItem().getItem(fitnessLevel),
|
||||||
itemAsString: (data) => t(data!.stateText),
|
itemAsString: (data) => t(data!.stateText),
|
||||||
@ -301,7 +301,6 @@ class _BMRState extends State<BMR> with Trans {
|
|||||||
color: Colors.yellow[200],
|
color: Colors.yellow[200],
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
//items: FitnessItem().toList()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _customMenuBuilder(BuildContext context, FitnessState? item, bool isSelected) {
|
Widget _customMenuBuilder(BuildContext context, FitnessState? item, bool isSelected) {
|
||||||
|
@ -88,7 +88,7 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
|
|||||||
alignment: AlignmentDirectional.topEnd,
|
alignment: AlignmentDirectional.topEnd,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.unlocked ? t("Keep testing") : t("Go Premium") + " ",
|
widget.unlocked ? t("Keep training") : t("Go Premium") + " ",
|
||||||
style: GoogleFonts.archivoBlack(
|
style: GoogleFonts.archivoBlack(
|
||||||
fontSize: widget.unlocked ? 20 : 24,
|
fontSize: widget.unlocked ? 20 : 24,
|
||||||
color: Colors.yellow[400],
|
color: Colors.yellow[400],
|
||||||
@ -257,11 +257,7 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
|
|||||||
list.add(TextSpan(text: t(" ")));
|
list.add(TextSpan(text: t(" ")));
|
||||||
list.add(
|
list.add(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: widget.unlockRound == 1
|
text: widget.unlockRound.toString() + " " + t("week"),
|
||||||
? t("the first")
|
|
||||||
: widget.unlockRound == 2
|
|
||||||
? t("the second")
|
|
||||||
: t("the third"),
|
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@ -282,7 +278,7 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
list.add(TextSpan(text: t(" ")));
|
list.add(TextSpan(text: t(" ")));
|
||||||
list.add(TextSpan(text: t("100% test circles")));
|
list.add(TextSpan(text: t("100% completed training")));
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ class _DialogTrialWidgetState extends State<DialogTrialWidget> with Trans {
|
|||||||
children: [
|
children: [
|
||||||
Image.asset('asset/icon/gomb_lila_b.png', width: 100, height: 45),
|
Image.asset('asset/icon/gomb_lila_b.png', width: 100, height: 45),
|
||||||
Text(
|
Text(
|
||||||
t("Nem"),
|
t("No"),
|
||||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -132,7 +132,7 @@ class _DialogTrialWidgetState extends State<DialogTrialWidget> with Trans {
|
|||||||
children: [
|
children: [
|
||||||
Image.asset('asset/icon/gomb_orange_c.png', width: 100, height: 45),
|
Image.asset('asset/icon/gomb_orange_c.png', width: 100, height: 45),
|
||||||
Text(
|
Text(
|
||||||
t("Igen"),
|
t("Yes"),
|
||||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,21 +1,113 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/tutorial/tutorial_bloc.dart';
|
|
||||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/util/trans.dart';
|
import 'package:aitrainer_app/util/trans.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/menu_image.dart';
|
||||||
import 'package:aitrainer_app/widgets/time_picker.dart';
|
import 'package:aitrainer_app/widgets/time_picker.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/tutorial_widget.dart';
|
||||||
|
import 'package:badges/badges.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:keyboard_actions/keyboard_actions.dart';
|
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||||
import 'package:keyboard_actions/keyboard_actions_config.dart';
|
import 'package:keyboard_actions/keyboard_actions_config.dart';
|
||||||
import 'package:stop_watch_timer/stop_watch_timer.dart';
|
import 'package:stop_watch_timer/stop_watch_timer.dart';
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
|
|
||||||
import 'dialog_common.dart';
|
|
||||||
import 'dialog_html.dart';
|
import 'dialog_html.dart';
|
||||||
|
|
||||||
|
enum Explanations { intro, introBold, explanationWeight, explanationRepeats, explanationButton, explanationButtonExt }
|
||||||
|
|
||||||
|
extension ExplanationsExt on Explanations {
|
||||||
|
String toStr() => this.toString().split(".").last;
|
||||||
|
bool equalsTo(Explanations type) => this.toString() == type.toString();
|
||||||
|
bool equalsStringTo(String type) => this.toStr() == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExplanationExt {
|
||||||
|
final ActivityDone tip;
|
||||||
|
final String? unitQuantityUnit;
|
||||||
|
final double? weight;
|
||||||
|
final int? repeats;
|
||||||
|
ExplanationExt({
|
||||||
|
required this.tip,
|
||||||
|
this.unitQuantityUnit,
|
||||||
|
required this.weight,
|
||||||
|
required this.repeats,
|
||||||
|
});
|
||||||
|
|
||||||
|
String getExplanation(Explanations explanation) {
|
||||||
|
String expl = "";
|
||||||
|
if (this.tip.equalsTo(ActivityDone.exerciseSaveTestTip)) {
|
||||||
|
if (explanation.equalsTo(Explanations.intro)) {
|
||||||
|
expl = "Please take a middle weight which you are able to do 8-20 times with.";
|
||||||
|
} else if (explanation.equalsTo(Explanations.introBold)) {
|
||||||
|
expl = "Execute your MAXIMUM repeats with it!";
|
||||||
|
} else if (explanation.equalsTo(Explanations.explanationWeight)) {
|
||||||
|
expl = "Type here your selected weight,";
|
||||||
|
} else if (explanation.equalsTo(Explanations.explanationRepeats)) {
|
||||||
|
expl = "then here, how many times could you repeat it!";
|
||||||
|
} else if (explanation.equalsTo(Explanations.explanationButton)) {
|
||||||
|
expl = "After you done, click to the OK button!";
|
||||||
|
} else if (explanation.equalsTo(Explanations.explanationButtonExt)) {
|
||||||
|
expl = "";
|
||||||
|
}
|
||||||
|
} else if (this.tip.equalsTo(ActivityDone.exerciseSaveTrainingTip)) {
|
||||||
|
if (unitQuantityUnit != null) {
|
||||||
|
if (weight == -1) {
|
||||||
|
if (explanation.equalsTo(Explanations.intro)) {
|
||||||
|
expl = "Please take a middle weight which you are able to do 8-20 times with.";
|
||||||
|
} else if (explanation.equalsTo(Explanations.introBold)) {
|
||||||
|
expl = "Execute your MAXIMUM repeats with it!";
|
||||||
|
}
|
||||||
|
} else if (repeats == 99) {
|
||||||
|
if (explanation.equalsTo(Explanations.intro)) {
|
||||||
|
expl = "It is time to exhaust your muscles";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (explanation.equalsTo(Explanations.intro)) {
|
||||||
|
expl = "For your optimal development we calculated a suitable weight and repeats";
|
||||||
|
} else if (explanation.equalsTo(Explanations.introBold)) {
|
||||||
|
expl = "You can change the weight, if you could not set it in the training room";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (explanation.equalsTo(Explanations.explanationButtonExt)) {
|
||||||
|
if (repeats != 99) {
|
||||||
|
expl = "If you could do less, then modify and click to OK";
|
||||||
|
}
|
||||||
|
} else if (explanation.equalsTo(Explanations.explanationWeight)) {
|
||||||
|
if (weight == -1 || weight == -2) {
|
||||||
|
expl = "Type here your selected weight,";
|
||||||
|
} else {
|
||||||
|
expl = "Here is your tailored weight,";
|
||||||
|
}
|
||||||
|
} else if (explanation.equalsTo(Explanations.explanationRepeats)) {
|
||||||
|
if (repeats == 99) {
|
||||||
|
expl = "and execute it with maximum repeats!";
|
||||||
|
} else {
|
||||||
|
expl = "and executed with this number of repeats!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (repeats == 99) {
|
||||||
|
if (explanation.equalsTo(Explanations.intro)) {
|
||||||
|
expl = "Please repeat as much times as you can! MAXIMIZE it!";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (explanation.equalsTo(Explanations.intro)) {
|
||||||
|
expl = "Please try to execute this exercise with exact repeats what is suggested";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (explanation.equalsTo(Explanations.explanationButton)) {
|
||||||
|
expl = "After you done, click to the OK button!";
|
||||||
|
}
|
||||||
|
} else if (this.tip.equalsTo(ActivityDone.exerciseSaveTestsetTip)) {}
|
||||||
|
|
||||||
|
return expl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class ExerciseSave extends StatefulWidget {
|
class ExerciseSave extends StatefulWidget {
|
||||||
final ValueChanged<double> onQuantityChanged;
|
final ValueChanged<double> onQuantityChanged;
|
||||||
@ -33,6 +125,8 @@ class ExerciseSave extends StatefulWidget {
|
|||||||
final int? set;
|
final int? set;
|
||||||
final int? exerciseNr;
|
final int? exerciseNr;
|
||||||
final int? originalQuantity;
|
final int? originalQuantity;
|
||||||
|
final MenuImage menuImage;
|
||||||
|
final ActivityDone? tip;
|
||||||
|
|
||||||
ExerciseSave(
|
ExerciseSave(
|
||||||
{required this.onQuantityChanged,
|
{required this.onQuantityChanged,
|
||||||
@ -49,7 +143,9 @@ class ExerciseSave extends StatefulWidget {
|
|||||||
this.repeats,
|
this.repeats,
|
||||||
this.set,
|
this.set,
|
||||||
this.exerciseNr,
|
this.exerciseNr,
|
||||||
this.originalQuantity});
|
this.originalQuantity,
|
||||||
|
required this.menuImage,
|
||||||
|
this.tip});
|
||||||
@override
|
@override
|
||||||
_ExerciseSaveState createState() => _ExerciseSaveState();
|
_ExerciseSaveState createState() => _ExerciseSaveState();
|
||||||
}
|
}
|
||||||
@ -72,12 +168,6 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
|||||||
@override
|
@override
|
||||||
initState() {
|
initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller1.text = widget.weight == null
|
|
||||||
? "0"
|
|
||||||
: widget.weight! % widget.weight!.round() == 0
|
|
||||||
? widget.weight!.toStringAsFixed(0)
|
|
||||||
: widget.weight!.toStringAsFixed(1);
|
|
||||||
_controller2.text = widget.repeats == null ? "12" : widget.repeats!.toStringAsFixed(0);
|
|
||||||
_nodeText1.addListener(() {
|
_nodeText1.addListener(() {
|
||||||
if (_nodeText1.hasFocus) {
|
if (_nodeText1.hasFocus) {
|
||||||
_controller1.selection = TextSelection(baseOffset: 0, extentOffset: _controller1.text.length);
|
_controller1.selection = TextSelection(baseOffset: 0, extentOffset: _controller1.text.length);
|
||||||
@ -98,25 +188,31 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
||||||
/* //final TutorialBloc bloc = BlocProvider.of<TutorialBloc>(context);
|
_controller1.text = widget.weight == null || widget.weight == -1
|
||||||
if (bloc.actualCheck == "directTest") {
|
? "--"
|
||||||
|
: widget.weight! % widget.weight!.round() == 0
|
||||||
|
? widget.weight!.toStringAsFixed(0)
|
||||||
|
: widget.weight!.toStringAsFixed(1);
|
||||||
|
_controller2.text = widget.repeats == null
|
||||||
|
? "--"
|
||||||
|
: widget.repeats! == 99
|
||||||
|
? "MAX"
|
||||||
|
: widget.repeats!.toStringAsFixed(0);
|
||||||
|
if (widget.unitQuantityUnit != null && widget.tip != null && Cache().isActivityDone(widget.tip!) == false) {
|
||||||
Timer(
|
Timer(
|
||||||
Duration(milliseconds: 2000),
|
Duration(milliseconds: 2000),
|
||||||
() => {
|
() => {
|
||||||
showDialog(
|
TutorialWidget().explanation(
|
||||||
context: context,
|
context,
|
||||||
barrierDismissible: false,
|
ExplanationWidget(
|
||||||
builder: (BuildContext context) {
|
unitQuantityUnit: widget.unitQuantityUnit,
|
||||||
return DialogCommon(
|
unit: widget.unit,
|
||||||
title: t("Attention"),
|
tip: widget.tip,
|
||||||
descriptions: t(widget.exerciseTask),
|
weight: widget.weight,
|
||||||
text: "OK",
|
repeats: widget.repeats,
|
||||||
onTap: () => Navigator.of(context).pop(),
|
)),
|
||||||
onCancel: () => Navigator.of(context).pop(),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
} */
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,13 +285,44 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget getExerciseWidget() {
|
Widget getExerciseWidget() {
|
||||||
|
ExplanationExt expl = ExplanationExt(
|
||||||
|
tip: widget.tip!,
|
||||||
|
weight: widget.weight,
|
||||||
|
repeats: widget.repeats,
|
||||||
|
unitQuantityUnit: widget.unitQuantityUnit,
|
||||||
|
);
|
||||||
|
|
||||||
return KeyboardActions(
|
return KeyboardActions(
|
||||||
config: _buildConfig(context),
|
config: _buildConfig(context),
|
||||||
child: Container(
|
child: Container(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
child: Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
|
child: Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
|
||||||
Text(
|
Stack(alignment: Alignment.bottomLeft, children: [
|
||||||
|
Badge(
|
||||||
|
elevation: 0,
|
||||||
|
padding: EdgeInsets.all(0),
|
||||||
|
position: BadgePosition.topEnd(top: 5, end: 5),
|
||||||
|
animationDuration: Duration(milliseconds: 1500),
|
||||||
|
animationType: BadgeAnimationType.fade,
|
||||||
|
badgeColor: Colors.transparent,
|
||||||
|
showBadge: true,
|
||||||
|
badgeContent: IconButton(
|
||||||
|
iconSize: 30,
|
||||||
|
onPressed: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return DialogHTML(title: widget.exerciseName, htmlData: '<p>' + widget.exerciseDescription + '</p>');
|
||||||
|
}),
|
||||||
|
icon: Icon(
|
||||||
|
CustomIcon.info_circle,
|
||||||
|
color: Colors.white,
|
||||||
|
)),
|
||||||
|
child: widget.menuImage,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(left: 10, bottom: 10, right: 10),
|
||||||
|
child: Text(
|
||||||
widget.exerciseName,
|
widget.exerciseName,
|
||||||
style: GoogleFonts.archivoBlack(
|
style: GoogleFonts.archivoBlack(
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@ -217,29 +344,57 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
|||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
maxLines: 4,
|
maxLines: 4,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
textAlign: TextAlign.center,
|
))
|
||||||
),
|
]),
|
||||||
SizedBox(
|
ListTile(
|
||||||
height: 15,
|
leading: IconButton(
|
||||||
),
|
iconSize: 30,
|
||||||
InkWell(
|
onPressed: () => {
|
||||||
child: Text(
|
if (widget.unitQuantityUnit != null)
|
||||||
t("Exercise descripton") + " »",
|
{
|
||||||
style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[200]),
|
TutorialWidget().explanation(
|
||||||
),
|
context,
|
||||||
onTap: () => {
|
ExplanationWidget(
|
||||||
showDialog(
|
unitQuantityUnit: widget.unitQuantityUnit,
|
||||||
context: context,
|
unit: widget.unit,
|
||||||
builder: (BuildContext context) {
|
tip: widget.tip,
|
||||||
return DialogHTML(title: widget.exerciseName, htmlData: '<p>' + widget.exerciseDescription + '</p>');
|
weight: widget.weight,
|
||||||
})
|
repeats: widget.repeats,
|
||||||
|
))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
icon: Icon(
|
||||||
|
CustomIcon.info_circle,
|
||||||
|
color: Colors.orange[100],
|
||||||
|
)),
|
||||||
|
subtitle: Text(
|
||||||
|
t(expl.getExplanation(Explanations.intro)),
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(2.0, 2.0),
|
||||||
|
blurRadius: 6.0,
|
||||||
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
Divider(
|
Shadow(
|
||||||
color: Colors.transparent,
|
offset: Offset(-3.0, 3.0),
|
||||||
|
blurRadius: 12.0,
|
||||||
|
color: Colors.black54,
|
||||||
),
|
),
|
||||||
Text(
|
],
|
||||||
t(widget.exerciseTask),
|
),
|
||||||
|
maxLines: 3,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
softWrap: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expl.getExplanation(Explanations.introBold).length > 0
|
||||||
|
? Text(
|
||||||
|
t(expl.getExplanation(Explanations.introBold)),
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
color: Colors.orange,
|
color: Colors.orange,
|
||||||
@ -261,10 +416,8 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
),
|
)
|
||||||
Divider(
|
: Offstage(),
|
||||||
color: Colors.transparent,
|
|
||||||
),
|
|
||||||
widget.unit == "second"
|
widget.unit == "second"
|
||||||
? Text(
|
? Text(
|
||||||
getTimeGoal(widget.originalQuantity),
|
getTimeGoal(widget.originalQuantity),
|
||||||
@ -289,29 +442,60 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
|||||||
)
|
)
|
||||||
: Offstage(),
|
: Offstage(),
|
||||||
columnQuantityUnit(),
|
columnQuantityUnit(),
|
||||||
Divider(
|
|
||||||
color: Colors.transparent,
|
|
||||||
),
|
|
||||||
columnQuantity(),
|
columnQuantity(),
|
||||||
Divider(
|
Divider(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
),
|
),
|
||||||
widget.hasUnitQuantity
|
Text(
|
||||||
? Text(
|
t(expl.getExplanation(Explanations.explanationButton)),
|
||||||
widget.set == null || widget.exerciseNr == null
|
|
||||||
? t("Step") + ": " + "1/4"
|
|
||||||
: t("Step") + ": " + "${widget.exerciseNr}/${widget.set}",
|
|
||||||
style: GoogleFonts.inter(
|
style: GoogleFonts.inter(
|
||||||
fontSize: 22,
|
fontSize: 14,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
)
|
),
|
||||||
: Offstage(),
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 35, right: 35),
|
||||||
|
child: Text(
|
||||||
|
t(expl.getExplanation(Explanations.explanationButtonExt)),
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.orange,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
maxLines: 3,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
softWrap: true,
|
||||||
|
)),
|
||||||
Divider(
|
Divider(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
),
|
),
|
||||||
@ -476,3 +660,168 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
|||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ExplanationWidget extends StatefulWidget {
|
||||||
|
final String? unitQuantityUnit;
|
||||||
|
final String unit;
|
||||||
|
final ActivityDone? tip;
|
||||||
|
final double? weight;
|
||||||
|
final int? repeats;
|
||||||
|
const ExplanationWidget({
|
||||||
|
Key? key,
|
||||||
|
this.unitQuantityUnit,
|
||||||
|
required this.unit,
|
||||||
|
this.tip,
|
||||||
|
this.weight,
|
||||||
|
this.repeats,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_ExplanationWidgetState createState() => _ExplanationWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExplanationWidgetState extends State<ExplanationWidget> with Trans {
|
||||||
|
bool _selected = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
ExplanationExt expl = ExplanationExt(
|
||||||
|
tip: widget.tip!,
|
||||||
|
weight: widget.weight,
|
||||||
|
repeats: widget.repeats,
|
||||||
|
unitQuantityUnit: widget.unitQuantityUnit,
|
||||||
|
);
|
||||||
|
setContext(context);
|
||||||
|
return Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10, left: 10, right: 10),
|
||||||
|
child: Text(t(expl.getExplanation(Explanations.intro)),
|
||||||
|
maxLines: 5,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 16,
|
||||||
|
))),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10, left: 10, right: 10),
|
||||||
|
child: Text(t(expl.getExplanation(Explanations.introBold)),
|
||||||
|
maxLines: 5,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: Colors.orange,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 16,
|
||||||
|
))),
|
||||||
|
Stack(children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 13, left: 18, right: 18),
|
||||||
|
child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||||
|
TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5),
|
||||||
|
labelText: t(widget.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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
initialValue: ".",
|
||||||
|
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||||
|
textInputAction: TextInputAction.done,
|
||||||
|
style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.transparent),
|
||||||
|
onChanged: (value) {}),
|
||||||
|
])),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top: 35, left: 35, right: 35),
|
||||||
|
child: Text(
|
||||||
|
t(expl.getExplanation(Explanations.explanationWeight)),
|
||||||
|
style: GoogleFonts.archivoBlack(fontSize: 23, color: Colors.yellow[300]),
|
||||||
|
)),
|
||||||
|
]),
|
||||||
|
Stack(children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10, left: 15, right: 15),
|
||||||
|
child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||||
|
TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5),
|
||||||
|
labelText: t(widget.unit),
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
initialValue: ".",
|
||||||
|
keyboardType: TextInputType.numberWithOptions(decimal: true),
|
||||||
|
textInputAction: TextInputAction.done,
|
||||||
|
style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.transparent),
|
||||||
|
onChanged: (value) {}),
|
||||||
|
])),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top: 25, left: 35, right: 35),
|
||||||
|
child: Text(
|
||||||
|
t(expl.getExplanation(Explanations.explanationRepeats)),
|
||||||
|
style: GoogleFonts.archivoBlack(fontSize: 23, color: Colors.yellow[300]),
|
||||||
|
)),
|
||||||
|
]),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10, left: 5, right: 5),
|
||||||
|
child: Text(
|
||||||
|
t("Don't forget, the app can give you only the right values, if you execute the task regurarly and after the exact instructions."),
|
||||||
|
maxLines: 5,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: GoogleFonts.inter(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 14,
|
||||||
|
))),
|
||||||
|
Divider(),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () => {
|
||||||
|
TutorialWidget().close(),
|
||||||
|
if (_selected && widget.tip != null)
|
||||||
|
{
|
||||||
|
Cache().setActivityDonePrefs(widget.tip!),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
Image.asset('asset/icon/gomb_orange_c.png', width: 100, height: 45),
|
||||||
|
Text(
|
||||||
|
t("Got It"),
|
||||||
|
style: TextStyle(fontSize: 20, color: Colors.white),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
Theme(
|
||||||
|
data: ThemeData(unselectedWidgetColor: Colors.white38),
|
||||||
|
child: CheckboxListTile(
|
||||||
|
value: _selected,
|
||||||
|
onChanged: (bool? checked) {
|
||||||
|
setState(() {
|
||||||
|
_selected = checked!;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
checkColor: Colors.white,
|
||||||
|
activeColor: Colors.orange[600],
|
||||||
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
|
title: Text(
|
||||||
|
t("Show this tip no more"),
|
||||||
|
style: GoogleFonts.inter(color: Colors.grey),
|
||||||
|
)))
|
||||||
|
],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -83,16 +83,16 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return DialogTrialWidget(
|
return DialogTrialWidget(
|
||||||
title: "10 days Premium for free",
|
title: t("10 days Premium for free"),
|
||||||
description: "Would you like to try all premium functions for 10 days, without any subscription or bank card data?",
|
description: t("Would you like to try all premium functions for 10 days, without any subscription or bank card data?"),
|
||||||
widget: Column(children: [
|
widget: Column(children: [
|
||||||
Text(
|
Text(
|
||||||
"If you click to 'Yes', all premium functions will be available right now.",
|
t("If you click to 'Yes', all premium functions will be available right now."),
|
||||||
style: GoogleFonts.inter(color: Colors.white),
|
style: GoogleFonts.inter(color: Colors.white),
|
||||||
),
|
),
|
||||||
Divider(),
|
Divider(),
|
||||||
Text(
|
Text(
|
||||||
"If you click to 'No', you can use all basic functions, and you will loose the oppurtunity to try the premium functions for free.",
|
t("If you click to 'No', you can use all basic functions, and you will loose the oppurtunity to try the premium functions for free."),
|
||||||
style: GoogleFonts.inter(color: Colors.white),
|
style: GoogleFonts.inter(color: Colors.white),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
|
@ -25,6 +25,46 @@ class TutorialWidget with Trans, Logging {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget explanationFrame(Widget widget) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(24),
|
||||||
|
boxShadow: [BoxShadow(color: Colors.black, offset: Offset(0, 10), blurRadius: 10)],
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_plainblack_background.jpg'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: widget,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void explanation(BuildContext context, Widget widget) {
|
||||||
|
tooltip = SuperTooltip(
|
||||||
|
top: 120,
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
backgroundColor: Colors.black87,
|
||||||
|
popupDirection: TooltipDirection.up,
|
||||||
|
maxWidth: 330,
|
||||||
|
borderColor: Colors.transparent,
|
||||||
|
borderWidth: 1.0,
|
||||||
|
minimumOutSidePadding: 20,
|
||||||
|
//snapsFarAwayVertically: false,
|
||||||
|
showCloseButton: ShowCloseButton.outside,
|
||||||
|
closeButtonColor: Colors.grey,
|
||||||
|
dismissOnTapOutside: true,
|
||||||
|
outsideBackgroundColor: Colors.black.withOpacity(0.6),
|
||||||
|
hasShadow: true,
|
||||||
|
touchThrougArea: null,
|
||||||
|
//onClose: () => bloc.add(TutorialFinished()),
|
||||||
|
custom: true,
|
||||||
|
content: explanationFrame(widget));
|
||||||
|
|
||||||
|
tooltip!.showBox(context);
|
||||||
|
}
|
||||||
|
|
||||||
void tip(BuildContext context) {
|
void tip(BuildContext context) {
|
||||||
final TutorialBloc bloc = BlocProvider.of<TutorialBloc>(context);
|
final TutorialBloc bloc = BlocProvider.of<TutorialBloc>(context);
|
||||||
if (bloc.action == null) {
|
if (bloc.action == null) {
|
||||||
|
13
pubspec.lock
13
pubspec.lock
@ -707,6 +707,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
mailto:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: mailto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1294,12 +1301,12 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.5.1"
|
version: "3.5.1"
|
||||||
url_launcher:
|
url_launcher:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.3"
|
version: "6.0.9"
|
||||||
url_launcher_linux:
|
url_launcher_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1320,7 +1327,7 @@ packages:
|
|||||||
name: url_launcher_platform_interface
|
name: url_launcher_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.4"
|
||||||
url_launcher_web:
|
url_launcher_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -58,6 +58,8 @@ dependencies:
|
|||||||
upgrader: ^3.5.1
|
upgrader: ^3.5.1
|
||||||
web_browser: ^0.5.0
|
web_browser: ^0.5.0
|
||||||
flutter_fadein: ^2.0.0
|
flutter_fadein: ^2.0.0
|
||||||
|
mailto: ^2.0.0
|
||||||
|
url_launcher: ^6.0.9
|
||||||
|
|
||||||
firebase_core: ^1.5.0
|
firebase_core: ^1.5.0
|
||||||
firebase_analytics: ^8.1.0
|
firebase_analytics: ^8.1.0
|
||||||
@ -280,6 +282,7 @@ flutter:
|
|||||||
- asset/menu/close_grip_front_lat_pulldown.jpg
|
- asset/menu/close_grip_front_lat_pulldown.jpg
|
||||||
- asset/menu/close_grip_pull_ups.jpg
|
- asset/menu/close_grip_pull_ups.jpg
|
||||||
- asset/menu/close_reverse_grip_lat_pulldown.jpg
|
- asset/menu/close_reverse_grip_lat_pulldown.jpg
|
||||||
|
- asset/menu/close_reverse_grip_pull_ups.jpg
|
||||||
- asset/menu/concentration.jpg
|
- asset/menu/concentration.jpg
|
||||||
- asset/menu/cooper.jpg
|
- asset/menu/cooper.jpg
|
||||||
- asset/menu/crisscross.jpg
|
- asset/menu/crisscross.jpg
|
||||||
@ -294,6 +297,7 @@ flutter:
|
|||||||
- asset/menu/donkey_calf_raises.jpg
|
- asset/menu/donkey_calf_raises.jpg
|
||||||
- asset/menu/dumbbell_alternate_bicep_curl.jpg
|
- asset/menu/dumbbell_alternate_bicep_curl.jpg
|
||||||
- asset/menu/dumbell_bench_presses.jpg
|
- asset/menu/dumbell_bench_presses.jpg
|
||||||
|
- asset/menu/dumbbell_presses.jpg
|
||||||
- asset/menu/ez_bar_burl.jpg
|
- asset/menu/ez_bar_burl.jpg
|
||||||
- asset/menu/flyes.jpg
|
- asset/menu/flyes.jpg
|
||||||
- asset/menu/forward_raise.jpg
|
- asset/menu/forward_raise.jpg
|
||||||
@ -358,6 +362,7 @@ flutter:
|
|||||||
- asset/menu/seated_dumbbell_curl.jpg
|
- asset/menu/seated_dumbbell_curl.jpg
|
||||||
- asset/menu/seated_dumbbell_shoulder_press.jpg
|
- asset/menu/seated_dumbbell_shoulder_press.jpg
|
||||||
- asset/menu/seated_lateral_raises.jpg
|
- asset/menu/seated_lateral_raises.jpg
|
||||||
|
- asset/menu/seated_leg_curls.jpg
|
||||||
- asset/menu/seated_triceps_extension.jpg
|
- asset/menu/seated_triceps_extension.jpg
|
||||||
- asset/menu/shrugs.jpg
|
- asset/menu/shrugs.jpg
|
||||||
- asset/menu/side_plank.jpg
|
- asset/menu/side_plank.jpg
|
||||||
@ -372,6 +377,7 @@ flutter:
|
|||||||
- asset/menu/sizes.jpg
|
- asset/menu/sizes.jpg
|
||||||
- asset/menu/smith_machine_chest_press.jpg
|
- asset/menu/smith_machine_chest_press.jpg
|
||||||
- asset/menu/smith_machine_squats.jpg
|
- asset/menu/smith_machine_squats.jpg
|
||||||
|
- asset/menu/smith_machine_front_press.jpg
|
||||||
- asset/menu/squats_with_kettlebell.jpg
|
- asset/menu/squats_with_kettlebell.jpg
|
||||||
- asset/menu/squat_jump_weight.jpg
|
- asset/menu/squat_jump_weight.jpg
|
||||||
- asset/menu/squat_jump.jpg
|
- asset/menu/squat_jump.jpg
|
||||||
@ -388,6 +394,7 @@ flutter:
|
|||||||
- asset/menu/standing_single_arm_lateral_raises.jpg
|
- asset/menu/standing_single_arm_lateral_raises.jpg
|
||||||
- asset/menu/standing_triceps_extension.jpg
|
- asset/menu/standing_triceps_extension.jpg
|
||||||
- asset/menu/stiff_legged_deadlift.jpg
|
- asset/menu/stiff_legged_deadlift.jpg
|
||||||
|
- asset/menu/straight_arm_pulldown.jpg
|
||||||
- asset/menu/straight-arm_rope_pull-down.jpg
|
- asset/menu/straight-arm_rope_pull-down.jpg
|
||||||
- asset/menu/stretching.jpg
|
- asset/menu/stretching.jpg
|
||||||
- asset/menu/t_bar_rows.jpg
|
- asset/menu/t_bar_rows.jpg
|
||||||
|
Loading…
Reference in New Issue
Block a user