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!",
|
||||
"feature is reachable after you finished": "feature is reachable after you finished",
|
||||
"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.",
|
||||
"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'",
|
||||
@ -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 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",
|
||||
"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!",
|
||||
"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.",
|
||||
@ -509,5 +510,35 @@
|
||||
"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",
|
||||
"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!",
|
||||
"feature is reachable after you finished": "funkció elérhető számodra, miután teljesítetted",
|
||||
"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",
|
||||
"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!",
|
||||
@ -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:",
|
||||
"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",
|
||||
"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;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -531,7 +531,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -566,7 +566,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 3;
|
||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
@ -1,97 +1,97 @@
|
||||
<?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">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>WorkoutTest</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>aitrainer.page.link</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>wt001</string>
|
||||
<string>fb584181112271127</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>FacebookAdvertiserIDCollectionEnabled</key>
|
||||
<string>TRUE</string>
|
||||
<key>FacebookAppID</key>
|
||||
<string>584181112271127</string>
|
||||
<key>FacebookAutoLogAppEventsEnabled</key>
|
||||
<string>TRUE</string>
|
||||
<key>FacebookDisplayName</key>
|
||||
<string>Workout Test</string>
|
||||
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||
<string>NO</string>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>https</string>
|
||||
<string>http</string>
|
||||
<string>fbapi</string>
|
||||
<string>fbapi20130214</string>
|
||||
<string>fbapi20130410</string>
|
||||
<string>fbapi20130702</string>
|
||||
<string>fbapi20131010</string>
|
||||
<string>fbapi20131219</string>
|
||||
<string>fbapi20140410</string>
|
||||
<string>fbapi20140116</string>
|
||||
<string>fbapi20150313</string>
|
||||
<string>fbapi20150629</string>
|
||||
<string>fbapi20160328</string>
|
||||
<string>fb-messenger-share-api</string>
|
||||
<string>fbauth2</string>
|
||||
<string>fbshareextension</string>
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.0.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>WorkoutTest</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>aitrainer.page.link</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>wt001</string>
|
||||
<string>fb584181112271127</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>Launch Screen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>FacebookAdvertiserIDCollectionEnabled</key>
|
||||
<string>TRUE</string>
|
||||
<key>FacebookAppID</key>
|
||||
<string>584181112271127</string>
|
||||
<key>FacebookAutoLogAppEventsEnabled</key>
|
||||
<string>TRUE</string>
|
||||
<key>FacebookDisplayName</key>
|
||||
<string>Workout Test</string>
|
||||
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||
<string>NO</string>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>https</string>
|
||||
<string>http</string>
|
||||
<string>fbapi</string>
|
||||
<string>fbapi20130214</string>
|
||||
<string>fbapi20130410</string>
|
||||
<string>fbapi20130702</string>
|
||||
<string>fbapi20131010</string>
|
||||
<string>fbapi20131219</string>
|
||||
<string>fbapi20140410</string>
|
||||
<string>fbapi20140116</string>
|
||||
<string>fbapi20150313</string>
|
||||
<string>fbapi20150629</string>
|
||||
<string>fbapi20160328</string>
|
||||
<string>fb-messenger-share-api</string>
|
||||
<string>fbauth2</string>
|
||||
<string>fbshareextension</string>
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>11.0.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>Launch Screen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/sport.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:bloc/bloc.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();
|
||||
height = this.customerRepository.getHeight() == 0 ? 170 : this.customerRepository.getHeight();
|
||||
|
||||
// selectedSport = customerRepository.getSport();
|
||||
//print("selected: $selectedFitnessItem sport: $selectedSport " + customerRepository.customer!.fitnessLevel.toString());
|
||||
selectedFitnessItem = customerRepository.fitnessLevel;
|
||||
selectedSport = customerRepository.getSport();
|
||||
}
|
||||
|
||||
Sport? selectedSport;
|
||||
@ -95,6 +96,7 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
||||
} else if (event is CustomerSportChange) {
|
||||
yield CustomerChangeLoading();
|
||||
selectedSport = event.sport;
|
||||
print("Selected Sport $selectedSport");
|
||||
yield CustomerDataChanged();
|
||||
} else if (event is CustomerSaveFitness) {
|
||||
yield CustomerChangeLoading();
|
||||
@ -137,6 +139,8 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
||||
}
|
||||
|
||||
await customerRepository.saveCustomer();
|
||||
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);
|
||||
await mauticRepository.sendMauticDataChange();
|
||||
Cache().initBadges();
|
||||
yield CustomerSaveSuccess();
|
||||
} else {
|
||||
@ -151,10 +155,6 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
||||
bool validation() {
|
||||
if (customerRepository.customer == null) throw Exception("Customer object not defined");
|
||||
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) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
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:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
@ -26,7 +27,6 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
late double initialRM;
|
||||
late double unitQuantity;
|
||||
late double quantity;
|
||||
late double origQuantity;
|
||||
late double oneRepQuantity;
|
||||
late double oneRepUnitQuantity;
|
||||
|
||||
@ -36,6 +36,8 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
double scrollOffset = 0;
|
||||
late ExerciseTypeLocal exerciseTypeLocal;
|
||||
|
||||
List<Exercise> controlList = [];
|
||||
|
||||
@override
|
||||
ExerciseControlBloc({required this.exerciseRepository, required this.readonly, required this.timerBloc})
|
||||
: super(ExerciseControlInitial()) {
|
||||
@ -53,29 +55,29 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
if (oneRepQuantity > 25) {
|
||||
quantity = 35;
|
||||
}
|
||||
origQuantity = quantity;
|
||||
|
||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||
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));
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<ExerciseControlState> mapEventToState(ExerciseControlEvent event) async* {
|
||||
try {
|
||||
/* if (event is ExerciseControlLoad) {
|
||||
yield ExerciseControlLoading();
|
||||
step = 1;
|
||||
yield ExerciseControlReady();
|
||||
} else */
|
||||
if (event is ExerciseControlQuantityChange) {
|
||||
//yield ExerciseControlLoading();
|
||||
if (event.step == step) {
|
||||
exerciseRepository.setQuantity(event.quantity);
|
||||
quantity = event.quantity;
|
||||
controlList[step - 1].quantity = quantity;
|
||||
}
|
||||
//yield ExerciseControlReady();
|
||||
} else if (event is ExerciseControlUnitQuantityChange) {
|
||||
yield ExerciseControlLoading();
|
||||
print("event step ${event.step} quantity ${event.quantity}");
|
||||
@ -85,7 +87,8 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
unitQuantity = event.quantity;
|
||||
quantity = calculateQuantityByUnitQuantity().toDouble();
|
||||
exerciseRepository.setQuantity(quantity);
|
||||
origQuantity = quantity;
|
||||
controlList[step - 1].unitQuantity = event.quantity;
|
||||
controlList[step - 1].quantity = quantity;
|
||||
}
|
||||
yield ExerciseControlReady();
|
||||
} else if (event is ExerciseControlSubmit) {
|
||||
@ -94,13 +97,11 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
step++;
|
||||
scrollOffset = step * 400.0;
|
||||
|
||||
quantity = origQuantity;
|
||||
if (exerciseRepository.exercise!.quantity == null) {
|
||||
exerciseRepository.setQuantity(quantity);
|
||||
}
|
||||
exerciseRepository.end = DateTime.now();
|
||||
await exerciseRepository.addExercise();
|
||||
//exerciseRepository.initExercise();
|
||||
|
||||
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 MenuBloc menuBloc;
|
||||
late AnimationController bmiAnimationController;
|
||||
double quantity = 12;
|
||||
double unitQuantity = 30;
|
||||
double quantity = -1;
|
||||
double unitQuantity = -1;
|
||||
double bmi = 0;
|
||||
double bmr = 0;
|
||||
double goalBMI = 0;
|
||||
@ -148,6 +148,10 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
||||
yield ExerciseNewReady();
|
||||
} else if (event is ExerciseNewSubmit) {
|
||||
yield ExerciseNewLoading();
|
||||
if (quantity == -1 || unitQuantity == -1) {
|
||||
yield ExerciseNewReady();
|
||||
throw Exception("Please type in a real number");
|
||||
}
|
||||
exerciseRepository.end = DateTime.now();
|
||||
await exerciseRepository.addExercise();
|
||||
// exerciseRepository.initExercise();
|
||||
|
@ -2,8 +2,11 @@ import 'dart:async';
|
||||
|
||||
import 'package:aitrainer_app/bloc/account/account_bloc.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/mautic_repository.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/util/common.dart';
|
||||
import 'package:aitrainer_app/util/enums.dart';
|
||||
@ -19,7 +22,7 @@ part 'login_state.dart';
|
||||
class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
||||
final AccountBloc accountBloc;
|
||||
final UserRepository userRepository;
|
||||
final CustomerRepository customerRepository = CustomerRepository();
|
||||
late CustomerRepository? customerRepository;
|
||||
final SplitTestRepository splitTestRepository = SplitTestRepository();
|
||||
final BuildContext context;
|
||||
final bool isRegistration;
|
||||
@ -30,7 +33,12 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
||||
Color testColor = Colors.green[800]!;
|
||||
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()) {
|
||||
String colorString = splitTestRepository.getSplitTestValue("registration_skip");
|
||||
if (colorString == "red") {
|
||||
@ -40,6 +48,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
||||
if (emailCheckboxString == "0") {
|
||||
emailCheckbox = false;
|
||||
}
|
||||
if (customerRepository == null) {
|
||||
customerRepository = CustomerRepository();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -87,56 +98,44 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
||||
yield LoginSuccess();
|
||||
} else if (event is RegistrationSubmit) {
|
||||
yield LoginLoading();
|
||||
/* if (!this.dataPolicyAllowed) {
|
||||
throw Exception("Please accept our data policy");
|
||||
} */
|
||||
|
||||
final String? validationError = validate();
|
||||
if (validationError != null) {
|
||||
yield LoginError(message: validationError);
|
||||
} else {
|
||||
await userRepository.addUser();
|
||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await saveCustomer();
|
||||
Track().track(TrackingEvent.registration, eventValue: "email");
|
||||
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await afterRegistration("email");
|
||||
Cache().setLoginType(LoginType.email);
|
||||
yield LoginSuccess();
|
||||
}
|
||||
} else if (event is RegistrationFB) {
|
||||
yield LoginLoading();
|
||||
/* if (!this.dataPolicyAllowed) {
|
||||
throw Exception("Please accept our data policy");
|
||||
} */
|
||||
|
||||
Cache().setLoginType(LoginType.fb);
|
||||
await userRepository.addUserFB();
|
||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await saveCustomer();
|
||||
Track().track(TrackingEvent.registration, eventValue: "FB");
|
||||
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await afterRegistration("FB");
|
||||
yield LoginSuccess();
|
||||
} else if (event is RegistrationGoogle) {
|
||||
yield LoginLoading();
|
||||
/* if (!this.dataPolicyAllowed) {
|
||||
throw Exception("Please accept our data policy");
|
||||
} */
|
||||
|
||||
Cache().setLoginType(LoginType.google);
|
||||
await userRepository.addUserGoogle();
|
||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await saveCustomer();
|
||||
Track().track(TrackingEvent.registration, eventValue: "Google");
|
||||
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await afterRegistration("Google");
|
||||
yield LoginSuccess();
|
||||
} else if (event is RegistrationApple) {
|
||||
yield LoginLoading();
|
||||
/* if (!this.dataPolicyAllowed) {
|
||||
throw Exception("Please accept our data policy");
|
||||
} */
|
||||
|
||||
Cache().setLoginType(LoginType.apple);
|
||||
await userRepository.addUserApple();
|
||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||
customerRepository.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await saveCustomer();
|
||||
Track().track(TrackingEvent.registration, eventValue: "Apple");
|
||||
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
|
||||
await afterRegistration("Apple");
|
||||
|
||||
yield LoginSuccess();
|
||||
} else if (event is DataProtectionClicked) {
|
||||
@ -162,10 +161,23 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveCustomer() async {
|
||||
customerRepository.customer = Cache().userLoggedIn!;
|
||||
customerRepository.customer!.dataPolicyAllowed = 1;
|
||||
await customerRepository.saveCustomer();
|
||||
Future<void> afterRegistration(String event) async {
|
||||
Customer tempCustomer = customerRepository!.customer!;
|
||||
customerRepository!.customer = Cache().userLoggedIn!;
|
||||
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) {
|
||||
|
@ -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_plan_detail.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/repository/training_plan_repository.dart';
|
||||
import 'package:aitrainer_app/service/exercise_service.dart';
|
||||
@ -29,6 +31,9 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
CustomerTrainingPlan? _myPlan;
|
||||
CustomerTrainingPlanDetails? _myDetail;
|
||||
|
||||
TrainingPlan? _myTrainingPlan;
|
||||
final List<String> trainingPlanDayNames = [];
|
||||
|
||||
bool started = false;
|
||||
final List<String> dayNames = [];
|
||||
bool restarting = false;
|
||||
@ -38,6 +43,9 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
CustomerTrainingPlan? getMyPlan() => this._myPlan;
|
||||
setMyPlan(CustomerTrainingPlan? myPlan) => this._myPlan = myPlan;
|
||||
|
||||
TrainingPlan? getMyTrainingPlan() => this._myTrainingPlan;
|
||||
setMyTrainingPlan(TrainingPlan? myTrainingPlan) => this._myTrainingPlan = myTrainingPlan;
|
||||
|
||||
CustomerTrainingPlanDetails? getMyDetail() => this._myDetail;
|
||||
setMyDetail(CustomerTrainingPlanDetails? value) => this._myDetail = value;
|
||||
|
||||
@ -88,6 +96,10 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
yield TrainingPlanReady();
|
||||
} else if (event is TrainingPlanSaveExercise) {
|
||||
yield TrainingPlanLoading();
|
||||
if (event.detail.repeats == -1) {
|
||||
yield TrainingPlanReady();
|
||||
throw Exception("Please type your repeats!");
|
||||
}
|
||||
if (event.detail.weight == -3) {
|
||||
print("DropSet");
|
||||
event.detail.state = ExercisePlanDetailState.finished;
|
||||
@ -293,6 +305,83 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> {
|
||||
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) {
|
||||
if (Cache().getExerciseTypes() == null) {
|
||||
return;
|
||||
|
@ -307,6 +307,60 @@ class SuperTooltip {
|
||||
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() {
|
||||
return Positioned(
|
||||
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 {
|
||||
|
@ -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_new.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/widgets/home.dart';
|
||||
import 'package:aitrainer_app/library/facebook_app_events/facebook_app_events.dart';
|
||||
@ -180,8 +179,8 @@ Future<Null> main() async {
|
||||
BlocProvider<TestSetExecuteBloc>(
|
||||
create: (BuildContext context) => TestSetExecuteBloc(),
|
||||
),
|
||||
/* BlocProvider<TutorialBloc>(
|
||||
create: (BuildContext context) => TutorialBloc(tutorialName: ActivityDone.tutorialExecuteFirstTest.toStr())), */
|
||||
BlocProvider<TutorialBloc>(
|
||||
create: (BuildContext context) => TutorialBloc(tutorialName: ActivityDone.tutorialExecuteFirstTest.toStr())),
|
||||
BlocProvider<TrainingPlanBloc>(create: (context) {
|
||||
final MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||
return TrainingPlanBloc(menuBloc: menuBloc, trainingPlanRepository: TrainingPlanRepository());
|
||||
@ -283,7 +282,6 @@ class WorkoutTestApp extends StatelessWidget {
|
||||
'myTrainingPlanCustom': (context) => TrainingPlanCustomPage(),
|
||||
'myTrainingPlanCustomAdd': (context) => TrainingPlanCustomAddPage(),
|
||||
'myTrainingPlanActivate': (context) => TrainingPlanActivatePage(),
|
||||
'myTrainingPlanExecute2': (context) => TrainingPlanExecutePage(),
|
||||
'myTrainingPlanExecute': (context) => TrainingPlanExecute(),
|
||||
'myTrainingPlanExercise': (context) => TrainingPlanExercise(),
|
||||
'myTrainingEvaluation': (context) => TrainingEvaluationPage(),
|
||||
|
@ -71,7 +71,11 @@ enum ActivityDone {
|
||||
tutorialBasicLegPress,
|
||||
tutorialDevelopment,
|
||||
isExerciseLogSeen,
|
||||
isMuscleDevelopmentSeen
|
||||
isMuscleDevelopmentSeen,
|
||||
isBodyTypeSeen,
|
||||
exerciseSaveTestTip,
|
||||
exerciseSaveTrainingTip,
|
||||
exerciseSaveTestsetTip
|
||||
}
|
||||
|
||||
extension ActivityDoneExt on ActivityDone {
|
||||
@ -641,8 +645,8 @@ class Cache with Logging {
|
||||
}
|
||||
if (this._exercises == null || this._exercises!.isEmpty) {
|
||||
setBadge("home", true);
|
||||
setBadge("Muscle Build / Shape Toning", true);
|
||||
setBadge("Cardio", true);
|
||||
setBadge("Custom Tests", true);
|
||||
setBadge("Start Training", true);
|
||||
}
|
||||
if (customerRepository.getHeight() == 0) {
|
||||
setBadge("BMI", true);
|
||||
@ -726,6 +730,8 @@ class Cache with Logging {
|
||||
sharedPreferences.setBool(activity.toStr(), true);
|
||||
}
|
||||
|
||||
bool isActivityDone(ActivityDone activity) => activitiesDone[activity.toStr()] == true;
|
||||
|
||||
List<Evaluation>? get evaluations => this._evaluations;
|
||||
set evaluations(List<Evaluation>? value) => this._evaluations = value;
|
||||
|
||||
|
@ -24,6 +24,7 @@ class Customer {
|
||||
DateTime? dateChange;
|
||||
int? emailSubscription;
|
||||
int? sportId;
|
||||
DateTime? syncedDate;
|
||||
DateTime? trialDate;
|
||||
|
||||
LinkedHashMap<String, CustomerProperty> properties = LinkedHashMap();
|
||||
@ -71,6 +72,7 @@ class Customer {
|
||||
this.dataPolicyAllowed = json['dataPolicyAllowed'];
|
||||
this.emailSubscription = json['emailSubscription'];
|
||||
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.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!),
|
||||
"emailSubscription": this.emailSubscription,
|
||||
"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) {
|
||||
if (this.properties[propertyName] == null) {
|
||||
return 0;
|
||||
|
@ -59,7 +59,7 @@ class CustomerTrainingPlanDetails {
|
||||
this.exerciseTypeId = json['exerciseTypeId'];
|
||||
this.set = json['set'];
|
||||
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.parallel = json['parallel'] == "false"
|
||||
? false
|
||||
|
@ -1,7 +1,5 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:aitrainer_app/util/app_language.dart';
|
||||
|
||||
class Faq {
|
||||
late int faqId;
|
||||
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 {
|
||||
late int sportId;
|
||||
late String name;
|
||||
late String sportNameTranslation;
|
||||
|
||||
HashMap<String, String> nameTranslations = HashMap();
|
||||
|
||||
Sport.fromJson(Map json) {
|
||||
this.sportId = json['sportId'];
|
||||
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() => {
|
||||
|
@ -10,6 +10,7 @@ class TrainingPlanDetail {
|
||||
bool? parallel;
|
||||
int? dayId;
|
||||
String? day;
|
||||
String? summary;
|
||||
|
||||
TrainingPlanDetail.fromJson(Map<String, dynamic> json) {
|
||||
this.trainingPlanDetailId = json['trainingPlanDetailId'];
|
||||
@ -35,6 +36,7 @@ class TrainingPlanDetail {
|
||||
"parallel": this.parallel,
|
||||
"dayId": this.dayId,
|
||||
"day": this.day,
|
||||
"summary": this.summary
|
||||
};
|
||||
|
||||
@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);
|
||||
if (trainingPlan == null || trainingPlan.details == null) {
|
||||
print("trainingPlan null");
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -274,14 +275,26 @@ class TrainingPlanRepository {
|
||||
|
||||
bool isWoman = Cache().userLoggedIn!.sex == "w";
|
||||
|
||||
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("beginner_split");
|
||||
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
|
||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_advanced") : getTrainingPlanByInternalName("man_routine4");
|
||||
if (Cache().userLoggedIn!.goal == "shape_forming") {
|
||||
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
|
||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner") : getTrainingPlanByInternalName("man_routine1");
|
||||
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
|
||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner_split") : getTrainingPlanByInternalName("man_routine3");
|
||||
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
|
||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_advanced") : getTrainingPlanByInternalName("man_routine4");
|
||||
} else {
|
||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_routine2") : getTrainingPlanByInternalName("man_routine2");
|
||||
}
|
||||
} else {
|
||||
trainingPlanId = isWoman ? getTrainingPlanByInternalName("5day") : getTrainingPlanByInternalName("5day");
|
||||
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}");
|
||||
@ -290,6 +303,7 @@ class TrainingPlanRepository {
|
||||
CustomerTrainingPlan? customerTrainingPlan = activateTrainingPlan(trainingPlanId);
|
||||
if (customerTrainingPlan != null) {
|
||||
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_finished,
|
||||
training_plan_custom,
|
||||
trial
|
||||
trial,
|
||||
feedback_email
|
||||
}
|
||||
|
||||
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 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/model/tracking.dart' as model;
|
||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flurry_data/flurry_data.dart';
|
||||
import 'package:flutter_uxcam/flutter_uxcam.dart';
|
||||
|
||||
@ -21,7 +22,7 @@ class Track with Logging {
|
||||
void track(TrackingEvent event, {String eventValue = ""}) {
|
||||
analytics.logEvent(name: event.enumToString(), parameters: {"value": eventValue});
|
||||
if (!isInDebugMode) {
|
||||
FlurryData.logEvent(event.toString());
|
||||
FlurryData.logEvent(event.enumToString());
|
||||
// Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
|
||||
FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
|
||||
model.Tracking tracking = model.Tracking();
|
||||
@ -32,6 +33,7 @@ class Track with Logging {
|
||||
tracking.eventValue = eventValue;
|
||||
}
|
||||
tracking.dateAdd = DateTime.now();
|
||||
FirebaseMessaging.instance.subscribeToTopic(event.enumToString());
|
||||
TrackingApi().saveTracking(tracking);
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ class AccountPage extends StatelessWidget with Trans {
|
||||
return ListView(padding: EdgeInsets.only(top: 35), children: <Widget>[
|
||||
ListTile(
|
||||
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(
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Text(customerName, style: TextStyle(color: Colors.blue)),
|
||||
@ -108,7 +108,7 @@ class AccountPage extends StatelessWidget with Trans {
|
||||
),
|
||||
ListTile(
|
||||
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(
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
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/trans.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:flutter/material.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;
|
||||
}
|
||||
|
||||
PreferredSizeWidget _bar = AppBarMin(
|
||||
back: true,
|
||||
);
|
||||
|
||||
setContext(context);
|
||||
return Scaffold(
|
||||
appBar: AppBarNav(depth: 0),
|
||||
appBar: _bar,
|
||||
body: Container(
|
||||
height: 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/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/repository/customer_repository.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 '../bloc/customer_change/customer_change_bloc.dart';
|
||||
import '../library/dropdown_search/dropdown_search.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class CustomerFitnessPage extends StatefulWidget {
|
||||
@ -76,8 +73,11 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||
} else if (state is CustomerSaveSuccess) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed("customerSexPage", arguments: changeBloc.customerRepository);
|
||||
if (fulldata) {
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
Navigator.of(context).popAndPushNamed("customerSexPage", arguments: changeBloc.customerRepository);
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
@ -103,15 +103,15 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> with Trans {
|
||||
changeBloc.add(CustomerSave()),
|
||||
}
|
||||
},
|
||||
backgroundColor: Color(0xffb4f500),
|
||||
backgroundColor: Colors.orange[600],
|
||||
icon: Icon(
|
||||
CustomIcon.save,
|
||||
color: Colors.black,
|
||||
color: Colors.white,
|
||||
size: 26,
|
||||
),
|
||||
label: Text(
|
||||
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(
|
||||
height: h,
|
||||
),
|
||||
|
||||
getButton("Beginner", "I am beginner", FitnessState.beginner),
|
||||
SizedBox(
|
||||
height: h,
|
||||
),
|
||||
getButton("Intermediate", "I am intermediate", FitnessState.intermediate),
|
||||
|
||||
SizedBox(
|
||||
height: h,
|
||||
),
|
||||
getButton("Advanced", "I am advanced", FitnessState.advanced),
|
||||
|
||||
SizedBox(
|
||||
height: h,
|
||||
),
|
||||
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),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
);
|
||||
//return
|
||||
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();
|
||||
}
|
||||
PreferredSizeWidget _bar = AppBarMin(
|
||||
back: false,
|
||||
back: true,
|
||||
);
|
||||
if (!fulldata) {
|
||||
_bar = AppBarProgress(max: 14, min: 0);
|
||||
@ -107,7 +107,11 @@ class _CustomerGoalPage extends State<CustomerGoalPage> with Trans {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||
} 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) {
|
||||
@ -136,15 +140,15 @@ class _CustomerGoalPage extends State<CustomerGoalPage> with Trans {
|
||||
changeBloc.add(CustomerSave()),
|
||||
}
|
||||
},
|
||||
backgroundColor: Color(0xffb4f500),
|
||||
backgroundColor: Colors.orange[600],
|
||||
icon: Icon(
|
||||
CustomIcon.save,
|
||||
color: Colors.black,
|
||||
color: Colors.white,
|
||||
size: 26,
|
||||
),
|
||||
label: Text(
|
||||
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(
|
||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||
} else if (state is CustomerSaveSuccess) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed("registration", arguments: changeBloc.customerRepository);
|
||||
if (fulldata) {
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
Navigator.of(context).popAndPushNamed("registration", arguments: changeBloc.customerRepository);
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
@ -76,15 +79,15 @@ class _CustomerHeightPageState extends State<CustomerHeightPage> with Trans {
|
||||
)),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () => changeBloc.add(CustomerSaveHeight()),
|
||||
backgroundColor: Color(0xffb4f500),
|
||||
backgroundColor: Colors.orange[600],
|
||||
icon: Icon(
|
||||
CustomIcon.save,
|
||||
color: Colors.black,
|
||||
color: Colors.white,
|
||||
size: 26,
|
||||
),
|
||||
label: Text(
|
||||
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/customer_change/customer_change_bloc.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/sport.dart';
|
||||
import 'package:aitrainer_app/util/app_language.dart';
|
||||
import 'package:aitrainer_app/util/enums.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||
@ -385,10 +388,119 @@ class CustomerModifyPage extends StatelessWidget with Trans {
|
||||
},
|
||||
),
|
||||
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(
|
||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||
} else if (state is CustomerSaveSuccess) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed("customerWeightPage", arguments: changeBloc.customerRepository);
|
||||
if (fulldata) {
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
Navigator.of(context).popAndPushNamed("customerWeightPage", arguments: changeBloc.customerRepository);
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
@ -84,15 +87,15 @@ class _CustomerSexPageState extends State<CustomerSexPage> with Trans {
|
||||
onPressed: () => {
|
||||
changeBloc.add(CustomerSaveSex()),
|
||||
},
|
||||
backgroundColor: Color(0xffb4f500),
|
||||
backgroundColor: Colors.orange[600],
|
||||
icon: Icon(
|
||||
CustomIcon.save,
|
||||
color: Colors.black,
|
||||
color: Colors.white,
|
||||
size: 26,
|
||||
),
|
||||
label: Text(
|
||||
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/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/util/trans.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(
|
||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||
} else if (state is CustomerSaveSuccess) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed("customerHeightPage", arguments: changeBloc.customerRepository);
|
||||
if (fulldata) {
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
Navigator.of(context).popAndPushNamed("customerHeightPage", arguments: changeBloc.customerRepository);
|
||||
}
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
@ -85,15 +87,15 @@ class _CustomerWeightPageState extends State<CustomerWeightPage> with Trans {
|
||||
onPressed: () => {
|
||||
changeBloc.add(CustomerSaveWeight()),
|
||||
},
|
||||
backgroundColor: Color(0xffb4f500),
|
||||
backgroundColor: Colors.orange[600],
|
||||
icon: Icon(
|
||||
CustomIcon.save,
|
||||
color: Colors.black,
|
||||
color: Colors.white,
|
||||
size: 26,
|
||||
),
|
||||
label: Text(
|
||||
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/widgets/app_bar_min.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -231,7 +231,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
Divider(),
|
||||
numberPickForm(exerciseBloc, 3),
|
||||
SizedBox(
|
||||
height: 80,
|
||||
height: 120,
|
||||
)
|
||||
]),
|
||||
)),
|
||||
@ -263,12 +263,10 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
}
|
||||
|
||||
Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) {
|
||||
final String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max.";
|
||||
//print("step $step, quantity ${exerciseBloc.origQuantity}");
|
||||
final String strTimes = step == 2 ? exerciseBloc.controlList[step - 1].quantity!.toStringAsFixed(0) : "max.";
|
||||
|
||||
String title = (step + 1).toString() + "/4 " + t("Control Exercise:");
|
||||
LinkedHashMap args = LinkedHashMap();
|
||||
final TutorialBloc tutorialBloc = BlocProvider.of<TutorialBloc>(context);
|
||||
|
||||
List<Widget> listWidgets = [
|
||||
Text(
|
||||
@ -294,7 +292,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
children: [
|
||||
TextSpan(text: t("Please repeat with ")),
|
||||
TextSpan(
|
||||
text: exerciseBloc.unitQuantity.toStringAsFixed(0) +
|
||||
text: exerciseBloc.controlList[step - 1].unitQuantity!.toStringAsFixed(0) +
|
||||
" " +
|
||||
exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit!,
|
||||
style: GoogleFonts.inter(
|
||||
@ -324,7 +322,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
NumberPickerWidget(
|
||||
minValue: 0,
|
||||
maxValue: 200,
|
||||
initalValue: exerciseBloc.origQuantity.round(),
|
||||
initalValue: exerciseBloc.controlList[step - 1].quantity!.round(),
|
||||
unit: t("reps"),
|
||||
color: Colors.yellow[50]!,
|
||||
onChange: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))}),
|
||||
@ -335,12 +333,6 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
onSurface: Colors.blueAccent,
|
||||
),
|
||||
onPressed: () {
|
||||
if (tutorialBloc.isActive) {
|
||||
if (!tutorialBloc.checkAction("Save")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
exerciseBloc.add(ExerciseControlSubmit(step: step));
|
||||
if (step == 3) {
|
||||
Navigator.of(context).pop();
|
||||
@ -354,7 +346,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
children: [
|
||||
Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60),
|
||||
Text(
|
||||
t("Save"),
|
||||
t("Done!"),
|
||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||
),
|
||||
],
|
||||
@ -436,9 +428,9 @@ class _UnitQuantityControlState extends State<UnitQuantityControl> with Trans {
|
||||
height: 20,
|
||||
),
|
||||
NumberPickerWidget(
|
||||
minValue: (widget.exerciseBloc.unitQuantity - 30).round(),
|
||||
maxValue: (widget.exerciseBloc.unitQuantity + 30).round(),
|
||||
initalValue: widget.exerciseBloc.unitQuantity.round(),
|
||||
minValue: (widget.exerciseBloc.controlList[widget.step - 1].unitQuantity! - 30).round(),
|
||||
maxValue: (widget.exerciseBloc.controlList[widget.step - 1].unitQuantity! + 30).round(),
|
||||
initalValue: widget.exerciseBloc.controlList[widget.step - 1].unitQuantity!.round(),
|
||||
unit: t("kg"),
|
||||
color: Colors.yellow[50]!,
|
||||
onChange: (value) => {
|
||||
@ -452,9 +444,9 @@ class _UnitQuantityControlState extends State<UnitQuantityControl> with Trans {
|
||||
onTap: () => {
|
||||
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)),
|
||||
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/exercise_ability.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/exercise_repository.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/dialog_common.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/tutorial_widget.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -55,7 +57,9 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
||||
title: t("Warning"),
|
||||
descriptions: t(state.message),
|
||||
text: "OK",
|
||||
onTap: () => Navigator.of(context).pushNamed("login"),
|
||||
onTap: () => {
|
||||
Navigator.of(context).pop(),
|
||||
},
|
||||
onCancel: () => {
|
||||
Navigator.of(context).pop(),
|
||||
},
|
||||
@ -114,10 +118,12 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
||||
return SizeWidget(exerciseBloc: exerciseBloc);
|
||||
}
|
||||
|
||||
WorkoutMenuTree? workoutTree = menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(exerciseType.exerciseTypeId);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
padding: EdgeInsets.only(top: 10, left: 20, right: 20),
|
||||
padding: EdgeInsets.only(),
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('asset/image/WT_black_background.jpg'),
|
||||
@ -126,37 +132,38 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
||||
),
|
||||
),
|
||||
child: ExerciseSave(
|
||||
exerciseName: exerciseBloc.exerciseRepository.exerciseType!.nameTranslation,
|
||||
exerciseDescription: exerciseBloc.exerciseRepository.exerciseType!.descriptionTranslation,
|
||||
exerciseTask: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit != null
|
||||
? t("Please take a relative bigger weight and repeat 12-20 times and do your best! MAXIMIZE it!")
|
||||
: t("Please repeat as much times as you can! MAXIMIZE it!"),
|
||||
unit: exerciseBloc.exerciseRepository.exerciseType!.unit,
|
||||
unitQuantityUnit: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit,
|
||||
hasUnitQuantity: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit != null,
|
||||
onQuantityChanged: (value) {
|
||||
exerciseBloc.add(ExerciseNewQuantityChange(quantity: value));
|
||||
},
|
||||
onUnitQuantityChanged: (value) => exerciseBloc.add(ExerciseNewQuantityUnitChange(quantity: value)),
|
||||
//onSubmit: () => confirmationDialog(exerciseBloc, menuBloc),
|
||||
exerciseTypeId: exerciseType.exerciseTypeId,
|
||||
)),
|
||||
exerciseName: exerciseBloc.exerciseRepository.exerciseType!.nameTranslation,
|
||||
exerciseDescription: exerciseBloc.exerciseRepository.exerciseType!.descriptionTranslation,
|
||||
exerciseTask: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit != null
|
||||
? t("Please take a relative bigger weight and repeat 12-20 times and do your best! MAXIMIZE it!")
|
||||
: t("Please repeat as much times as you can! MAXIMIZE it!"),
|
||||
unit: exerciseBloc.exerciseRepository.exerciseType!.unit,
|
||||
unitQuantityUnit: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit,
|
||||
hasUnitQuantity: exerciseBloc.exerciseRepository.exerciseType!.unitQuantityUnit != null,
|
||||
onQuantityChanged: (value) {
|
||||
exerciseBloc.add(ExerciseNewQuantityChange(quantity: value));
|
||||
},
|
||||
onUnitQuantityChanged: (value) => exerciseBloc.add(ExerciseNewQuantityUnitChange(quantity: value)),
|
||||
//onSubmit: () => confirmationDialog(exerciseBloc, menuBloc),
|
||||
exerciseTypeId: exerciseType.exerciseTypeId,
|
||||
tip: ActivityDone.exerciseSaveTestTip,
|
||||
menuImage: MenuImage(
|
||||
imageName: workoutTree!.imageName,
|
||||
workoutTreeId: workoutTree.id,
|
||||
radius: 0,
|
||||
))),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () => save(exerciseBloc, menuBloc),
|
||||
backgroundColor: Colors.orange[800],
|
||||
backgroundColor: Colors.orange[600],
|
||||
icon: Icon(
|
||||
CustomIcon.save,
|
||||
CustomIcon.ok_circled,
|
||||
size: 20,
|
||||
),
|
||||
label: Text(
|
||||
t("Save"),
|
||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 12),
|
||||
t("Done!"),
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
? bloc.exerciseRepository.exercise!.quantity!.round().toString()
|
||||
: bloc.exerciseRepository.exercise!.quantity!.toString();
|
||||
@ -209,9 +221,9 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
|
||||
// ignore: close_sinks
|
||||
final TestSetExecuteBloc executeBloc = BlocProvider.of<TestSetExecuteBloc>(context);
|
||||
|
||||
final question = bloc.exerciseRepository.exercise!.quantity! == 12.0
|
||||
? "Did you try the MAXIMUM what you can do? Are you sure we save the exercise with ONLY 12 repeats?"
|
||||
: "Do you save this exercise with these parameters?";
|
||||
/* 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?" */
|
||||
final question = "Do you save this exercise with these parameters?";
|
||||
|
||||
showCupertinoDialog(
|
||||
useRootNavigator: true,
|
||||
|
@ -37,7 +37,7 @@ class _MyDevelopmentBodyPage extends State<MyDevelopmentBodyPage> with Trans, Co
|
||||
setContext(context);
|
||||
return DialogPremium(
|
||||
unlocked: Cache().hasPurchased,
|
||||
unlockRound: 2,
|
||||
unlockRound: 4,
|
||||
function: "My Whole Body Development",
|
||||
unlockedText: null,
|
||||
onTap: () => {Navigator.of(context).pop(), Navigator.of(context).pop()},
|
||||
|
@ -163,7 +163,7 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
||||
builder: (BuildContext context) {
|
||||
return DialogPremium(
|
||||
unlocked: Cache().hasPurchased,
|
||||
unlockRound: 3,
|
||||
unlockRound: 12,
|
||||
function: "Predictions",
|
||||
unlockedText: null,
|
||||
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/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/user_repository.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
@ -23,12 +24,23 @@ class RegistrationPage extends StatelessWidget with Trans {
|
||||
@override
|
||||
Widget build(BuildContext 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);
|
||||
return Scaffold(
|
||||
appBar: AppBarMin(),
|
||||
body: BlocProvider(
|
||||
create: (context) =>
|
||||
LoginBloc(userRepository: UserRepository(), accountBloc: accountBloc, context: context, isRegistration: true),
|
||||
create: (context) => LoginBloc(
|
||||
userRepository: UserRepository(),
|
||||
accountBloc: accountBloc,
|
||||
context: context,
|
||||
isRegistration: true,
|
||||
customerRepository: customerRepository),
|
||||
child: BlocConsumer<LoginBloc, LoginState>(listener: (context, state) {
|
||||
if (state is LoginError) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@ -67,7 +79,9 @@ class RegistrationPage extends StatelessWidget with Trans {
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final loginBloc = BlocProvider.of<LoginBloc>(context);
|
||||
|
||||
if (customerRepository != null) {
|
||||
print("Customer data ${customerRepository.customer!.toJson()}");
|
||||
}
|
||||
return ModalProgressHUD(
|
||||
child: loadForm(loginBloc, accountBloc),
|
||||
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/settings/settings_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:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
|
||||
import 'package:toggle_switch/toggle_switch.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'dart:async';
|
||||
import 'package:mailto/mailto.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class SettingsPage extends StatelessWidget with Trans {
|
||||
@ -87,7 +85,7 @@ class SettingsPage extends StatelessWidget with Trans {
|
||||
//getTuturialBasic(settingsBloc),
|
||||
getTermsOfUse(),
|
||||
getPrivacy(),
|
||||
getFaq(),
|
||||
mailTo(),
|
||||
getVersion(),
|
||||
//getDevice(settingsBloc),
|
||||
]);
|
||||
@ -264,25 +262,40 @@ class SettingsPage extends StatelessWidget with Trans {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _printAndCopy(String cmd) async {
|
||||
print(cmd);
|
||||
|
||||
await Clipboard.setData(ClipboardData(text: cmd));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Copied to Clipboard')),
|
||||
ListTile mailTo() {
|
||||
return ListTile(
|
||||
leading: Icon(CustomIcon.mail_1),
|
||||
title: TextButton(
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
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() {
|
||||
String? cmd;
|
||||
String cmdSuffix;
|
||||
if (Platform.isIOS) {
|
||||
cmd = '/usr/bin/xcrun simctl openurl booted';
|
||||
} else if (Platform.isAndroid) {
|
||||
cmd = '\$ANDROID_HOME/platform-tools/adb shell \'am start'
|
||||
' -a android.intent.action.VIEW'
|
||||
' -c android.intent.category.BROWSABLE -d';
|
||||
cmdSuffix = "'";
|
||||
}
|
||||
launchMailto() async {
|
||||
String from = Cache().userLoggedIn == null ? "" : Cache().userLoggedIn!.customerId!.toStringAsFixed(0);
|
||||
final mailtoLink = Mailto(
|
||||
to: ['service@workouttest.com'],
|
||||
subject: 'Feedback from app: $from',
|
||||
body: '',
|
||||
);
|
||||
// Convert the Mailto instance into a string.
|
||||
// Use either Dart's string interpolation
|
||||
// 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_new/test_set_new_bloc.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_type.dart';
|
||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||
import 'package:aitrainer_app/widgets/bottom_bar_multiple_exercises.dart';
|
||||
import 'package:aitrainer_app/widgets/exercise_save.dart';
|
||||
import 'package:aitrainer_app/widgets/menu_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
@ -29,7 +32,6 @@ class TestSetNew extends StatelessWidget with Trans {
|
||||
return Scaffold(
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('asset/image/WT_black_background.jpg'),
|
||||
@ -77,7 +79,7 @@ class TestSetNew extends StatelessWidget with Trans {
|
||||
backgroundColor: Colors.orange[800],
|
||||
icon: Icon(CustomIcon.save),
|
||||
label: Text(
|
||||
t("Save"),
|
||||
t("Done"),
|
||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
||||
),
|
||||
),
|
||||
@ -89,6 +91,8 @@ class TestSetNew extends StatelessWidget with Trans {
|
||||
}
|
||||
|
||||
Widget getExercises(TestSetNewBloc bloc) {
|
||||
WorkoutMenuTree? workoutTree =
|
||||
bloc.executeBloc.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(bloc.exerciseType.exerciseTypeId);
|
||||
return ExerciseSave(
|
||||
exerciseName: bloc.exerciseType.nameTranslation,
|
||||
exerciseDescription: bloc.exerciseType.descriptionTranslation,
|
||||
@ -103,6 +107,12 @@ class TestSetNew extends StatelessWidget with Trans {
|
||||
},
|
||||
onUnitQuantityChanged: (value) => bloc.add(TestSetNewChangeQuantityUnit(quantity: value)),
|
||||
exerciseTypeId: bloc.exerciseType.exerciseTypeId,
|
||||
tip: ActivityDone.exerciseSaveTestsetTip,
|
||||
menuImage: MenuImage(
|
||||
imageName: workoutTree!.imageName,
|
||||
workoutTreeId: workoutTree.id,
|
||||
radius: 0,
|
||||
),
|
||||
/* onSubmit: () {
|
||||
Navigator.of(context).pop();
|
||||
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/model/cache.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/util/app_language.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
@ -58,7 +59,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
||||
title: t("Warning"),
|
||||
descriptions: t(state.message),
|
||||
text: "OK",
|
||||
onTap: () => Navigator.of(context).pushNamed("login"),
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
onCancel: () => {
|
||||
Navigator.of(context).pop(),
|
||||
},
|
||||
@ -197,21 +198,45 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
||||
icon: Icon(Icons.list_sharp),
|
||||
color: Colors.blue[800],
|
||||
),
|
||||
children: _getChildList(element, bloc),
|
||||
children: _getDays(element, bloc),
|
||||
)));
|
||||
});
|
||||
|
||||
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 = [];
|
||||
|
||||
bool restricted = (!plan.free && !Cache().hasPurchased);
|
||||
|
||||
list.add(Card(
|
||||
margin: EdgeInsets.only(left: 10, top: 5),
|
||||
color: Colors.white60,
|
||||
color: Colors.white24,
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
child: Column(children: [
|
||||
@ -262,7 +287,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
||||
),
|
||||
))
|
||||
: Offstage(),
|
||||
getPlanDetails(plan, bloc),
|
||||
getPlanDetails(plan, bloc, dayName),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
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(
|
||||
headerRowHeight: 30,
|
||||
rowHeight: 60,
|
||||
rowHeight: 70,
|
||||
columnWidthMode: ColumnWidthMode.lastColumnFill,
|
||||
defaultColumnWidth: 50,
|
||||
source: TrainingPlanDetailSource(
|
||||
plan: plan,
|
||||
menuBloc: bloc.menuBloc,
|
||||
bloc: bloc,
|
||||
dayName: dayName,
|
||||
onWeightTap: () => {
|
||||
showDialog(
|
||||
context: context,
|
||||
@ -438,18 +467,23 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
||||
columns: [
|
||||
GridTextColumn(
|
||||
columnWidthMode: ColumnWidthMode.lastColumnFill,
|
||||
maximumWidth: 160,
|
||||
maximumWidth: 130,
|
||||
columnName: 'exerciseImage',
|
||||
label: Container(
|
||||
color: Colors.green[50],
|
||||
color: Colors.black38,
|
||||
padding: EdgeInsets.only(left: 8.0),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
t('Exercise'),
|
||||
style: GoogleFonts.inter(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.start,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))),
|
||||
GridTextColumn(
|
||||
maximumWidth: 0,
|
||||
visible: false,
|
||||
columnName: 'exerciseName',
|
||||
label: Container(
|
||||
@ -462,47 +496,40 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))),
|
||||
GridTextColumn(
|
||||
maximumWidth: 40,
|
||||
columnName: 'set',
|
||||
maximumWidth: 60,
|
||||
columnName: 'Set',
|
||||
label: Container(
|
||||
color: Colors.green[50],
|
||||
color: Colors.black38,
|
||||
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
t('Set'),
|
||||
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))),
|
||||
GridTextColumn(
|
||||
maximumWidth: 50,
|
||||
columnName: 'repeats',
|
||||
maximumWidth: 100,
|
||||
columnWidthMode: ColumnWidthMode.fill,
|
||||
columnName: 'Repeats',
|
||||
label: Container(
|
||||
color: Colors.green[50],
|
||||
color: Colors.black38,
|
||||
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
t('Reps'),
|
||||
t('Repeats'),
|
||||
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))),
|
||||
GridTextColumn(
|
||||
maximumWidth: 60,
|
||||
columnName: 'weight',
|
||||
columnName: 'Weight',
|
||||
label: Container(
|
||||
color: Colors.green[50],
|
||||
color: Colors.black38,
|
||||
padding: EdgeInsets.symmetric(horizontal: 2.0),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
t('Weight'),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))),
|
||||
GridTextColumn(
|
||||
maximumWidth: 50,
|
||||
columnName: 'day',
|
||||
label: Container(
|
||||
color: Colors.green[50],
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
t('Day'),
|
||||
t('Weight_'),
|
||||
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))),
|
||||
],
|
||||
@ -512,19 +539,25 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
|
||||
|
||||
class TrainingPlanDetailSource extends DataGridSource {
|
||||
final TrainingPlan plan;
|
||||
final TrainingPlanBloc bloc;
|
||||
final MenuBloc menuBloc;
|
||||
final dayName;
|
||||
final VoidCallback onDropsetTap;
|
||||
final VoidCallback onWeightTap;
|
||||
final VoidCallback onRepeatTap;
|
||||
TrainingPlanDetailSource({
|
||||
required this.plan,
|
||||
required this.menuBloc,
|
||||
required this.bloc,
|
||||
required this.dayName,
|
||||
required this.onDropsetTap,
|
||||
required this.onWeightTap,
|
||||
required this.onRepeatTap,
|
||||
}) {
|
||||
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);
|
||||
if (menuTree == null) {
|
||||
return DataGridRow(cells: []);
|
||||
@ -539,9 +572,8 @@ class TrainingPlanDetailSource extends DataGridSource {
|
||||
)),
|
||||
DataGridCell<String>(columnName: 'exerciseName', value: menuTree.name),
|
||||
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<String>(columnName: 'day', value: dataGridRow.day),
|
||||
]);
|
||||
}).toList();
|
||||
}
|
||||
@ -557,9 +589,9 @@ class TrainingPlanDetailSource extends DataGridSource {
|
||||
if (row.getCells().isEmpty) {
|
||||
return null;
|
||||
}
|
||||
String name = row.getCells()[1].value;
|
||||
String name = row.getCells()[1].value.toString();
|
||||
return DataGridRowAdapter(
|
||||
color: Colors.white60,
|
||||
color: Colors.white12,
|
||||
cells: row.getCells().map<Widget>((dataGridCell) {
|
||||
return Container(
|
||||
alignment: dataGridCell.columnName == "exerciseImage" ? Alignment.centerLeft : Alignment.centerLeft,
|
||||
@ -573,8 +605,7 @@ class TrainingPlanDetailSource extends DataGridSource {
|
||||
name,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style:
|
||||
GoogleFonts.inter(fontSize: 10, color: Colors.yellow[600], fontWeight: FontWeight.bold, shadows: <Shadow>[
|
||||
style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold, shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(2.0, 2.0),
|
||||
blurRadius: 6.0,
|
||||
@ -590,7 +621,7 @@ class TrainingPlanDetailSource extends DataGridSource {
|
||||
},
|
||||
child: Icon(
|
||||
CustomIcon.question_circle,
|
||||
color: Colors.indigo[300],
|
||||
color: Colors.white,
|
||||
))
|
||||
: dataGridCell.columnName == "weight" && dataGridCell.value == -3
|
||||
? GestureDetector(
|
||||
@ -608,12 +639,12 @@ class TrainingPlanDetailSource extends DataGridSource {
|
||||
},
|
||||
child: Icon(
|
||||
CustomIcon.question_circle,
|
||||
color: Colors.indigo[600],
|
||||
color: Colors.white,
|
||||
))
|
||||
: Text(dataGridCell.value.toString(),
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
color: Colors.indigo,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
)));
|
||||
}).toList());
|
||||
|
@ -45,8 +45,20 @@ class _TrainingPlanExecuteState extends State<TrainingPlanExecute> with Trans {
|
||||
),
|
||||
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))));
|
||||
showDialog(
|
||||
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) {
|
||||
bloc.celebrating = false;
|
||||
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]!.isNotEmpty) {
|
||||
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(
|
||||
onTap: () =>
|
||||
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/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/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar.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_bloc/flutter_bloc.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
@ -26,7 +28,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
||||
body: Container(
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(20),
|
||||
//padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage("asset/image/WT_black_background.jpg"),
|
||||
@ -75,7 +77,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
||||
backgroundColor: Colors.orange[800],
|
||||
icon: Icon(CustomIcon.save),
|
||||
label: Text(
|
||||
isDropSet ? t("Done") : t("Save"),
|
||||
t("Done"),
|
||||
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
|
||||
),
|
||||
),
|
||||
@ -92,7 +94,7 @@ class TrainingPlanExercise extends StatelessWidget with Trans {
|
||||
unit: detail.exerciseType!.unit,
|
||||
unitQuantityUnit: detail.exerciseType!.unitQuantityUnit,
|
||||
hasUnitQuantity: detail.exerciseType!.unitQuantityUnit != null,
|
||||
weight: detail.weight == -1 ? 0 : detail.weight,
|
||||
weight: detail.weight,
|
||||
repeats: detail.repeats == -1 ? 99 : detail.repeats,
|
||||
set: detail.set,
|
||||
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)),
|
||||
exerciseTypeId: detail.exerciseType!.exerciseTypeId,
|
||||
originalQuantity: originalQuantity,
|
||||
tip: ActivityDone.exerciseSaveTrainingTip,
|
||||
menuImage: MenuImage(
|
||||
imageName: bloc.getActualImageName(detail.exerciseType!.exerciseTypeId),
|
||||
workoutTreeId: bloc.getActualWorkoutTreeId(detail.exerciseType!.exerciseTypeId)!,
|
||||
radius: 0,
|
||||
filter: false,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return getDropSet(bloc, detail);
|
||||
|
@ -44,7 +44,7 @@ class MyTrainingPlans extends StatelessWidget with Trans, Logging {
|
||||
title: t("Warning"),
|
||||
descriptions: t(state.message),
|
||||
text: "OK",
|
||||
onTap: () => Navigator.of(context).pushNamed("login"),
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
onCancel: () => {
|
||||
Navigator.of(context).pop(),
|
||||
},
|
||||
|
@ -286,7 +286,7 @@ class _BMRState extends State<BMR> with Trans {
|
||||
),
|
||||
),
|
||||
mode: Mode.MENU,
|
||||
compareFn: (FitnessState i, FitnessState s) => i.isEqual(s),
|
||||
compareFn: (FitnessState? i, FitnessState? s) => i!.isEqual(s),
|
||||
showSelectedItem: true,
|
||||
selectedItem: FitnessItem().getItem(fitnessLevel),
|
||||
itemAsString: (data) => t(data!.stateText),
|
||||
@ -301,7 +301,6 @@ class _BMRState extends State<BMR> with Trans {
|
||||
color: Colors.yellow[200],
|
||||
),
|
||||
));
|
||||
//items: FitnessItem().toList()));
|
||||
}
|
||||
|
||||
Widget _customMenuBuilder(BuildContext context, FitnessState? item, bool isSelected) {
|
||||
|
@ -88,7 +88,7 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
|
||||
alignment: AlignmentDirectional.topEnd,
|
||||
children: [
|
||||
Text(
|
||||
widget.unlocked ? t("Keep testing") : t("Go Premium") + " ",
|
||||
widget.unlocked ? t("Keep training") : t("Go Premium") + " ",
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: widget.unlocked ? 20 : 24,
|
||||
color: Colors.yellow[400],
|
||||
@ -257,11 +257,7 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
|
||||
list.add(TextSpan(text: t(" ")));
|
||||
list.add(
|
||||
TextSpan(
|
||||
text: widget.unlockRound == 1
|
||||
? t("the first")
|
||||
: widget.unlockRound == 2
|
||||
? t("the second")
|
||||
: t("the third"),
|
||||
text: widget.unlockRound.toString() + " " + t("week"),
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
@ -282,7 +278,7 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
|
||||
),
|
||||
);
|
||||
list.add(TextSpan(text: t(" ")));
|
||||
list.add(TextSpan(text: t("100% test circles")));
|
||||
list.add(TextSpan(text: t("100% completed training")));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ class _DialogTrialWidgetState extends State<DialogTrialWidget> with Trans {
|
||||
children: [
|
||||
Image.asset('asset/icon/gomb_lila_b.png', width: 100, height: 45),
|
||||
Text(
|
||||
t("Nem"),
|
||||
t("No"),
|
||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||
),
|
||||
],
|
||||
@ -132,7 +132,7 @@ class _DialogTrialWidgetState extends State<DialogTrialWidget> with Trans {
|
||||
children: [
|
||||
Image.asset('asset/icon/gomb_orange_c.png', width: 100, height: 45),
|
||||
Text(
|
||||
t("Igen"),
|
||||
t("Yes"),
|
||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||
),
|
||||
],
|
||||
|
@ -1,21 +1,113 @@
|
||||
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/model/cache.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/tutorial_widget.dart';
|
||||
import 'package:badges/badges.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||
import 'package:keyboard_actions/keyboard_actions_config.dart';
|
||||
import 'package:stop_watch_timer/stop_watch_timer.dart';
|
||||
import 'package:wakelock/wakelock.dart';
|
||||
|
||||
import 'dialog_common.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
|
||||
class ExerciseSave extends StatefulWidget {
|
||||
final ValueChanged<double> onQuantityChanged;
|
||||
@ -33,6 +125,8 @@ class ExerciseSave extends StatefulWidget {
|
||||
final int? set;
|
||||
final int? exerciseNr;
|
||||
final int? originalQuantity;
|
||||
final MenuImage menuImage;
|
||||
final ActivityDone? tip;
|
||||
|
||||
ExerciseSave(
|
||||
{required this.onQuantityChanged,
|
||||
@ -49,7 +143,9 @@ class ExerciseSave extends StatefulWidget {
|
||||
this.repeats,
|
||||
this.set,
|
||||
this.exerciseNr,
|
||||
this.originalQuantity});
|
||||
this.originalQuantity,
|
||||
required this.menuImage,
|
||||
this.tip});
|
||||
@override
|
||||
_ExerciseSaveState createState() => _ExerciseSaveState();
|
||||
}
|
||||
@ -72,12 +168,6 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
||||
@override
|
||||
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(() {
|
||||
if (_nodeText1.hasFocus) {
|
||||
_controller1.selection = TextSelection(baseOffset: 0, extentOffset: _controller1.text.length);
|
||||
@ -98,25 +188,31 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
||||
}
|
||||
|
||||
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
||||
/* //final TutorialBloc bloc = BlocProvider.of<TutorialBloc>(context);
|
||||
if (bloc.actualCheck == "directTest") {
|
||||
_controller1.text = widget.weight == null || widget.weight == -1
|
||||
? "--"
|
||||
: 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(
|
||||
Duration(milliseconds: 2000),
|
||||
() => {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return DialogCommon(
|
||||
title: t("Attention"),
|
||||
descriptions: t(widget.exerciseTask),
|
||||
text: "OK",
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
onCancel: () => Navigator.of(context).pop(),
|
||||
);
|
||||
})
|
||||
TutorialWidget().explanation(
|
||||
context,
|
||||
ExplanationWidget(
|
||||
unitQuantityUnit: widget.unitQuantityUnit,
|
||||
unit: widget.unit,
|
||||
tip: widget.tip,
|
||||
weight: widget.weight,
|
||||
repeats: widget.repeats,
|
||||
)),
|
||||
});
|
||||
} */
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -189,82 +285,139 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
||||
}
|
||||
|
||||
Widget getExerciseWidget() {
|
||||
ExplanationExt expl = ExplanationExt(
|
||||
tip: widget.tip!,
|
||||
weight: widget.weight,
|
||||
repeats: widget.repeats,
|
||||
unitQuantityUnit: widget.unitQuantityUnit,
|
||||
);
|
||||
|
||||
return KeyboardActions(
|
||||
config: _buildConfig(context),
|
||||
child: Container(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
|
||||
Text(
|
||||
widget.exerciseName,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
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,
|
||||
),
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 4,
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
InkWell(
|
||||
child: Text(
|
||||
t("Exercise descripton") + " »",
|
||||
style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[200]),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 10, bottom: 10, right: 10),
|
||||
child: Text(
|
||||
widget.exerciseName,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
),
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 4,
|
||||
softWrap: true,
|
||||
))
|
||||
]),
|
||||
ListTile(
|
||||
leading: IconButton(
|
||||
iconSize: 30,
|
||||
onPressed: () => {
|
||||
if (widget.unitQuantityUnit != null)
|
||||
{
|
||||
TutorialWidget().explanation(
|
||||
context,
|
||||
ExplanationWidget(
|
||||
unitQuantityUnit: widget.unitQuantityUnit,
|
||||
unit: widget.unit,
|
||||
tip: widget.tip,
|
||||
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,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
),
|
||||
maxLines: 3,
|
||||
textAlign: TextAlign.left,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: true,
|
||||
),
|
||||
onTap: () => {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return DialogHTML(title: widget.exerciseName, htmlData: '<p>' + widget.exerciseDescription + '</p>');
|
||||
})
|
||||
},
|
||||
),
|
||||
Divider(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
Text(
|
||||
t(widget.exerciseTask),
|
||||
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(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
expl.getExplanation(Explanations.introBold).length > 0
|
||||
? Text(
|
||||
t(expl.getExplanation(Explanations.introBold)),
|
||||
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,
|
||||
)
|
||||
: Offstage(),
|
||||
widget.unit == "second"
|
||||
? Text(
|
||||
getTimeGoal(widget.originalQuantity),
|
||||
@ -289,29 +442,60 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
||||
)
|
||||
: Offstage(),
|
||||
columnQuantityUnit(),
|
||||
Divider(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
columnQuantity(),
|
||||
Divider(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
widget.hasUnitQuantity
|
||||
? Text(
|
||||
widget.set == null || widget.exerciseNr == null
|
||||
? t("Step") + ": " + "1/4"
|
||||
: t("Step") + ": " + "${widget.exerciseNr}/${widget.set}",
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 22,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 3,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: true,
|
||||
)
|
||||
: Offstage(),
|
||||
Text(
|
||||
t(expl.getExplanation(Explanations.explanationButton)),
|
||||
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,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
),
|
||||
maxLines: 3,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: true,
|
||||
),
|
||||
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(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
@ -476,3 +660,168 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
|
||||
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,
|
||||
builder: (BuildContext context) {
|
||||
return DialogTrialWidget(
|
||||
title: "10 days Premium for free",
|
||||
description: "Would you like to try all premium functions for 10 days, without any subscription or bank card data?",
|
||||
title: t("10 days Premium for free"),
|
||||
description: t("Would you like to try all premium functions for 10 days, without any subscription or bank card data?"),
|
||||
widget: Column(children: [
|
||||
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),
|
||||
),
|
||||
Divider(),
|
||||
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),
|
||||
),
|
||||
]),
|
||||
|
@ -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) {
|
||||
final TutorialBloc bloc = BlocProvider.of<TutorialBloc>(context);
|
||||
if (bloc.action == null) {
|
||||
|
13
pubspec.lock
13
pubspec.lock
@ -707,6 +707,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
mailto:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: mailto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1294,12 +1301,12 @@ packages:
|
||||
source: hosted
|
||||
version: "3.5.1"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.3"
|
||||
version: "6.0.9"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1320,7 +1327,7 @@ packages:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
version: "2.0.4"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -58,6 +58,8 @@ dependencies:
|
||||
upgrader: ^3.5.1
|
||||
web_browser: ^0.5.0
|
||||
flutter_fadein: ^2.0.0
|
||||
mailto: ^2.0.0
|
||||
url_launcher: ^6.0.9
|
||||
|
||||
firebase_core: ^1.5.0
|
||||
firebase_analytics: ^8.1.0
|
||||
@ -280,6 +282,7 @@ flutter:
|
||||
- asset/menu/close_grip_front_lat_pulldown.jpg
|
||||
- asset/menu/close_grip_pull_ups.jpg
|
||||
- asset/menu/close_reverse_grip_lat_pulldown.jpg
|
||||
- asset/menu/close_reverse_grip_pull_ups.jpg
|
||||
- asset/menu/concentration.jpg
|
||||
- asset/menu/cooper.jpg
|
||||
- asset/menu/crisscross.jpg
|
||||
@ -294,6 +297,7 @@ flutter:
|
||||
- asset/menu/donkey_calf_raises.jpg
|
||||
- asset/menu/dumbbell_alternate_bicep_curl.jpg
|
||||
- asset/menu/dumbell_bench_presses.jpg
|
||||
- asset/menu/dumbbell_presses.jpg
|
||||
- asset/menu/ez_bar_burl.jpg
|
||||
- asset/menu/flyes.jpg
|
||||
- asset/menu/forward_raise.jpg
|
||||
@ -358,6 +362,7 @@ flutter:
|
||||
- asset/menu/seated_dumbbell_curl.jpg
|
||||
- asset/menu/seated_dumbbell_shoulder_press.jpg
|
||||
- asset/menu/seated_lateral_raises.jpg
|
||||
- asset/menu/seated_leg_curls.jpg
|
||||
- asset/menu/seated_triceps_extension.jpg
|
||||
- asset/menu/shrugs.jpg
|
||||
- asset/menu/side_plank.jpg
|
||||
@ -372,6 +377,7 @@ flutter:
|
||||
- asset/menu/sizes.jpg
|
||||
- asset/menu/smith_machine_chest_press.jpg
|
||||
- asset/menu/smith_machine_squats.jpg
|
||||
- asset/menu/smith_machine_front_press.jpg
|
||||
- asset/menu/squats_with_kettlebell.jpg
|
||||
- asset/menu/squat_jump_weight.jpg
|
||||
- asset/menu/squat_jump.jpg
|
||||
@ -388,6 +394,7 @@ flutter:
|
||||
- asset/menu/standing_single_arm_lateral_raises.jpg
|
||||
- asset/menu/standing_triceps_extension.jpg
|
||||
- asset/menu/stiff_legged_deadlift.jpg
|
||||
- asset/menu/straight_arm_pulldown.jpg
|
||||
- asset/menu/straight-arm_rope_pull-down.jpg
|
||||
- asset/menu/stretching.jpg
|
||||
- asset/menu/t_bar_rows.jpg
|
||||
|
Loading…
Reference in New Issue
Block a user