diff --git a/android/app/build.gradle b/android/app/build.gradle
index 43a6c8c..35efa81 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -78,7 +78,5 @@ dependencies {
     implementation 'com.google.firebase:firebase-analytics:18.0.0'
     implementation 'com.facebook.android:facebook-login:5.15.3'
     implementation 'com.android.support:multidex:1.0.3'
-    def billing_version = "3.0.0"
-    implementation "com.android.billingclient:billing:$billing_version"
 }
 sourceCompatibility = '1.8'
\ No newline at end of file
diff --git a/i18n/en.json b/i18n/en.json
index 8a8815c..b0a4ce5 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -172,10 +172,10 @@
   "8. Calf": "8. Calf",
 
   "Execute My Selected Training Plan": "Execute My Selected Training Plan",
-  "Edit My Custom Plan": "Edit My Custom Plan",
+  "Edit My Custom Plan": "Create My Custom Plan",
   "Suggested Training Plan": "Suggested Training Plan",
   "My Special Plan": "My Special Plan",
-  "Star's Exercise Plan":"Celeb Exercise Plan",
+  "Training Programs":"Training Programs",
   "My Trainee's Plan": "My Trainee's Plan",
   "Execute My Trainee's Training Plan": "Execute My Trainee's Training Plan",
 
@@ -250,11 +250,15 @@
   "Done": "Done",
   "Height":"Height",
   "Actual Height":"Height",
-  "Actual Weight":"Weight",
-  "Based on your weight and height your goal for BMI and weight:":"Based on your weight and height your goal for BMI and weight:",
+  "Actual Weight":"Bodyweight",
+  "Bodyweight":"Bodyweight",
+  "Based on your weight and height your goal for BMI and weight:":"Based on your bodyweight and height your goal for BMI and weight:",
   "Body Mass Index":"Body Mass Index",
+  "first step":"first step",
+  "goal":"goal",
   "Basal Metabolic Rate":"Basal Metabolic Rate",
-  "Based on your weight, height and activity your BMR value":"Based on your weight, height and activity this is your daily calory demand.",
+  "Resting Metabolic Rate":"Resting Metabolic Rate",
+  "Based on your weight, height and activity your BMR value":"Based on your bodyweight, height and activity this is your daily calory demand.",
   "Your Sizes":"Your Sizes",
   "Size Of Your":"Size Of Your",
   "Please type the following data:":"Please type the following data:",
@@ -303,7 +307,10 @@
 
   "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'",
-  "Jump there »":"Jump there »"
-
+  "Jump there »":"Jump there »",
 
+  "Exception: Purchase was not successful":"Purchase was not successful",
+  "Exception: Purchase was cancelled":"Purchase was cancelled",
+  "Successful Purchase": "Successful Purchase",
+  "Now you can use the premium features of WorkoutTest!":"Now you can use the premium features of WorkoutTest!"
 }
\ No newline at end of file
diff --git a/i18n/hu.json b/i18n/hu.json
index 7ed0c37..688aa77 100644
--- a/i18n/hu.json
+++ b/i18n/hu.json
@@ -169,10 +169,10 @@
   "8. Calf": "8. Vádli",
 
   "Execute My Selected Training Plan": "Edzésterv végrehajtása",
-  "Edit My Custom Plan": "Egyéni edzésterv",
+  "Edit My Custom Plan": "Egyéni edzésterv létrehozása",
   "Suggested Training Plan": "Javasolt edzésterv",
   "My Special Plan": "Speciális edzésterv",
-  "Star's Exercise Plan": "Sztárok edzésterve",
+  "Training Programs":"Edzés programok",
   "My Trainee's Plan" : "Kliensem edzésterve",
   "Execute My Trainee's Training Plan": "Kliensem edzéstervének végrehajtása",
 
@@ -245,11 +245,15 @@
   "Done": "Kész",
   "Height":"Magasság",
   "Actual Height":"Magasság",
-  "Actual Weight":"Tömeg",
-  "Based on your weight and height your goal for BMI and weight:":"A jelenlegi tömeged és magasságod alapján kiszámoltuk, hogy mennyi legyen a célod a BMI (testtömegindex) és tömeg elérésben:",
+  "Actual Weight":"Testtömeg",
+  "Bodyweight":"Testtömeg",
+  "Based on your weight and height your goal for BMI and weight:":"A jelenlegi testtömeged és magasságod alapján kiszámoltuk, hogy mennyi legyen a célod a BMI (testtömegindex) és tömeg elérésben:",
   "Body Mass Index":"Testtömegindex",
+  "first step":"első lépés",
+  "goal":"cél",
   "Basal Metabolic Rate":"Alapanyagcsere érték",
-  "Based on your weight, height and activity your BMR value":"A tömeged, magasságod és aktivitásod alapján megközelítőleg ennyi a napi kalóriaszükségleted.",
+  "Resting Metabolic Rate":"Minimum energiaszükséglet",
+  "Based on your weight, height and activity your BMR value":"A testtömeged, magasságod és aktivitásod alapján megközelítőleg ennyi a napi kalóriaszükségleted.",
   "Your Sizes":"Méreteid",
   "Size Of Your":"Testméret:",
   "Please type the following data:":"Kérlek írd be a következő adatot:",
@@ -299,6 +303,11 @@
 
   "Please define your Exercise Plan":"Kérlek készíts edzéstervet!",
   "Go to: 'Training Plan' - 'Edit My Custom Plan'":"Menj a 'Edzéstervem' - 'Egyéni edzésterv' menübe",
-  "Jump there »":"Vigyél oda »"
+  "Jump there »":"Vigyél oda »",
+
+  "Exception: Purchase was not successful":"A vásárlás sikertelen volt",
+  "Exception: Purchase was cancelled":"A vásárlás megszakadt",
+  "Successful Purchase": "Sikeres vásárlás!",
+  "Now you can use the premium features of WorkoutTest!":"Most már eléred a WorkoutTest prémium tartalmait."
 
 }
\ No newline at end of file
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 3158eba..cae6543 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
 	<key>CFBundleVersion</key>
 	<string>1.0</string>
 	<key>MinimumOSVersion</key>
-	<string>10.0</string>
+	<string>12.0</string>
 </dict>
 </plist>
diff --git a/ios/Podfile b/ios/Podfile
index 1e8c3c9..efd72bd 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
 # Uncomment this line to define a global platform for your project
-# platform :ios, '9.0'
+platform :ios, '9.0'
 
 # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
 ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@@ -37,5 +37,8 @@ end
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     flutter_additional_ios_build_settings(target)
+    target.build_configurations.each do |config|
+      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
+    end
   end
 end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 3b8901b..f4e1035 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -155,6 +155,14 @@ PODS:
     - Flutter
   - PromisesObjC (1.2.11)
   - Protobuf (3.13.0)
+  - Purchases (3.9.2):
+    - PurchasesCoreSwift (= 3.9.2)
+  - purchases_flutter (2.0.0):
+    - Flutter
+    - PurchasesHybridCommon (= 1.5.0)
+  - PurchasesCoreSwift (3.9.2)
+  - PurchasesHybridCommon (1.5.0):
+    - Purchases (= 3.9.2)
   - shared_preferences (0.0.1):
     - Flutter
   - sqflite (0.0.2):
@@ -180,6 +188,7 @@ DEPENDENCIES:
   - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
   - google_sign_in (from `.symlinks/plugins/google_sign_in/ios`)
   - path_provider (from `.symlinks/plugins/path_provider/ios`)
+  - purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
   - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
   - sqflite (from `.symlinks/plugins/sqflite/ios`)
   - video_player (from `.symlinks/plugins/video_player/ios`)
@@ -210,6 +219,9 @@ SPEC REPOS:
     - nanopb
     - PromisesObjC
     - Protobuf
+    - Purchases
+    - PurchasesCoreSwift
+    - PurchasesHybridCommon
 
 EXTERNAL SOURCES:
   apple_sign_in:
@@ -236,6 +248,8 @@ EXTERNAL SOURCES:
     :path: ".symlinks/plugins/google_sign_in/ios"
   path_provider:
     :path: ".symlinks/plugins/path_provider/ios"
+  purchases_flutter:
+    :path: ".symlinks/plugins/purchases_flutter/ios"
   shared_preferences:
     :path: ".symlinks/plugins/shared_preferences/ios"
   sqflite:
@@ -282,12 +296,16 @@ SPEC CHECKSUMS:
   path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
   PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f
   Protobuf: 3dac39b34a08151c6d949560efe3f86134a3f748
+  Purchases: d8a798c9c7552fe66b550bf314a143e94ffa70c8
+  purchases_flutter: 27f87080055c0fd2cd124c247b10cae75b46e7e1
+  PurchasesCoreSwift: ea4eabae180416e580ac60366f41aa1fefec0693
+  PurchasesHybridCommon: d9bfb34309db4c9ba82a6f7f3a6275c13befdca7
   shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
   sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
   video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
   wakelock: bfc7955c418d0db797614075aabbc58a39ab5107
   webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96
 
-PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
+PODFILE CHECKSUM: 28226b39c1afd238c6168e31e2bd3829c3d67530
 
 COCOAPODS: 1.10.0
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 32adb50..b2540af 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -16,6 +16,7 @@
 		BB69292B2521AF45001FBA4C /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BB69292A2521AF45001FBA4C /* Launch Screen.storyboard */; };
 		BB81345024BB4BE10078D9A4 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB81344F24BB4BE10078D9A4 /* GoogleService-Info.plist */; };
 		BB8D3BFA25A8CBFE00BF29FE /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB8D3BF925A8CBFE00BF29FE /* AuthenticationServices.framework */; };
+		BB98CEAF25B8867C000724FE /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BB98CEAE25B8867C000724FE /* StoreKit.framework */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -50,6 +51,7 @@
 		BB69292A2521AF45001FBA4C /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
 		BB81344F24BB4BE10078D9A4 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
 		BB8D3BF925A8CBFE00BF29FE /* AuthenticationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthenticationServices.framework; path = System/Library/Frameworks/AuthenticationServices.framework; sourceTree = SDKROOT; };
+		BB98CEAE25B8867C000724FE /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
 		D5EDDC52125075FB9E21AD35 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
 		F39E6E227EB942E5663A6086 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
@@ -59,6 +61,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				BB98CEAF25B8867C000724FE /* StoreKit.framework in Frameworks */,
 				BB8D3BFA25A8CBFE00BF29FE /* AuthenticationServices.framework in Frameworks */,
 				42B6B159AF35AFB6DE777DFB /* Pods_Runner.framework in Frameworks */,
 			);
@@ -80,6 +83,7 @@
 		3ADC50290ED054951FAC1F56 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				BB98CEAE25B8867C000724FE /* StoreKit.framework */,
 				BB8D3BF925A8CBFE00BF29FE /* AuthenticationServices.framework */,
 				09BD889296C5C90D989820C8 /* Pods_Runner.framework */,
 			);
@@ -384,7 +388,7 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
-				CURRENT_PROJECT_VERSION = 2;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = SFJJBDCU6Z;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -401,7 +405,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/Flutter",
 				);
-				MARKETING_VERSION = 1.1.3;
+				MARKETING_VERSION = 1.1.5;
 				PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -527,7 +531,7 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
-				CURRENT_PROJECT_VERSION = 2;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = SFJJBDCU6Z;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -544,7 +548,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/Flutter",
 				);
-				MARKETING_VERSION = 1.1.3;
+				MARKETING_VERSION = 1.1.5;
 				PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -562,7 +566,7 @@
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
-				CURRENT_PROJECT_VERSION = 2;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = SFJJBDCU6Z;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -579,7 +583,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/Flutter",
 				);
-				MARKETING_VERSION = 1.1.3;
+				MARKETING_VERSION = 1.1.5;
 				PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
diff --git a/lib/bloc/exercise_new/exercise_new_bloc.dart b/lib/bloc/exercise_new/exercise_new_bloc.dart
index 83665aa..608a7b6 100644
--- a/lib/bloc/exercise_new/exercise_new_bloc.dart
+++ b/lib/bloc/exercise_new/exercise_new_bloc.dart
@@ -31,11 +31,15 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
   double bmr = 0;
   double goalBMI = 0;
   double goalWeight = 0;
+  double goalMilestoneBMI = 0;
+  double goalMilestoneWeight = 0;
   double bmiAngle = 0;
   double bmiTop = 0;
   double bmiLeft = 0;
   double weight;
   double height;
+  double bmrEnergy = 0;
+  int birthYear;
   String fitnessLevel;
   bool changedWeight = false;
   bool changedSizes = false;
@@ -66,6 +70,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
       customerRepository.customer = Cache().userLoggedIn;
       weight = customerRepository.customer.getProperty("Weight");
       height = customerRepository.customer.getProperty("Height");
+      birthYear = customerRepository.customer.birthYear;
       fitnessLevel = customerRepository.customer.fitnessLevel;
       this.isMan = (customerRepository.customer.sex == "m");
     }
@@ -315,6 +320,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
         changedWeight = true;
         weight = event.value;
         getBMI();
+        getGoalBMI();
         getBMR();
         yield ExerciseNewReady();
       } else if (event is ExerciseNewFitnessLevelChange) {
@@ -324,12 +330,20 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
         changedWeight = true;
         getBMR();
         yield ExerciseNewReady();
+      } else if (event is ExerciseNewBirthyearChange) {
+        yield ExerciseNewLoading();
+        changedWeight = true;
+        customerRepository.setBirthYear(event.value.toInt());
+        birthYear = event.value;
+        getBMR();
+        yield ExerciseNewReady();
       } else if (event is ExerciseNewHeightChange) {
         yield ExerciseNewLoading();
         customerRepository.setHeight(event.value.toInt());
         changedWeight = true;
         height = event.value;
         getBMI();
+        getGoalBMI();
         getBMR();
         yield ExerciseNewReady();
       } else if (event is ExerciseNewSaveWeight) {
@@ -390,6 +404,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
       //BMR = 655.1 + ( 9.563 × ömeg kg-ban ) + ( 1.85 × magasság cm-ben) − ( 4.676 × életkor évben kifejezve )
       bmr = 655.1 + (9.563 * weight) + (1.85 * height) - (4.676 * (year - customerRepository.customer.birthYear));
     }
+    bmrEnergy = bmr;
 
     if (customerRepository.customer.fitnessLevel == FitnessState.beginner) {
       bmr *= 1.2;
@@ -424,32 +439,38 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
 
     this.bmiAngle = (bmi * 90 / 25) - 90;
     if (bmi < 18.5) {
-      goalBMI = 19;
+      goalMilestoneBMI = 19;
+      goalBMI = 21.75;
       this.bmiTop = 99 * distortionHeight;
       this.bmiLeft = 77 * distortionWidth;
       bmiAngle = -62;
     } else if (bmi > 18.5 && bmi < 25) {
-      goalBMI = this.bmi;
+      goalBMI = 21.75;
+      goalMilestoneBMI = 21.75;
       this.bmiTop = 48 * distortionHeight;
       this.bmiLeft = 130 * distortionWidth;
       bmiAngle = -23;
     } else if (bmi < 30 && bmi > 24.9) {
-      goalBMI = 24;
+      goalMilestoneBMI = 24;
+      goalBMI = 21.75;
       this.bmiTop = 40.0 * distortionHeight;
       this.bmiLeft = 184.0 * distortionWidth;
       bmiAngle = 7.2;
     } else if (bmi < 34.9 && 29.9 < bmi) {
-      goalBMI = 29;
+      goalMilestoneBMI = 29;
+      goalBMI = 24;
       bmiTop = 48 * distortionHeight;
       bmiLeft = 211 * distortionWidth;
     } else if (bmi > 35) {
-      goalBMI = 34;
+      goalMilestoneBMI = 34;
+      goalBMI = 24;
       bmiTop = 94 * distortionHeight;
       bmiLeft = 260 * distortionWidth;
       bmiAngle = 59;
     }
 
     this.goalWeight = goalBMI * (height * height / 10000);
+    this.goalMilestoneWeight = goalMilestoneBMI * (height * height / 10000);
 
     //print("Angle: " + bmiAngle.toStringAsFixed(1));
 
diff --git a/lib/bloc/exercise_new/exercise_new_event.dart b/lib/bloc/exercise_new/exercise_new_event.dart
index 15013c3..bdb01cf 100644
--- a/lib/bloc/exercise_new/exercise_new_event.dart
+++ b/lib/bloc/exercise_new/exercise_new_event.dart
@@ -28,6 +28,13 @@ class ExerciseNewQuantityUnitChange extends ExerciseNewEvent {
   List<Object> get props => [quantity];
 }
 
+class ExerciseNewBirthyearChange extends ExerciseNewEvent {
+  final int value;
+  const ExerciseNewBirthyearChange({this.value});
+  @override
+  List<Object> get props => [value];
+}
+
 class ExerciseNewWeightChange extends ExerciseNewEvent {
   final double value;
   const ExerciseNewWeightChange({this.value});
diff --git a/lib/bloc/exercise_plan/exercise_plan_bloc.dart b/lib/bloc/exercise_plan/exercise_plan_bloc.dart
index 9e8694e..817b83b 100644
--- a/lib/bloc/exercise_plan/exercise_plan_bloc.dart
+++ b/lib/bloc/exercise_plan/exercise_plan_bloc.dart
@@ -7,7 +7,6 @@ import 'package:aitrainer_app/repository/workout_tree_repository.dart';
 import 'package:bloc/bloc.dart';
 import 'package:equatable/equatable.dart';
 import 'package:flurry/flurry.dart';
-import 'package:flurry/flurry.dart';
 import 'package:meta/meta.dart';
 
 part 'exercise_plan_event.dart';
diff --git a/lib/bloc/menu/menu_bloc.dart b/lib/bloc/menu/menu_bloc.dart
index bd17683..63f8f06 100644
--- a/lib/bloc/menu/menu_bloc.dart
+++ b/lib/bloc/menu/menu_bloc.dart
@@ -164,7 +164,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
         ability = ExerciseAbility.endurance;
         break;
       case "Cardio":
-      case "Body Compositions":
+      case "My Body":
         ability = ExerciseAbility.none;
         break;
     }
diff --git a/lib/bloc/result/result_bloc.dart b/lib/bloc/result/result_bloc.dart
index 913fc49..a5643d0 100644
--- a/lib/bloc/result/result_bloc.dart
+++ b/lib/bloc/result/result_bloc.dart
@@ -1,6 +1,5 @@
 import 'dart:async';
 
-import 'package:aitrainer_app/model/cache.dart';
 import 'package:aitrainer_app/model/result.dart';
 import 'package:aitrainer_app/repository/exercise_repository.dart';
 import 'package:aitrainer_app/repository/exercise_result_repository.dart';
@@ -38,6 +37,10 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
   ResultBloc({this.resultRepository, this.exerciseRepository, this.context}) : super(ResultInitial()) {
     this.startTime = exerciseRepository.start;
     this.endTime = exerciseRepository.end;
+    if (this.startTime == null) {
+      this.startTime = exerciseRepository.exercise.dateAdd;
+      exerciseRepository.start = exerciseRepository.exercise.dateAdd;
+    }
   }
 
   @override
diff --git a/lib/bloc/sales/sales_bloc.dart b/lib/bloc/sales/sales_bloc.dart
index df069d8..9de73e3 100644
--- a/lib/bloc/sales/sales_bloc.dart
+++ b/lib/bloc/sales/sales_bloc.dart
@@ -1,16 +1,19 @@
 import 'dart:async';
 import 'dart:io';
-import 'dart:math';
+import 'dart:math' as math;
 
 import 'package:aitrainer_app/model/cache.dart';
 import 'package:aitrainer_app/model/product.dart';
 import 'package:aitrainer_app/model/product_test.dart';
+import 'package:aitrainer_app/model/purchase.dart';
 import 'package:aitrainer_app/service/logging.dart';
-import 'package:aitrainer_app/service/product_test_service.dart';
-import 'package:aitrainer_app/util/platform_purchase.dart';
+import 'package:aitrainer_app/service/purchase.dart';
+import 'package:aitrainer_app/util/common.dart';
+import 'package:aitrainer_app/util/purchases.dart';
 import 'package:bloc/bloc.dart';
 import 'package:equatable/equatable.dart';
 import 'package:flurry/flurry.dart';
+import 'package:purchases_flutter/offering_wrapper.dart';
 
 part 'sales_event.dart';
 part 'sales_state.dart';
@@ -28,15 +31,34 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
     try {
       if (event is SalesLoad) {
         yield SalesLoading();
-        //Flurry.logEvent("SalesPageOpen");
-        // await PlatformPurchaseApi().initPurchasePlatformState();
-        //  this.getProductSet();
+        log("Load Sales");
+        Common.sendMessage("Salespage Load");
+        Flurry.logEvent("SalesPageOpen");
+        //await PlatformPurchaseApi().initPurchasePlatform();
+        await RevenueCatPurchases().getOfferings();
+        this.getProductSet();
         yield SalesReady();
       } else if (event is SalesPurchase) {
+        if (Cache().hasPurchased) {
+          throw Exception("You have already a successfull subscription");
+        }
+        yield SalesLoading();
         final int productId = event.productId;
-        trace("Requesting purchase for" + productId.toString());
-        //Flurry.logEvent("PurchaseRequest");
-        // PlatformPurchaseApi().purchase(getSelectedProduct(productId));
+        log("Requesting purchase for: " + productId.toString());
+        Flurry.logEvent("PurchaseRequest");
+        final Product selectedProduct = this.getSelectedProduct(productId);
+        log("SelectedProduct for purchase " + selectedProduct.toString());
+        await RevenueCatPurchases().makePurchase(selectedProduct);
+        if (Cache().hasPurchased) {
+          Purchase purchase = Purchase(customerId: Cache().userLoggedIn.customerId, productId: productId);
+          purchase.dateAdd = DateTime.now();
+          purchase.purchaseSum = 0;
+          purchase.currency = "EUR";
+          await PurchaseApi().savePurchase(purchase);
+          Flurry.logEvent("PurchaseSuccessful");
+          Common.sendMessage("Purchase: " + purchase.toJson().toString());
+        }
+        yield SalesSuccessful();
       }
     } on Exception catch (ex) {
       yield SalesError(message: ex.toString());
@@ -53,18 +75,24 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
     return prod;
   }
 
-  /*  String getLocalizedPrice(String productId) {
+  String getLocalizedPrice(String productId) {
     String price = "";
-    for (var product in PlatformPurchaseApi().getIAPItems()) {
-      if (Platform.isAndroid) {
-        print("PlatformProduct " + product.toString());
-        if (productId == product.productId) {
-          price = product.localizedPrice;
+    Offering offering = RevenueCatPurchases().offering;
+    if (offering != null) {
+      for (var package in offering.availablePackages) {
+        log("PlatformProduct " + package.toString());
+        if (productId == package.product.identifier) {
+          price = package.product.priceString;
+          if (price.contains(r'HUF')) {
+            price = price.replaceAll(RegExp(r'HUF'), 'Ft');
+            price = price.replaceAll(RegExp(r',00'), "");
+          }
           break;
         }
       }
+    } else {
+      log(" !!! No Offering");
     }
-
     return price;
   }
 
@@ -73,7 +101,7 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
     this.tests = Cache().productTests;
 
     if (tests.isEmpty) {
-      var rand = Random.secure();
+      var rand = math.Random.secure();
       productSet = rand.nextInt(5) + 1;
     } else {
       trace("Previous ProductTest: " + tests[0].toJson().toString());
@@ -88,7 +116,9 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
     }
 
     ProductTest productTest = ProductTest();
-    trace("ProductSet: " + productSet.toString());
+
+    productSet = 2;
+    log("ProductSet: " + productSet.toString());
     for (var elem in Cache().products) {
       Product product = elem as Product;
 
@@ -109,5 +139,5 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
     productTest.dateView = DateTime.now();
     //ProductTestApi().saveProductTest(productTest);
     //Cache().productTests.add(productTest);
-  } */
+  }
 }
diff --git a/lib/bloc/sales/sales_state.dart b/lib/bloc/sales/sales_state.dart
index e6391b7..3cc5c09 100644
--- a/lib/bloc/sales/sales_state.dart
+++ b/lib/bloc/sales/sales_state.dart
@@ -19,6 +19,10 @@ class SalesReady extends SalesState {
   const SalesReady();
 }
 
+class SalesSuccessful extends SalesState {
+  const SalesSuccessful();
+}
+
 class SalesError extends SalesState {
   final String message;
   const SalesError({this.message});
diff --git a/lib/bloc/session/session_bloc.dart b/lib/bloc/session/session_bloc.dart
index 57bac26..fca4dac 100644
--- a/lib/bloc/session/session_bloc.dart
+++ b/lib/bloc/session/session_bloc.dart
@@ -3,7 +3,6 @@ import 'dart:async';
 import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
 import 'package:aitrainer_app/localization/app_language.dart';
 import 'package:aitrainer_app/service/logging.dart';
-import 'package:aitrainer_app/util/platform_purchase.dart';
 import 'package:aitrainer_app/util/session.dart';
 import 'package:bloc/bloc.dart';
 import 'package:equatable/equatable.dart';
diff --git a/lib/bloc/settings/settings_bloc.dart b/lib/bloc/settings/settings_bloc.dart
index 7f2d6a5..3215ff6 100644
--- a/lib/bloc/settings/settings_bloc.dart
+++ b/lib/bloc/settings/settings_bloc.dart
@@ -74,7 +74,7 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
       HealthDataType.RESTING_HEART_RATE
     ];
     final HealthFactory health = HealthFactory(); */
-    DateTime now = DateTime.now();
+    //DateTime now = DateTime.now();
     //List<HealthDataPoint> _healthDataList = await health.getHealthDataFromTypes(now.subtract(Duration(minutes: 5)), now, types);
     //log(_healthDataList.toString());
   }
diff --git a/lib/main.dart b/lib/main.dart
index 43a2c73..4c9ac16 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -52,7 +52,7 @@ import 'bloc/menu/menu_bloc.dart';
 import 'bloc/session/session_bloc.dart';
 import 'bloc/settings/settings_bloc.dart';
 
-final SentryClient _sentry = new SentryClient(dsn: 'https://5fac40cbfcfb4c15aa80c7a8638d7310@o418565.ingest.sentry.io/5322520');
+const dsn = 'https://5fac40cbfcfb4c15aa80c7a8638d7310@o418565.ingest.sentry.io/5322520';
 
 /// Whether the VM is running in debug mode.
 ///
@@ -80,16 +80,12 @@ Future<Null> _reportError(dynamic error, dynamic stackTrace) async {
 
   print('Reporting to Sentry.io...');
 
-  final SentryResponse response = await _sentry.captureException(
-    exception: error,
+  final sentryId = await Sentry.captureException(
+    error,
     stackTrace: stackTrace,
   );
 
-  if (response.isSuccessful) {
-    print('Success! Event ID: ${response.eventId}');
-  } else {
-    print('Failed to report to Sentry.io: ${response.error}');
-  }
+  print('Capture exception result : SentryId : $sentryId');
 }
 
 Future<Null> main() async {
@@ -119,8 +115,10 @@ Future<Null> main() async {
   runZonedGuarded<Future<Null>>(() async {
     final WorkoutTreeRepository menuTreeRepository = WorkoutTreeRepository();
     WidgetsFlutterBinding.ensureInitialized();
+
     print(" -- FireBase init..");
     await FirebaseApi().initializeFlutterFire();
+
     runApp(MultiBlocProvider(
       providers: [
         BlocProvider<SessionBloc>(
@@ -157,8 +155,6 @@ Future<Null> main() async {
 
 Future<void> initFlurry() async {
   await Flurry.initialize(androidKey: "JNYCTCWBT34FM3J8TV36", iosKey: "3QBG7BSMGPDH24S8TRQP", enableLog: true);
-  //await Flurry.setUserId("userId");
-  //await Flurry.logEvent("eventName");
 }
 
 class WorkoutTestApp extends StatelessWidget {
@@ -232,7 +228,7 @@ class WorkoutTestApp extends StatelessWidget {
           //primarySwatch: Colors.transparent,
           //fontFamily: 'Arial',
           textTheme: TextTheme(
-            bodyText1: GoogleFonts.openSans(textStyle: TextStyle(fontSize: 14.0)),
+            bodyText1: GoogleFonts.inter(textStyle: TextStyle(fontSize: 14.0)),
           )),
       navigatorObservers: [
         FirebaseAnalyticsObserver(analytics: analytics),
diff --git a/lib/model/cache.dart b/lib/model/cache.dart
index 6987ce3..0ae3570 100644
--- a/lib/model/cache.dart
+++ b/lib/model/cache.dart
@@ -5,7 +5,7 @@ import 'package:aitrainer_app/model/exercise_plan_detail.dart';
 import 'package:aitrainer_app/model/exercise_tree.dart';
 import 'package:aitrainer_app/model/exercise.dart';
 import 'package:aitrainer_app/model/model_change.dart';
-import 'package:aitrainer_app/model/product.dart';
+import 'package:aitrainer_app/model/product.dart' as wt_product;
 import 'package:aitrainer_app/model/product_test.dart';
 import 'package:aitrainer_app/model/property.dart';
 import 'package:aitrainer_app/model/purchase.dart';
@@ -84,7 +84,7 @@ class Cache with Logging {
   List<Exercise> _exercises;
   ExercisePlan _myExercisePlan;
   List<Property> _properties;
-  List<Product> _products;
+  List<wt_product.Product> _products;
   List<Purchase> _purchases = List();
   List<ProductTest> _productTests;
 
@@ -405,18 +405,18 @@ class Cache with Logging {
         setBadge("Sizes", true);
         setBadge("BMI", true);
         setBadge("BMR", true);
-        setBadgeNr("Body Compositions", 3);
+        setBadgeNr("My Body", 3);
         setBadgeNr("home", 3);
       } else if (customerRepository.getWeight() == 0) {
         setBadge("BMI", true);
         setBadge("BMR", true);
-        setBadge("Body Compositions", true);
+        setBadge("My Body", true);
         setBadgeNr("home", 1);
       }
       if (customerRepository.getHeight() == 0) {
         setBadge("BMI", true);
         setBadge("BMR", true);
-        setBadge("Body Compositions", true);
+        setBadge("My Body", true);
         setBadgeNr("home", 1);
       }
     }
@@ -450,7 +450,7 @@ class Cache with Logging {
     await customerRepository.getPurchase();
     await customerRepository.getProductTests();
 
-    this.hasPurchased = this._purchases.isNotEmpty;
+    //this.hasPurchased = this._purchases.isNotEmpty;
     Cache().startPage = "home";
   }
 
diff --git a/lib/model/exercise_type.dart b/lib/model/exercise_type.dart
index 5af9122..0176011 100644
--- a/lib/model/exercise_type.dart
+++ b/lib/model/exercise_type.dart
@@ -55,7 +55,6 @@ class ExerciseType {
         this.parents.add(parent['exerciseTreeId']);
       });
     }
-    ;
   }
 
   Map<String, dynamic> toJson() => {
diff --git a/lib/model/purchase.dart b/lib/model/purchase.dart
index d68cbbe..8307d72 100644
--- a/lib/model/purchase.dart
+++ b/lib/model/purchase.dart
@@ -9,6 +9,8 @@ class Purchase {
   double purchaseSum;
   String currency;
 
+  Purchase({this.customerId, this.productId});
+
   Purchase.fromJson(Map json) {
     this.purchaseId = json['purchaseId'];
     this.customerId = json['customerId'];
diff --git a/lib/repository/customer_repository.dart b/lib/repository/customer_repository.dart
index 87349f7..3df20b9 100644
--- a/lib/repository/customer_repository.dart
+++ b/lib/repository/customer_repository.dart
@@ -270,7 +270,7 @@ class CustomerRepository with Logging {
     try {
       int customerId = Cache().userLoggedIn.customerId;
       tests = await ProductTestApi().getProductTestByCustomer(customerId);
-    } on NotFoundException catch (ex) {
+    } on NotFoundException catch (_) {
       log("Product Tests not found");
       Cache().productTests = tests;
     } on Exception catch (ex) {
diff --git a/lib/repository/exercise_repository.dart b/lib/repository/exercise_repository.dart
index 1c88557..38e2359 100644
--- a/lib/repository/exercise_repository.dart
+++ b/lib/repository/exercise_repository.dart
@@ -259,6 +259,17 @@ class ExerciseRepository {
     return actualExerciseType;
   }
 
+  void getSameExercise(int exerciseTypeId, String day) {
+    this.actualExerciseList = List();
+    for (int i = 0; i < this.exerciseList.length; i++) {
+      Exercise exercise = exerciseList[i];
+      String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd);
+      if (exerciseTypeId == exercise.exerciseTypeId && exerciseDate == day) {
+        this.actualExerciseList.add(exercise);
+      }
+    }
+  }
+
   void sortByDate() {
     if (exerciseList.isEmpty) {
       return;
diff --git a/lib/repository/exercise_result_repository.dart b/lib/repository/exercise_result_repository.dart
index 2b5af13..648189b 100644
--- a/lib/repository/exercise_result_repository.dart
+++ b/lib/repository/exercise_result_repository.dart
@@ -1,7 +1,6 @@
 import 'package:aitrainer_app/model/cache.dart';
 import 'package:aitrainer_app/model/exercise_result.dart';
 import 'package:aitrainer_app/model/result.dart';
-import 'package:aitrainer_app/service/exercise_result_service.dart';
 
 enum ResultType { running, man, woman, none }
 
diff --git a/lib/repository/user_repository.dart b/lib/repository/user_repository.dart
index c54381a..1506f19 100644
--- a/lib/repository/user_repository.dart
+++ b/lib/repository/user_repository.dart
@@ -59,6 +59,11 @@ class UserRepository with Logging {
       if (e.code == 'email-already-in-use') {
         log('The account already exists for that email.');
         throw Exception("The email address has been registered already");
+      } else if (e.code == 'weak-password') {
+        log('The password provided is too weak.');
+        throw Exception("Password too short");
+      } else {
+        throw Exception(e);
       }
     } on WorkoutTestException catch (ex) {
       if (ex.code == WorkoutTestException.CUSTOMER_EXISTS) {
@@ -66,8 +71,8 @@ class UserRepository with Logging {
         throw Exception("The email address has been registered already");
       }
     } on Exception catch (ex) {
-      log("Google exception: " + ex.toString());
-      throw Exception("Google Sign In failed");
+      log("FB exception: " + ex.toString());
+      throw Exception("Facebook Sign In failed");
     }
   }
 
@@ -90,6 +95,8 @@ class UserRepository with Logging {
       if (e.code == 'email-already-in-use') {
         log('The account already exists for that email.');
         throw Exception("The email address has been registered already");
+      } else {
+        throw Exception(e);
       }
     } on WorkoutTestException catch (ex) {
       if (ex.code == WorkoutTestException.CUSTOMER_EXISTS) {
@@ -167,17 +174,18 @@ class UserRepository with Logging {
 
   Future<void> getUserByGoogle() async {
     final User modelUser = this.user;
-    Map<String, dynamic> userData = await FirebaseApi().signInWithGoogle();
-    if (userData == null || userData['email'] == null) {
-      throw new Exception("Google login was not successful");
-    }
-    modelUser.email = userData['email'];
     try {
+      Map<String, dynamic> userData = await FirebaseApi().signInWithGoogle();
+      if (userData == null || userData['email'] == null) {
+        throw new Exception("Google login was not successful");
+      }
+      modelUser.email = userData['email'];
+
       await CustomerApi().getUserByEmail(modelUser.email);
       await Cache().afterFirebaseLogin();
     } on Exception catch (ex) {
       log("Google exception: " + ex.toString());
-      throw Exception("Customer does not exist or the password is wrong");
+      throw Exception(ex);
     }
   }
 
diff --git a/lib/repository/workout_tree_repository.dart b/lib/repository/workout_tree_repository.dart
index 28c2e0a..36b1c17 100644
--- a/lib/repository/workout_tree_repository.dart
+++ b/lib/repository/workout_tree_repository.dart
@@ -10,7 +10,6 @@ import 'package:aitrainer_app/service/exercise_tree_service.dart';
 import 'package:aitrainer_app/service/exercisetype_service.dart';
 import 'package:aitrainer_app/service/logging.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
 
 class Antagonist {
   static String chest = "Chest";
@@ -48,7 +47,7 @@ class WorkoutTreeRepository with Logging {
     Antagonist.calf: Antagonist.calfNr
   };
 
-  Future<String> _buildImage(String imageUrl) async {
+  /* Future<String> _buildImage(String imageUrl) async {
     String assetImage = 'asset/menu/' + imageUrl.substring(7);
     //print("Loading image " + assetImage);
     return rootBundle.load(assetImage).then((value) {
@@ -59,7 +58,7 @@ class WorkoutTreeRepository with Logging {
       //print("Exception: " + assetImage + " will be loaded from the network " + url);
       return url;
     });
-  }
+  } */
 
   Future<void> createTree() async {
     isEnglish = AppLanguage().appLocal == Locale('en');
diff --git a/lib/service/customer_exercise_device_service.dart b/lib/service/customer_exercise_device_service.dart
index 71022be..8e9f61b 100644
--- a/lib/service/customer_exercise_device_service.dart
+++ b/lib/service/customer_exercise_device_service.dart
@@ -15,7 +15,7 @@ class CustomerExerciseDeviceApi with Logging {
       final body = await _client.get("customer_exercise_device/customer/" + customerId.toString(), "");
       final Iterable json = jsonDecode(body);
       devices = json.map((device) => CustomerExerciseDevice.fromJson(device)).toList();
-    } on NotFoundException catch (e) {
+    } on NotFoundException catch (_) {
       log("No devices found");
     }
     return devices;
diff --git a/lib/service/firebase_api.dart b/lib/service/firebase_api.dart
index 42f7466..53b6243 100644
--- a/lib/service/firebase_api.dart
+++ b/lib/service/firebase_api.dart
@@ -165,41 +165,37 @@ class FirebaseApi with logging.Logging {
   Future<Map<String, dynamic>> signInWithGoogle() async {
     Map<String, dynamic> userData = Map();
 
-    try {
-      // Trigger the authentication flow
-      GoogleSignIn _googleSignIn = GoogleSignIn(
-        scopes: [
-          'email',
-          'https://www.googleapis.com/auth/contacts.readonly',
-        ],
-      );
-      final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
+    // Trigger the authentication flow
+    GoogleSignIn _googleSignIn = GoogleSignIn(
+      scopes: [
+        'email',
+        'https://www.googleapis.com/auth/contacts.readonly',
+      ],
+    );
+    final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
 
-      if (googleUser == null) {
-        throw Exception("Google Sign In failed");
-      }
-
-      // Obtain the auth details from the request
-      final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
-
-      // Create a new credential
-      final GoogleAuthCredential credential = GoogleAuthProvider.credential(
-        accessToken: googleAuth.accessToken,
-        idToken: googleAuth.idToken,
-      );
-
-      await FirebaseAuth.instance.signInWithCredential(credential);
-
-      if (googleUser != null) {
-        log("GoogleUser: " + googleUser.toString());
-        userData['email'] = googleUser.email;
-        userData['id'] = googleUser.id;
-        userData['name'] = googleUser.displayName;
-      }
-    } on Exception catch (ex) {
-      log("Google exception: " + ex.toString());
+    if (googleUser == null) {
       throw Exception("Google Sign In failed");
     }
+
+    // Obtain the auth details from the request
+    final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
+
+    // Create a new credential
+    final GoogleAuthCredential credential = GoogleAuthProvider.credential(
+      accessToken: googleAuth.accessToken,
+      idToken: googleAuth.idToken,
+    );
+
+    await FirebaseAuth.instance.signInWithCredential(credential);
+
+    if (googleUser != null) {
+      log("GoogleUser: " + googleUser.toString());
+      userData['email'] = googleUser.email;
+      userData['id'] = googleUser.id;
+      userData['name'] = googleUser.displayName;
+    }
+
     return userData;
   }
 
@@ -266,15 +262,16 @@ class FirebaseApi with logging.Logging {
       Cache().accessTokenFacebook = accessToken;
       // get the user data
       userData = await FacebookAuth.instance.getUserData();
+      log("FB user data: " + userData.toString());
 
       // Create a credential from the access token
       final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(accessToken.token);
 
       // Once signed in, return the UserCredential
       final userCredential = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
+      log("Email by FB: " + userData['email'] + " FB credential: " + userCredential.toString());
 
       Cache().firebaseUid = userCredential.user.uid;
-      log(userData.toString());
     } else {
       throw Exception("Facebook login was not successful");
     }
diff --git a/lib/service/purchase.dart b/lib/service/purchase.dart
index 594947a..ecb1953 100644
--- a/lib/service/purchase.dart
+++ b/lib/service/purchase.dart
@@ -15,7 +15,7 @@ class PurchaseApi with Logging {
       final Iterable json = jsonDecode(body);
       final List<Purchase> purchases = json.map((purchase) => Purchase.fromJson(purchase)).toList();
       Cache().setPurchases(purchases);
-    } on NotFoundException catch (e) {
+    } on NotFoundException catch (_) {
       log("No purchases found");
     }
     return purchases;
diff --git a/lib/util/common.dart b/lib/util/common.dart
index 6ffbd21..1d72988 100644
--- a/lib/util/common.dart
+++ b/lib/util/common.dart
@@ -8,6 +8,7 @@ import 'package:badges/badges.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:intl/intl.dart';
+import 'package:sentry/sentry.dart';
 
 class DateRate {
   static String daily = "daily";
@@ -130,4 +131,13 @@ mixin Common {
       ),
     );
   }
+
+  static Future<void> sendMessage(String message) async {
+    // Sends a full Sentry event payload to show the different parts of the UI.
+    await Sentry.captureMessage(
+      message,
+      level: SentryLevel.info,
+      template: 'Message: %s, customerId: ' + Cache().userLoggedIn.customerId.toString(),
+    );
+  }
 }
diff --git a/lib/util/platform_purchase.dart b/lib/util/platform_purchase.dart
index a0f7df8..a183e98 100644
--- a/lib/util/platform_purchase.dart
+++ b/lib/util/platform_purchase.dart
@@ -1,28 +1,29 @@
-import 'dart:async';
-import 'dart:io';
 /* 
 import 'package:aitrainer_app/model/cache.dart';
 import 'package:aitrainer_app/model/product.dart';
 import 'package:aitrainer_app/service/logging.dart';
-import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';
+import 'package:in_app_purchase/in_app_purchase.dart';
 
 class PlatformPurchaseApi with Logging {
   static final PlatformPurchaseApi _singleton = PlatformPurchaseApi._internal();
 
-  StreamSubscription _purchaseUpdatedSubscription;
-  StreamSubscription _purchaseErrorSubscription;
-  StreamSubscription _conectionSubscription;
-  String _platformVersion = 'Unknown';
-  List<IAPItem> _items = [];
-  List getIAPItems() => _items;
-  List<PurchasedItem> _purchases = [];
+  bool _kAutoConsume = true;
+  final String _kConsumableId = 'consumable';
+  final InAppPurchaseConnection _connection = InAppPurchaseConnection.instance;
+  bool _isAvailable = false;
+  List<ProductDetails> _products = [];
+  List<PurchaseDetails> _purchases = [];
+  List<String> _notFoundIds = [];
+  List<String> _consumables = [];
+  bool _purchasePending = false;
+  String _queryProductError;
+
+  StreamSubscription<List<PurchaseDetails>> _subscription;
 
   final List<String> _productList = List();
 
   List getProductList() => _productList;
 
- 
-
   factory PlatformPurchaseApi() {
     return _singleton;
   }
@@ -30,55 +31,152 @@ class PlatformPurchaseApi with Logging {
   PlatformPurchaseApi._internal();
 
   Future<void> close() async {
-    if (_conectionSubscription != null) {
-      _conectionSubscription.cancel();
-      _conectionSubscription = null;
+    _subscription.cancel();
+  }
+
+  Future<void> initStoreInfo() async {
+    final bool isAvailable = await _connection.isAvailable();
+    if (!isAvailable) {
+      _isAvailable = isAvailable;
+      _products = [];
+      _purchases = [];
+      _notFoundIds = [];
+      _consumables = [];
+      _purchasePending = false;
+      log("Payment processor not available");
+      return;
     }
-    await FlutterInappPurchase.instance.endConnection;
+
+    getSubscriptions();
+    ProductDetailsResponse productDetailResponse = await _connection.queryProductDetails(_productList.toSet());
+    log("ProductDetailsResponse " + productDetailResponse.toString());
+    if (productDetailResponse.error != null) {
+      _queryProductError = productDetailResponse.error.message;
+      _isAvailable = isAvailable;
+      _products = productDetailResponse.productDetails;
+      _purchases = [];
+      _notFoundIds = productDetailResponse.notFoundIDs;
+      _consumables = [];
+      _purchasePending = false;
+      log("Payment processor not available");
+      return;
+    }
+
+    if (productDetailResponse.productDetails.isEmpty) {
+      _queryProductError = null;
+      _isAvailable = isAvailable;
+      _products = productDetailResponse.productDetails;
+      _purchases = [];
+      _notFoundIds = productDetailResponse.notFoundIDs;
+      _consumables = [];
+      _purchasePending = false;
+
+      return;
+    }
+
+    _products = productDetailResponse.productDetails;
+    _products.forEach((element) {
+      ProductDetails product = element as ProductDetails;
+      log("Product " + product.id + " " + product.price + " " + product.skuDetail.toString());
+    });
+
+    final QueryPurchaseDetailsResponse purchaseResponse = await _connection.queryPastPurchases();
+    if (purchaseResponse.error != null) {
+      // handle query past purchase error..
+    }
+
+    final List<PurchaseDetails> verifiedPurchases = [];
+    for (PurchaseDetails purchase in purchaseResponse.pastPurchases) {
+      if (await _verifyPurchase(purchase)) {
+        verifiedPurchases.add(purchase);
+      }
+    }
+
+    //TODO List<String> consumables = await ConsumableStore.load();
+    _isAvailable = isAvailable;
+    _products = productDetailResponse.productDetails;
+    _purchases = verifiedPurchases;
+    _notFoundIds = productDetailResponse.notFoundIDs;
+    //_consumables = consumables;
+    _purchasePending = false;
   }
 
   // Platform messages are asynchronous, so we initialize in an async method.
-  Future<void> initPurchasePlatformState() async {
+  Future<void> initPurchasePlatform() async {
     if (_productList.length > 0) {
       return;
     }
+    log(' --- InappPurchase connection: $_connection');
     log(" --- Init PurchasePlatform");
-    String platformVersion;
-    // Platform messages may fail, so we use a try/catch PlatformException.
-    try {
-      platformVersion = await FlutterInappPurchase.instance.platformVersion;
-    } on Exception {
-      platformVersion = 'Failed to get platform version for InAppPurchase.';
-      log("PlatformVersion" + platformVersion);
+    await this.initStoreInfo();
+
+    Stream purchaseUpdated = InAppPurchaseConnection.instance.purchaseUpdatedStream;
+    _subscription = purchaseUpdated.listen((purchaseDetailsList) {
+      _listenToPurchaseUpdated(purchaseDetailsList);
+    }, onDone: () {
+      _subscription.cancel();
+    }, onError: (error) {
+      // handle error here.
+      log("Error listen purchase updated " + error.toString());
+    });
+  }
+
+  void deliverProduct(PurchaseDetails purchaseDetails) async {
+    log("DeliverProduct");
+    // IMPORTANT!! Always verify a purchase purchase details before delivering the product.
+    if (purchaseDetails.productID == _kConsumableId) {
+      //TODO
+      //await ConsumableStore.save(purchaseDetails.purchaseID);
+      //List<String> consumables = await ConsumableStore.load();
+
+      _purchasePending = false;
+      //_consumables = consumables;
+    } else {
+      _purchases.add(purchaseDetails);
+      _purchasePending = false;
     }
+  }
 
-    // prepare
-    var result = await FlutterInappPurchase.instance.initConnection;
-    log(' FlutterInappPurchase init result: $result');
+  Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) {
+    log("verifyPurchase");
+    // IMPORTANT!! Always verify a purchase before delivering the product.
+    // For the purpose of an example, we directly return true.
+    log("Verifying Purchase" + purchaseDetails.toString());
+    return Future<bool>.value(true);
+  }
 
-    _platformVersion = platformVersion;
+  void _handleInvalidPurchase(PurchaseDetails purchaseDetails) {
+    // handle invalid purchase here if  _verifyPurchase` failed.
+    log("Invalid Purchase" + purchaseDetails.toString());
+  }
 
-    // refresh items for android
-    try {
-      String msg = await FlutterInappPurchase.instance.consumeAllItems;
-      log('consumeAllItems: $msg');
-    } catch (err) {
-      log('consumeAllItems error: $err');
-    }
-
-    _conectionSubscription = FlutterInappPurchase.connectionUpdated.listen((connected) {
-      log('connected: $connected');
+  void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
+    purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
+      if (purchaseDetails.status == PurchaseStatus.pending) {
+        //showPendingUI();
+        log("Purchase pending");
+      } else {
+        if (purchaseDetails.status == PurchaseStatus.error) {
+          //handleError(purchaseDetails.error);
+        } else if (purchaseDetails.status == PurchaseStatus.purchased) {
+          bool valid = await _verifyPurchase(purchaseDetails);
+          if (valid) {
+            deliverProduct(purchaseDetails);
+          } else {
+            _handleInvalidPurchase(purchaseDetails);
+            return;
+          }
+        }
+        if (Platform.isAndroid) {
+          if (!_kAutoConsume && purchaseDetails.productID == _kConsumableId) {
+            await InAppPurchaseConnection.instance.consumePurchase(purchaseDetails);
+          }
+        }
+        if (purchaseDetails.pendingCompletePurchase) {
+          await InAppPurchaseConnection.instance.completePurchase(purchaseDetails);
+        }
+      }
     });
-
-    _purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen((productItem) {
-      log('purchase-updated: $productItem');
-    });
-
-    _purchaseErrorSubscription = FlutterInappPurchase.purchaseError.listen((purchaseError) {
-      log('purchase-error: $purchaseError');
-    });
-
-    getSubscriptions();
   }
 
   void getSubscriptions() {
@@ -98,7 +196,6 @@ class PlatformPurchaseApi with Logging {
     _productList.forEach((element) {
       print(element);
     });
-    _getSubscription();
   }
 
   void purchase(Product product) {
@@ -106,57 +203,29 @@ class PlatformPurchaseApi with Logging {
       throw Exception("No product to purchase");
     }
     String productId = Platform.isAndroid ? product.productIdAndroid : product.productIdIos;
-    IAPItem selected;
-    for (var item in _items) {
-      if (item.productId == productId) {
-        selected = item;
-        log("Item to purchase: " + item.toString());
+    ProductDetails productDetails;
+    _products.forEach((element) {
+      if (element.id == productId) {
+        productDetails = element;
+        log("product to purchase: " +
+            productDetails.id +
+            " title " +
+            productDetails.title +
+            " price " +
+            productDetails.price +
+            " period " +
+            productDetails.skuDetail.subscriptionPeriod);
       }
-    }
+    });
 
-    if (selected != null) {
-      requestPurchase(selected);
-    } else {
-      throw Exception("product " + productId + " not defined in the PlatformStore");
-    }
-  }
-
-  void requestPurchase(IAPItem item) {
-    //FlutterInappPurchase.instance.requestPurchase(item.productId);
-    FlutterInappPurchase.instance.requestPurchase(item.productId);
-  }
-
-  Future _getSubscription() async {
-    List<IAPItem> items = await FlutterInappPurchase.instance.getSubscriptions(_productList);
-    for (var item in items) {
-      log('${item.toString()}');
-      this._items.add(item);
-    }
-
-    this._items = items;
-    this._purchases = [];
-  }
-
-  Future _getPurchases() async {
-    List<PurchasedItem> items = await FlutterInappPurchase.instance.getAvailablePurchases();
-    for (var item in items) {
-      log('${item.toString()}');
-      this._purchases.add(item);
-    }
-
-    this._items = [];
-    this._purchases = items;
-  }
-
-  Future _getPurchaseHistory() async {
-    List<PurchasedItem> items = await FlutterInappPurchase.instance.getPurchaseHistory();
-    for (var item in items) {
-      log('${item.toString()}');
-      this._purchases.add(item);
-    }
-
-    this._items = [];
-    this._purchases = items;
+    final PurchaseParam purchaseParam = PurchaseParam(productDetails: productDetails);
+/*     if (_isConsumable(productDetails)) {
+        InAppPurchaseConnection.instance.buyConsumable(purchaseParam: purchaseParam);
+    } else { */
+    InAppPurchaseConnection.instance.buyNonConsumable(purchaseParam: purchaseParam);
+    //}
+// From here the purchase flow will be handled by the underlying storefront.
+// Updates will be delivered to the `InAppPurchaseConnection.instance.purchaseUpdatedStream`.
   }
 }
  */
diff --git a/lib/util/purchases.dart b/lib/util/purchases.dart
new file mode 100644
index 0000000..7cc41ed
--- /dev/null
+++ b/lib/util/purchases.dart
@@ -0,0 +1,120 @@
+import 'dart:io';
+
+import 'package:aitrainer_app/model/cache.dart';
+import 'package:aitrainer_app/service/logging.dart';
+import 'package:aitrainer_app/util/common.dart';
+import 'package:flutter/services.dart';
+import 'package:purchases_flutter/purchases_flutter.dart';
+import 'package:aitrainer_app/model/product.dart' as wtproduct;
+
+class RevenueCatPurchases with Logging {
+  static final RevenueCatPurchases _singleton = RevenueCatPurchases._internal();
+  Offering _offering;
+  String appUserId;
+
+  factory RevenueCatPurchases() {
+    return _singleton;
+  }
+
+  RevenueCatPurchases._internal();
+
+  Offering get offering => _offering;
+
+  Future<void> initPlatform() async {
+    if (Cache().userLoggedIn != null) {
+      await Purchases.setDebugLogsEnabled(true);
+      await Purchases.setup("yLxGFWaeRtThLImqznvBnUEKjgArSsZE", appUserId: Cache().userLoggedIn.customerId.toString());
+      appUserId = await Purchases.appUserID;
+      log("AppUserId: " + appUserId);
+      await this.restore();
+    }
+  }
+
+  Future<void> restore() async {
+    if (appUserId != null) {
+      try {
+        PurchaserInfo purchaserInfo = await Purchases.restoreTransactions();
+        if (purchaserInfo != null &&
+            purchaserInfo.entitlements.all["wt_subscription"] != null &&
+            purchaserInfo.entitlements.all["wt_subscription"].isActive) {
+          Cache().hasPurchased = true;
+          log(" ******************************************** ");
+          log(" Purchase active ! ");
+        } else {
+          log(" ** No subscription active");
+        }
+      } on PlatformException catch (e) {
+        log("Purchaserinfo not reachable " + e.toString());
+      }
+    }
+  }
+
+  Future<Offering> getOfferings() async {
+    if (appUserId == null) {
+      await initPlatform();
+    }
+    log(" .. acessing offerings...");
+    try {
+      Offerings offerings = await Purchases.getOfferings();
+      if (offerings.current != null && offerings.current.availablePackages.isNotEmpty) {
+        // Display packages for sale
+        _offering = offerings.current;
+      } else {
+        log("No current offerings");
+        Common.sendMessage("No Current offerings");
+      }
+    } on PlatformException catch (e) {
+      // optional error handling
+      log("!!!! Getting offerings error " + e.toString());
+    }
+    return _offering;
+  }
+
+  Future<void> makePurchase(wtproduct.Product product) async {
+    try {
+      if (_offering == null) {
+        _offering = await getOfferings();
+      }
+      if (_offering != null) {
+        String productId = Platform.isAndroid ? product.productIdAndroid : product.productIdIos;
+        Package selectedPackage;
+        log("Nr of packages: " + _offering.availablePackages.length.toString() + " ProductId: " + productId);
+        for (var package in _offering.availablePackages) {
+          log("package to check " + package.product.identifier.toString());
+          if (package.product.identifier == productId) {
+            selectedPackage = package;
+            log("**** Selected package to purchase" + package.product.identifier);
+            break;
+          }
+        }
+        if (selectedPackage != null) {
+          PurchaserInfo purchaserInfo = await Purchases.purchasePackage(selectedPackage);
+          if (purchaserInfo.entitlements.all["wt_subscription"].isActive) {
+            Cache().hasPurchased = true;
+          }
+        } else {
+          log("!!!! No Selected package to purchase");
+          Common.sendMessage("No Selected package to purchase");
+          throw Exception("Purchase was not successful");
+        }
+      } else {
+        log("!!!! No active offering");
+      }
+    } on PlatformException catch (e) {
+      var errorCode = PurchasesErrorHelper.getErrorCode(e);
+      if (errorCode == PurchasesErrorCode.invalidReceiptError) {
+        log("iOS Sandbox invalid receipt");
+        Cache().hasPurchased = true;
+        return;
+      }
+      log(e.toString());
+      if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
+        Common.sendMessage("Purchase was cancelled");
+        throw Exception("Purchase was cancelled");
+      } else {
+        Common.sendMessage("Purchase was not successful");
+        throw Exception("Purchase was not successful");
+      }
+    }
+  }
+}
diff --git a/lib/util/session.dart b/lib/util/session.dart
index fcf6abc..663e5cf 100644
--- a/lib/util/session.dart
+++ b/lib/util/session.dart
@@ -6,6 +6,7 @@ import 'package:aitrainer_app/service/api.dart';
 import 'package:aitrainer_app/service/logging.dart';
 import 'package:aitrainer_app/service/product_service.dart';
 import 'package:aitrainer_app/service/property_service.dart';
+import 'package:aitrainer_app/util/purchases.dart';
 import 'package:devicelocale/devicelocale.dart';
 import 'package:flutter/services.dart';
 import 'package:shared_preferences/shared_preferences.dart';
@@ -28,6 +29,7 @@ class Session with Logging {
       Cache().setServerAddress(_sharedPreferences);
       Cache().getHardware(_sharedPreferences);
       await _fetchToken(_sharedPreferences);
+      await RevenueCatPurchases().initPlatform();
       //initDeviceLocale();
 
       // Create the initialization Future outside of `build`:
diff --git a/lib/view/account.dart b/lib/view/account.dart
index 3128562..463897f 100644
--- a/lib/view/account.dart
+++ b/lib/view/account.dart
@@ -5,7 +5,6 @@ import 'package:aitrainer_app/model/customer.dart';
 import 'package:aitrainer_app/util/common.dart';
 import 'package:aitrainer_app/util/trans.dart';
 import 'package:aitrainer_app/widgets/app_bar_min.dart';
-import 'package:badges/badges.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:aitrainer_app/widgets/bottom_nav.dart';
 import 'package:flutter/material.dart';
diff --git a/lib/view/evaluation.dart b/lib/view/evaluation.dart
index 514d069..d6d3218 100644
--- a/lib/view/evaluation.dart
+++ b/lib/view/evaluation.dart
@@ -4,7 +4,9 @@ import 'dart:ui';
 import 'package:aitrainer_app/bloc/result/result_bloc.dart';
 import 'package:aitrainer_app/localization/app_language.dart';
 import 'package:aitrainer_app/model/cache.dart';
+import 'package:aitrainer_app/model/exercise.dart';
 import 'package:aitrainer_app/model/exercise_ability.dart';
+import 'package:aitrainer_app/model/exercise_type.dart';
 import 'package:aitrainer_app/repository/exercise_repository.dart';
 import 'package:aitrainer_app/repository/exercise_result_repository.dart';
 import 'package:aitrainer_app/util/trans.dart';
@@ -15,6 +17,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_form_bloc/flutter_form_bloc.dart';
 import 'package:google_fonts/google_fonts.dart';
 import 'package:aitrainer_app/model/result.dart';
+import 'package:modal_progress_hud/modal_progress_hud.dart';
 
 // ignore: must_be_immutable
 class EvaluationPage extends StatelessWidget with Trans {
@@ -22,7 +25,7 @@ class EvaluationPage extends StatelessWidget with Trans {
   Widget build(BuildContext context) {
     LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
     ExerciseRepository exerciseRepository;
-    // ignore: close_sinks
+
     if (arguments != null) {
       exerciseRepository = arguments['exerciseRepository'];
     } else {
@@ -37,10 +40,22 @@ class EvaluationPage extends StatelessWidget with Trans {
       resultType = ResultType.man;
       imageUrl = 'asset/image/WT_Results_for_female.png';
     }
+
+    if (arguments['past'] != null && arguments['past'] == true) {
+      Exercise exercise = arguments['exercise'];
+      if (exercise != null) {
+        ExerciseType exerciseType = exerciseRepository.getExerciseTypeById(exercise.exerciseTypeId);
+        exerciseRepository.exerciseType = exerciseType;
+        exerciseRepository.exercise = exercise;
+        String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd);
+        exerciseRepository.getSameExercise(exercise.exerciseTypeId, exerciseDate);
+      }
+    }
     if (exerciseRepository.exerciseType.getAbility().equalsTo(ExerciseAbility.running)) {
       resultType = ResultType.running;
       imageUrl = 'asset/image/WT_Results_for_runners.png';
     }
+
     setContext(context);
     return Scaffold(
         appBar: AppBarMin(
@@ -61,7 +76,7 @@ class EvaluationPage extends StatelessWidget with Trans {
                 create: (context) => ResultBloc(
                     resultRepository: ExerciseResultRepository(resultType: resultType),
                     exerciseRepository: exerciseRepository,
-                    context: context), //..add(ResultLoad())
+                    context: context),
                 child: BlocConsumer<ResultBloc, ResultState>(listener: (context, state) {
                   if (state is ResultError) {
                     Scaffold.of(context).showSnackBar(
@@ -74,7 +89,13 @@ class EvaluationPage extends StatelessWidget with Trans {
                   }
                 }, builder: (context, state) {
                   final resultBloc = BlocProvider.of<ResultBloc>(context);
-                  return getEvaluationWidgets(resultBloc);
+                  return ModalProgressHUD(
+                    child: getEvaluationWidgets(resultBloc),
+                    inAsyncCall: state is ResultLoading,
+                    opacity: 0.5,
+                    color: Colors.black54,
+                    progressIndicator: CircularProgressIndicator(),
+                  );
                 }))),
         bottomNavigationBar: BottomNavigator(bottomNavIndex: 0));
   }
@@ -89,13 +110,15 @@ class EvaluationPage extends StatelessWidget with Trans {
           SliverAppBar(
             pinned: true,
             backgroundColor: Colors.transparent,
-            expandedHeight: 50.0,
+            expandedHeight: 120.0,
+            collapsedHeight: 80,
+            toolbarHeight: 30,
             automaticallyImplyLeading: false,
             flexibleSpace: FlexibleSpaceBar(
               title: Text(exerciseName,
                   textAlign: TextAlign.center,
                   maxLines: 3,
-                  softWrap: true,
+                  //softWrap: true,
                   style: GoogleFonts.archivoBlack(
                     fontSize: 24,
                     color: Colors.white,
@@ -382,14 +405,12 @@ class EvaluationPage extends StatelessWidget with Trans {
   Widget getSummary(ResultBloc bloc) {
     int index = 0;
     List<Text> resultList = List();
-    /* for (int i = 0; i < bloc.exerciseRepository.actualExerciseList.length; i++) {
-      print("Q " +
-          bloc.exerciseRepository.actualExerciseList[i].quantity.toString() +
-          " Qu: " +
-          bloc.exerciseRepository.actualExerciseList[i].unitQuantity.toString());
-    } */
+
     bloc.exerciseRepository.actualExerciseList.forEach((actual) {
-      final String unit = t(bloc.exerciseRepository.exerciseType.unit);
+      //final String unit = t(bloc.exerciseRepository.exerciseType.unit);
+      final String unit = bloc.exerciseRepository.exerciseType.unitQuantityUnit != null
+          ? bloc.exerciseRepository.exerciseType.unitQuantityUnit
+          : bloc.exerciseRepository.exerciseType.unit;
       String exerciseElement = "";
       String exerciseRepeats = actual.quantity.toStringAsFixed(0);
       if (bloc.exerciseRepository.exerciseType.unit == "second") {
@@ -407,7 +428,7 @@ class EvaluationPage extends StatelessWidget with Trans {
       }
       index++;
       resultList.add(
-        Text(exerciseElement + exerciseRepeats + exerciseUnitQuantity + " " + unit,
+        Text(exerciseElement + exerciseRepeats + exerciseUnitQuantity + " " + t(unit),
             textAlign: TextAlign.center,
             maxLines: 2,
             softWrap: true,
diff --git a/lib/view/exercise_log_page.dart b/lib/view/exercise_log_page.dart
index 4f5cfdc..deca86c 100644
--- a/lib/view/exercise_log_page.dart
+++ b/lib/view/exercise_log_page.dart
@@ -200,7 +200,7 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
                       iconSize: 36,
                       icon: Icon(CustomIcon.heart_1, color: Colors.blue[800]),
                       onPressed: () {
-                        evaluation();
+                        evaluation(exerciseRepository, exercise);
                       },
                     ),
                     Cache().hasPurchased
@@ -212,7 +212,7 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
                               width: 25,
                             ),
                             onTap: () {
-                              evaluation();
+                              evaluation(exerciseRepository, exercise);
                             }),
                   ],
                 ),
@@ -230,19 +230,27 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
     return list;
   }
 
-  void evaluation() {
-    showDialog(
-        context: context,
-        builder: (BuildContext context) {
-          return DialogPremium(
-            unlocked: true,
-            unlockRound: 1,
-            unlockedText: t("Enjoy also this premium fetaure to show all old evaluation data of your successful exercises."),
-            function: "My Exercise Logs",
-            onTap: () => {Navigator.of(context).pop()},
-            onCancel: () => {Navigator.of(context).pop()},
-          );
-        });
+  void evaluation(ExerciseRepository exerciseRepository, Exercise exercise) {
+    if (!Cache().hasPurchased) {
+      showDialog(
+          context: context,
+          builder: (BuildContext context) {
+            return DialogPremium(
+              unlocked: Cache().hasPurchased,
+              unlockRound: 1,
+              unlockedText: t("Enjoy also this premium fetaure to show all old evaluation data of your successful exercises."),
+              function: "My Exercise Logs",
+              onTap: () => {Navigator.of(context).pop()},
+              onCancel: () => {Navigator.of(context).pop()},
+            );
+          });
+    } else {
+      LinkedHashMap args = LinkedHashMap();
+      args['exerciseRepository'] = exerciseRepository;
+      args['exercise'] = exercise;
+      args['past'] = true;
+      Navigator.of(context).pushNamed('evaluationPage', arguments: args);
+    }
   }
 
   void confirmationDialog(ExerciseLogBloc bloc, Exercise exercise) {
diff --git a/lib/view/exercise_new_page.dart b/lib/view/exercise_new_page.dart
index da9f039..627b1fa 100644
--- a/lib/view/exercise_new_page.dart
+++ b/lib/view/exercise_new_page.dart
@@ -22,6 +22,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_form_bloc/flutter_form_bloc.dart';
 import 'package:google_fonts/google_fonts.dart';
 import 'package:keyboard_actions/keyboard_actions.dart';
+import 'package:modal_progress_hud/modal_progress_hud.dart';
 import 'package:stop_watch_timer/stop_watch_timer.dart';
 import 'package:wakelock/wakelock.dart';
 
@@ -101,11 +102,14 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans, Logging {
             }
           },
           builder: (context, state) {
-            if (state is ExerciseNewReady) {
-              //LoadingDialog.hide(context);
-            }
             final exerciseBloc = BlocProvider.of<ExerciseNewBloc>(context);
-            return getExerciseWidget(exerciseBloc, exerciseType, menuBloc);
+            return ModalProgressHUD(
+              child: getExerciseWidget(exerciseBloc, exerciseType, menuBloc),
+              inAsyncCall: state is ExerciseNewLoading,
+              opacity: 0.5,
+              color: Colors.black54,
+              progressIndicator: CircularProgressIndicator(),
+            );
           },
         ));
   }
diff --git a/lib/view/mydevelopment_body_page.dart b/lib/view/mydevelopment_body_page.dart
index f896fcf..8bdc2cf 100644
--- a/lib/view/mydevelopment_body_page.dart
+++ b/lib/view/mydevelopment_body_page.dart
@@ -28,7 +28,7 @@ class _MyDevelopmentBodyPage extends State<MyDevelopmentBodyPage> with Trans, Co
   void initState() {
     super.initState();
     Flurry.logEvent("myDevelopmentBody");
-    if (!Cache().hasPurchased) {
+    if (!Cache().hasPurchased || true) {
       Timer(
           Duration(milliseconds: 2000),
           () => {
@@ -38,10 +38,10 @@ class _MyDevelopmentBodyPage extends State<MyDevelopmentBodyPage> with Trans, Co
                     builder: (BuildContext context) {
                       setContext(context);
                       return DialogPremium(
-                        unlocked: false,
+                        unlocked: Cache().hasPurchased,
                         unlockRound: 2,
                         function: "My Whole Body Development",
-                        unlockedText: "",
+                        unlockedText: null,
                         onTap: () => {Navigator.of(context).pop(), Navigator.of(context).pop()},
                         onCancel: () => {Navigator.of(context).pop(), Navigator.of(context).pop()},
                       );
diff --git a/lib/view/mydevelopment_muscle_page.dart b/lib/view/mydevelopment_muscle_page.dart
index 63885e2..65dc5c2 100644
--- a/lib/view/mydevelopment_muscle_page.dart
+++ b/lib/view/mydevelopment_muscle_page.dart
@@ -217,27 +217,37 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
             )));
     exerciseTypes.add(explanation);
 
+    LinkedHashMap<String, dynamic> rc = LinkedHashMap();
     tree.forEach((name, list) {
+      rc = _getChildList(list, bloc);
+      final List<Widget> children = rc['list'];
+      final bool hasNoData = rc['hasNoData'];
       exerciseTypes.add(Container(
           margin: const EdgeInsets.only(left: 4.0),
           child: TreeViewChild(
             startExpanded: false,
-            parent: _getExerciseWidget(exerciseTypeName: name),
-            children: _getChildList(list, bloc),
+            parent: _getExerciseWidget(exerciseTypeName: name, noData: hasNoData),
+            children: children,
           )));
     });
 
     return exerciseTypes;
   }
 
-  Widget _getExerciseWidget({@required String exerciseTypeName, List<WorkoutMenuTree> list}) {
-    return TreeviewParentWidget(text: exerciseTypeName);
+  Widget _getExerciseWidget({@required String exerciseTypeName, bool noData = false}) {
+    return TreeviewParentWidget(
+        text: exerciseTypeName,
+        backgroundColor: !noData ? Colors.white38 : Colors.white12,
+        color: !noData ? Colors.blue[800] : Colors.grey[400]);
   }
 
-  List<Widget> _getChildList(List<WorkoutMenuTree> listWorkoutTree, DevelopmentByMuscleBloc bloc) {
+  LinkedHashMap<String, dynamic> _getChildList(List<WorkoutMenuTree> listWorkoutTree, DevelopmentByMuscleBloc bloc) {
+    LinkedHashMap<String, dynamic> rc = LinkedHashMap();
     List<Widget> list = List();
+    bool hasSummaryNoData = true;
     listWorkoutTree.forEach((element) {
-      bool hasNoData = (bloc.listChartData[element.exerciseTypeId] == null);
+      final bool hasNoData = (bloc.listChartData[element.exerciseTypeId] == null);
+      hasSummaryNoData = hasSummaryNoData && hasNoData;
       String unit = " kg";
       if (bloc.diagramType == DiagramType.percent) {
         unit = " %";
@@ -320,7 +330,8 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
         ),
       ));
     });
-
-    return list;
+    rc['list'] = list;
+    rc['hasNoData'] = hasSummaryNoData;
+    return rc;
   }
 }
diff --git a/lib/view/mydevelopment_page.dart b/lib/view/mydevelopment_page.dart
index 43be52d..e3fa85f 100644
--- a/lib/view/mydevelopment_page.dart
+++ b/lib/view/mydevelopment_page.dart
@@ -106,10 +106,10 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
                           context: context,
                           builder: (BuildContext context) {
                             return DialogPremium(
-                              unlocked: false,
-                              unlockRound: 2,
+                              unlocked: Cache().hasPurchased,
+                              unlockRound: 3,
                               function: "Predictions",
-                              unlockedText: "",
+                              unlockedText: null,
                               onTap: () => {Navigator.of(context).pop()},
                             );
                           })
diff --git a/lib/view/myexcercise_plan_page.dart b/lib/view/myexcercise_plan_page.dart
index bd56e75..dab24f5 100644
--- a/lib/view/myexcercise_plan_page.dart
+++ b/lib/view/myexcercise_plan_page.dart
@@ -97,10 +97,10 @@ class _MyExercisePlanPage extends State<MyExercisePlanPage> with Trans, Logging
                           context: context,
                           builder: (BuildContext context) {
                             return DialogPremium(
-                              unlocked: false,
+                              unlocked: Cache().hasPurchased,
                               unlockRound: 1,
                               function: "Suggested Training Plan",
-                              unlockedText: "",
+                              unlockedText: null,
                               onTap: () => {Navigator.of(context).pop()},
                               onCancel: () => {Navigator.of(context).pop()},
                             );
@@ -111,25 +111,25 @@ class _MyExercisePlanPage extends State<MyExercisePlanPage> with Trans, Logging
                   ImageButton(
                     width: imageWidth,
                     textAlignment: Alignment.topLeft,
-                    text: t("My Special Plan"),
+                    text: t("Training Programs"),
                     style: GoogleFonts.robotoMono(
                         textStyle: TextStyle(
                             fontSize: 14,
                             color: Colors.white,
                             fontWeight: FontWeight.bold,
                             backgroundColor: Colors.black54.withOpacity(0.4))),
-                    image: "asset/image/exercise_plan_special.jpg",
+                    image: "asset/image/exercise_plan_stars.jpg",
                     left: 5,
                     onTap: () => {
-                      Flurry.logEvent("SpecialTrainingPlan"),
+                      Flurry.logEvent("SpecialTraining Programs"),
                       showDialog(
                           context: context,
                           builder: (BuildContext context) {
                             return DialogPremium(
-                              unlocked: false,
+                              unlocked: Cache().hasPurchased,
                               unlockRound: 1,
-                              function: "My Special Plan",
-                              unlockedText: "",
+                              function: "Training Programs",
+                              unlockedText: null,
                               onTap: () => {Navigator.of(context).pop()},
                               onCancel: () => {Navigator.of(context).pop()},
                             );
@@ -137,7 +137,7 @@ class _MyExercisePlanPage extends State<MyExercisePlanPage> with Trans, Logging
                     },
                     isLocked: true,
                   ),
-                  ImageButton(
+                  /* ImageButton(
                     width: imageWidth,
                     textAlignment: Alignment.topLeft,
                     text: t("Star's Exercise Plan"),
@@ -165,7 +165,7 @@ class _MyExercisePlanPage extends State<MyExercisePlanPage> with Trans, Logging
                           })
                     },
                     isLocked: true,
-                  ),
+                  ), */
                   hiddenPlanWidget(exerciseRepository),
                   hiddenTrainingWidget(),
                 ]),
diff --git a/lib/view/sales_page.dart b/lib/view/sales_page.dart
index c0cf855..c2f6fbe 100644
--- a/lib/view/sales_page.dart
+++ b/lib/view/sales_page.dart
@@ -2,6 +2,7 @@ import 'package:aitrainer_app/bloc/sales/sales_bloc.dart';
 import 'package:aitrainer_app/service/logging.dart';
 import 'package:aitrainer_app/util/trans.dart';
 import 'package:aitrainer_app/widgets/app_bar_min.dart';
+import 'package:aitrainer_app/widgets/dialog_common.dart';
 import 'package:aitrainer_app/widgets/sales_button.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
@@ -23,7 +24,25 @@ class SalesPage extends StatelessWidget with Trans, Logging {
               if (state is SalesError) {
                 log("Error: " + state.message);
                 Scaffold.of(context).showSnackBar(
-                    SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
+                    SnackBar(backgroundColor: Colors.orange, content: Text(t(state.message), style: TextStyle(color: Colors.white))));
+              } else if (state is SalesSuccessful) {
+                showDialog(
+                    context: context,
+                    builder: (BuildContext context) {
+                      return DialogCommon(
+                        title: t("Successful Purchase"),
+                        descriptions: t("Now you can use the premium features of WorkoutTest!"),
+                        text: "OK",
+                        onTap: () => {
+                          Navigator.of(context).pop(),
+                          Navigator.of(context).pushNamed("home"),
+                        },
+                        onCancel: () => {
+                          Navigator.of(context).pop(),
+                          Navigator.of(context).pushNamed("home"),
+                        },
+                      );
+                    });
               }
             }, builder: (context, state) {
               final salesBloc = BlocProvider.of<SalesBloc>(context);
@@ -38,8 +57,6 @@ class SalesPage extends StatelessWidget with Trans, Logging {
   }
 
   Widget salesWidget(SalesBloc bloc) {
-    final double mediaWidth = MediaQuery.of(context).size.width;
-    final double imageWidth = (mediaWidth - 5) / 2;
     return Container(
         decoration: BoxDecoration(
           image: DecorationImage(
@@ -54,7 +71,7 @@ class SalesPage extends StatelessWidget with Trans, Logging {
             Divider(),
             Container(
                 padding: EdgeInsets.only(left: 65, right: 65),
-                child: Text("Unleash Your Development Now!",
+                child: Text(t("Unleash Your Development Now!"),
                     textAlign: TextAlign.center,
                     maxLines: 4,
                     softWrap: true,
@@ -77,7 +94,7 @@ class SalesPage extends StatelessWidget with Trans, Logging {
             Divider(),
             Container(
                 padding: EdgeInsets.only(left: 45, right: 45),
-                child: Text("Learn about your development, enjoy AI-driven predictions of all of your skills and bodyparts.",
+                child: Text(t("Learn about your development, enjoy AI-driven predictions of all of your skills and bodyparts."),
                     textAlign: TextAlign.left,
                     maxLines: 4,
                     softWrap: true,
@@ -106,47 +123,45 @@ class SalesPage extends StatelessWidget with Trans, Logging {
             Container(
                 padding: EdgeInsets.only(left: 55, right: 55),
                 child: Text(
-                  "Subscription Conditions",
+                  t("Subscription Conditions"),
                   style: GoogleFonts.inter(fontSize: 14, fontWeight: FontWeight.bold, color: Colors.white),
                 )),
             Divider(),
             Container(
                 padding: EdgeInsets.only(left: 55, right: 55),
                 child: Text(
-                  "Payment will be charged to your account. Subscription automatically renews unless auto-renew is turned off at least 24 hourse before the end of the current period",
+                  t("Payment will be charged to your account. Subscription automatically renews unless auto-renew is turned off at least 24 hours before the end of the current period"),
                   style: GoogleFonts.inter(fontSize: 12, color: Colors.white),
                 )),
             Divider(),
             Container(
                 padding: EdgeInsets.only(left: 55, right: 55),
                 child: Text(
-                  "Account will be charged for renewal within 24 hours prior to the end of the current period",
+                  t("Account will be charged for renewal within 24 hours prior to the end of the current period"),
                   style: GoogleFonts.inter(fontSize: 12, color: Colors.white),
                 )),
           ])),
         ]));
-    ;
   }
 
   List<Widget> getButtons(SalesBloc bloc) {
     List<Widget> buttons = List();
 
     bloc.product2Display.forEach((element) {
-      final String title = element.sort == 3 ? "Montly" : "Annual";
-      final String interval = element.sort == 3 ? " / month" : " / year";
-      final String desc4 = element.sort == 1 ? "" : "AI driven predictions";
+      final String title = element.sort == 3 ? t("Montly") : t("Annual");
+      final String desc4 = element.sort == 1 ? "" : t("AI driven predictions");
       String badge;
       if (element.sort == 2) {
-        badge = "14% discount";
+        badge = t("14% discount");
       } else if (element.sort == 1) {
-        badge = "2 months free";
+        badge = t("2 months free");
       }
       Widget button = SalesButton(
         title: title,
         price: element.localizedPrice,
-        desc1: "Development programs",
-        desc2: "Suggestions based on your actual status",
-        desc3: "Special customized training plans",
+        desc1: t("Development programs"),
+        desc2: t("Suggestions based on your actual status"),
+        desc3: t("Special customized training plans"),
         desc4: desc4,
         descStyle: GoogleFonts.inter(fontSize: 10, color: Colors.blue[800]),
         badgeText: badge,
diff --git a/lib/view/settings.dart b/lib/view/settings.dart
index 7e284b6..2f16d90 100644
--- a/lib/view/settings.dart
+++ b/lib/view/settings.dart
@@ -10,6 +10,7 @@ import 'package:aitrainer_app/widgets/bottom_nav.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:modal_progress_hud/modal_progress_hud.dart';
 import 'package:toggle_switch/toggle_switch.dart';
 
 // ignore: must_be_immutable
@@ -40,16 +41,15 @@ class SettingsPage extends StatelessWidget with Trans {
                     SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
               } else if (state is SettingsReady) {
                 menuBloc.add(MenuRecreateTree());
-              } else if (state is SettingsLoading) {
-                Scaffold.of(context).showSnackBar(SnackBar(
-                    duration: Duration(milliseconds: 100),
-                    backgroundColor: Colors.transparent,
-                    content: Container(child: Center(child: CircularProgressIndicator()))));
               }
-            },
-                // ignore: missing_return
-                builder: (context, state) {
-              return settingsUI(context, settingsBloc, menuBloc);
+            }, builder: (context, state) {
+              return ModalProgressHUD(
+                child: settingsUI(context, settingsBloc, menuBloc),
+                inAsyncCall: state is SettingsLoading,
+                opacity: 0.5,
+                color: Colors.black54,
+                progressIndicator: CircularProgressIndicator(),
+              );
             }),
           ),
         ),
@@ -101,7 +101,6 @@ class SettingsPage extends StatelessWidget with Trans {
         inactiveFgColor: Colors.grey[900],
         labels: [t('Live-Server'), t('Test-Server')],
         onToggle: (index) {
-          //Cache().setServer(index == 0);
           settingsBloc.add(SettingsSetServer(live: index == 0));
         },
       ),
diff --git a/lib/widgets/bmi_widget.dart b/lib/widgets/bmi_widget.dart
index 13f90a9..1a572af 100644
--- a/lib/widgets/bmi_widget.dart
+++ b/lib/widgets/bmi_widget.dart
@@ -2,7 +2,6 @@ import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
 import 'package:aitrainer_app/localization/app_localization.dart';
 import 'package:aitrainer_app/util/trans.dart';
 import 'package:animated_widgets/widgets/rotation_animated.dart';
-import 'package:flurry/flurry.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
@@ -71,7 +70,6 @@ class _BMIState extends State<BMI> with Trans {
   @override
   Widget build(BuildContext context) {
     setContext(context);
-    Flurry.logEvent("BMI");
     double mediaWidth = MediaQuery.of(context).size.width * .8;
     double mediaHeight = MediaQuery.of(context).size.height * .8;
     //print("w " + mediaWidth.toString() + "h " + mediaHeight.toString());
@@ -109,18 +107,35 @@ class _BMIState extends State<BMI> with Trans {
                             fontSize: 30,
                             color: Colors.orange[500],
                           )),
-                      Text(widget.exerciseBloc.bmi.toStringAsFixed(1) + "%",
-                          style: GoogleFonts.archivoBlack(
-                            shadows: <Shadow>[
-                              Shadow(
-                                offset: Offset(5.0, 5.0),
-                                blurRadius: 3.0,
-                                color: Colors.black54,
-                              ),
-                            ],
-                            fontSize: 60,
-                            color: Colors.orange[500],
-                          )),
+                      Row(
+                        mainAxisAlignment: MainAxisAlignment.center,
+                        children: [
+                          Text(widget.exerciseBloc.bmi.toStringAsFixed(1),
+                              style: GoogleFonts.archivoBlack(
+                                shadows: <Shadow>[
+                                  Shadow(
+                                    offset: Offset(5.0, 5.0),
+                                    blurRadius: 3.0,
+                                    color: Colors.black54,
+                                  ),
+                                ],
+                                fontSize: 60,
+                                color: Colors.orange[500],
+                              )),
+                          Text(" kg/m2",
+                              style: GoogleFonts.archivoBlack(
+                                shadows: <Shadow>[
+                                  Shadow(
+                                    offset: Offset(5.0, 5.0),
+                                    blurRadius: 3.0,
+                                    color: Colors.black54,
+                                  ),
+                                ],
+                                fontSize: 30,
+                                color: Colors.orange[500],
+                              )),
+                        ],
+                      ),
                       Divider(color: Colors.transparent),
                       Stack(alignment: Alignment.center, children: [
                         Container(
@@ -153,15 +168,31 @@ class _BMIState extends State<BMI> with Trans {
                               color: Colors.yellow[200],
                             )),
                       ),
-                      Text("BMI" + ": " + widget.exerciseBloc.goalBMI.toStringAsFixed(0),
+                      Text("BMI" + " " + t("first step") + ": " + widget.exerciseBloc.goalMilestoneBMI.toStringAsFixed(1),
                           style: GoogleFonts.archivoBlack(
-                            fontSize: 40,
+                            fontSize: 20,
+                            color: Colors.orange[200],
+                          )),
+                      Text(
+                          t("Bodyweight") +
+                              " " +
+                              t("first step") +
+                              ": " +
+                              widget.exerciseBloc.goalMilestoneWeight.toStringAsFixed(0) +
+                              " kg",
+                          style: GoogleFonts.archivoBlack(
+                            fontSize: 20,
+                            color: Colors.orange[200],
+                          )),
+                      Text("BMI" + " " + t("goal") + ": " + widget.exerciseBloc.goalBMI.toStringAsFixed(1),
+                          style: GoogleFonts.archivoBlack(
+                            fontSize: 20,
                             color: Colors.orange[500],
                           )),
-                      Text(t("Weight") + ": " + widget.exerciseBloc.goalWeight.toStringAsFixed(0) + " kg",
+                      Text(t("Bodyweight") + " " + t("goal") + ": " + widget.exerciseBloc.goalWeight.toStringAsFixed(0) + " kg",
                           style: GoogleFonts.archivoBlack(
-                            fontSize: 30,
-                            color: Colors.orange[200],
+                            fontSize: 20,
+                            color: Colors.orange[500],
                           )),
                     ]))))));
   }
diff --git a/lib/widgets/bmr_widget.dart b/lib/widgets/bmr_widget.dart
index b9a80b2..fb6f193 100644
--- a/lib/widgets/bmr_widget.dart
+++ b/lib/widgets/bmr_widget.dart
@@ -2,7 +2,6 @@ import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
 import 'package:aitrainer_app/localization/app_localization.dart';
 import 'package:aitrainer_app/model/fitness_state.dart';
 import 'package:aitrainer_app/util/trans.dart';
-import 'package:flurry/flurry.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/widgets.dart';
@@ -26,6 +25,7 @@ class _BMRState extends State<BMR> with Trans {
 
   final FocusNode _nodeText1 = FocusNode();
   final FocusNode _nodeText2 = FocusNode();
+  final FocusNode _nodeText3 = FocusNode();
 
   KeyboardActionsConfig _buildConfig(BuildContext context) {
     return KeyboardActionsConfig(
@@ -34,6 +34,21 @@ class _BMRState extends State<BMR> with Trans {
       keyboardSeparatorColor: Colors.black26,
       nextFocus: true,
       actions: [
+        KeyboardActionsItem(focusNode: _nodeText3, toolbarButtons: [
+          (node) {
+            return GestureDetector(
+              onTap: () => node.unfocus(),
+              child: Container(
+                padding: EdgeInsets.all(8.0),
+                color: Colors.orange[500],
+                child: Text(
+                  AppLocalizations.of(context).translate("Done"),
+                  style: TextStyle(color: Colors.white),
+                ),
+              ),
+            );
+          }
+        ]),
         KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [
           (node) {
             return GestureDetector(
@@ -75,7 +90,6 @@ class _BMRState extends State<BMR> with Trans {
   @override
   Widget build(BuildContext context) {
     setContext(context);
-    Flurry.logEvent("BMR");
     return Form(
         child: Scaffold(
             resizeToAvoidBottomInset: true,
@@ -99,6 +113,35 @@ class _BMRState extends State<BMR> with Trans {
                           getWeightInput(),
                           getFitnessLevel(),
                           Divider(),
+                          Container(
+                            padding: EdgeInsets.only(left: 35, right: 35),
+                            child: Text(t("Resting Metabolic Rate"),
+                                textAlign: TextAlign.center,
+                                style: GoogleFonts.archivoBlack(
+                                  shadows: <Shadow>[
+                                    Shadow(
+                                      offset: Offset(5.0, 5.0),
+                                      blurRadius: 3.0,
+                                      color: Colors.black54,
+                                    ),
+                                  ],
+                                  fontSize: 24,
+                                  color: Colors.orange[300],
+                                )),
+                          ),
+                          Text(widget.exerciseBloc.bmrEnergy.toStringAsFixed(0) + " kCal",
+                              style: GoogleFonts.archivoBlack(
+                                shadows: <Shadow>[
+                                  Shadow(
+                                    offset: Offset(5.0, 5.0),
+                                    blurRadius: 3.0,
+                                    color: Colors.black54,
+                                  ),
+                                ],
+                                fontSize: 30,
+                                color: Colors.orange[300],
+                              )),
+                          SizedBox(height: 20),
                           Container(
                             padding: EdgeInsets.only(left: 35, right: 35),
                             child: Text(t("Basal Metabolic Rate"),
@@ -111,7 +154,7 @@ class _BMRState extends State<BMR> with Trans {
                                       color: Colors.black54,
                                     ),
                                   ],
-                                  fontSize: 30,
+                                  fontSize: 24,
                                   color: Colors.orange[500],
                                 )),
                           ),
@@ -124,7 +167,7 @@ class _BMRState extends State<BMR> with Trans {
                                     color: Colors.black54,
                                   ),
                                 ],
-                                fontSize: 50,
+                                fontSize: 30,
                                 color: Colors.orange[500],
                               )),
                           Container(
@@ -168,6 +211,30 @@ class _BMRState extends State<BMR> with Trans {
     }
   }
 
+  Widget getBirthyearInput() {
+    return Flexible(
+      child: TextFormField(
+          focusNode: _nodeText3,
+          decoration: InputDecoration(
+            contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5),
+            labelText: AppLocalizations.of(context).translate("Birth Year"),
+            labelStyle: GoogleFonts.inter(fontSize: 16, color: Colors.yellow[50]),
+            fillColor: Colors.black38,
+            filled: true,
+            border: OutlineInputBorder(
+              gapPadding: 4.0,
+              borderRadius: BorderRadius.circular(12.0),
+              borderSide: BorderSide(color: Colors.white12, width: 0.4),
+            ),
+          ),
+          initialValue: widget.exerciseBloc.birthYear.toStringAsFixed(0),
+          keyboardType: TextInputType.numberWithOptions(decimal: false),
+          textInputAction: TextInputAction.done,
+          style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.yellow[300]),
+          onChanged: (value) => {widget.exerciseBloc.add(ExerciseNewBirthyearChange(value: int.parse(value)))}),
+    );
+  }
+
   Widget getFitnessLevel() {
     String fitnessLevel = widget.exerciseBloc.fitnessLevel;
     return Container(
@@ -254,14 +321,18 @@ class _BMRState extends State<BMR> with Trans {
 
   Widget getWeightInput() {
     return Container(
-        padding: EdgeInsets.only(top: 15, left: 65, right: 65, bottom: 10),
+        padding: EdgeInsets.only(top: 15, left: 35, right: 35, bottom: 10),
         alignment: Alignment.center,
         child: Row(
           mainAxisAlignment: MainAxisAlignment.start,
           children: [
+            getBirthyearInput(),
+            SizedBox(
+              width: 5,
+            ),
             getHeightInput(),
             SizedBox(
-              width: 10,
+              width: 5,
             ),
             Flexible(
               child: TextFormField(
diff --git a/lib/widgets/bottom_nav.dart b/lib/widgets/bottom_nav.dart
index 95ad802..bb4c540 100644
--- a/lib/widgets/bottom_nav.dart
+++ b/lib/widgets/bottom_nav.dart
@@ -1,9 +1,7 @@
 import 'package:aitrainer_app/localization/app_localization.dart';
-import 'package:aitrainer_app/model/cache.dart';
 import 'package:aitrainer_app/service/logging.dart';
 import 'package:aitrainer_app/util/common.dart';
 import 'package:aitrainer_app/util/trans.dart';
-import 'package:badges/badges.dart';
 import 'package:flurry/flurry.dart';
 import 'package:flutter/material.dart';
 import 'package:gradient_bottom_navigation_bar/gradient_bottom_navigation_bar.dart';
diff --git a/lib/widgets/dialog_premium.dart b/lib/widgets/dialog_premium.dart
index 1fefcc0..27baa49 100644
--- a/lib/widgets/dialog_premium.dart
+++ b/lib/widgets/dialog_premium.dart
@@ -26,9 +26,6 @@ class DialogPremium extends StatefulWidget {
       : super(key: key) {
     description = description ?? "";
     function = function ?? "";
-    unlockedText = unlockedText ?? "";
-
-    unlocked = true;
   }
 
   @override
@@ -92,7 +89,7 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
                     Text(
                       widget.unlocked ? t("Keep testing") : t("Go Premium") + "   ",
                       style: GoogleFonts.archivoBlack(
-                        fontSize: widget.unlocked ? 18 : 24,
+                        fontSize: widget.unlocked ? 20 : 24,
                         color: Colors.yellow[400],
                         shadows: <Shadow>[
                           Shadow(
@@ -226,9 +223,10 @@ class _DialogPremiumState extends State<DialogPremium> with Trans {
   List<TextSpan> getDescriptionText() {
     List<TextSpan> list = List();
 
-    /* if (widget.unlocked) {
+    if (widget.unlockedText != null) {
       list.add(TextSpan(text: widget.unlockedText));
-    } */
+      return list;
+    }
     list.add(TextSpan(text: t("The")));
     list.add(TextSpan(text: t(" ")));
     list.add(
diff --git a/lib/widgets/home.dart b/lib/widgets/home.dart
index 94f2423..93456a7 100644
--- a/lib/widgets/home.dart
+++ b/lib/widgets/home.dart
@@ -2,14 +2,12 @@ import 'package:aitrainer_app/bloc/session/session_bloc.dart';
 import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
 import 'package:aitrainer_app/model/cache.dart';
 import 'package:aitrainer_app/service/logging.dart';
-import 'package:aitrainer_app/util/platform_purchase.dart';
 import 'package:aitrainer_app/view/login.dart';
 import 'package:aitrainer_app/view/menu_page.dart';
 import 'package:aitrainer_app/view/registration.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/scheduler.dart';
-import 'package:flutter/semantics.dart';
 import 'package:flutter/widgets.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'loading.dart';
diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart
index 69c2685..df2047b 100644
--- a/lib/widgets/menu_page_widget.dart
+++ b/lib/widgets/menu_page_widget.dart
@@ -8,14 +8,12 @@ import 'package:aitrainer_app/localization/app_localization.dart';
 import 'package:aitrainer_app/model/cache.dart';
 import 'package:aitrainer_app/model/workout_menu_tree.dart';
 import 'package:aitrainer_app/service/logging.dart';
-import 'package:aitrainer_app/util/not_found_exception.dart';
 import 'package:aitrainer_app/util/trans.dart';
 import 'package:aitrainer_app/widgets/dialog_common.dart';
 import 'package:badges/badges.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/painting.dart';
-import 'package:flutter/services.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:google_fonts/google_fonts.dart';
 
diff --git a/lib/widgets/treeview_parent_widget.dart b/lib/widgets/treeview_parent_widget.dart
index a31561a..67200c0 100644
--- a/lib/widgets/treeview_parent_widget.dart
+++ b/lib/widgets/treeview_parent_widget.dart
@@ -4,21 +4,23 @@ import 'package:google_fonts/google_fonts.dart';
 
 class TreeviewParentWidget extends StatelessWidget {
   final String text;
+  final Color backgroundColor;
+  final Color color;
   //final DateTime lastModified;
 
-  TreeviewParentWidget({@required this.text});
+  TreeviewParentWidget({@required this.text, this.backgroundColor = Colors.white38, this.color});
 
   @override
   Widget build(BuildContext context) {
     Widget parentWidget = Text(
       this.text,
-      style: GoogleFonts.archivoBlack(fontSize: 24, color: Colors.blue[800], backgroundColor: Colors.transparent),
+      style: GoogleFonts.archivoBlack(fontSize: 24, color: color ?? Colors.blue[800], backgroundColor: Colors.transparent),
     );
 
     Icon icon = Icon(Icons.person);
 
     return Card(
-      color: Colors.white38,
+      color: backgroundColor,
       shadowColor: Colors.black54,
       elevation: 0.0,
       child: ListTile(
diff --git a/pubspec.lock b/pubspec.lock
index 1ace789..692d4c8 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -84,7 +84,7 @@ packages:
       name: build
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.6.0"
+    version: "1.6.1"
   build_config:
     dependency: transitive
     description:
@@ -98,28 +98,28 @@ packages:
       name: build_daemon
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.1.4"
+    version: "2.1.6"
   build_resolvers:
     dependency: transitive
     description:
       name: build_resolvers
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.5.1"
+    version: "1.5.2"
   build_runner:
     dependency: "direct dev"
     description:
       name: build_runner
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.10.11"
+    version: "1.10.13"
   build_runner_core:
     dependency: transitive
     description:
       name: build_runner_core
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "6.1.5"
+    version: "6.1.6"
   built_collection:
     dependency: transitive
     description:
@@ -189,7 +189,7 @@ packages:
       name: code_builder
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.5.0"
+    version: "3.6.0"
   collection:
     dependency: transitive
     description:
@@ -432,7 +432,7 @@ packages:
       name: flutter_html
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.1.1"
+    version: "1.2.0"
   flutter_keyboard_visibility:
     dependency: transitive
     description:
@@ -447,6 +447,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.8.1"
+  flutter_layout_grid:
+    dependency: transitive
+    description:
+      name: flutter_layout_grid
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.10.3"
   flutter_localizations:
     dependency: "direct main"
     description: flutter
@@ -713,7 +720,7 @@ packages:
       name: path_provider
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.6.24"
+    version: "1.6.27"
   path_provider_linux:
     dependency: transitive
     description:
@@ -727,7 +734,7 @@ packages:
       name: path_provider_macos
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.0.4+6"
+    version: "0.0.4+8"
   path_provider_platform_interface:
     dependency: transitive
     description:
@@ -797,7 +804,7 @@ packages:
       name: provider
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "4.3.2+3"
+    version: "4.3.2+4"
   pub_semver:
     dependency: transitive
     description:
@@ -812,6 +819,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.1.7"
+  purchases_flutter:
+    dependency: "direct main"
+    description:
+      name: purchases_flutter
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.0.0"
   quiver:
     dependency: transitive
     description:
@@ -846,7 +860,7 @@ packages:
       name: sentry
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.0.1"
+    version: "4.0.3"
   shared_preferences:
     dependency: "direct dev"
     description:
@@ -963,14 +977,14 @@ packages:
       name: sqflite
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.2+1"
+    version: "1.3.2+2"
   sqflite_common:
     dependency: transitive
     description:
       name: sqflite_common
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.0.2+1"
+    version: "1.0.3"
   stack_trace:
     dependency: transitive
     description:
@@ -1041,6 +1055,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.3.12-nullsafety.5"
+  timeline_tile:
+    dependency: "direct main"
+    description:
+      name: timeline_tile
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.0"
   timing:
     dependency: transitive
     description:
@@ -1062,13 +1083,6 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "1.3.0-nullsafety.3"
-  usage:
-    dependency: transitive
-    description:
-      name: usage
-      url: "https://pub.dartlang.org"
-    source: hosted
-    version: "3.4.2"
   uuid:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 9c4cb66..8fea36d 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
 # Read more about iOS versioning at
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
-version: 1.1.4+46
+version: 1.1.5+48
 
 environment:
   sdk: ">=2.7.0 <3.0.0"
@@ -27,7 +27,7 @@ dependencies:
   cupertino_icons: ^1.0.0
   google_fonts: ^1.1.1
   devicelocale: ^0.3.3
-  sentry: ^3.0.1
+  sentry: ^4.0.3
   flutter_bloc: ^6.1.1
   equatable: ^1.2.5
   #freezed: ^0.12.2
@@ -45,11 +45,12 @@ dependencies:
   #health: ^3.0.0
   stop_watch_timer: ^0.6.0+1
   #geolocator: ^6.1.13
-  #flutter_inapp_purchase: ^3.0.1
   modal_progress_hud: ^0.1.3
   flutter_html: ^1.1.1
   wakelock: ^0.2.1+1
-
+  timeline_tile: ^1.0.0
+  purchases_flutter: ^2.0.0
+  
 
   firebase_core: ^0.5.0
   firebase_analytics: ^6.2.0
diff --git a/test_driver/service/customer_service.dart b/test_driver/service/customer_service.dart
index 865ed0e..d16e1c2 100644
--- a/test_driver/service/customer_service.dart
+++ b/test_driver/service/customer_service.dart
@@ -1,5 +1,3 @@
-import 'dart:html';
-
 import 'package:aitrainer_app/model/customer.dart';
 import 'package:flutter/material.dart';
 import '../../lib/helper/database.dart';