WT 1.1.0+39 evaluation, health data
BIN
asset/icon/gomb_orange_c.png
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
asset/image/WT_Results_for_female.png
Normal file
After Width: | Height: | Size: 2.9 MiB |
BIN
asset/image/WT_Results_for_men.png
Normal file
After Width: | Height: | Size: 2.8 MiB |
BIN
asset/image/WT_Results_for_runners.png
Normal file
After Width: | Height: | Size: 5.4 MiB |
BIN
asset/image/pict_calorie.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
asset/image/pict_development_by_bodypart_percent.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
asset/image/pict_distance_m.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
asset/image/pict_fatburn_percent.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
asset/image/pict_hravg_bpm.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
asset/image/pict_hrmax_bpm.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
asset/image/pict_hrmin_bpm.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
asset/image/pict_hypertrophy.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
asset/image/pict_maxspeed_kmh.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
asset/image/pict_reps_volumen_db.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
asset/image/pict_steps.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
asset/image/pict_time_h.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
asset/image/pict_weight_volumen_tonna.png
Normal file
After Width: | Height: | Size: 32 KiB |
17
i18n/en.json
@ -235,5 +235,20 @@
|
||||
"Live-Server":"Live-Server",
|
||||
"Test-Server":"Test-Server",
|
||||
"All Exercises has been filtered out":"All Exercises has been filtered out",
|
||||
"base":"base"
|
||||
"base":"base",
|
||||
"Hypertrophy":"Hypertrophy",
|
||||
"Gain Strength":"Gain Strength",
|
||||
"repeats":"repeats",
|
||||
"minutes":"minutes",
|
||||
"Rest time":"Rest time",
|
||||
"Suggestions based on your test":"Suggestions based on your test",
|
||||
"Repeats volume":"Repeats volume",
|
||||
"Weight volume":"Weight volume",
|
||||
"Calorie":"Calorie",
|
||||
"Max BPM":"Max BPM",
|
||||
"Min BPM":"Min BPM",
|
||||
"Average BPM":"Average BPM",
|
||||
"Fatburn %":"Fatburn %",
|
||||
"Health Data Summary":"Health Data Summary"
|
||||
|
||||
}
|
17
i18n/hu.json
@ -236,5 +236,20 @@
|
||||
"Live-Server":"Live-Server",
|
||||
"Test-Server":"Test-Server",
|
||||
"All Exercises has been filtered out":"Az összes gyakorlatot kiszűrted",
|
||||
"base":"alap"
|
||||
"base":"alap",
|
||||
"Hypertrophy":"Izomnövelés",
|
||||
"Gain Strength":"Erőnövelés",
|
||||
"repeats":"ismétlés",
|
||||
"Rest time":"Pihenőidő",
|
||||
"minutes":"perc",
|
||||
"Suggestions based on your test":"Javaslatok a teszted alapján",
|
||||
"Repeats volume":"Össz. ismétlés",
|
||||
"Weight volume":"Össztömeg",
|
||||
"Calorie":"Kalória",
|
||||
"Max BPM":"Max pulzus",
|
||||
"Min BPM":"Min pulzus",
|
||||
"Average BPM":"Átl pulzus",
|
||||
"Fatburn %":"Zsírégetés %",
|
||||
"Health Data Summary":"Egészségadatok összefoglalás"
|
||||
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
PODS:
|
||||
- device_info (0.0.1):
|
||||
- Flutter
|
||||
- devicelocale (0.0.1):
|
||||
- Flutter
|
||||
- Firebase/Auth (6.33.0):
|
||||
@ -84,6 +86,8 @@ PODS:
|
||||
- GoogleUtilities/UserDefaults (6.7.2):
|
||||
- GoogleUtilities/Logger
|
||||
- GTMSessionFetcher/Core (1.5.0)
|
||||
- health (1.0.1):
|
||||
- Flutter
|
||||
- nanopb (1.30906.0):
|
||||
- nanopb/decode (= 1.30906.0)
|
||||
- nanopb/encode (= 1.30906.0)
|
||||
@ -100,6 +104,7 @@ PODS:
|
||||
- FMDB (>= 2.7.5)
|
||||
|
||||
DEPENDENCIES:
|
||||
- device_info (from `.symlinks/plugins/device_info/ios`)
|
||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
@ -107,6 +112,7 @@ DEPENDENCIES:
|
||||
- flurry (from `.symlinks/plugins/flurry/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||
- health (from `.symlinks/plugins/health/ios`)
|
||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
@ -130,6 +136,8 @@ SPEC REPOS:
|
||||
- Protobuf
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
device_info:
|
||||
:path: ".symlinks/plugins/device_info/ios"
|
||||
devicelocale:
|
||||
:path: ".symlinks/plugins/devicelocale/ios"
|
||||
firebase_auth:
|
||||
@ -144,6 +152,8 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter
|
||||
flutter_keyboard_visibility:
|
||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||
health:
|
||||
:path: ".symlinks/plugins/health/ios"
|
||||
path_provider:
|
||||
:path: ".symlinks/plugins/path_provider/ios"
|
||||
shared_preferences:
|
||||
@ -152,6 +162,7 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/sqflite/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
|
||||
devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00
|
||||
Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5
|
||||
firebase_auth: cb33b01b51904969161403bbcb20036519f0c578
|
||||
@ -171,6 +182,7 @@ SPEC CHECKSUMS:
|
||||
GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
|
||||
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
|
||||
GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52
|
||||
health: 44840ad4328aa5586e77bef289898bfed644a81c
|
||||
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
|
||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||
PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f
|
||||
|
@ -15,6 +15,7 @@
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
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 */; };
|
||||
BBDBEBB825862170006762F6 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBDBEBB725862170006762F6 /* HealthKit.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
@ -48,6 +49,7 @@
|
||||
BB43773E2540715900D74BFA /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
BBDBEBB725862170006762F6 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.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 */
|
||||
@ -58,6 +60,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
42B6B159AF35AFB6DE777DFB /* Pods_Runner.framework in Frameworks */,
|
||||
BBDBEBB825862170006762F6 /* HealthKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -77,6 +80,7 @@
|
||||
3ADC50290ED054951FAC1F56 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BBDBEBB725862170006762F6 /* HealthKit.framework */,
|
||||
09BD889296C5C90D989820C8 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
@ -362,7 +366,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 38;
|
||||
CURRENT_PROJECT_VERSION = 39;
|
||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -505,7 +509,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 38;
|
||||
CURRENT_PROJECT_VERSION = 39;
|
||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -540,7 +544,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 38;
|
||||
CURRENT_PROJECT_VERSION = 39;
|
||||
DEVELOPMENT_TEAM = SFJJBDCU6Z;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
@ -46,6 +46,10 @@
|
||||
<string>10.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSHealthShareUsageDescription</key>
|
||||
<string>We will sync your data with the Apple Health app to give you better insights</string>
|
||||
<key>NSHealthUpdateUsageDescription</key>
|
||||
<string>We will sync your data with the Apple Health app to give you better insights</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
|
@ -4,5 +4,11 @@
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.healthkit</key>
|
||||
<true/>
|
||||
<key>com.apple.developer.healthkit.access</key>
|
||||
<array>
|
||||
<string>health-records</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -23,6 +23,8 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
double firstQuantity; // quantity of the first test
|
||||
double firstUnitQuantity; // unit quantity of the first test
|
||||
|
||||
double scrollOffset = 0;
|
||||
|
||||
@override
|
||||
ExerciseControlBloc({this.exerciseRepository, this.readonly, this.percentToCalculate}) : super(ExerciseControlInitial()) {
|
||||
firstUnitQuantity = exerciseRepository.exercise.unitQuantity;
|
||||
@ -36,7 +38,6 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
origQuantity = quantity;
|
||||
|
||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
@ -46,23 +47,31 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
yield ExerciseControlLoading();
|
||||
step = 1;
|
||||
yield ExerciseControlReady();
|
||||
} else if (event is ExerciseControlQuantityChange ) {
|
||||
} else if (event is ExerciseControlQuantityChange) {
|
||||
yield ExerciseControlLoading();
|
||||
if ( event.step == step) {
|
||||
if (event.step == step) {
|
||||
exerciseRepository.setQuantity(event.quantity);
|
||||
quantity = event.quantity;
|
||||
}
|
||||
yield ExerciseControlReady();
|
||||
} else if (event is ExerciseControlSubmit ) {
|
||||
} else if (event is ExerciseControlSubmit) {
|
||||
yield ExerciseControlLoading();
|
||||
if ( event.step == step) {
|
||||
if (event.step == step) {
|
||||
step++;
|
||||
//print("step " + step.toString() + " quantity " + quantity.toString() + " origQ: " + origQuantity.toString());
|
||||
scrollOffset = step * 200.0;
|
||||
print("step " +
|
||||
step.toString() +
|
||||
" quantity " +
|
||||
quantity.toString() +
|
||||
" origQuantity: " +
|
||||
origQuantity.toString() +
|
||||
" scrollOffset: " +
|
||||
scrollOffset.toString());
|
||||
repeats.add(quantity);
|
||||
quantity = origQuantity;
|
||||
exerciseRepository.end = DateTime.now();
|
||||
await exerciseRepository.addExercise();
|
||||
|
||||
|
||||
exerciseRepository.setQuantity(quantity);
|
||||
}
|
||||
yield ExerciseControlReady();
|
||||
@ -78,7 +87,7 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
||||
}
|
||||
double weight = exerciseRepository.exercise.unitQuantity;
|
||||
double repeat = exerciseRepository.exercise.quantity;
|
||||
if ( weight == 0 || repeat == 0) {
|
||||
if (weight == 0 || repeat == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ import 'package:flutter/animation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:stop_watch_timer/stop_watch_timer.dart';
|
||||
|
||||
part 'exercise_new_event.dart';
|
||||
part 'exercise_new_state.dart';
|
||||
@ -45,6 +46,11 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
|
||||
double mediaHeight = 0;
|
||||
bool isMan = true;
|
||||
|
||||
final StopWatchTimer stopWatchTimer = StopWatchTimer(
|
||||
isLapHours: false,
|
||||
);
|
||||
int timerValue;
|
||||
|
||||
@override
|
||||
ExerciseNewBloc({this.exerciseRepository, this.menuBloc, this.customerRepository, ExerciseType exerciseType})
|
||||
: super(ExerciseNewInitial()) {
|
||||
@ -52,14 +58,15 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
|
||||
exerciseRepository.setQuantity(quantity);
|
||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||
exerciseRepository.exercise.exercisePlanDetailId = 0;
|
||||
exerciseRepository.start = DateTime.now();
|
||||
if (Cache().userLoggedIn != null) {
|
||||
customerRepository.customer = Cache().userLoggedIn;
|
||||
weight = customerRepository.customer.getProperty("Weight");
|
||||
height = customerRepository.customer.getProperty("Height");
|
||||
fitnessLevel = customerRepository.customer.fitnessLevel;
|
||||
this.isMan = (customerRepository.customer.sex == "m");
|
||||
print("Sex Man? " + isMan.toString() + " " + customerRepository.customer.sex);
|
||||
}
|
||||
stopWatchTimer.rawTime.listen((value) => timerValue = value);
|
||||
}
|
||||
|
||||
void setMediaDimensions(double width, double height) {
|
||||
@ -75,7 +82,6 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
|
||||
}
|
||||
final double distortionWidth = mediaWidth / baseWidth;
|
||||
final double distortionHeight = mediaHeight / baseHeight;
|
||||
print("distiortionW " + distortionWidth.toString() + " dH " + distortionHeight.toString());
|
||||
if (isMan) {
|
||||
properties.forEach((element) {
|
||||
if (element.propertyName == "Shoulder") {
|
||||
@ -146,12 +152,10 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
|
||||
element.top = (122 * distortionHeight).toInt();
|
||||
element.left = (151 * distortionWidth).toInt();
|
||||
element.value = customerRepository.customer.getProperty("Shoulder");
|
||||
print("CHEST top: " + element.top.toString() + " left " + element.left.toString());
|
||||
manSizes.add(element);
|
||||
} else if (element.propertyName == "Neck") {
|
||||
element.top = (78 * distortionHeight).toInt();
|
||||
element.left = (151 * distortionWidth).toInt();
|
||||
print("Neck top: " + element.top.toString() + " left " + element.left.toString());
|
||||
element.value = customerRepository.customer.getProperty("Neck");
|
||||
manSizes.add(element);
|
||||
} else if (element.propertyName == "Biceps") {
|
||||
@ -279,6 +283,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
|
||||
yield ExerciseNewReady();
|
||||
} else if (event is ExerciseNewSubmit) {
|
||||
yield ExerciseNewLoading();
|
||||
exerciseRepository.end = DateTime.now();
|
||||
await exerciseRepository.addExercise();
|
||||
menuBloc.add(MenuTreeDown(parent: 0));
|
||||
Cache().initBadges();
|
||||
@ -373,4 +378,9 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> {
|
||||
|
||||
return goalBMI;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() async {
|
||||
await stopWatchTimer.dispose();
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_device_repository.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
@ -15,8 +16,6 @@ import 'package:meta/meta.dart';
|
||||
part 'menu_event.dart';
|
||||
part 'menu_state.dart';
|
||||
|
||||
enum ExerciseAbility { oneRepMax, endurance, none }
|
||||
|
||||
class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
|
||||
final WorkoutTreeRepository menuTreeRepository;
|
||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||
@ -106,8 +105,9 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
|
||||
yield MenuLoading();
|
||||
parent = event.parent;
|
||||
workoutItem = event.item;
|
||||
if (workoutItem != null) {
|
||||
setAbility(workoutItem.nameEnglish);
|
||||
//print("menuitem " + workoutItem.id.toString() + " parent "+workoutItem.parent.toString());
|
||||
}
|
||||
menuTreeRepository.getBranch(event.parent);
|
||||
yield MenuReady();
|
||||
} else if (event is MenuTreeUp) {
|
||||
@ -117,7 +117,6 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
|
||||
workoutItem = menuTreeRepository.getParentItem(parent);
|
||||
|
||||
if (workoutItem != null) {
|
||||
//print("UP menuitem " + workoutItem.id.toString() + " parent " + workoutItem.parent.toString());
|
||||
menuTreeRepository.getBranch(workoutItem.parent);
|
||||
setAbility(workoutItem.nameEnglish);
|
||||
}
|
||||
@ -128,7 +127,6 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
|
||||
workoutItem = menuTreeRepository.getParentItem(parent);
|
||||
|
||||
if (workoutItem != null) {
|
||||
//print("JUMP menuitem " + workoutItem.id.toString() + " parent " + workoutItem.parent.toString());
|
||||
menuTreeRepository.getBranch(workoutItem.parent);
|
||||
setAbility(workoutItem.nameEnglish);
|
||||
}
|
||||
|
225
lib/bloc/result/result_bloc.dart
Normal file
@ -0,0 +1,225 @@
|
||||
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';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
import 'package:health/health.dart';
|
||||
|
||||
part 'result_event.dart';
|
||||
part 'result_state.dart';
|
||||
|
||||
class ResultBloc extends Bloc<ResultEvent, ResultState> {
|
||||
final ExerciseResultRepository resultRepository;
|
||||
final ExerciseRepository exerciseRepository;
|
||||
List<HealthDataPoint> _healthDataList = List();
|
||||
DateTime startTime;
|
||||
DateTime endTime;
|
||||
final HealthFactory health = HealthFactory();
|
||||
final List<HealthDataType> types = [
|
||||
HealthDataType.ACTIVE_ENERGY_BURNED,
|
||||
HealthDataType.WATER,
|
||||
HealthDataType.STEPS,
|
||||
HealthDataType.HEART_RATE,
|
||||
HealthDataType.BASAL_ENERGY_BURNED,
|
||||
HealthDataType.BODY_TEMPERATURE,
|
||||
HealthDataType.HIGH_HEART_RATE_EVENT,
|
||||
HealthDataType.LOW_HEART_RATE_EVENT,
|
||||
HealthDataType.RESTING_HEART_RATE
|
||||
];
|
||||
|
||||
ResultBloc({this.resultRepository, this.exerciseRepository}) : super(ResultInitial()) {
|
||||
this.startTime = exerciseRepository.start;
|
||||
this.endTime = exerciseRepository.end;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<ResultState> mapEventToState(
|
||||
ResultEvent event,
|
||||
) async* {
|
||||
try {
|
||||
if (event is ResultLoad) {
|
||||
yield ResultLoading();
|
||||
|
||||
await _fetchHealthData();
|
||||
_matchExerciseData();
|
||||
yield ResultReady();
|
||||
}
|
||||
} on Exception catch (ex) {
|
||||
yield ResultError(error: ex.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void _matchExerciseData() {
|
||||
resultRepository.getResults().forEach((element) {
|
||||
switch (element.item) {
|
||||
case ResultItem.bpm_avg:
|
||||
element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.bpm_min:
|
||||
element.data = element.data = _gethHealthDataPointValueMin(HealthDataType.HEART_RATE).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.bpm_max:
|
||||
element.data = element.data = _gethHealthDataPointValueMax(HealthDataType.HEART_RATE).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.calorie:
|
||||
element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED).toStringAsFixed(0);
|
||||
break;
|
||||
case ResultItem.development_percent_bodypart:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
case ResultItem.distance:
|
||||
if (exerciseRepository.exerciseType.unit == "meter") {
|
||||
element.data = exerciseRepository.exercise.quantity.toStringAsFixed(0);
|
||||
}
|
||||
break;
|
||||
case ResultItem.fatburn_percent:
|
||||
DateTime today = DateTime.now();
|
||||
int age = today.year - Cache().userLoggedIn.birthYear;
|
||||
double minBpm = (200 - age) * 0.6;
|
||||
double maxBpm = (200 - age) * 0.7;
|
||||
int counter = 0;
|
||||
int burnCounter = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == HealthDataType.ACTIVE_ENERGY_BURNED) {
|
||||
if (dataPoint.value >= minBpm && dataPoint.value <= maxBpm) {
|
||||
burnCounter++;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
if (counter > 0) {
|
||||
element.data = (burnCounter / counter * 100).toStringAsFixed(2);
|
||||
} else {
|
||||
element.data = "0";
|
||||
}
|
||||
break;
|
||||
case ResultItem.speed_max:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
case ResultItem.reps_volume:
|
||||
if (exerciseRepository.exerciseType.unit == "repeat") {
|
||||
double value = 0;
|
||||
exerciseRepository.actualExerciseList.forEach((element) {
|
||||
value += element.quantity;
|
||||
});
|
||||
element.data = value.toStringAsFixed(0);
|
||||
}
|
||||
break;
|
||||
case ResultItem.steps:
|
||||
element.data = _gethHealthDataPointValueSum(HealthDataType.STEPS).toStringAsFixed(0);
|
||||
break;
|
||||
/* case ResultItem.time:
|
||||
final Duration duration = this.endTime.difference(this.startTime);
|
||||
element.data = _printDuration(duration);
|
||||
break; */
|
||||
case ResultItem.weight_volume:
|
||||
if (exerciseRepository.exerciseType.unitQuantityUnit == "kilogram") {
|
||||
double value = 0;
|
||||
exerciseRepository.actualExerciseList.forEach((element) {
|
||||
value += element.quantity * element.unitQuantity;
|
||||
});
|
||||
element.data = value.toStringAsFixed(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String _printDuration(Duration duration) {
|
||||
String twoDigits(int n) => n.toString().padLeft(2, "0");
|
||||
String twoDigitMinutes = twoDigits(duration.inMinutes);
|
||||
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
|
||||
String twoDigitMilliSeconds = duration.inMilliseconds.remainder(1000).toString();
|
||||
return "$twoDigitMinutes:$twoDigitSeconds:$twoDigitMilliSeconds" + '"';
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueAvg(HealthDataType dataType) {
|
||||
double value = 0;
|
||||
double counter = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
value += dataPoint.value;
|
||||
counter++;
|
||||
}
|
||||
});
|
||||
double avg = 0;
|
||||
if (counter > 0) {
|
||||
avg = value / counter;
|
||||
}
|
||||
return avg;
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueSum(HealthDataType dataType) {
|
||||
double value = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
value += dataPoint.value;
|
||||
}
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueMax(HealthDataType dataType) {
|
||||
double max = 0;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
if (max < dataPoint.value) {
|
||||
max = dataPoint.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
return max;
|
||||
}
|
||||
|
||||
double _gethHealthDataPointValueMin(HealthDataType dataType) {
|
||||
double min = 9999999;
|
||||
_healthDataList.forEach((dataPoint) {
|
||||
if (dataPoint.type == dataType) {
|
||||
if (min > dataPoint.value && dataPoint.value != 0) {
|
||||
min = dataPoint.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (min == 9999999) {
|
||||
min = 0;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
Future<void> _fetchHealthData() async {
|
||||
if (health == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
print("Get Health data between " + startTime.toString() + " AND " + endTime.toString());
|
||||
_healthDataList = await health.getHealthDataFromTypes(this.startTime, this.endTime, types);
|
||||
_healthDataList.forEach((element) {
|
||||
print(element.toString());
|
||||
});
|
||||
} on Exception catch (e) {
|
||||
print("Caught exception in getHealthDataFromTypes: $e");
|
||||
throw Exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
double calculate1RM({double percent}) {
|
||||
if (exerciseRepository.exercise == null) {
|
||||
exerciseRepository.getLastExercise();
|
||||
}
|
||||
double weight = exerciseRepository.exercise.unitQuantity;
|
||||
double repeat = exerciseRepository.exercise.quantity;
|
||||
if (weight == 0 || repeat == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double rmWendler = weight * repeat * 0.0333 + weight;
|
||||
double rmOconner = weight * (1 + repeat / 40);
|
||||
double average = (rmWendler + rmOconner) / 2;
|
||||
|
||||
return average * percent;
|
||||
}
|
||||
}
|
12
lib/bloc/result/result_event.dart
Normal file
@ -0,0 +1,12 @@
|
||||
part of 'result_bloc.dart';
|
||||
|
||||
abstract class ResultEvent extends Equatable {
|
||||
const ResultEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ResultLoad extends ResultEvent {
|
||||
const ResultLoad();
|
||||
}
|
28
lib/bloc/result/result_state.dart
Normal file
@ -0,0 +1,28 @@
|
||||
part of 'result_bloc.dart';
|
||||
|
||||
abstract class ResultState extends Equatable {
|
||||
const ResultState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class ResultInitial extends ResultState {
|
||||
const ResultInitial();
|
||||
}
|
||||
|
||||
class ResultLoading extends ResultState {
|
||||
const ResultLoading();
|
||||
}
|
||||
|
||||
class ResultReady extends ResultState {
|
||||
const ResultReady();
|
||||
}
|
||||
|
||||
class ResultError extends ResultState {
|
||||
final String error;
|
||||
const ResultError({this.error});
|
||||
|
||||
@override
|
||||
List<Object> get props => [this.error];
|
||||
}
|
@ -2,9 +2,11 @@ import 'dart:async';
|
||||
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:health/health.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
part 'settings_event.dart';
|
||||
@ -31,18 +33,52 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
||||
) async* {
|
||||
if (event is SettingsChangeLanguage) {
|
||||
yield SettingsLoading();
|
||||
await _changeLang( event.language);
|
||||
await _changeLang(event.language);
|
||||
yield SettingsReady(_locale);
|
||||
} else if ( event is SettingsGetLanguage) {
|
||||
} else if (event is SettingsGetLanguage) {
|
||||
await AppLanguage().fetchLocale();
|
||||
_locale = AppLanguage().appLocal;
|
||||
yield SettingsReady(_locale);
|
||||
} else if (event is SettingsSetServer) {
|
||||
yield SettingsLoading();
|
||||
final bool live = event.live;
|
||||
Cache().setServer(live);
|
||||
yield SettingsReady(_locale);
|
||||
} else if (event is SettingsSetHardware) {
|
||||
yield SettingsLoading();
|
||||
|
||||
bool selectedHardwareBefore = await Cache().selectedHardwareBefore();
|
||||
print("selectedBefore " + selectedHardwareBefore.toString());
|
||||
if (!selectedHardwareBefore) {
|
||||
await _accessHealthData();
|
||||
}
|
||||
final bool hasHardware = event.hasHardware;
|
||||
await Cache().setHardware(hasHardware);
|
||||
yield SettingsReady(_locale);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _changeLang( String lang ) async{
|
||||
Future<void> _accessHealthData() async {
|
||||
final List<HealthDataType> types = [
|
||||
HealthDataType.ACTIVE_ENERGY_BURNED,
|
||||
HealthDataType.WATER,
|
||||
HealthDataType.STEPS,
|
||||
HealthDataType.HEART_RATE,
|
||||
HealthDataType.BASAL_ENERGY_BURNED,
|
||||
HealthDataType.BODY_TEMPERATURE,
|
||||
HealthDataType.HIGH_HEART_RATE_EVENT,
|
||||
HealthDataType.LOW_HEART_RATE_EVENT,
|
||||
HealthDataType.RESTING_HEART_RATE
|
||||
];
|
||||
final HealthFactory health = HealthFactory();
|
||||
DateTime now = DateTime.now();
|
||||
List<HealthDataPoint> _healthDataList = await health.getHealthDataFromTypes(now.subtract(Duration(minutes: 5)), now, types);
|
||||
print(_healthDataList.toString());
|
||||
}
|
||||
|
||||
Future<void> _changeLang(String lang) async {
|
||||
print("_change to $lang");
|
||||
switch ( lang ) {
|
||||
switch (lang) {
|
||||
case "English":
|
||||
case "en":
|
||||
case "Angol":
|
||||
@ -59,8 +95,8 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
||||
await loadLang();
|
||||
}
|
||||
|
||||
Future<void> loadLang() async{
|
||||
if ( _locale != null ) {
|
||||
Future<void> loadLang() async {
|
||||
if (_locale != null) {
|
||||
print(" -- Loading lang $_locale");
|
||||
if (context != null) {
|
||||
AppLocalizations.of(context).setLocale(_locale);
|
||||
|
@ -15,3 +15,19 @@ class SettingsChangeLanguage extends SettingsEvent {
|
||||
class SettingsGetLanguage extends SettingsEvent {
|
||||
const SettingsGetLanguage();
|
||||
}
|
||||
|
||||
class SettingsSetServer extends SettingsEvent {
|
||||
final bool live;
|
||||
const SettingsSetServer({this.live});
|
||||
|
||||
@override
|
||||
List<Object> get props => [this.live];
|
||||
}
|
||||
|
||||
class SettingsSetHardware extends SettingsEvent {
|
||||
final bool hasHardware;
|
||||
const SettingsSetHardware({this.hasHardware});
|
||||
|
||||
@override
|
||||
List<Object> get props => [this.hasHardware];
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import 'package:aitrainer_app/view/customer_fitness_page.dart';
|
||||
import 'package:aitrainer_app/view/customer_goal_page.dart';
|
||||
import 'package:aitrainer_app/view/customer_modify_page.dart';
|
||||
import 'package:aitrainer_app/view/customer_welcome_page.dart';
|
||||
import 'package:aitrainer_app/view/evaluation.dart';
|
||||
import 'package:aitrainer_app/view/exercise_control_page.dart';
|
||||
import 'package:aitrainer_app/view/exercise_execute_page.dart';
|
||||
import 'package:aitrainer_app/view/exercise_execute_plan_add_page.dart';
|
||||
@ -216,6 +217,7 @@ class WorkoutTestApp extends StatelessWidget {
|
||||
'exerciseExecuteAddPage': (context) => ExerciseExecutePlanAddPage(),
|
||||
'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(),
|
||||
'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(),
|
||||
'evaluationPage': (context) => EvaluationPage(),
|
||||
},
|
||||
initialRoute: 'home',
|
||||
title: 'WorkoutTest',
|
||||
|
@ -55,6 +55,7 @@ class Cache {
|
||||
static final String isLoggedInKey = 'is_logged_in';
|
||||
static final String langKey = 'lang';
|
||||
static final String serverKey = 'live';
|
||||
static final String hardwareKey = 'hardware';
|
||||
|
||||
static String baseUrl = 'http://aitrainer.info:8888/api/';
|
||||
static final String mediaUrl = 'https://aitrainer.info:4343/media/';
|
||||
@ -92,6 +93,7 @@ class Cache {
|
||||
String startPage;
|
||||
String testEnvironment;
|
||||
bool liveServer = true;
|
||||
bool hasHardware = false;
|
||||
|
||||
factory Cache() {
|
||||
return _singleton;
|
||||
@ -114,7 +116,7 @@ class Cache {
|
||||
return this.authToken;
|
||||
}
|
||||
|
||||
void setServer(bool live) async {
|
||||
Future<void> setServer(bool live) async {
|
||||
if (this.testEnvironment == "1") {
|
||||
liveServer = false;
|
||||
live = false;
|
||||
@ -123,10 +125,34 @@ class Cache {
|
||||
SharedPreferences sharedPreferences;
|
||||
sharedPreferences = await prefs;
|
||||
liveServer = live;
|
||||
print("Set Live servier. live? " + live.toString() + " env? " + this.testEnvironment);
|
||||
sharedPreferences.setBool(Cache.serverKey, live);
|
||||
}
|
||||
|
||||
void getHardware(SharedPreferences prefs) {
|
||||
final bool hasHardware = prefs.getBool(Cache.hardwareKey);
|
||||
print("Has Hardware: " + hasHardware.toString());
|
||||
this.hasHardware = hasHardware;
|
||||
if (hasHardware == null) {
|
||||
this.hasHardware = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> selectedHardwareBefore() async {
|
||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||
SharedPreferences sharedPreferences = await prefs;
|
||||
|
||||
final bool selectedHardware = sharedPreferences.getBool(Cache.hardwareKey);
|
||||
return selectedHardware == null;
|
||||
}
|
||||
|
||||
Future<void> setHardware(bool hasHardware) async {
|
||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||
SharedPreferences sharedPreferences;
|
||||
sharedPreferences = await prefs;
|
||||
sharedPreferences.setBool(Cache.hardwareKey, hasHardware);
|
||||
this.hasHardware = hasHardware;
|
||||
}
|
||||
|
||||
void setServerAddress(SharedPreferences prefs) {
|
||||
if (this.testEnvironment == "1") {
|
||||
baseUrl = 'http://aitrainer.app:8899/api/';
|
||||
|
6
lib/model/exercise_ability.dart
Normal file
@ -0,0 +1,6 @@
|
||||
enum ExerciseAbility { oneRepMax, endurance, running, none }
|
||||
|
||||
extension ExerciseAbilityExt on ExerciseAbility {
|
||||
bool equalsTo(ExerciseAbility ability) => this.toString() == ability.toString();
|
||||
bool equalsStringTo(String ability) => this.toString() == ability;
|
||||
}
|
44
lib/model/exercise_result.dart
Normal file
@ -0,0 +1,44 @@
|
||||
import 'package:aitrainer_app/model/result.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
|
||||
class ExerciseResult {
|
||||
int exerciseResultId;
|
||||
int customerId;
|
||||
int exerciseId;
|
||||
int exercisePlanId;
|
||||
String resultType;
|
||||
double value;
|
||||
DateTime dateFrom;
|
||||
DateTime dateTo;
|
||||
|
||||
ResultExt resultExtension;
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
String formattedDateTo;
|
||||
if (dateTo != null) {
|
||||
formattedDateTo = DateFormat('yyyy-MM-dd HH:mm').format(dateTo);
|
||||
}
|
||||
|
||||
return {
|
||||
"customerId": customerId,
|
||||
"exerciseId": exerciseId,
|
||||
"exercisePlanId": exercisePlanId,
|
||||
"resultType": resultType,
|
||||
"value": value,
|
||||
"dateFrom": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateFrom),
|
||||
"dateTo": formattedDateTo,
|
||||
};
|
||||
}
|
||||
|
||||
ExerciseResult.fromJson(Map json) {
|
||||
this.exerciseResultId = json['exerciseResultId'];
|
||||
this.exerciseId = json['exerciseId'];
|
||||
this.exercisePlanId = json['exercisePlanId'];
|
||||
this.customerId = json['customerId'];
|
||||
this.resultType = json['resultType'];
|
||||
this.value = json["value"];
|
||||
this.dateFrom = DateTime.parse(json['dateFrom']);
|
||||
this.dateTo = DateTime.parse(json['dateTo']);
|
||||
this.resultExtension = ResultExt(itemString: this.resultType);
|
||||
}
|
||||
}
|
@ -37,6 +37,7 @@ class ExerciseTree {
|
||||
if (parentId != -1) {
|
||||
newTree.parentId = parentId;
|
||||
}
|
||||
newTree.active = this.active;
|
||||
|
||||
return newTree;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class ExerciseType {
|
||||
@ -17,8 +18,7 @@ class ExerciseType {
|
||||
List<int> devices = List();
|
||||
List<int> parents = List();
|
||||
|
||||
bool is1RM;
|
||||
bool isEndurance;
|
||||
ExerciseAbility ability;
|
||||
|
||||
ExerciseType({this.name, this.description});
|
||||
|
||||
@ -70,19 +70,19 @@ class ExerciseType {
|
||||
"parents": this.parents.toString()
|
||||
};
|
||||
|
||||
void set1RM(bool is1RM) {
|
||||
this.is1RM = is1RM;
|
||||
void setAbility(ExerciseAbility ability) {
|
||||
this.ability = ability;
|
||||
}
|
||||
|
||||
bool get1RM() {
|
||||
return this.is1RM;
|
||||
ExerciseAbility getAbility() {
|
||||
return this.ability;
|
||||
}
|
||||
|
||||
void setEndurance(bool isEndurance) {
|
||||
this.isEndurance = isEndurance;
|
||||
bool isEndurance() {
|
||||
return this.ability.equalsTo(ExerciseAbility.endurance);
|
||||
}
|
||||
|
||||
bool getEndurance() {
|
||||
return this.isEndurance;
|
||||
bool is1RM() {
|
||||
return this.ability.equalsTo(ExerciseAbility.oneRepMax);
|
||||
}
|
||||
}
|
||||
|
93
lib/model/result.dart
Normal file
@ -0,0 +1,93 @@
|
||||
enum ResultItem {
|
||||
calorie,
|
||||
development_percent_bodypart,
|
||||
distance,
|
||||
fatburn_percent,
|
||||
bpm_avg,
|
||||
bpm_min,
|
||||
bpm_max,
|
||||
speed_max,
|
||||
reps_volume,
|
||||
steps,
|
||||
//time,
|
||||
weight_volume
|
||||
}
|
||||
|
||||
extension ResultItemExt on ResultItem {
|
||||
static const ResultItemDesc = {
|
||||
ResultItem.calorie: "Calorie",
|
||||
ResultItem.development_percent_bodypart: "Development in %",
|
||||
ResultItem.distance: "Distance",
|
||||
ResultItem.bpm_avg: "Average BPM",
|
||||
ResultItem.bpm_min: "Min BPM",
|
||||
ResultItem.bpm_max: "Max BPM",
|
||||
ResultItem.speed_max: "Max speed",
|
||||
ResultItem.reps_volume: "Repeats volume",
|
||||
ResultItem.steps: "Steps",
|
||||
//ResultItem.time: "Time",
|
||||
ResultItem.weight_volume: "Weight volume",
|
||||
ResultItem.fatburn_percent: "Fatburn %",
|
||||
};
|
||||
|
||||
static const ResultItemImg = {
|
||||
ResultItem.calorie: "pict_calorie.png",
|
||||
ResultItem.development_percent_bodypart: "pic_development_by_bodypart_percent.png",
|
||||
ResultItem.distance: "pict_distance_m.png",
|
||||
ResultItem.bpm_avg: "pict_hravg_bpm.png",
|
||||
ResultItem.bpm_min: "pict_hrmin_bpm.png",
|
||||
ResultItem.bpm_max: "pict_hrmax_bpm.png",
|
||||
ResultItem.speed_max: "pict_maxspeed_kmh.png",
|
||||
ResultItem.reps_volume: "pict_reps_volumen_db.png",
|
||||
ResultItem.steps: "pict_steps.png",
|
||||
//ResultItem.time: "pict_time_h.png",
|
||||
ResultItem.weight_volume: "pict_weight_volumen_tonna.png",
|
||||
ResultItem.fatburn_percent: "pict_fatburn_percent.png",
|
||||
};
|
||||
|
||||
static const HardwareData = {
|
||||
ResultItem.calorie: true,
|
||||
ResultItem.development_percent_bodypart: false,
|
||||
ResultItem.distance: true,
|
||||
ResultItem.bpm_avg: true,
|
||||
ResultItem.bpm_min: true,
|
||||
ResultItem.bpm_max: true,
|
||||
ResultItem.speed_max: true,
|
||||
ResultItem.reps_volume: false,
|
||||
ResultItem.steps: true,
|
||||
//ResultItem.time: false,
|
||||
ResultItem.weight_volume: false,
|
||||
ResultItem.fatburn_percent: true,
|
||||
};
|
||||
|
||||
bool equals(ResultItem item) => this.toString() == item.toString();
|
||||
bool equalsString(String item) => this.description == item;
|
||||
|
||||
String get description => ResultItemDesc[this];
|
||||
String get image => ResultItemImg[this];
|
||||
bool get isHardware => HardwareData[this];
|
||||
|
||||
String displayString() => description;
|
||||
}
|
||||
|
||||
class ResultExt {
|
||||
final String itemString;
|
||||
ResultItem item;
|
||||
String data = "0";
|
||||
|
||||
ResultExt({this.itemString}) {
|
||||
ResultItem.values.forEach((element) {
|
||||
if (element.equalsString(itemString)) {
|
||||
item = element;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
String getDescription() => item.description;
|
||||
String getImage() => "asset/image/" + item.image;
|
||||
bool isHardware() {
|
||||
return item.isHardware;
|
||||
}
|
||||
|
||||
bool equals(ResultItem item) => this.item.equals(item);
|
||||
bool equalsString(String item) => this.item.equalsString(item);
|
||||
}
|
@ -2,6 +2,22 @@ import 'dart:ui';
|
||||
|
||||
import 'exercise_type.dart';
|
||||
|
||||
enum WorkoutType { endurance, oneRepMax, cardio, staticExercise }
|
||||
|
||||
extension WorkoutTypeExt on WorkoutType {
|
||||
static const WorkoutTypeMenu = {
|
||||
WorkoutType.endurance: "Endurance",
|
||||
WorkoutType.cardio: "Cardio",
|
||||
WorkoutType.oneRepMax: "One Rep Max",
|
||||
WorkoutType.staticExercise: "Static"
|
||||
};
|
||||
|
||||
bool equals(WorkoutType type) => this.toString() == type.toString();
|
||||
bool equalsString(String type) => this.toString() == type;
|
||||
|
||||
String get menu => WorkoutTypeMenu[this];
|
||||
}
|
||||
|
||||
class WorkoutMenuTree {
|
||||
int id;
|
||||
int parent;
|
||||
@ -16,13 +32,15 @@ class WorkoutMenuTree {
|
||||
|
||||
bool is1RM;
|
||||
bool isEndurance;
|
||||
bool isRunning;
|
||||
List<WorkoutType> workoutTypes = List();
|
||||
bool selected = false;
|
||||
bool executed = false;
|
||||
String exerciseDetail;
|
||||
String nameEnglish;
|
||||
|
||||
WorkoutMenuTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exerciseTypeId,
|
||||
this.exerciseType, this.base, this.is1RM, this.isEndurance, this.nameEnglish);
|
||||
this.exerciseType, this.base, this.is1RM, this.isEndurance, this.isRunning, this.nameEnglish);
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
@ -37,6 +55,7 @@ class WorkoutMenuTree {
|
||||
"base": base.toString(),
|
||||
"is1RM": is1RM.toString(),
|
||||
"isEndurance": isEndurance.toString(),
|
||||
"isRunning": isRunning.toString(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ class ExerciseRepository {
|
||||
Customer customer;
|
||||
ExerciseType exerciseType;
|
||||
List<Exercise> exerciseList;
|
||||
List<Exercise> actualExerciseList = List();
|
||||
|
||||
double rmWendler = 0;
|
||||
double rmMcglothlin = 0;
|
||||
@ -20,28 +21,35 @@ class ExerciseRepository {
|
||||
double rmOconner = 0;
|
||||
double rmWathen = 0;
|
||||
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
|
||||
ExerciseRepository() {
|
||||
this.createNew();
|
||||
}
|
||||
|
||||
createNew() {
|
||||
this.exercise = Exercise();
|
||||
exercise.dateAdd = DateTime.now();
|
||||
}
|
||||
|
||||
setQuantity(double quantity) {
|
||||
if ( this.exercise == null ) {
|
||||
if (this.exercise == null) {
|
||||
this.createNew();
|
||||
}
|
||||
this.exercise.quantity = quantity;
|
||||
}
|
||||
|
||||
setUnitQuantity(double unitQuantity) {
|
||||
if ( this.exercise == null ) {
|
||||
if (this.exercise == null) {
|
||||
this.createNew();
|
||||
}
|
||||
|
||||
this.exercise.unitQuantity = unitQuantity;
|
||||
}
|
||||
|
||||
setUnit( String unit) {
|
||||
if ( this.exercise == null ) {
|
||||
setUnit(String unit) {
|
||||
if (this.exercise == null) {
|
||||
this.createNew();
|
||||
}
|
||||
|
||||
@ -49,7 +57,7 @@ class ExerciseRepository {
|
||||
}
|
||||
|
||||
setDatetimeExercise(DateTime datetimeExercise) {
|
||||
if ( this.exercise == null ) {
|
||||
if (this.exercise == null) {
|
||||
this.createNew();
|
||||
}
|
||||
|
||||
@ -66,10 +74,15 @@ class ExerciseRepository {
|
||||
final Exercise modelExercise = this.exercise;
|
||||
modelExercise.customerId = this.customer.customerId;
|
||||
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
|
||||
if (exerciseType.unitQuantity != "1") {
|
||||
modelExercise.unitQuantity = null;
|
||||
}
|
||||
this.actualExerciseList.add(modelExercise);
|
||||
Exercise savedExercise = await ExerciseApi().addExercise(modelExercise);
|
||||
if ( customer.customerId == Cache().userLoggedIn.customerId) {
|
||||
|
||||
if (customer.customerId == Cache().userLoggedIn.customerId) {
|
||||
Cache().addExercise(savedExercise);
|
||||
} else if ( Cache().getTrainee() != null && customer.customerId == Cache().getTrainee().customerId ) {
|
||||
} else if (Cache().getTrainee() != null && customer.customerId == Cache().getTrainee().customerId) {
|
||||
Cache().addExerciseTrainee(savedExercise);
|
||||
}
|
||||
}
|
||||
@ -78,21 +91,17 @@ class ExerciseRepository {
|
||||
await ExerciseApi().deleteExercise(exercise);
|
||||
}
|
||||
|
||||
|
||||
setCustomer(Customer customer) => this.customer = customer;
|
||||
|
||||
setExerciseType( ExerciseType exerciseType) => this.exerciseType = exerciseType;
|
||||
setExerciseType(ExerciseType exerciseType) => this.exerciseType = exerciseType;
|
||||
|
||||
|
||||
Future<List<Exercise>> getExercisesByCustomer( int customerId ) async {
|
||||
Future<List<Exercise>> getExercisesByCustomer(int customerId) async {
|
||||
final results = await ExerciseApi().getExercisesByCustomer(customerId);
|
||||
this.exerciseList = results;
|
||||
if ( Cache().userLoggedIn != null ) {
|
||||
if (Cache().userLoggedIn != null) {
|
||||
if (customerId == Cache().userLoggedIn.customerId) {
|
||||
Cache().setExercises(exerciseList);
|
||||
} else if (Cache().getTrainee() != null && customerId == Cache()
|
||||
.getTrainee()
|
||||
.customerId) {
|
||||
} else if (Cache().getTrainee() != null && customerId == Cache().getTrainee().customerId) {
|
||||
Cache().setExercisesTrainee(exerciseList);
|
||||
}
|
||||
}
|
||||
@ -110,11 +119,11 @@ class ExerciseRepository {
|
||||
}
|
||||
|
||||
String nextMissingBaseExercise(SplayTreeMap sortedTree) {
|
||||
if ( exerciseList == null ) {
|
||||
if (exerciseList == null) {
|
||||
exerciseList = Cache().getExercises();
|
||||
}
|
||||
|
||||
if ( exerciseList == null ) {
|
||||
if (exerciseList == null) {
|
||||
return "";
|
||||
}
|
||||
String missingTreeName;
|
||||
@ -127,12 +136,12 @@ class ExerciseRepository {
|
||||
treeName = treeName.substring(3);
|
||||
foundTreeName = null;
|
||||
listByMuscle.forEach((exercise) {
|
||||
if ( missingTreeName == null ) {
|
||||
if (missingTreeName == null) {
|
||||
missingTreeName = treeName;
|
||||
}
|
||||
if ( exercise.base ) {
|
||||
if (exercise.base) {
|
||||
exerciseList.forEach((element) {
|
||||
if ( element.exerciseTypeId == exercise.exerciseTypeId ) {
|
||||
if (element.exerciseTypeId == exercise.exerciseTypeId) {
|
||||
foundTreeName = treeName;
|
||||
//print("Found " + foundTreeName + " Missing actual: " + missingTreeName);
|
||||
isBreak = true;
|
||||
@ -140,7 +149,7 @@ class ExerciseRepository {
|
||||
});
|
||||
}
|
||||
});
|
||||
if ( foundTreeName == null &&! isBreak ) {
|
||||
if (foundTreeName == null && !isBreak) {
|
||||
missingTreeName = treeName;
|
||||
isBreak = true;
|
||||
}
|
||||
@ -156,37 +165,35 @@ class ExerciseRepository {
|
||||
int count1RMExercises = 0;
|
||||
LinkedHashMap<String, WorkoutMenuTree> tree = Cache().getWorkoutMenuTree();
|
||||
|
||||
if ( tree == null ) {
|
||||
if (tree == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
tree.forEach((key, value) {
|
||||
WorkoutMenuTree treeItem = value;
|
||||
if (treeItem.exerciseType != null &&
|
||||
treeItem.exerciseType.base == true &&
|
||||
!baseTreeItem.contains(treeItem.parent)) {
|
||||
if (treeItem.exerciseType != null && treeItem.exerciseType.base == true && !baseTreeItem.contains(treeItem.parent)) {
|
||||
baseTreeItem.add(treeItem.parent);
|
||||
}
|
||||
});
|
||||
|
||||
if ( exerciseList == null ) {
|
||||
if (exerciseList == null) {
|
||||
exerciseList = Cache().getExercises();
|
||||
}
|
||||
|
||||
if ( exerciseList == null ) {
|
||||
if (exerciseList == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
exerciseList.forEach((element) {
|
||||
Exercise exercise = element;
|
||||
if ( !checkedExerciseTypeId.contains(exercise.exerciseTypeId )) {
|
||||
if (!checkedExerciseTypeId.contains(exercise.exerciseTypeId)) {
|
||||
checkedExerciseTypeId.add(exercise.exerciseTypeId);
|
||||
tree.forEach((key, value) {
|
||||
WorkoutMenuTree treeItem = value;
|
||||
if (treeItem.exerciseType != null
|
||||
&& treeItem.exerciseType.base == true
|
||||
&& exercise.exerciseTypeId == treeItem.exerciseType.exerciseTypeId
|
||||
&& !checkedBaseTreeItem.contains(treeItem.parent)) {
|
||||
if (treeItem.exerciseType != null &&
|
||||
treeItem.exerciseType.base == true &&
|
||||
exercise.exerciseTypeId == treeItem.exerciseType.exerciseTypeId &&
|
||||
!checkedBaseTreeItem.contains(treeItem.parent)) {
|
||||
//print ("id: " + exercise.exerciseTypeId.toString());
|
||||
checkedBaseTreeItem.add(treeItem.parent);
|
||||
count1RMExercises++;
|
||||
@ -207,7 +214,7 @@ class ExerciseRepository {
|
||||
Exercise lastExercise = exercises[0];
|
||||
exercises.forEach((element) {
|
||||
Exercise actualExercise = element;
|
||||
if ( actualExercise.dateAdd.compareTo(lastExercise.dateAdd) > 0 ) {
|
||||
if (actualExercise.dateAdd.compareTo(lastExercise.dateAdd) > 0) {
|
||||
lastExercise = actualExercise;
|
||||
}
|
||||
});
|
||||
@ -221,16 +228,15 @@ class ExerciseRepository {
|
||||
ExerciseType actualExerciseType;
|
||||
Cache().getExerciseTypes().forEach((element) {
|
||||
ExerciseType exerciseType = element;
|
||||
if ( exerciseType.exerciseTypeId == exerciseTypeId) {
|
||||
if (exerciseType.exerciseTypeId == exerciseTypeId) {
|
||||
actualExerciseType = exerciseType;
|
||||
}
|
||||
});
|
||||
if ( actualExerciseType == null ) {
|
||||
throw Exception("Data error, no ExerciseType for exerciseTypeId $exerciseTypeId" );
|
||||
if (actualExerciseType == null) {
|
||||
throw Exception("Data error, no ExerciseType for exerciseTypeId $exerciseTypeId");
|
||||
}
|
||||
return actualExerciseType;
|
||||
}
|
||||
|
||||
void sortByDate() => exerciseList.sort( (a, b) => b.dateAdd.compareTo(a.dateAdd) );
|
||||
|
||||
void sortByDate() => exerciseList.sort((a, b) => b.dateAdd.compareTo(a.dateAdd));
|
||||
}
|
40
lib/repository/exercise_result_repository.dart
Normal file
@ -0,0 +1,40 @@
|
||||
import 'package:aitrainer_app/model/result.dart';
|
||||
|
||||
enum ResultType { running, man, woman, none }
|
||||
|
||||
extension ResultTypeExt on ResultType {
|
||||
bool equals(ResultType type) => this.toString() == type.toString();
|
||||
}
|
||||
|
||||
class ExerciseResultRepository {
|
||||
final List<ResultExt> _results = List();
|
||||
ResultType resultType;
|
||||
|
||||
ExerciseResultRepository({this.resultType}) {
|
||||
if (resultType == null) {
|
||||
resultType = ResultType.man;
|
||||
}
|
||||
if (resultType.equals(ResultType.man) || resultType.equals(ResultType.woman)) {
|
||||
//_results.add(ResultExt(itemString: ResultItem.time.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.reps_volume.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.weight_volume.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.bpm_max.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.calorie.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.bpm_avg.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.fatburn_percent.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.bpm_min.description));
|
||||
} else {
|
||||
//_results.add(ResultExt(itemString: ResultItem.time.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.distance.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.bpm_max.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.calorie.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.bpm_avg.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.fatburn_percent.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.bpm_min.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.steps.description));
|
||||
_results.add(ResultExt(itemString: ResultItem.speed_max.description));
|
||||
}
|
||||
}
|
||||
|
||||
List<ResultExt> getResults() => this._results;
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import 'dart:collection';
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||
import 'package:aitrainer_app/model/exercise_tree.dart';
|
||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||
import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||
@ -32,6 +33,7 @@ class WorkoutTreeRepository {
|
||||
final LinkedHashMap tree = LinkedHashMap<String, WorkoutMenuTree>();
|
||||
SplayTreeMap sortedTree = SplayTreeMap<String, List<WorkoutMenuTree>>();
|
||||
bool isEnglish;
|
||||
WorkoutType workoutType;
|
||||
|
||||
final Map<String, int> _antagonist = {
|
||||
Antagonist.chest: Antagonist.chestNr,
|
||||
@ -59,8 +61,8 @@ class WorkoutTreeRepository {
|
||||
}
|
||||
|
||||
exerciseTree.forEach((treeItem) async {
|
||||
//print(" -- TreeItem " + treeItem.toJson().toString());
|
||||
|
||||
//print(" -- TreeItem " + treeItem.toJson().toString() + " active " + treeItem.active.toString());
|
||||
if (treeItem.active == true) {
|
||||
String treeName = isEnglish ? treeItem.name : treeItem.nameTranslation;
|
||||
String assetImage = 'asset/menu/' + treeItem.imageUrl.substring(7);
|
||||
|
||||
@ -74,7 +76,12 @@ class WorkoutTreeRepository {
|
||||
isEndurance = isParentEndurance(treeItem.parentId);
|
||||
}
|
||||
|
||||
final WorkoutMenuTree menuItem = WorkoutMenuTree(
|
||||
bool isRunning = treeItem.name == "Cardio" ? true : false;
|
||||
if (isRunning == false && treeItem.parentId != 0) {
|
||||
isRunning = isParentRunning(treeItem.parentId);
|
||||
}
|
||||
|
||||
WorkoutMenuTree menuItem = WorkoutMenuTree(
|
||||
treeItem.treeId,
|
||||
treeItem.parentId,
|
||||
treeName,
|
||||
@ -87,32 +94,38 @@ class WorkoutTreeRepository {
|
||||
false,
|
||||
is1RM,
|
||||
isEndurance,
|
||||
isRunning,
|
||||
treeItem.name,
|
||||
);
|
||||
menuItem = this.setWorkoutTypes(menuItem, treeItem);
|
||||
this.tree[treeItem.name + "_" + treeItem.parentId.toString()] = menuItem;
|
||||
//print("WorkoutMenuTree item " + menuItem.toJson().toString());
|
||||
}
|
||||
});
|
||||
|
||||
exerciseTypes.forEach((exerciseType) {
|
||||
if (!(exerciseType.imageUrl.isEmpty || exerciseType.name.isEmpty || exerciseType.nameTranslation.isEmpty)) {
|
||||
if (!(exerciseType.imageUrl.isEmpty || exerciseType.name.isEmpty || exerciseType.nameTranslation.isEmpty) &&
|
||||
exerciseType.active == true) {
|
||||
String exerciseTypeName = isEnglish ? exerciseType.name : exerciseType.nameTranslation;
|
||||
String assetImage = 'asset/menu/' + exerciseType.imageUrl.substring(7);
|
||||
if (exerciseType.parents.isNotEmpty) {
|
||||
exerciseType.parents.forEach((parentId) {
|
||||
bool is1RM = this.isParent1RM(parentId);
|
||||
bool isEndurance = this.isParentEndurance(parentId);
|
||||
exerciseType.is1RM = is1RM;
|
||||
exerciseType.isEndurance = isEndurance;
|
||||
if (is1RM) exerciseType.setAbility(ExerciseAbility.oneRepMax);
|
||||
if (isEndurance) exerciseType.setAbility(ExerciseAbility.endurance);
|
||||
bool isRunning = this.isParentRunning(parentId);
|
||||
if (isRunning) exerciseType.setAbility(ExerciseAbility.running);
|
||||
WorkoutMenuTree menuItem = WorkoutMenuTree(exerciseType.exerciseTypeId, parentId, exerciseTypeName, assetImage, Colors.white,
|
||||
24, true, exerciseType.exerciseTypeId, exerciseType, exerciseType.base, is1RM, isEndurance, exerciseType.name);
|
||||
24, true, exerciseType.exerciseTypeId, exerciseType, exerciseType.base, is1RM, isEndurance, isRunning, exerciseType.name);
|
||||
this.tree[exerciseType.name] = menuItem;
|
||||
//print("WorkoutMenuTree item " + menuItem.toJson().toString());
|
||||
/*print("ExerciseType in Menu item " +
|
||||
print("WorkoutMenuTree item " + menuItem.toJson().toString());
|
||||
print("ExerciseType in Menu item " +
|
||||
exerciseType.toJson().toString() +
|
||||
" is1RM: " +
|
||||
is1RM.toString() +
|
||||
" isEndurance: " +
|
||||
isEndurance.toString());*/
|
||||
isEndurance.toString());
|
||||
});
|
||||
} else {
|
||||
//print("No Parents " + exerciseType.toJson().toString());
|
||||
@ -127,6 +140,39 @@ class WorkoutTreeRepository {
|
||||
exerciseRepository.getBaseExerciseFinishedPercent();
|
||||
}
|
||||
|
||||
WorkoutMenuTree setWorkoutTypes(WorkoutMenuTree menu, ExerciseTree treeItem) {
|
||||
WorkoutType.values.forEach((workoutType) {
|
||||
if (workoutType.equalsString(treeItem.name) || existWorkoutTypeInTree(workoutType)) {
|
||||
menu.workoutTypes.add(workoutType);
|
||||
}
|
||||
});
|
||||
return menu;
|
||||
}
|
||||
|
||||
bool existWorkoutTypeInTree(WorkoutType workoutType) {
|
||||
bool exists = false;
|
||||
this.tree.forEach((key, treeItem) {
|
||||
if (workoutType.equalsString(treeItem.name)) {
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
return exists;
|
||||
}
|
||||
|
||||
bool isParentRunning(int treeId) {
|
||||
bool isTreeItemRunning = false;
|
||||
|
||||
this.tree.forEach((key, value) {
|
||||
WorkoutMenuTree treeItem = value as WorkoutMenuTree;
|
||||
if (treeItem.id == treeId) {
|
||||
isTreeItemRunning = isTreeItemRunning || treeItem.isRunning;
|
||||
//print (treeItem.name + " 1RM " + treeItem.is1RM.toString() );
|
||||
}
|
||||
});
|
||||
|
||||
return isTreeItemRunning;
|
||||
}
|
||||
|
||||
bool isParent1RM(int treeId) {
|
||||
bool isTreeItem1RM = false;
|
||||
|
||||
|
@ -35,7 +35,7 @@ class ExerciseTreeApi {
|
||||
if (index > 0) {
|
||||
ExerciseTree newElement = element.copy(parent.exerciseTreeParentId);
|
||||
exerciseTree.add(newElement);
|
||||
print("ExerciseTree " + newElement.toJson().toString());
|
||||
//print("ExerciseTree " + newElement.toJson().toString());
|
||||
} else {
|
||||
element.parentId = parent.exerciseTreeParentId;
|
||||
exerciseTree[treeIndex].parentId = parent.exerciseTreeParentId;
|
||||
|
@ -31,6 +31,7 @@ class Session {
|
||||
await AppLocalizations.delegate.load(AppLanguage().appLocal);
|
||||
print(" -- Session: fetch token..");
|
||||
Cache().setServerAddress(_sharedPreferences);
|
||||
Cache().getHardware(_sharedPreferences);
|
||||
await _fetchToken(_sharedPreferences);
|
||||
print(" -- FireBase init..");
|
||||
await FirebaseApi().initializeFlutterFire();
|
||||
|
@ -3,7 +3,6 @@ import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
||||
import 'package:aitrainer_app/library/numberpicker.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||
import 'package:aitrainer_app/widgets/splash.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
503
lib/view/evaluation.dart
Normal file
@ -0,0 +1,503 @@
|
||||
import 'dart:collection';
|
||||
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_ability.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';
|
||||
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class EvaluationPage extends StatelessWidget with Trans {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
|
||||
ExerciseRepository exerciseRepository;
|
||||
// ignore: close_sinks
|
||||
if (arguments != null) {
|
||||
exerciseRepository = arguments['exerciseRepository'];
|
||||
} else {
|
||||
exerciseRepository = ExerciseRepository();
|
||||
}
|
||||
ResultType resultType = ResultType.none;
|
||||
String imageUrl = "";
|
||||
if (Cache().userLoggedIn.sex == "m") {
|
||||
resultType = ResultType.man;
|
||||
imageUrl = 'asset/image/WT_Results_for_men.png';
|
||||
} else {
|
||||
resultType = ResultType.man;
|
||||
imageUrl = 'asset/image/WT_Results_for_female.png';
|
||||
}
|
||||
if (exerciseRepository.exerciseType.getAbility().equalsTo(ExerciseAbility.running)) {
|
||||
resultType = ResultType.running;
|
||||
imageUrl = 'asset/image/WT_Results_for_runners.png';
|
||||
}
|
||||
print("ResultType: " + resultType.toString());
|
||||
setContext(context);
|
||||
return Scaffold(
|
||||
appBar: AppBarMin(
|
||||
back: true,
|
||||
),
|
||||
body: Container(
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage(imageUrl),
|
||||
fit: BoxFit.cover,
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
),
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
ResultBloc(resultRepository: ExerciseResultRepository(resultType: resultType), exerciseRepository: exerciseRepository)
|
||||
..add(ResultLoad()),
|
||||
child: BlocConsumer<ResultBloc, ResultState>(listener: (context, state) {
|
||||
if (state is ResultError) {
|
||||
Scaffold.of(context).showSnackBar(
|
||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.error, style: TextStyle(color: Colors.white))));
|
||||
} else if (state is ResultLoading) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
duration: Duration(milliseconds: 100),
|
||||
backgroundColor: Colors.transparent,
|
||||
content: Container(child: Center(child: CircularProgressIndicator()))));
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final resultBloc = BlocProvider.of<ResultBloc>(context);
|
||||
return getEvaluationWidgets(resultBloc);
|
||||
}))),
|
||||
bottomNavigationBar: BottomNavigator(bottomNavIndex: 0));
|
||||
}
|
||||
|
||||
Widget getEvaluationWidgets(ResultBloc resultBloc) {
|
||||
String exerciseName = AppLanguage().appLocal == Locale("en")
|
||||
? resultBloc.exerciseRepository.exerciseType.name
|
||||
: resultBloc.exerciseRepository.exerciseType.nameTranslation;
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 10, right: 10),
|
||||
child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [
|
||||
SliverAppBar(
|
||||
pinned: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedHeight: 50.0,
|
||||
automaticallyImplyLeading: false,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
title: Text(exerciseName,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 3,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 24,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
Text(DateFormat('y-M-d HH:mm', AppLanguage().appLocal.toString()).format(resultBloc.exerciseRepository.start),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
Divider(color: Colors.transparent),
|
||||
Divider(color: Colors.transparent),
|
||||
Text(t("Summary of your test"),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 20,
|
||||
color: Colors.yellow[300],
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
]),
|
||||
),
|
||||
getResultSummary(resultBloc),
|
||||
getSuggestionTitle(resultBloc),
|
||||
getSuggestion(resultBloc),
|
||||
emptySliver(),
|
||||
getResultTitle(resultBloc),
|
||||
getResults(resultBloc),
|
||||
]));
|
||||
}
|
||||
|
||||
Widget getSuggestionTitle(ResultBloc resultBloc) {
|
||||
if (resultBloc.exerciseRepository.exerciseType.unitQuantityUnit != null) {
|
||||
return SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
Divider(color: Colors.transparent),
|
||||
Divider(color: Colors.transparent),
|
||||
Text(t("Suggestions based on your test"),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 20,
|
||||
color: Colors.yellow[300],
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else
|
||||
return emptySliver();
|
||||
}
|
||||
|
||||
Widget getResultTitle(ResultBloc resultBloc) {
|
||||
return SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
Divider(color: Colors.transparent),
|
||||
Divider(color: Colors.transparent),
|
||||
Text(t("Health Data Summary"),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 20,
|
||||
color: Colors.yellow[300],
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
Divider(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getSuggestion(ResultBloc resultBloc) {
|
||||
if (resultBloc.exerciseRepository.exerciseType.unitQuantityUnit != null) {
|
||||
return SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
getSuggestionWidget(resultBloc, "Hypertrophy", "asset/image/pict_hypertrophy.png", "3x10-12", 0.9, "2"),
|
||||
Divider(color: Colors.transparent),
|
||||
getSuggestionWidget(resultBloc, "Gain Strength", "asset/image/pict_weight_volumen_tonna.png", "3x10-12", 0.75, "3-5"),
|
||||
Divider(color: Colors.transparent),
|
||||
getSuggestionWidget(resultBloc, "Endurance", "asset/image/pict_reps_volumen_db.png", "4x25-35", 0.50, "3"),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else
|
||||
return emptySliver();
|
||||
}
|
||||
|
||||
Widget emptySliver({int count = 1}) {
|
||||
return SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
Container(),
|
||||
Divider(color: Colors.transparent),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getSuggestionWidget(ResultBloc resultBloc, String title, String picture, String repeats, double percent, String restTime) {
|
||||
String unitQuantityUnit = resultBloc.exerciseRepository.exerciseType.unitQuantityUnit == null
|
||||
? ""
|
||||
: resultBloc.exerciseRepository.exerciseType.unitQuantityUnit;
|
||||
return Column(
|
||||
children: [
|
||||
Text(t(title),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 30,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
Row(children: [
|
||||
Image.asset(
|
||||
picture,
|
||||
height: 80,
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(repeats + " " + t("repeats"),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 18,
|
||||
color: Colors.orange,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
))
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(t("Weight") + ": " + resultBloc.calculate1RM(percent: percent).toStringAsFixed(0) + " " + unitQuantityUnit,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 18,
|
||||
color: Colors.orange,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(t("Rest time") + ": " + restTime + " " + t("minutes"),
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontSize: 18,
|
||||
color: Colors.orange,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget getSummary(ResultBloc bloc) {
|
||||
int index = 0;
|
||||
List<Text> resultList = List();
|
||||
bloc.exerciseRepository.actualExerciseList.forEach((exercise) {
|
||||
final String unit = t(bloc.exerciseRepository.exerciseType.unit);
|
||||
String exerciseElement = "";
|
||||
final String exerciseRepeats = exercise.quantity.toStringAsFixed(0);
|
||||
final String exerciseUnitQuantity = exercise.unitQuantity != null ? "x" + exercise.unitQuantity.toStringAsFixed(0) : "";
|
||||
if (index == 0) {
|
||||
exerciseElement = t("Test") + ": ";
|
||||
} else if (index == 1) {
|
||||
exerciseElement = t("1st Control") + ": ";
|
||||
} else if (index == 2) {
|
||||
exerciseElement = t("2nd Control") + ": ";
|
||||
} else if (index == 3) {
|
||||
exerciseElement = t("3rd Control") + ": ";
|
||||
}
|
||||
index++;
|
||||
resultList.add(
|
||||
Text(exerciseElement + exerciseRepeats + exerciseUnitQuantity + " " + unit,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: GoogleFonts.inter(
|
||||
fontSize: 18,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
)),
|
||||
);
|
||||
});
|
||||
return Column(children: resultList);
|
||||
}
|
||||
|
||||
Widget getResultSummary(ResultBloc resultBloc) {
|
||||
return SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[Divider(color: Colors.transparent), getSummary(resultBloc)],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getResults(ResultBloc resultBloc) {
|
||||
return SliverGrid(
|
||||
delegate: SliverChildListDelegate(
|
||||
getResultData(resultBloc),
|
||||
),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
mainAxisSpacing: 5.0,
|
||||
crossAxisSpacing: 5.0,
|
||||
childAspectRatio: 1.1,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getResultData(ResultBloc resultBloc) {
|
||||
List<Widget> data = List();
|
||||
|
||||
resultBloc.resultRepository.getResults().forEach((element) {
|
||||
data.add(getResultWidget(element));
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
Widget getResultWidget(ResultExt element) {
|
||||
bool hasHardware = Cache().hasHardware;
|
||||
bool blur = (!hasHardware && element.isHardware());
|
||||
/* print("Blur: " +
|
||||
element.getDescription() +
|
||||
": " +
|
||||
blur.toString() +
|
||||
" hasHardware:" +
|
||||
hasHardware.toString() +
|
||||
" isHw: " +
|
||||
element.isHardware().toString()); */
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
blur
|
||||
? Stack(children: [
|
||||
Image.asset(
|
||||
element.getImage(),
|
||||
height: 80,
|
||||
//color: Colors.white12,
|
||||
),
|
||||
Image.asset(
|
||||
element.getImage(),
|
||||
height: 80,
|
||||
color: Colors.black54,
|
||||
),
|
||||
])
|
||||
: Image.asset(
|
||||
element.getImage(),
|
||||
height: 80,
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
element.data,
|
||||
style: GoogleFonts.archivoBlack(fontSize: 28, color: blur ? Colors.white30 : Colors.white),
|
||||
),
|
||||
Text(
|
||||
t(element.getDescription()),
|
||||
style: GoogleFonts.archivoBlack(fontSize: 14, color: blur ? Colors.white30 : Colors.white),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -2,16 +2,17 @@ import 'dart:collection';
|
||||
|
||||
import 'package:aitrainer_app/bloc/exercise_control/exercise_control_bloc.dart';
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||
import 'package:aitrainer_app/widgets/number_picker.dart';
|
||||
import 'package:aitrainer_app/widgets/splash.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
import 'package:aitrainer_app/library/numberpicker.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class ExerciseControlPage extends StatefulWidget {
|
||||
@ -32,16 +33,16 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
..add(ExerciseControlLoad()),
|
||||
child: BlocConsumer<ExerciseControlBloc, ExerciseControlState>(listener: (context, state) {
|
||||
if (state is ExerciseControlError) {
|
||||
//LoadingDialog.hide(context);
|
||||
Scaffold.of(context).showSnackBar(
|
||||
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
||||
} else if (state is ExerciseControlLoading) {
|
||||
//LoadingDialog.show(context);
|
||||
return LoadingDialog();
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final exerciseBloc = BlocProvider.of<ExerciseControlBloc>(context);
|
||||
if (state is ExerciseControlReady) {
|
||||
//LoadingDialog.hide(context);
|
||||
if (state is ExerciseControlLoading) {
|
||||
return LoadingDialog();
|
||||
} else if (state is ExerciseControlReady) {
|
||||
return getControlForm(exerciseBloc);
|
||||
} else {
|
||||
return getControlForm(exerciseBloc);
|
||||
@ -53,49 +54,80 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
String exerciseName = AppLanguage().appLocal == Locale("en")
|
||||
? exerciseBloc.exerciseRepository.exerciseType.name
|
||||
: exerciseBloc.exerciseRepository.exerciseType.nameTranslation;
|
||||
|
||||
return Form(
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage('asset/image/WT_black_background.png'),
|
||||
fit: BoxFit.fill,
|
||||
alignment: Alignment.center,
|
||||
image: Cache().userLoggedIn.sex == "m"
|
||||
? AssetImage("asset/image/WT_Results_for_men.png")
|
||||
: AssetImage("asset/image/WT_Results_for_female.png"),
|
||||
fit: BoxFit.cover,
|
||||
alignment: Alignment.topCenter,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(top: 25, left: 25, right: 25),
|
||||
padding: const EdgeInsets.only(top: 10, left: 25, right: 25),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
controller: ScrollController(
|
||||
initialScrollOffset: exerciseBloc.scrollOffset,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
exerciseName,
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.orange),
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(2.0, 2.0),
|
||||
blurRadius: 6.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
),
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
),
|
||||
FlatButton(
|
||||
Divider(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
Divider(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
Divider(
|
||||
color: Colors.transparent,
|
||||
),
|
||||
/* FlatButton(
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||
Icon(
|
||||
Icons.info,
|
||||
color: Colors.yellow[300],
|
||||
color: Colors.yellow[50],
|
||||
),
|
||||
Flexible(
|
||||
child: Text(t("Why do you need Exercise Control?"),
|
||||
style: TextStyle(color: Colors.yellow[300], fontWeight: FontWeight.normal, fontSize: 14)),
|
||||
style: TextStyle(color: Colors.yellow[50], fontWeight: FontWeight.normal, fontSize: 14)),
|
||||
),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: Colors.yellow[300],
|
||||
color: Colors.yellow[50],
|
||||
),
|
||||
]),
|
||||
textColor: Colors.blueAccent,
|
||||
@ -103,20 +135,21 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
onPressed: () => {
|
||||
//Navigator.of(context).pushNamed('exerciseTypeDescription', arguments: exerciseBloc.exerciseRepository),
|
||||
},
|
||||
),
|
||||
), */
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(t("Your 1RM:"),
|
||||
style: GoogleFonts.inter(
|
||||
color: Colors.yellow[300],
|
||||
fontSize: 18,
|
||||
)),
|
||||
Text(
|
||||
" " +
|
||||
exerciseBloc.initialRM.toStringAsFixed(0) +
|
||||
" " +
|
||||
exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit,
|
||||
style: GoogleFonts.inter(color: Colors.yellow[300], fontWeight: FontWeight.bold),
|
||||
style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -134,7 +167,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
}
|
||||
|
||||
Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) {
|
||||
String strTimes = step == 2 ? exerciseBloc.origQuantity.toString() : "max.";
|
||||
String strTimes = step == 2 ? exerciseBloc.origQuantity.toStringAsFixed(0) : "max.";
|
||||
String textInstruction = "";
|
||||
textInstruction = t("Please repeat with ") +
|
||||
exerciseBloc.unitQuantity.toStringAsFixed(0) +
|
||||
@ -149,44 +182,46 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
);
|
||||
|
||||
String title = step.toString() + ". " + t("Control Exercise:");
|
||||
LinkedHashMap args = LinkedHashMap();
|
||||
|
||||
List<Widget> listWidgets = [
|
||||
Text(
|
||||
title,
|
||||
style: GoogleFonts.inter(color: Colors.yellow[300], fontWeight: FontWeight.bold),
|
||||
style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
textInstruction,
|
||||
style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 12),
|
||||
style: GoogleFonts.inter(color: Colors.yellow[300], fontSize: 16),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
NumberPicker.horizontal(
|
||||
highlightSelectedValue: step == exerciseBloc.step,
|
||||
initialValue: exerciseBloc.quantity.toInt(),
|
||||
NumberPickerWidget(
|
||||
minValue: 0,
|
||||
maxValue: 200,
|
||||
step: 1,
|
||||
onChanged: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))},
|
||||
listViewHeight: 80,
|
||||
textStyleHighlighted: GoogleFonts.archivoBlack(color: Colors.orange[300], fontSize: 24),
|
||||
//decoration: _decoration,
|
||||
),
|
||||
initalValue: exerciseBloc.quantity.toInt(),
|
||||
unit: t("reps"),
|
||||
color: Colors.yellow[50],
|
||||
onChange: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))}),
|
||||
FlatButton(
|
||||
padding: EdgeInsets.all(0),
|
||||
textColor: Colors.white,
|
||||
//color: step == exerciseBloc.step ? Colors.orange : Colors.black26,
|
||||
focusColor: Colors.blueAccent,
|
||||
onPressed: () => {
|
||||
exerciseBloc.add(ExerciseControlSubmit(step: step)),
|
||||
if (step == 3) {confirmationDialog(exerciseBloc)}
|
||||
if (step == 3)
|
||||
{
|
||||
//confirmationDialog(exerciseBloc)
|
||||
Navigator.of(context).pop(),
|
||||
args['exerciseRepository'] = exerciseBloc.exerciseRepository,
|
||||
Navigator.of(context).pushNamed('evaluationPage', arguments: args)
|
||||
}
|
||||
},
|
||||
child: step == exerciseBloc.step
|
||||
? Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image.asset('asset/icon/gomb_orange_a.png', width: 140, height: 60),
|
||||
Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60),
|
||||
Text(
|
||||
t("Save"),
|
||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||
@ -206,6 +241,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
|
||||
void confirmationDialog(ExerciseControlBloc bloc) {
|
||||
String unit = t(bloc.exerciseRepository.exerciseType.unit);
|
||||
LinkedHashMap args = LinkedHashMap();
|
||||
|
||||
showCupertinoDialog(
|
||||
useRootNavigator: true,
|
||||
@ -235,7 +271,11 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
|
||||
actions: [
|
||||
FlatButton(
|
||||
child: Text(t("OK")),
|
||||
onPressed: () => {Navigator.of(context).pop(), Navigator.of(context).pop()},
|
||||
onPressed: () => {
|
||||
Navigator.of(context).pop(),
|
||||
args['exerciseRepository'] = bloc.exerciseRepository,
|
||||
Navigator.of(context).pushNamed('evaluationPage', arguments: args)
|
||||
},
|
||||
)
|
||||
],
|
||||
));
|
||||
|
@ -241,11 +241,11 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
|
||||
style: (TextStyle(color: Colors.blue)),
|
||||
),
|
||||
Text(
|
||||
exercise.quantity.toStringAsFixed(0) +
|
||||
"x" +
|
||||
exercise.unitQuantity.toStringAsFixed(0) +
|
||||
" " +
|
||||
exerciseType.unitQuantityUnit,
|
||||
exercise.quantity.toStringAsFixed(0) + "x" + exercise.unitQuantity.toStringAsFixed(0) + " ",
|
||||
//+
|
||||
//exerciseType.unitQuantityUnit == null
|
||||
// ? ""
|
||||
// : exerciseType.unitQuantityUnit,
|
||||
style: (TextStyle(color: Colors.deepOrange)),
|
||||
),
|
||||
Text(
|
||||
|
@ -2,8 +2,10 @@ import 'dart:collection';
|
||||
|
||||
import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart';
|
||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/exercise_ability.dart';
|
||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
@ -19,6 +21,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:stop_watch_timer/stop_watch_timer.dart';
|
||||
|
||||
class ExerciseNewPage extends StatefulWidget {
|
||||
_ExerciseNewPageState createState() => _ExerciseNewPageState();
|
||||
@ -132,15 +135,20 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
|
||||
return SizeWidget(exerciseBloc: exerciseBloc);
|
||||
}
|
||||
|
||||
bool isSecond = false;
|
||||
String exerciseTask = "";
|
||||
if (exerciseBloc.exerciseRepository.exerciseType.is1RM && menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString()) {
|
||||
if (exerciseBloc.exerciseRepository.exerciseType.unit != "second") {
|
||||
if (exerciseBloc.exerciseRepository.exerciseType.is1RM() && menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString()) {
|
||||
exerciseTask = "Please take a relative bigger weight and repeat 12-20 times";
|
||||
exerciseBloc.quantity = 12;
|
||||
} else if (exerciseBloc.exerciseRepository.exerciseType.isEndurance &&
|
||||
} else if (exerciseBloc.exerciseRepository.exerciseType.isEndurance() &&
|
||||
menuBloc.ability.toString() == ExerciseAbility.endurance.toString()) {
|
||||
exerciseTask = "Please take a medium weight and repeat 20-30 times";
|
||||
exerciseBloc.quantity = 20;
|
||||
}
|
||||
} else {
|
||||
isSecond = true;
|
||||
}
|
||||
|
||||
return Form(
|
||||
child: Scaffold(
|
||||
@ -159,20 +167,34 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
|
||||
child: KeyboardActions(
|
||||
config: _buildConfig(context),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.only(top: 5, left: 55, right: 55),
|
||||
padding: const EdgeInsets.only(top: 25, left: 55, right: 55),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(t('Save Exercise'), style: TextStyle(fontSize: 14, color: Colors.blue[200])),
|
||||
Divider(),
|
||||
Text(
|
||||
exerciseName,
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.orange),
|
||||
style: GoogleFonts.archivoBlack(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 24,
|
||||
color: Colors.white,
|
||||
shadows: <Shadow>[
|
||||
Shadow(
|
||||
offset: Offset(5.0, 5.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
Shadow(
|
||||
offset: Offset(-3.0, 3.0),
|
||||
blurRadius: 12.0,
|
||||
color: Colors.black54,
|
||||
),
|
||||
],
|
||||
),
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 2,
|
||||
maxLines: 4,
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
@ -235,7 +257,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image.asset('asset/icon/gomb_orange_a.png', width: 140, height: 60),
|
||||
Image.asset('asset/icon/gomb_orange_c.png', width: 140, height: 60),
|
||||
Text(
|
||||
t("Save"),
|
||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||
@ -280,6 +302,80 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
|
||||
Column columnQuantity(ExerciseNewBloc bloc) {
|
||||
if (bloc.exerciseRepository.exerciseType.unit == "second") {
|
||||
return Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 0),
|
||||
child: StreamBuilder<int>(
|
||||
stream: bloc.stopWatchTimer.rawTime,
|
||||
initialData: bloc.stopWatchTimer.rawTime.value,
|
||||
builder: (context, snap) {
|
||||
final value = snap.data;
|
||||
final displayTime = StopWatchTimer.getDisplayTime(value, hours: false);
|
||||
return Column(children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Text(
|
||||
displayTime,
|
||||
style: const TextStyle(fontSize: 40, fontFamily: 'Helvetica', fontWeight: FontWeight.bold, color: Colors.white),
|
||||
),
|
||||
),
|
||||
]);
|
||||
})),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: IconButton(
|
||||
padding: const EdgeInsets.all(2),
|
||||
color: Colors.white70,
|
||||
//shape: const StadiumBorder(),
|
||||
onPressed: () async {
|
||||
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.start);
|
||||
},
|
||||
icon: Icon(CustomIcon.play_1),
|
||||
iconSize: 40,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: IconButton(
|
||||
padding: const EdgeInsets.all(2),
|
||||
iconSize: 40,
|
||||
color: Colors.white70,
|
||||
//shape: const StadiumBorder(),
|
||||
onPressed: () async {
|
||||
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.stop);
|
||||
},
|
||||
icon: Icon(CustomIcon.stop),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: IconButton(
|
||||
padding: const EdgeInsets.all(2),
|
||||
iconSize: 40,
|
||||
color: Colors.white70,
|
||||
onPressed: () async {
|
||||
bloc.stopWatchTimer.onExecute.add(StopWatchExecute.reset);
|
||||
},
|
||||
icon: Icon(CustomIcon.creative_commons_zero),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Divider(),
|
||||
Divider(),
|
||||
Text("Or type the time manually:", style: GoogleFonts.inter(color: Colors.white)),
|
||||
TimePickerWidget(
|
||||
onChange: (value) => {bloc.add(ExerciseNewQuantityChange(quantity: value))},
|
||||
)
|
||||
@ -360,18 +456,26 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> with Trans {
|
||||
child: Text(t("Yes")),
|
||||
onPressed: () => {
|
||||
bloc.exerciseRepository.setCustomer(Cache().userLoggedIn),
|
||||
bloc.exerciseRepository.addExercise(),
|
||||
bloc.add(ExerciseNewSubmit()),
|
||||
Navigator.pop(context),
|
||||
Navigator.pop(context),
|
||||
if (bloc.exerciseRepository.exerciseType.is1RM && menuBloc.ability.toString() == ExerciseAbility.oneRepMax.toString())
|
||||
print("Ability " +
|
||||
menuBloc.ability.toString() +
|
||||
" exerciseType 1rm " +
|
||||
bloc.exerciseRepository.exerciseType.is1RM().toString()),
|
||||
if (bloc.exerciseRepository.exerciseType.unitQuantityUnit == null)
|
||||
{
|
||||
args['exerciseRepository'] = bloc.exerciseRepository,
|
||||
Navigator.of(context).pushNamed('evaluationPage', arguments: args)
|
||||
}
|
||||
else if (menuBloc.ability.equalsTo(ExerciseAbility.oneRepMax))
|
||||
{
|
||||
args['exerciseRepository'] = bloc.exerciseRepository,
|
||||
args['percent'] = 0.75,
|
||||
args['readonly'] = false,
|
||||
Navigator.of(context).pushNamed('exerciseControlPage', arguments: args)
|
||||
}
|
||||
else if (bloc.exerciseRepository.exerciseType.isEndurance &&
|
||||
menuBloc.ability.toString() == ExerciseAbility.endurance.toString())
|
||||
else if (menuBloc.ability.equalsTo(ExerciseAbility.endurance))
|
||||
{
|
||||
args['exerciseRepository'] = bloc.exerciseRepository,
|
||||
args['percent'] = 0.50,
|
||||
|
@ -7,7 +7,6 @@ import 'package:aitrainer_app/model/workout_menu_tree.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||
import 'package:aitrainer_app/widgets/splash.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -161,7 +160,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
|
||||
Text(
|
||||
exerciseName,
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.archivoBlack(fontSize: 18, color: Colors.deepOrange),
|
||||
style: GoogleFonts.archivoBlack(fontSize: 18, color: Colors.yellow[200]),
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 3,
|
||||
softWrap: true,
|
||||
|
@ -9,7 +9,6 @@ import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
|
||||
import 'package:aitrainer_app/widgets/splash.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
||||
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
@ -36,20 +37,16 @@ class SettingsPage extends StatelessWidget with Trans {
|
||||
if (state is SettingsError) {
|
||||
} 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) {
|
||||
if (state is SettingsLoading) {
|
||||
//LoadingDialog.show(context);
|
||||
} else if (state is SettingsInitial) {
|
||||
return settingsUI(context, settingsBloc, menuBloc);
|
||||
} else if (state is SettingsReady) {
|
||||
//LoadingDialog.hide(context);
|
||||
return settingsUI(context, settingsBloc, menuBloc);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
@ -72,11 +69,12 @@ class SettingsPage extends StatelessWidget with Trans {
|
||||
onChanged: (String lang) => {
|
||||
settingsBloc.add(SettingsChangeLanguage(language: lang)),
|
||||
})),
|
||||
getServer(),
|
||||
getServer(settingsBloc),
|
||||
getDevice(settingsBloc),
|
||||
]);
|
||||
}
|
||||
|
||||
ListTile getServer() {
|
||||
ListTile getServer(SettingsBloc settingsBloc) {
|
||||
if (Cache().userLoggedIn.admin != 1) {
|
||||
return ListTile(
|
||||
title: Container(),
|
||||
@ -100,7 +98,29 @@ class SettingsPage extends StatelessWidget with Trans {
|
||||
inactiveFgColor: Colors.grey[900],
|
||||
labels: [t('Live-Server'), t('Test-Server')],
|
||||
onToggle: (index) {
|
||||
Cache().setServer(index == 0);
|
||||
//Cache().setServer(index == 0);
|
||||
settingsBloc.add(SettingsSetServer(live: index == 0));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
ListTile getDevice(SettingsBloc settingsBloc) {
|
||||
return ListTile(
|
||||
leading: Icon(CustomIcon.cog),
|
||||
subtitle: Text("Do you have Smart watch, or any device which collects the fit/health data?"),
|
||||
title: ToggleSwitch(
|
||||
minWidth: 120.0,
|
||||
minHeight: 30.0,
|
||||
fontSize: 14.0,
|
||||
initialLabelIndex: Cache().hasHardware ? 0 : 1,
|
||||
activeBgColor: Colors.indigo,
|
||||
activeFgColor: Colors.white,
|
||||
inactiveBgColor: Colors.white60,
|
||||
inactiveFgColor: Colors.grey[900],
|
||||
labels: [t('Yes'), t('No')],
|
||||
onToggle: (index) {
|
||||
settingsBloc.add(SettingsSetHardware(hasHardware: index == 0));
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -5,7 +5,8 @@ import 'package:flutter/material.dart';
|
||||
class LoadingScreenMain extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Image _backgroundImage = Image.asset('asset/image/WT01_loading_layers.png',
|
||||
final Image _backgroundImage = Image.asset(
|
||||
'asset/image/WT01_loading_layers.png',
|
||||
fit: BoxFit.cover,
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
@ -23,13 +24,14 @@ class LoadingScreenMain extends StatelessWidget {
|
||||
new Container(
|
||||
decoration: BoxDecoration(color: Colors.white),
|
||||
),
|
||||
|
||||
/// Render the background image
|
||||
new Container(
|
||||
child: SafeArea(
|
||||
bottom: false,
|
||||
child: _backgroundImage,
|
||||
)
|
||||
),
|
||||
)),
|
||||
|
||||
/// Render the Title widget, loader and messages below each other
|
||||
new Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@ -43,7 +45,6 @@ class LoadingScreenMain extends StatelessWidget {
|
||||
new Padding(
|
||||
padding: const EdgeInsets.only(top: 30.0),
|
||||
),
|
||||
|
||||
],
|
||||
)),
|
||||
),
|
||||
@ -54,8 +55,7 @@ class LoadingScreenMain extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
/// Loader Animation Widget
|
||||
CircularProgressIndicator(
|
||||
valueColor: new AlwaysStoppedAnimation<Color>(
|
||||
Colors.lightGreenAccent),
|
||||
valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightGreenAccent),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20.0),
|
||||
|
71
lib/widgets/number_picker.dart
Normal file
@ -0,0 +1,71 @@
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NumberPickerWidget extends StatefulWidget {
|
||||
final Function(double) onChange;
|
||||
final int minValue;
|
||||
final int maxValue;
|
||||
final int initalValue;
|
||||
final String unit;
|
||||
final Color color;
|
||||
|
||||
const NumberPickerWidget({Key key, this.minValue, this.maxValue, this.initalValue, this.unit, this.color, this.onChange})
|
||||
: super(key: key);
|
||||
@override
|
||||
_NumberPickerWidgetState createState() => _NumberPickerWidgetState();
|
||||
}
|
||||
|
||||
class _NumberPickerWidgetState extends State<NumberPickerWidget> with Trans {
|
||||
Widget durationPicker({bool inSeconds = false, bool inHundredths = false}) {
|
||||
double value = 0;
|
||||
return CupertinoPicker(
|
||||
scrollController: FixedExtentScrollController(initialItem: widget.initalValue),
|
||||
backgroundColor: Colors.transparent,
|
||||
onSelectedItemChanged: (x) {
|
||||
currentData = x.toDouble();
|
||||
value = x.toDouble();
|
||||
//print("sec" + seconds.toStringAsFixed(2));
|
||||
setState(() {});
|
||||
widget.onChange(value);
|
||||
},
|
||||
children: List.generate(widget.maxValue, (index) => Text('$index ' + widget.unit, style: TextStyle(color: widget.color))),
|
||||
itemExtent: 40,
|
||||
);
|
||||
}
|
||||
|
||||
double currentData = 0;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
setContext(context);
|
||||
return Container(
|
||||
//color: Colors.white24,
|
||||
width: MediaQuery.of(context).size.width * .45,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
color: Colors.transparent,
|
||||
width: MediaQuery.of(context).size.width * .3,
|
||||
child: Center(
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
width: MediaQuery.of(context).size.width * 0.95,
|
||||
height: MediaQuery.of(context).size.height * 0.25,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(child: durationPicker()),
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
28
pubspec.lock
@ -211,6 +211,20 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.10"
|
||||
device_info:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.2+10"
|
||||
device_info_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
devicelocale:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -430,6 +444,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
health:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: health
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.9"
|
||||
http:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -869,6 +890,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0-nullsafety.1"
|
||||
stop_watch_timer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: stop_watch_timer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.0+1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
23
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.2+36
|
||||
version: 1.1.2+39
|
||||
|
||||
environment:
|
||||
sdk: ">=2.10.0 <3.0.0"
|
||||
@ -42,7 +42,9 @@ dependencies:
|
||||
keyboard_actions: ^3.3.1+1
|
||||
dropdown_search: ^0.4.8
|
||||
badges: ^1.1.4
|
||||
#health: ^2.0.9
|
||||
health: ^2.0.9
|
||||
stop_watch_timer: ^0.6.0+1
|
||||
#geolocator: ^6.1.13
|
||||
|
||||
|
||||
firebase_core: ^0.5.2
|
||||
@ -97,6 +99,7 @@ flutter:
|
||||
assets:
|
||||
- asset/icon/gomb_kek_a-2.png
|
||||
- asset/icon/gomb_orange_a.png
|
||||
- asset/icon/gomb_orange_c.png
|
||||
- asset/icon/gomb_pink_a.png
|
||||
- asset/icon/gomb_pink_b.png
|
||||
- asset/icon/gomb_zold_b-1.png
|
||||
@ -116,6 +119,9 @@ flutter:
|
||||
- asset/image/Gain_muscle.png
|
||||
- asset/image/WT_weight_loss.png
|
||||
- asset/image/WT_welcome.png
|
||||
- asset/image/WT_Results_for_runners.png
|
||||
- asset/image/WT_Results_for_female.png
|
||||
- asset/image/WT_Results_for_men.png
|
||||
- asset/image/login_fb.png
|
||||
- asset/image/lock.png
|
||||
- asset/image/Congrats_N1.jpg
|
||||
@ -157,6 +163,19 @@ flutter:
|
||||
- asset/image/equipment_gym_place.jpg
|
||||
- asset/image/equipment_street_place.jpg
|
||||
- asset/image/haken.png
|
||||
- asset/image/pict_calorie.png
|
||||
- asset/image/pict_development_by_bodypart_percent.png
|
||||
- asset/image/pict_distance_m.png
|
||||
- asset/image/pict_fatburn_percent.png
|
||||
- asset/image/pict_hravg_bpm.png
|
||||
- asset/image/pict_hrmin_bpm.png
|
||||
- asset/image/pict_hrmax_bpm.png
|
||||
- asset/image/pict_maxspeed_kmh.png
|
||||
- asset/image/pict_reps_volumen_db.png
|
||||
- asset/image/pict_steps.png
|
||||
- asset/image/pict_time_h.png
|
||||
- asset/image/pict_hypertrophy.png
|
||||
- asset/image/pict_weight_volumen_tonna.png
|
||||
- asset/menu/1.cardio.png
|
||||
- asset/menu/1.1.aerob.png
|
||||
- asset/menu/1.2.anaerob.png
|
||||
|
21
test/result_test.dart
Normal file
@ -0,0 +1,21 @@
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/result.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
main() {
|
||||
setUp(() {
|
||||
Cache().setTestBaseUrl();
|
||||
});
|
||||
|
||||
group('Result', () {
|
||||
test('test ResultExt constructor', () async {
|
||||
final ResultExt resultExt = ResultExt(itemString: "Calorie");
|
||||
|
||||
expect(resultExt.getImage(), "asset/image/pic_calorie.png");
|
||||
expect(resultExt.getDescription(), "Calorie");
|
||||
expect(resultExt.item.equals(ResultItem.calorie), true);
|
||||
expect(resultExt.equals(ResultItem.calorie), true);
|
||||
expect(resultExt.equalsString("Calorie"), true);
|
||||
});
|
||||
});
|
||||
}
|