diff --git a/asset/image/equipment_baar.jpg b/asset/image/equipment_baar.jpg new file mode 100644 index 0000000..61a3d71 Binary files /dev/null and b/asset/image/equipment_baar.jpg differ diff --git a/asset/image/equipment_bands.jpg b/asset/image/equipment_bands.jpg new file mode 100644 index 0000000..b777193 Binary files /dev/null and b/asset/image/equipment_bands.jpg differ diff --git a/asset/image/equipment_barbells.jpg b/asset/image/equipment_barbells.jpg new file mode 100644 index 0000000..2be5257 Binary files /dev/null and b/asset/image/equipment_barbells.jpg differ diff --git a/asset/image/equipment_cables.jpg b/asset/image/equipment_cables.jpg new file mode 100644 index 0000000..9d6c7f8 Binary files /dev/null and b/asset/image/equipment_cables.jpg differ diff --git a/asset/image/equipment_dumbbells.jpg b/asset/image/equipment_dumbbells.jpg new file mode 100644 index 0000000..3db6920 Binary files /dev/null and b/asset/image/equipment_dumbbells.jpg differ diff --git a/asset/image/equipment_exerciseball.jpg b/asset/image/equipment_exerciseball.jpg new file mode 100644 index 0000000..0262c36 Binary files /dev/null and b/asset/image/equipment_exerciseball.jpg differ diff --git a/asset/image/equipment_ez-baar_.jpg b/asset/image/equipment_ez-baar_.jpg new file mode 100644 index 0000000..c409fc5 Binary files /dev/null and b/asset/image/equipment_ez-baar_.jpg differ diff --git a/asset/image/equipment_home.jpg b/asset/image/equipment_home.jpg new file mode 100644 index 0000000..fb8c0b4 Binary files /dev/null and b/asset/image/equipment_home.jpg differ diff --git a/asset/image/equipment_instabils.jpg b/asset/image/equipment_instabils.jpg new file mode 100644 index 0000000..ab7193f Binary files /dev/null and b/asset/image/equipment_instabils.jpg differ diff --git a/asset/image/equipment_kettlebells.jpg b/asset/image/equipment_kettlebells.jpg new file mode 100644 index 0000000..f36d14a Binary files /dev/null and b/asset/image/equipment_kettlebells.jpg differ diff --git a/asset/image/equipment_machine.jpg b/asset/image/equipment_machine.jpg new file mode 100644 index 0000000..0e7304d Binary files /dev/null and b/asset/image/equipment_machine.jpg differ diff --git a/asset/image/equipment_medicine.jpg b/asset/image/equipment_medicine.jpg new file mode 100644 index 0000000..a42ec95 Binary files /dev/null and b/asset/image/equipment_medicine.jpg differ diff --git a/asset/image/equipment_none.jpg b/asset/image/equipment_none.jpg new file mode 100644 index 0000000..14503fd Binary files /dev/null and b/asset/image/equipment_none.jpg differ diff --git a/asset/image/equipment_others.jpg b/asset/image/equipment_others.jpg new file mode 100644 index 0000000..424017f Binary files /dev/null and b/asset/image/equipment_others.jpg differ diff --git a/asset/image/equipment_roll.jpg b/asset/image/equipment_roll.jpg new file mode 100644 index 0000000..4069c7d Binary files /dev/null and b/asset/image/equipment_roll.jpg differ diff --git a/asset/image/equipment_rope.jpg b/asset/image/equipment_rope.jpg new file mode 100644 index 0000000..3a1843e Binary files /dev/null and b/asset/image/equipment_rope.jpg differ diff --git a/asset/image/equipment_specialshome.jpg b/asset/image/equipment_specialshome.jpg new file mode 100644 index 0000000..2feb318 Binary files /dev/null and b/asset/image/equipment_specialshome.jpg differ diff --git a/asset/image/equipment_strap.jpg b/asset/image/equipment_strap.jpg new file mode 100644 index 0000000..e94fdf6 Binary files /dev/null and b/asset/image/equipment_strap.jpg differ diff --git a/asset/image/equipment_street.jpg b/asset/image/equipment_street.jpg new file mode 100644 index 0000000..6d07d84 Binary files /dev/null and b/asset/image/equipment_street.jpg differ diff --git a/asset/image/equipment_weightplates.jpg b/asset/image/equipment_weightplates.jpg new file mode 100644 index 0000000..66ffb71 Binary files /dev/null and b/asset/image/equipment_weightplates.jpg differ diff --git a/asset/image/haken.png b/asset/image/haken.png new file mode 100644 index 0000000..0e934e1 Binary files /dev/null and b/asset/image/haken.png differ diff --git a/i18n/en.json b/i18n/en.json index f5ac39b..b16ca34 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -223,5 +223,10 @@ "Your Sizes":"Your Sizes", "Size Of Your":"Size Of Your", "Please type the following data:":"Please type the following data:", - "Cancel": "Cancel" + "Cancel": "Cancel", + "Available Devices":"Available Devices", + "select your equipments by tapping":"select your equipments by tapping", + "Available Equipments":"Available Equipments", + "select your places by tapping":"select your places by tapping", + "Available Training Places":"Available Training Places" } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index db6faad..3bcd0a5 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -224,5 +224,10 @@ "Your Sizes":"Méreteid", "Size Of Your":"Testméret:", "Please type the following data:":"Kérlek írd be a következő adatot:", - "Cancel": "Mégsem" + "Cancel": "Mégsem", + "Available Devices":"Edzés eszközök", + "select your equipments by tapping":"válaszd ki az eszközeidet, kattints a képre", + "Available Equipments":"Elérhető eszközök", + "select your places by tapping":"kattints az edzéshelyszínre", + "Available Training Places":"Elérhető edzéshelyszínek" } \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 12a98eb..6978a27 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,109 +1,91 @@ PODS: - devicelocale (0.0.1): - Flutter - - FBSDKCoreKit (7.1.1): - - FBSDKCoreKit/Basics (= 7.1.1) - - FBSDKCoreKit/Core (= 7.1.1) - - FBSDKCoreKit/Basics (7.1.1) - - FBSDKCoreKit/Core (7.1.1): - - FBSDKCoreKit/Basics - - FBSDKLoginKit (7.1.1): - - FBSDKLoginKit/Login (= 7.1.1) - - FBSDKLoginKit/Login (7.1.1): - - FBSDKCoreKit (~> 7.1.1) - - Firebase/Auth (6.26.0): + - Firebase/Auth (6.33.0): - Firebase/CoreOnly - - FirebaseAuth (~> 6.5.3) - - Firebase/CoreOnly (6.26.0): - - FirebaseCore (= 6.7.2) - - Firebase/Messaging (6.26.0): + - FirebaseAuth (~> 6.9.2) + - Firebase/CoreOnly (6.33.0): + - FirebaseCore (= 6.10.3) + - Firebase/Messaging (6.33.0): - Firebase/CoreOnly - - FirebaseMessaging (~> 4.4.1) - - firebase_auth (0.18.1-2): - - Firebase/Auth (~> 6.26.0) - - Firebase/CoreOnly (~> 6.26.0) + - FirebaseMessaging (~> 4.7.0) + - firebase_auth (0.18.3): + - Firebase/Auth (~> 6.33.0) + - Firebase/CoreOnly (~> 6.33.0) - firebase_core - Flutter - - firebase_core (0.5.0-1): - - Firebase/CoreOnly (~> 6.26.0) + - firebase_core (0.5.2): + - Firebase/CoreOnly (~> 6.33.0) - Flutter - firebase_messaging (7.0.3): - - Firebase/CoreOnly (~> 6.26.0) - - Firebase/Messaging (~> 6.26.0) + - Firebase/CoreOnly (~> 6.33.0) + - Firebase/Messaging (~> 6.33.0) - firebase_core - Flutter - - FirebaseAnalyticsInterop (1.5.0) - - FirebaseAuth (6.5.3): - - FirebaseAuthInterop (~> 1.0) - - FirebaseCore (~> 6.6) - - GoogleUtilities/AppDelegateSwizzler (~> 6.5) - - GoogleUtilities/Environment (~> 6.5) + - FirebaseAuth (6.9.2): + - FirebaseCore (~> 6.10) + - GoogleUtilities/AppDelegateSwizzler (~> 6.7) + - GoogleUtilities/Environment (~> 6.7) - GTMSessionFetcher/Core (~> 1.1) - - FirebaseAuthInterop (1.1.0) - - FirebaseCore (6.7.2): - - FirebaseCoreDiagnostics (~> 1.3) - - FirebaseCoreDiagnosticsInterop (~> 1.2) - - GoogleUtilities/Environment (~> 6.5) - - GoogleUtilities/Logger (~> 6.5) - - FirebaseCoreDiagnostics (1.4.0): - - GoogleDataTransportCCTSupport (~> 3.1) - - GoogleUtilities/Environment (~> 6.5) - - GoogleUtilities/Logger (~> 6.5) - - nanopb (~> 1.30905.0) - - FirebaseCoreDiagnosticsInterop (1.2.0) - - FirebaseInstallations (1.3.0): - - FirebaseCore (~> 6.6) - - GoogleUtilities/Environment (~> 6.6) - - GoogleUtilities/UserDefaults (~> 6.6) + - FirebaseCore (6.10.3): + - FirebaseCoreDiagnostics (~> 1.6) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/Logger (~> 6.7) + - FirebaseCoreDiagnostics (1.7.0): + - GoogleDataTransport (~> 7.4) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/Logger (~> 6.7) + - nanopb (~> 1.30906.0) + - FirebaseInstallations (1.7.0): + - FirebaseCore (~> 6.10) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/UserDefaults (~> 6.7) - PromisesObjC (~> 1.2) - - FirebaseInstanceID (4.3.4): - - FirebaseCore (~> 6.6) - - FirebaseInstallations (~> 1.0) - - GoogleUtilities/Environment (~> 6.5) - - GoogleUtilities/UserDefaults (~> 6.5) - - FirebaseMessaging (4.4.1): - - FirebaseAnalyticsInterop (~> 1.5) - - FirebaseCore (~> 6.6) - - FirebaseInstanceID (~> 4.3) - - GoogleUtilities/AppDelegateSwizzler (~> 6.5) - - GoogleUtilities/Environment (~> 6.5) - - GoogleUtilities/Reachability (~> 6.5) - - GoogleUtilities/UserDefaults (~> 6.5) + - FirebaseInstanceID (4.8.0): + - FirebaseCore (~> 6.10) + - FirebaseInstallations (~> 1.6) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/UserDefaults (~> 6.7) + - FirebaseMessaging (4.7.1): + - FirebaseCore (~> 6.10) + - FirebaseInstanceID (~> 4.7) + - GoogleUtilities/AppDelegateSwizzler (~> 6.7) + - GoogleUtilities/Environment (~> 6.7) + - GoogleUtilities/Reachability (~> 6.7) + - GoogleUtilities/UserDefaults (~> 6.7) - Protobuf (>= 3.9.2, ~> 3.9) - - Flutter (1.0.0) - - flutter_facebook_auth (0.3.1): - - FBSDKCoreKit (~> 7.1.0) - - FBSDKLoginKit (~> 7.1.0) + - flurry (0.0.4): + - Flurry-iOS-SDK/FlurrySDK - Flutter + - Flurry-iOS-SDK/FlurrySDK (11.1.1) + - Flutter (1.0.0) - flutter_keyboard_visibility (0.0.1): - Flutter - - GoogleDataTransport (6.2.1) - - GoogleDataTransportCCTSupport (3.2.0): - - GoogleDataTransport (~> 6.1) - - nanopb (~> 1.30905.0) - - GoogleUtilities/AppDelegateSwizzler (6.6.0): + - GoogleDataTransport (7.5.1): + - nanopb (~> 1.30906.0) + - GoogleUtilities/AppDelegateSwizzler (6.7.2): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (6.6.0): + - GoogleUtilities/Environment (6.7.2): - PromisesObjC (~> 1.2) - - GoogleUtilities/Logger (6.6.0): + - GoogleUtilities/Logger (6.7.2): - GoogleUtilities/Environment - - GoogleUtilities/Network (6.6.0): + - GoogleUtilities/Network (6.7.2): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (6.6.0)" - - GoogleUtilities/Reachability (6.6.0): + - "GoogleUtilities/NSData+zlib (6.7.2)" + - GoogleUtilities/Reachability (6.7.2): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (6.6.0): + - GoogleUtilities/UserDefaults (6.7.2): - GoogleUtilities/Logger - - GTMSessionFetcher/Core (1.4.0) - - nanopb (1.30905.0): - - nanopb/decode (= 1.30905.0) - - nanopb/encode (= 1.30905.0) - - nanopb/decode (1.30905.0) - - nanopb/encode (1.30905.0) + - GTMSessionFetcher/Core (1.5.0) + - nanopb (1.30906.0): + - nanopb/decode (= 1.30906.0) + - nanopb/encode (= 1.30906.0) + - nanopb/decode (1.30906.0) + - nanopb/encode (1.30906.0) - path_provider (0.0.1): - Flutter - PromisesObjC (1.2.11) @@ -116,28 +98,23 @@ DEPENDENCIES: - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - flurry (from `.symlinks/plugins/flurry/ios`) - Flutter (from `Flutter`) - - flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`) - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) - path_provider (from `.symlinks/plugins/path_provider/ios`) - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) SPEC REPOS: trunk: - - FBSDKCoreKit - - FBSDKLoginKit - Firebase - - FirebaseAnalyticsInterop - FirebaseAuth - - FirebaseAuthInterop - FirebaseCore - FirebaseCoreDiagnostics - - FirebaseCoreDiagnosticsInterop - FirebaseInstallations - FirebaseInstanceID - FirebaseMessaging + - Flurry-iOS-SDK - GoogleDataTransport - - GoogleDataTransportCCTSupport - GoogleUtilities - GTMSessionFetcher - nanopb @@ -153,10 +130,10 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_core/ios" firebase_messaging: :path: ".symlinks/plugins/firebase_messaging/ios" + flurry: + :path: ".symlinks/plugins/flurry/ios" Flutter: :path: Flutter - flutter_facebook_auth: - :path: ".symlinks/plugins/flutter_facebook_auth/ios" flutter_keyboard_visibility: :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" path_provider: @@ -166,29 +143,24 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00 - FBSDKCoreKit: b46507dc8b8cefed31d644e74d7cc30e2a715ef8 - FBSDKLoginKit: 1a61d79e2b25e2fc0d03dccab1e34b38bbdf2546 - Firebase: 7cf5f9c67f03cb3b606d1d6535286e1080e57eb6 - firebase_auth: 8ae6798925da84bf8745668a73c936b148c1b04d - firebase_core: 00e54a4744164a6b5a250b96dd1ad5afaba7a342 - firebase_messaging: 666d9994651b1ecf8c582b52dd913f3fa58c17ef - FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae - FirebaseAuth: 7047aec89c0b17ecd924a550c853f0c27ac6015e - FirebaseAuthInterop: a0f37ae05833af156e72028f648d313f7e7592e9 - FirebaseCore: f42e5e5f382cdcf6b617ed737bf6c871a6947b17 - FirebaseCoreDiagnostics: 4505e4d4009b1d93f605088ee7d7764d5f0d1c84 - FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 - FirebaseInstallations: 6f5f680e65dc374397a483c32d1799ba822a395b - FirebaseInstanceID: cef67c4967c7cecb56ea65d8acbb4834825c587b - FirebaseMessaging: 29543feb343b09546ab3aa04d008ee8595b43c44 + Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5 + firebase_auth: 240419f6b00dea39c60a2a9c4379c16c4a4b02fb + firebase_core: 350ba329d1641211bc6183a3236893cafdacfea7 + firebase_messaging: 0aea2cd5885b65e19ede58ee3507f485c992cc75 + FirebaseAuth: c92d49ada7948d1a23466e3db17bc4c2039dddc3 + FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd + FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1 + FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2 + FirebaseInstanceID: bd3ffc24367f901a43c063b36c640b345a4a5dd1 + FirebaseMessaging: 5eca4ef173de76253352511aafef774caa1cba2a + flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad + Flurry-iOS-SDK: 8f3f7fce27177002f15f145eede88dc1b9ac0cd0 Flutter: 0e3d915762c693b495b44d77113d4970485de6ec - flutter_facebook_auth: 85c86b1f574faa5eaacd6de0db6b416fa94b326c flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 - GoogleDataTransport: 9a8a16f79feffc7f42096743de2a7c4815e84020 - GoogleDataTransportCCTSupport: 489c1265d2c85b68187a83a911913d190012158d - GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1 - GTMSessionFetcher: 6f5c8abbab8a9bce4bb3f057e317728ec6182b10 - nanopb: c43f40fadfe79e8b8db116583945847910cbabc9 + GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833 + GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 + GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52 + nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f Protobuf: 3dac39b34a08151c6d949560efe3f86134a3f748 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 738d8ad..f876646 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -362,7 +362,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 32; + CURRENT_PROJECT_VERSION = 33; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -505,7 +505,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 32; + CURRENT_PROJECT_VERSION = 33; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -540,7 +540,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 32; + CURRENT_PROJECT_VERSION = 33; DEVELOPMENT_TEAM = SFJJBDCU6Z; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index af6bf0f..0020715 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -1,9 +1,6 @@ - - diff --git a/lib/bloc/customer_change/customer_change_bloc.dart b/lib/bloc/customer_change/customer_change_bloc.dart index 3777b72..6c6612b 100644 --- a/lib/bloc/customer_change/customer_change_bloc.dart +++ b/lib/bloc/customer_change/customer_change_bloc.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; @@ -77,6 +78,7 @@ class CustomerChangeBloc extends Bloc yield CustomerSaving(); if (validation()) { await customerRepository.saveCustomer(); + Cache().initBadges(); yield CustomerSaveSuccess(); } else { yield CustomerSaveError(message: "Please provide the necessary information"); diff --git a/lib/bloc/customer_exercise_device/customer_exercise_device_bloc.dart b/lib/bloc/customer_exercise_device/customer_exercise_device_bloc.dart new file mode 100644 index 0000000..194bb06 --- /dev/null +++ b/lib/bloc/customer_exercise_device/customer_exercise_device_bloc.dart @@ -0,0 +1,51 @@ +import 'dart:async'; + +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/model/exercise_device.dart'; +import 'package:aitrainer_app/repository/customer_exercise_device_repository.dart'; +import 'package:bloc/bloc.dart'; +import 'package:equatable/equatable.dart'; + +part 'customer_exercise_device_event.dart'; +part 'customer_exercise_device_state.dart'; + +class CustomerExerciseDeviceBloc extends Bloc { + final CustomerExerciseDeviceRepository repository; + final List devices; + + CustomerExerciseDeviceBloc({this.repository, this.devices}) : super(CustomerExerciseDeviceInitial()) { + if (repository.getDevices().isEmpty) { + repository.setDevices(Cache().getCustomerDevices()); + } + } + + @override + Stream mapEventToState( + CustomerExerciseDeviceEvent event, + ) async* { + try { + if (event is CustomerExerciseDeviceLoad) { + yield CustomerExerciseDeviceLoading(); + yield CustomerExerciseDeviceReady(); + } else if (event is CustomerExerciseDeviceAdd) { + yield CustomerExerciseDeviceLoading(); + print("Add device " + event.device.exerciseDeviceId.toString()); + await repository.addDevice(event.device); + Cache().initBadges(); + yield CustomerExerciseDeviceReady(); + } else if (event is CustomerExerciseDeviceRemove) { + print("Remove device " + event.device.exerciseDeviceId.toString()); + yield CustomerExerciseDeviceLoading(); + await repository.removeDevice(event.device); + Cache().initBadges(); + yield CustomerExerciseDeviceReady(); + } + } on Exception catch (ex) { + yield CustomerExerciseDeviceError(message: ex.toString()); + } + } + + bool hasCustomerDevice(int exerciseDeviceId) { + return repository.hasDevice(exerciseDeviceId); + } +} diff --git a/lib/bloc/customer_exercise_device/customer_exercise_device_event.dart b/lib/bloc/customer_exercise_device/customer_exercise_device_event.dart new file mode 100644 index 0000000..cd4c90c --- /dev/null +++ b/lib/bloc/customer_exercise_device/customer_exercise_device_event.dart @@ -0,0 +1,32 @@ +part of 'customer_exercise_device_bloc.dart'; + +abstract class CustomerExerciseDeviceEvent extends Equatable { + const CustomerExerciseDeviceEvent(); + + @override + List get props => []; +} + +class CustomerExerciseDeviceLoad extends CustomerExerciseDeviceEvent { + const CustomerExerciseDeviceLoad(); +} + +class CustomerExerciseDeviceAdd extends CustomerExerciseDeviceEvent { + final ExerciseDevice device; + const CustomerExerciseDeviceAdd({this.device}); + + @override + List get props => [device]; +} + +class CustomerExerciseDeviceRemove extends CustomerExerciseDeviceEvent { + final ExerciseDevice device; + const CustomerExerciseDeviceRemove({this.device}); + + @override + List get props => [device]; +} + +class CustomerExerciseDeviceSave extends CustomerExerciseDeviceEvent { + const CustomerExerciseDeviceSave(); +} diff --git a/lib/bloc/customer_exercise_device/customer_exercise_device_state.dart b/lib/bloc/customer_exercise_device/customer_exercise_device_state.dart new file mode 100644 index 0000000..b958e24 --- /dev/null +++ b/lib/bloc/customer_exercise_device/customer_exercise_device_state.dart @@ -0,0 +1,28 @@ +part of 'customer_exercise_device_bloc.dart'; + +abstract class CustomerExerciseDeviceState extends Equatable { + const CustomerExerciseDeviceState(); + + @override + List get props => []; +} + +class CustomerExerciseDeviceInitial extends CustomerExerciseDeviceState { + const CustomerExerciseDeviceInitial(); +} + +class CustomerExerciseDeviceLoading extends CustomerExerciseDeviceState { + const CustomerExerciseDeviceLoading(); +} + +class CustomerExerciseDeviceReady extends CustomerExerciseDeviceState { + const CustomerExerciseDeviceReady(); +} + +class CustomerExerciseDeviceError extends CustomerExerciseDeviceState { + final String message; + const CustomerExerciseDeviceError({this.message}); + + @override + List get props => [message]; +} diff --git a/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart b/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart index 7992aa9..799c002 100644 --- a/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart +++ b/lib/bloc/exercise_execute_plan_add/exercise_execute_plan_add_bloc.dart @@ -7,6 +7,7 @@ import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flurry/flurry.dart'; import 'package:meta/meta.dart'; part 'exercise_execute_plan_add_event.dart'; @@ -30,27 +31,23 @@ class ExerciseExecutePlanAddBloc extends Bloc { customerRepository.saveCustomer(); changedWeight = false; this.changedSizes = false; + Cache().initBadges(); + Flurry.logEvent("Sizes"); yield ExerciseNewReady(); } else if (event is ExerciseNewSizeChange) { yield ExerciseNewLoading(); @@ -277,6 +280,8 @@ class ExerciseNewBloc extends Bloc { yield ExerciseNewLoading(); await exerciseRepository.addExercise(); menuBloc.add(MenuTreeDown(parent: 0)); + Cache().initBadges(); + Flurry.logEvent("newExercise"); yield ExerciseNewReady(); } else if (event is ExerciseNewBMIAnimate) { yield ExerciseNewLoading(); @@ -288,7 +293,7 @@ class ExerciseNewBloc extends Bloc { } double getBMI() { - if (height == 0) { + if (height == 0 || weight == 0) { this.bmi = 0; return 0; } @@ -299,6 +304,10 @@ class ExerciseNewBloc extends Bloc { double getBMR() { var date = DateTime.now(); + if (height == 0 || weight == 0) { + this.bmi = 0; + return 0; + } int year = int.parse(DateFormat(DateFormat.YEAR).format(date)); @@ -334,14 +343,15 @@ class ExerciseNewBloc extends Bloc { this.bmiLeft = 72; bmiAngle = -62; } else if (bmi < 25 && 18.5 < bmi) { - goalBMI = bmi; + goalBMI = 27; this.bmiTop = 46; this.bmiLeft = 130; - bmiAngle = -21; + bmiAngle = -23; } else if (bmi < 30 && 24.9 < bmi) { goalBMI = 24; this.bmiTop = 38.0; this.bmiLeft = 186.0; + bmiAngle = 7.2; } else if (bmi < 34.9 && 29.9 < bmi) { goalBMI = 29; bmiTop = 48; diff --git a/lib/bloc/exercise_plan/exercise_plan_bloc.dart b/lib/bloc/exercise_plan/exercise_plan_bloc.dart index e5de460..9757c7b 100644 --- a/lib/bloc/exercise_plan/exercise_plan_bloc.dart +++ b/lib/bloc/exercise_plan/exercise_plan_bloc.dart @@ -1,10 +1,12 @@ import 'dart:async'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; +import 'package:aitrainer_app/model/model_change.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flurry/flurry.dart'; import 'package:meta/meta.dart'; part 'exercise_plan_event.dart'; @@ -31,7 +33,7 @@ class ExercisePlanBloc extends Bloc { workoutTree.selected = false; if (exercisePlanRepository.getExercisePlanDetailSize() > 0) { ExercisePlanDetail planDetail = exercisePlanRepository.getExercisePlanDetailByExerciseId(workoutTree.exerciseTypeId); - if (planDetail != null && planDetail.change != ExercisePlanDetailChange.deleted) { + if (planDetail != null && planDetail.change != ModelChange.deleted) { workoutTree.selected = true; } } @@ -39,7 +41,7 @@ class ExercisePlanBloc extends Bloc { }); } - void setExercisePlanRepository(ExercisePlanRepository repo ) => exercisePlanRepository = repo; + void setExercisePlanRepository(ExercisePlanRepository repo) => exercisePlanRepository = repo; @override Stream mapEventToState(ExercisePlanEvent event) async* { @@ -55,14 +57,12 @@ class ExercisePlanBloc extends Bloc { WorkoutMenuTree workoutTree = event.workoutTree; if (workoutTree != null) { - exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType); - workoutTree.selected = true; + exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType); + workoutTree.selected = true; } yield ExercisePlanReady(); - } - - else if (event is ExercisePlanAddExercise) { + } else if (event is ExercisePlanAddExercise) { yield ExercisePlanLoading(); ExercisePlanDetail planDetail = event.exercisePlanDetail; exercisePlanRepository.actualPlanDetail = planDetail; @@ -74,16 +74,14 @@ class ExercisePlanBloc extends Bloc { this.menuTreeRepository.sortedTree.forEach((key, value) { List listTreeItem = value; listTreeItem.forEach((element) { - if ( element.exerciseType.exerciseTypeId == planDetail.exerciseTypeId) { + if (element.exerciseType.exerciseTypeId == planDetail.exerciseTypeId) { element.selected = true; } }); }); yield ExercisePlanReady(); - } - - else if (event is ExercisePlanRemoveExercise) { + } else if (event is ExercisePlanRemoveExercise) { yield ExercisePlanLoading(); ExercisePlanDetail planDetail = event.exercisePlanDetail; exercisePlanRepository.removeExerciseTypeFromPlanByExerciseTypeId(planDetail.exerciseTypeId); @@ -91,7 +89,7 @@ class ExercisePlanBloc extends Bloc { this.menuTreeRepository.sortedTree.forEach((key, value) { List listTreeItem = value; listTreeItem.forEach((element) { - if ( element.exerciseType.exerciseTypeId == planDetail.exerciseTypeId) { + if (element.exerciseType.exerciseTypeId == planDetail.exerciseTypeId) { element.selected = false; } }); @@ -99,12 +97,11 @@ class ExercisePlanBloc extends Bloc { if (exercisePlanRepository.getExercisePlanDetailSize() != 0) { exercisePlanRepository.saveExercisePlan(); + Flurry.logEvent("SaveExercisePlan"); } - yield ExercisePlanReady(); } - } on Exception catch (e) { yield ExercisePlanError(message: e.toString()); } diff --git a/lib/bloc/login_form_bloc.dart b/lib/bloc/login_form_bloc.dart index 2180212..edc43cf 100644 --- a/lib/bloc/login_form_bloc.dart +++ b/lib/bloc/login_form_bloc.dart @@ -59,6 +59,7 @@ class LoginFormBloc extends FormBloc with Common { } emitSuccess(canSubmitAgain: false); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); + Cache().initBadges(); } } on Exception catch (ex) { emitFailure(failureResponse: ex.toString()); diff --git a/lib/bloc/registration_form_bloc.dart b/lib/bloc/registration_form_bloc.dart index 55d5097..dd443fa 100644 --- a/lib/bloc/registration_form_bloc.dart +++ b/lib/bloc/registration_form_bloc.dart @@ -11,19 +11,14 @@ class RegistrationFormBloc extends FormBloc with Common { FieldBlocValidators.required, ], ); - final passwordField = TextFieldBloc( - validators: [ - FieldBlocValidators.required, - ] - ); + final passwordField = TextFieldBloc(validators: [ + FieldBlocValidators.required, + ]); final UserRepository userRepository; RegistrationFormBloc({this.userRepository, this.accountBloc}) { - addFieldBlocs(fieldBlocs: [ - emailField, - passwordField - ]); - + addFieldBlocs(fieldBlocs: [emailField, passwordField]); + emailField.onValueChanges(onData: (previous, current) async* { userRepository.setEmail(current.value); }); @@ -31,18 +26,17 @@ class RegistrationFormBloc extends FormBloc with Common { passwordField.onValueChanges(onData: (previous, current) async* { userRepository.setPassword(current.value); }); - } @override void onSubmitting() async { try { emitLoading(progress: 30); - if ( ! validateEmail(userRepository)) { + if (!validateEmail(userRepository)) { emailField.addFieldError(EMAIL_ERROR, isPermanent: true); emitFailure(failureResponse: EMAIL_ERROR); - } else if ( ! validatePassword(userRepository)) { + } else if (!validatePassword(userRepository)) { passwordField.addFieldError(PASSWORD_ERROR, isPermanent: true); emitFailure(failureResponse: PASSWORD_ERROR); } else { @@ -50,12 +44,10 @@ class RegistrationFormBloc extends FormBloc with Common { await userRepository.addUser(); emitSuccess(canSubmitAgain: false); accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn)); + Cache().initBadges(); } } on Exception catch (ex) { emitFailure(failureResponse: ex.toString()); - } } - - -} \ No newline at end of file +} diff --git a/lib/main.dart b/lib/main.dart index 5d1171e..e5be538 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:aitrainer_app/bloc/customer_exercise_device/customer_exercise_device_bloc.dart'; import 'package:aitrainer_app/push_notifications.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; @@ -31,8 +30,7 @@ import 'package:aitrainer_app/view/registration.dart'; import 'package:aitrainer_app/view/reset_password.dart'; import 'package:aitrainer_app/view/settings.dart'; import 'package:aitrainer_app/widgets/home.dart'; -//import 'package:firebase_analytics/firebase_analytics.dart'; -//import 'package:firebase_analytics/observer.dart'; +import 'package:flurry/flurry.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -143,18 +141,25 @@ Future main() async { create: (BuildContext context) => BodyDevelopmentBloc(workoutTreeRepository: menuTreeRepository), ), ], - child: AitrainerApp(), + child: WorkoutTestApp(), )); }, (error, stackTrace) async { await _reportError(error, stackTrace); }); } -class AitrainerApp extends StatelessWidget { +Future initFlurry() async { + await Flurry.initialize(androidKey: "JNYCTCWBT34FM3J8TV36", iosKey: "3QBG7BSMGPDH24S8TRQP", enableLog: true); + //await Flurry.setUserId("userId"); + //await Flurry.logEvent("eventName"); +} + +class WorkoutTestApp extends StatelessWidget { @override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); //final FirebaseAnalytics analytics = FirebaseAnalytics(); + initFlurry(); PushNotificationsManager().init(); return MaterialApp( localizationsDelegates: [ diff --git a/lib/model/cache.dart b/lib/model/cache.dart index 64e518d..9c1efba 100644 --- a/lib/model/cache.dart +++ b/lib/model/cache.dart @@ -4,15 +4,22 @@ import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; import 'package:aitrainer_app/model/exercise_tree.dart'; import 'package:aitrainer_app/model/exercise.dart'; +import 'package:aitrainer_app/model/model_change.dart'; import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; +import 'package:aitrainer_app/service/customer_exercise_device_service.dart'; import 'package:aitrainer_app/service/exercise_tree_service.dart'; import 'package:aitrainer_app/service/exercisetype_service.dart'; import 'package:aitrainer_app/util/env.dart'; +import 'package:flurry/flurry.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; +import 'customer_exercise_device.dart'; +import 'exercise_device.dart'; + enum SharePrefsChange { login, registration, @@ -64,6 +71,8 @@ class Cache { List _exercises; ExercisePlan _myExercisePlan; List _properties; + List _devices; + List _customerDevices; LinkedHashMap _myExercisesPlanDetails = LinkedHashMap(); @@ -75,6 +84,8 @@ class Cache { ExercisePlan _traineeExercisePlan; List _traineeExercisesPlanDetail; + LinkedHashMap _badges = LinkedHashMap(); + List deviceLanguages; String startPage; @@ -158,7 +169,10 @@ class Cache { sharedPreferences.setString(Cache.firebaseUidKey, firebaseUid); await ExerciseTypeApi().getExerciseTypes(); await ExerciseTreeApi().getExerciseTree(); + final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId); + Cache().setCustomerDevices(customerDevices); await exerciseRepository.getExercisesByCustomer(customerId); + Flurry.setUserId(customerId.toString()); } else if (type == SharePrefsChange.login) { Cache().startPage = "home"; sharedPreferences.setInt(Cache.customerIdKey, customerId); @@ -166,13 +180,17 @@ class Cache { sharedPreferences.setBool(Cache.isLoggedInKey, true); await ExerciseTypeApi().getExerciseTypes(); await ExerciseTreeApi().getExerciseTree(); + final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId); + Cache().setCustomerDevices(customerDevices); await exerciseRepository.getExercisesByCustomer(customerId); + Flurry.setUserId(customerId.toString()); } else if (type == SharePrefsChange.logout) { sharedPreferences.setBool(Cache.isLoggedInKey, false); sharedPreferences.setInt(Cache.customerIdKey, 0); sharedPreferences.setString(Cache.firebaseUidKey, null); sharedPreferences.setString(authTokenKey, ""); } + initBadges(); } void setExerciseTypes(List exerciseTypes) { @@ -241,13 +259,85 @@ class Cache { void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => this.deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId); void deletedMyExercisePlanDetail(ExercisePlanDetail detail) => - this._myExercisesPlanDetails[detail.exerciseTypeId].change = ExercisePlanDetailChange.deleted; + this._myExercisesPlanDetails[detail.exerciseTypeId].change = ModelChange.deleted; void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) { - this._myExercisesPlanDetails[exerciseTypeId].change = ExercisePlanDetailChange.delete; + this._myExercisesPlanDetails[exerciseTypeId].change = ModelChange.delete; } void setProperties(List properties) => this._properties = properties; List getProperties() => _properties; + + void setDevices(List devices) => this._devices = devices; + + List getDevices() => this._devices; + + void setCustomerDevices(List devices) => this._customerDevices = devices; + + List getCustomerDevices() => this._customerDevices; + + LinkedHashMap getBadges() => _badges; + + void setBadge(String key, bool inc) { + if (inc) { + if (_badges[key] != null) { + _badges[key]++; + } else { + _badges[key] = 1; + } + } else { + if (_badges[key] != null) { + if (_badges[key] == 1) { + _badges.remove(key); + } else { + _badges[key]--; + } + } + } + } + + void setBadgeNr(String key, int counter) { + if (_badges[key] != null) { + _badges[key] += counter; + } else { + _badges[key] = counter; + } + } + + void initBadges() { + CustomerRepository customerRepository = CustomerRepository(); + _badges = LinkedHashMap(); + customerRepository.setCustomer(userLoggedIn); + if (this.userLoggedIn != null) { + if (this.userLoggedIn.firstname == null || userLoggedIn.firstname.length == 0) { + setBadge("personalData", true); + setBadge("account", true); + } + if (this._customerDevices == null || this._customerDevices.isEmpty) { + setBadge("customerDevice", true); + setBadge("account", true); + } + if (userLoggedIn.properties == null || userLoggedIn.properties.isEmpty) { + setBadge("personalData", true); + setBadge("Sizes", true); + setBadge("BMI", true); + setBadge("BMR", true); + setBadgeNr("Body Compositions", 3); + setBadgeNr("home", 3); + } else if (customerRepository.getWeight() == 0) { + setBadge("BMI", true); + setBadge("BMR", true); + setBadge("Body Compositions", true); + setBadgeNr("home", 1); + } + if (customerRepository.getHeight() == 0) { + setBadge("BMI", true); + setBadge("BMR", true); + setBadge("Body Compositions", true); + setBadgeNr("home", 1); + } + } + print("Badges: " + _badges.toString()); + } } diff --git a/lib/model/customer_exercise_device.dart b/lib/model/customer_exercise_device.dart new file mode 100644 index 0000000..e5163e8 --- /dev/null +++ b/lib/model/customer_exercise_device.dart @@ -0,0 +1,42 @@ +import 'package:flutter_form_bloc/flutter_form_bloc.dart'; + +class CustomerExerciseDevice { + int customerExerciseDeviceId; + int exerciseDeviceId; + int customerId; + bool favourite; + DateTime dateAdd; + + String change; + + CustomerExerciseDevice({this.exerciseDeviceId, this.customerId, this.favourite}) { + dateAdd = DateTime.now(); + } + + CustomerExerciseDevice.fromJson(Map json) { + this.customerExerciseDeviceId = json['customerExerciseDeviceId']; + this.exerciseDeviceId = json['exerciseDeviceId']; + this.customerId = json['customerId']; + this.favourite = json['favourite'] == 1 ? true : false; + this.dateAdd = DateTime.parse(json['dateAdd']); + } + + Map toJson() { + if (customerExerciseDeviceId == null) { + return { + "exerciseDeviceId": exerciseDeviceId, + "customerId": customerId, + "favourite": favourite == true ? 1 : 0, + "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), + }; + } else { + return { + "customerExerciseDeviceId": customerExerciseDeviceId, + "exerciseDeviceId": exerciseDeviceId, + "customerId": customerId, + "favourite": favourite == true ? 1 : 0, + "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), + }; + } + } +} diff --git a/lib/model/exercise_device.dart b/lib/model/exercise_device.dart new file mode 100644 index 0000000..3693c76 --- /dev/null +++ b/lib/model/exercise_device.dart @@ -0,0 +1,19 @@ +class ExerciseDevice { + int exerciseDeviceId; + String name; + String description; + String imageUrl; + String nameTranslation; + int sort; + bool place; + + ExerciseDevice.fromJson(Map json) { + this.exerciseDeviceId = json['exerciseDeviceId']; + this.name = json['name']; + this.description = json['description']; + this.imageUrl = json['imageUrl']; + this.nameTranslation = json['translations'][0]['name']; + this.sort = json['sort']; + this.place = json['place'] == 1 ? true : false; + } +} diff --git a/lib/model/exercise_plan.dart b/lib/model/exercise_plan.dart index b2b77d8..129a536 100644 --- a/lib/model/exercise_plan.dart +++ b/lib/model/exercise_plan.dart @@ -21,19 +21,18 @@ class ExercisePlan { this.name = json['name']; this.private = json['private']; this.description = json['description']; - this.dateAdd = json['dateAdd'] == null ? null : DateTime.parse( json['dateAdd'] ); - this.dateUpd = json['dateUpd'] == null ? null : DateTime.parse( json['dateUpd'] ); + this.dateAdd = json['dateAdd'] == null ? null : DateTime.parse(json['dateAdd']); + this.dateUpd = json['dateUpd'] == null ? null : DateTime.parse(json['dateUpd']); } Map toJson() { String formattedDateAdd; - if ( dateAdd != null) { + if (dateAdd != null) { formattedDateAdd = DateFormat('yyyy-MM-dd HH:mm').format(dateAdd); } String formattedDateUpd = DateFormat('yyyy-MM-dd HH:mm').format(dateUpd); - print("DateAdd $formattedDateAdd"); - if ( exercisePlanId == null ) { + if (exercisePlanId == null) { return { "customerId": customerId, "name": name, @@ -54,5 +53,4 @@ class ExercisePlan { }; } } - -} \ No newline at end of file +} diff --git a/lib/model/exercise_plan_detail.dart b/lib/model/exercise_plan_detail.dart index 89f79da..68642ec 100644 --- a/lib/model/exercise_plan_detail.dart +++ b/lib/model/exercise_plan_detail.dart @@ -1,13 +1,5 @@ import 'exercise_type.dart'; -class ExercisePlanDetailChange { - static const String add = "add"; - static const String delete = "delete"; - static const String update = "update"; - static const String deleted = "deleted"; - static const String saved = "saved"; -} - class ExercisePlanDetail { int exercisePlanDetailId; int exercisePlanId; @@ -32,12 +24,11 @@ class ExercisePlanDetail { this.weightEquation = json['weightEquation']; } - Map toJson() => - { - "exercisePlanId": exercisePlanId, - "exerciseTypeId": exerciseTypeId, - "serie": serie, - "repeats": repeats, - "weightEquation": weightEquation - }; -} \ No newline at end of file + Map toJson() => { + "exercisePlanId": exercisePlanId, + "exerciseTypeId": exerciseTypeId, + "serie": serie, + "repeats": repeats, + "weightEquation": weightEquation + }; +} diff --git a/lib/model/fitness_state.dart b/lib/model/fitness_state.dart index dd6fffa..8a6d2ee 100644 --- a/lib/model/fitness_state.dart +++ b/lib/model/fitness_state.dart @@ -1,5 +1,3 @@ -import 'package:flutter/semantics.dart'; - class FitnessState { final String value; final String stateText; diff --git a/lib/model/model_change.dart b/lib/model/model_change.dart new file mode 100644 index 0000000..deae972 --- /dev/null +++ b/lib/model/model_change.dart @@ -0,0 +1,7 @@ +class ModelChange { + static const String add = "add"; + static const String delete = "delete"; + static const String update = "update"; + static const String deleted = "deleted"; + static const String saved = "saved"; +} diff --git a/lib/repository/customer_exercise_device_repository.dart b/lib/repository/customer_exercise_device_repository.dart new file mode 100644 index 0000000..9bff8c0 --- /dev/null +++ b/lib/repository/customer_exercise_device_repository.dart @@ -0,0 +1,76 @@ +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/model/customer_exercise_device.dart'; +import 'package:aitrainer_app/model/exercise_device.dart'; +import 'package:aitrainer_app/model/model_change.dart'; +import 'package:aitrainer_app/service/customer_exercise_device_service.dart'; + +class CustomerExerciseDeviceRepository { + List _devices = List(); + + List getDevices() => this._devices; + + void setDevices(List devices) => this._devices = devices; + + Future> getDBDevices() async { + if (Cache().userLoggedIn != null) { + final int customerId = Cache().userLoggedIn.customerId; + this._devices = await CustomerExerciseDeviceApi().getDevices(customerId); + } + return this._devices; + } + + Future addDevice(ExerciseDevice device) async { + CustomerExerciseDevice found; + if (_devices != null) { + this._devices.forEach((element) { + if (element.exerciseDeviceId == device.exerciseDeviceId) { + found = element; + } + }); + } + if (found == null) { + int customerId; + if (Cache().userLoggedIn != null) { + customerId = Cache().userLoggedIn.customerId; + } + CustomerExerciseDevice newDevice = + CustomerExerciseDevice(customerId: customerId, exerciseDeviceId: device.exerciseDeviceId, favourite: false); + newDevice.change = ModelChange.add; + await CustomerExerciseDeviceApi().addDevice(newDevice); + this._devices.add(newDevice); + Cache().setCustomerDevices(_devices); + } + } + + Future removeDevice(ExerciseDevice device) async { + print("Remove " + device.name); + + CustomerExerciseDevice found; + if (_devices != null) { + this._devices.forEach((element) { + if (element.exerciseDeviceId == device.exerciseDeviceId) { + found = element; + } + }); + } + if (found != null) { + this._devices.remove(found); + if (found.change != ModelChange.add) { + await CustomerExerciseDeviceApi().removeDevice(found.customerExerciseDeviceId); + } + Cache().setCustomerDevices(_devices); + } + } + + bool hasDevice(int exerciseDeviceId) { + bool found = false; + if (_devices != null) { + this._devices.forEach((element) { + if (element.exerciseDeviceId == exerciseDeviceId) { + found = true; + } + }); + } + return found; + } +} diff --git a/lib/repository/exercise_device_repository.dart b/lib/repository/exercise_device_repository.dart new file mode 100644 index 0000000..2f052e1 --- /dev/null +++ b/lib/repository/exercise_device_repository.dart @@ -0,0 +1,15 @@ +import 'package:aitrainer_app/model/exercise_device.dart'; +import 'package:aitrainer_app/service/exercise_device_service.dart'; + +class ExerciseDeviceRepository { + List _devices = List(); + + List getDevices() { + return this._devices; + } + + Future> getDBDevices() async { + this._devices = await ExerciseDeviceApi().getDevices(); + return this._devices; + } +} diff --git a/lib/repository/exercise_plan_repository.dart b/lib/repository/exercise_plan_repository.dart index f34ea8f..88faac4 100644 --- a/lib/repository/exercise_plan_repository.dart +++ b/lib/repository/exercise_plan_repository.dart @@ -4,17 +4,17 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; +import 'package:aitrainer_app/model/model_change.dart'; import 'package:aitrainer_app/service/exercise_plan_service.dart'; class ExercisePlanRepository { bool newPlan = true; ExercisePlan exercisePlan; - LinkedHashMap exercisePlanDetails = - LinkedHashMap(); + LinkedHashMap exercisePlanDetails = LinkedHashMap(); int customerId = 0; ExercisePlanDetail actualPlanDetail; - void setCustomerId( int customerId ) { + void setCustomerId(int customerId) { this.customerId = customerId; } @@ -24,11 +24,10 @@ class ExercisePlanRepository { this.exercisePlan = plan; } - ExercisePlan getExercisePlan() => exercisePlan; void addDetailToPlan() { - if ( exercisePlan != null ) { + if (exercisePlan != null) { actualPlanDetail.exercisePlanId = exercisePlan.exercisePlanId; } exercisePlanDetails[actualPlanDetail.exerciseTypeId] = actualPlanDetail; @@ -39,7 +38,7 @@ class ExercisePlanRepository { void setActualPlanDetailByExerciseType(ExerciseType exerciseType) { ExercisePlanDetail detail = exercisePlanDetails[exerciseType.exerciseTypeId]; - if ( detail != null ) { + if (detail != null) { actualPlanDetail = detail; } else { actualPlanDetail = ExercisePlanDetail(exerciseType.exerciseTypeId); @@ -49,7 +48,7 @@ class ExercisePlanRepository { ExercisePlanDetail getActualPlanDetail() => actualPlanDetail; - void setActualPlanDetail( ExercisePlanDetail detail ) { + void setActualPlanDetail(ExercisePlanDetail detail) { this.actualPlanDetail = detail; } @@ -58,10 +57,8 @@ class ExercisePlanRepository { String getPlanDetail(int exerciseTypeId) { ExercisePlanDetail detail = exercisePlanDetails[exerciseTypeId]; String detailString = ""; - if ( detail != null) { - detailString = - detail.serie.toString() + "x" + detail.repeats.toString() + " " + - detail.weightEquation + "kg"; + if (detail != null) { + detailString = detail.serie.toString() + "x" + detail.repeats.toString() + " " + detail.weightEquation + "kg"; } return detailString; } @@ -71,14 +68,14 @@ class ExercisePlanRepository { } void updateExercisePlanDetail(ExerciseType exerciseType, int serie, int repeat, String weight) { - if ( exercisePlanDetails[exerciseType.exerciseTypeId] == null) { + if (exercisePlanDetails[exerciseType.exerciseTypeId] == null) { return; } ExercisePlanDetail exercisePlanDetail = exercisePlanDetails[exerciseType.exerciseTypeId]; exercisePlanDetail.serie = serie; exercisePlanDetail.repeats = repeat; exercisePlanDetail.weightEquation = weight; - exercisePlanDetail.change = ExercisePlanDetailChange.update; + exercisePlanDetail.change = ModelChange.update; exercisePlanDetails[exerciseType.exerciseTypeId] = exercisePlanDetail; } @@ -88,19 +85,18 @@ class ExercisePlanRepository { } void removeExerciseTypeFromPlanByExerciseTypeId(int exerciseTypeId) { - exercisePlanDetails[exerciseTypeId].change = ExercisePlanDetailChange.delete; + exercisePlanDetails[exerciseTypeId].change = ModelChange.delete; Cache().deleteMyExercisePlanDetailByExerciseTypeId(exerciseTypeId); } Future saveExercisePlan() async { - - if ( exercisePlan == null ) { - if ( Cache().userLoggedIn == null ) { + if (exercisePlan == null) { + if (Cache().userLoggedIn == null) { throw Exception("please log in"); } String exercisePlanName; - if ( this.customerId == Cache().userLoggedIn.customerId) { + if (this.customerId == Cache().userLoggedIn.customerId) { exercisePlanName = Cache().userLoggedIn.name + " private"; } else { exercisePlanName = Cache().getTrainee().name + " " + Cache().getTrainee().firstname + " private"; @@ -108,55 +104,47 @@ class ExercisePlanRepository { exercisePlan = ExercisePlan(exercisePlanName, this.customerId); } - if ( newPlan ) { + if (newPlan) { exercisePlan.dateAdd = DateTime.now(); exercisePlan.private = true; - ExercisePlan savedExercisePlan = - await ExercisePlanApi().saveExercisePlan(exercisePlan); + ExercisePlan savedExercisePlan = await ExercisePlanApi().saveExercisePlan(exercisePlan); - LinkedHashMap savedExercisePlanDetails = LinkedHashMap(); - exercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async { - exercisePlanDetail.exercisePlanId = savedExercisePlan.exercisePlanId; - ExercisePlanDetail savedDetail = await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail); - savedExercisePlanDetails[savedDetail.exerciseTypeId] = savedDetail; - }); + LinkedHashMap savedExercisePlanDetails = LinkedHashMap(); + exercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async { + exercisePlanDetail.exercisePlanId = savedExercisePlan.exercisePlanId; + ExercisePlanDetail savedDetail = await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail); + savedExercisePlanDetails[savedDetail.exerciseTypeId] = savedDetail; + }); exercisePlan = savedExercisePlan; exercisePlanDetails = savedExercisePlanDetails; - } else { - //await ExercisePlanApi().updateExercisePlan(exercisePlan, exercisePlan.exercisePlanId); exercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async { - if ( exercisePlanDetail.change == ExercisePlanDetailChange.delete ) { - await ExercisePlanApi() - .deleteExercisePlanDetail(exercisePlanDetail.exercisePlanDetailId); - exercisePlanDetail.change = ExercisePlanDetailChange.deleted; + if (exercisePlanDetail.change == ModelChange.delete) { + await ExercisePlanApi().deleteExercisePlanDetail(exercisePlanDetail.exercisePlanDetailId); + exercisePlanDetail.change = ModelChange.deleted; Cache().deletedMyExercisePlanDetail(exercisePlanDetail); - } else if ( exercisePlanDetail.change == ExercisePlanDetailChange.update ) { - await ExercisePlanApi() - .updateExercisePlanDetail(exercisePlanDetail, exercisePlanDetail.exercisePlanDetailId); + } else if (exercisePlanDetail.change == ModelChange.update) { + await ExercisePlanApi().updateExercisePlanDetail(exercisePlanDetail, exercisePlanDetail.exercisePlanDetailId); Cache().updateMyExercisePlanDetail(exercisePlanDetail); - exercisePlanDetail.change = ExercisePlanDetailChange.saved; - } else if ( exercisePlanDetail.change == ExercisePlanDetailChange.add ) { - await ExercisePlanApi() - .saveExercisePlanDetail(exercisePlanDetail); + exercisePlanDetail.change = ModelChange.saved; + } else if (exercisePlanDetail.change == ModelChange.add) { + await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail); Cache().addToMyExercisePlanDetails(exercisePlanDetail); - exercisePlanDetail.change = ExercisePlanDetailChange.saved; + exercisePlanDetail.change = ModelChange.saved; } }); - - } } Future getLastExercisePlan() async { - if ( customerId == 0) { + if (customerId == 0) { return null; } ExercisePlan myExercisePlan = Cache().getMyExercisePlan(); - if ( myExercisePlan != null ) { + if (myExercisePlan != null) { exercisePlan = myExercisePlan; return myExercisePlan; } @@ -171,15 +159,15 @@ class ExercisePlanRepository { Future getExercisePlanDetails() async { if (exercisePlan == null) { ExercisePlan exercisePlan = await this.getLastExercisePlan(); - if ( exercisePlan == null ) { + if (exercisePlan == null) { exercisePlanDetails = LinkedHashMap(); return; } } List list = List(); - LinkedHashMap listCache = Cache().getMyExercisePlanDetails(); - if ( listCache.length > 0) { + LinkedHashMap listCache = Cache().getMyExercisePlanDetails(); + if (listCache.length > 0) { exercisePlanDetails = listCache; return; } else { @@ -197,5 +185,4 @@ class ExercisePlanRepository { return; } - -} \ No newline at end of file +} diff --git a/lib/repository/property_repository.dart b/lib/repository/property_repository.dart index f3ed981..1960c26 100644 --- a/lib/repository/property_repository.dart +++ b/lib/repository/property_repository.dart @@ -1,5 +1,3 @@ -import 'dart:collection'; - import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/service/property_service.dart'; diff --git a/lib/repository/user_repository.dart b/lib/repository/user_repository.dart index 4888683..6798955 100644 --- a/lib/repository/user_repository.dart +++ b/lib/repository/user_repository.dart @@ -41,9 +41,7 @@ class UserRepository { String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password); if (rc == FirebaseApi.SIGN_IN_OK) { - print("Firebase login ok"); await CustomerApi().getUserByEmail(modelUser.email); - print("GetUserBy Email OK"); Cache().afterFirebaseLogin(); } else { print("Exception: user not found or password is wrong"); diff --git a/lib/service/customer_exercise_device_service.dart b/lib/service/customer_exercise_device_service.dart new file mode 100644 index 0000000..34c5f83 --- /dev/null +++ b/lib/service/customer_exercise_device_service.dart @@ -0,0 +1,44 @@ +import 'package:aitrainer_app/model/customer_exercise_device.dart'; +import 'package:aitrainer_app/util/not_found_exception.dart'; +import 'dart:convert'; + +import 'api.dart'; + +class CustomerExerciseDeviceApi { + final APIClient _client = new APIClient(); + + Future> getDevices(int customerId) async { + List devices; + try { + final body = await _client.get("customer_exercise_device/customer/" + customerId.toString(), ""); + final Iterable json = jsonDecode(body); + devices = json.map((device) => CustomerExerciseDevice.fromJson(device)).toList(); + } on NotFoundException catch (e) { + print("No devices found"); + } + return devices; + } + + Future addDevice(CustomerExerciseDevice device) async { + CustomerExerciseDevice savedDevice; + try { + final String body = JsonEncoder().convert(device.toJson()); + print(" --- add customer_exercise_device: " + body); + final String responseBody = await _client.post("customer_exercise_device", body); + savedDevice = CustomerExerciseDevice.fromJson(jsonDecode(responseBody)); + } on Exception catch (e) { + throw new Exception(e.toString()); + } + return savedDevice; + } + + Future removeDevice(int id) async { + try { + print(" --- delete customer_exercise_device: " + id.toString()); + await _client.post("customer_exercise_device/delete/" + id.toString(), ""); + } on Exception catch (e) { + throw new Exception(e.toString()); + } + return; + } +} diff --git a/lib/service/customer_service.dart b/lib/service/customer_service.dart index 5cd229d..da870d3 100644 --- a/lib/service/customer_service.dart +++ b/lib/service/customer_service.dart @@ -6,7 +6,6 @@ import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/user.dart'; import 'package:aitrainer_app/service/api.dart'; import 'package:aitrainer_app/model/cache.dart'; -import 'package:aitrainer_app/util/not_found_exception.dart'; class CustomerApi { final APIClient _client = new APIClient(); diff --git a/lib/service/exercise_device_service.dart b/lib/service/exercise_device_service.dart new file mode 100644 index 0000000..4b15433 --- /dev/null +++ b/lib/service/exercise_device_service.dart @@ -0,0 +1,17 @@ +import 'package:aitrainer_app/model/cache.dart'; +import 'dart:convert'; +import 'package:aitrainer_app/model/exercise_device.dart'; + +import 'api.dart'; + +class ExerciseDeviceApi { + final APIClient _client = new APIClient(); + + Future> getDevices() async { + final body = await _client.get("exercise_device/", ""); + final Iterable json = jsonDecode(body); + final List devices = json.map((device) => ExerciseDevice.fromJson(device)).toList(); + Cache().setDevices(devices); + return devices; + } +} diff --git a/lib/service/exercise_service.dart b/lib/service/exercise_service.dart index 843fcc4..0abb9e9 100644 --- a/lib/service/exercise_service.dart +++ b/lib/service/exercise_service.dart @@ -2,30 +2,27 @@ import 'dart:convert'; import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/service/api.dart'; - class ExerciseApi { - final APIClient _client=new APIClient(); + final APIClient _client = new APIClient(); Future> getExerciseTypes(String param) async { final body = await _client.get("exercises", param); final Iterable json = jsonDecode(body); - final List exerciseTypes = json.map( (exerciseType) => Exercise.fromJson(exerciseType) ).toList(); + final List exerciseTypes = json.map((exerciseType) => Exercise.fromJson(exerciseType)).toList(); return exerciseTypes; } Future saveExercise(Exercise exercise) async { String body = JsonEncoder().convert(exercise.toJson()); - print(" ===== saving exercise id: " + exercise.exerciseId.toString() + ":" + body ); - await _client.post( - "exercises/"+exercise.exerciseId.toString(), - body); + print(" ===== saving exercise id: " + exercise.exerciseId.toString() + ":" + body); + await _client.post("exercises/" + exercise.exerciseId.toString(), body); } - Future> getExercisesByCustomer(int customerId ) async { - final body = await _client.get("exercises/customer/", customerId.toString() ); + Future> getExercisesByCustomer(int customerId) async { + final body = await _client.get("exercises/customer/", customerId.toString()); final Iterable json = jsonDecode(body); - final List exercises = json.map( (exercise) { + final List exercises = json.map((exercise) { Exercise item = Exercise.fromJson(exercise); return item; }).toList(); @@ -36,19 +33,16 @@ class ExerciseApi { Future addExercise(Exercise exercise) async { String body = JsonEncoder().convert(exercise.toJson()); - print(" ===== add new exercise: " + body ); - final String response = await _client.post( - "exercises", - body); + print(" ===== add new exercise: " + body); + final String response = await _client.post("exercises", body); final Exercise savedExercise = Exercise.fromJson(jsonDecode(response)); return savedExercise; } Future deleteExercise(Exercise exercise) async { int exerciseId = exercise.exerciseId; - print(" ===== delete exercise: " + exerciseId.toString() ); - final String response = await _client.post("exercises/" + exerciseId.toString(), ""); + print(" ===== delete exercise: " + exerciseId.toString()); + await _client.post("exercises/" + exerciseId.toString(), ""); return; } - -} \ No newline at end of file +} diff --git a/lib/service/firebase_api.dart b/lib/service/firebase_api.dart index 58b89c2..c3d3c83 100644 --- a/lib/service/firebase_api.dart +++ b/lib/service/firebase_api.dart @@ -1,7 +1,7 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; +//import 'package:flutter_facebook_auth/flutter_facebook_auth.dart'; class FirebaseApi { static FirebaseApi _instance; @@ -66,10 +66,6 @@ class FirebaseApi { print('The account already exists for that email.'); rc = REGISTER_EMAIL_IN_USE; throw Exception("The email address has been registered already"); - /* userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password); - if (rc != null) { - rc = SIGN_IN_OK; - } */ } } catch (e) { print(e); @@ -78,7 +74,7 @@ class FirebaseApi { return rc; } - Future signInWithFacebook() async { + /*Future signInWithFacebook() async { // Trigger the sign-in flow final LoginResult result = await FacebookAuth.instance.login(); @@ -87,7 +83,7 @@ class FirebaseApi { // Once signed in, return the UserCredential return await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential); - } + }*/ Future signOut() async { await FirebaseAuth.instance.signOut(); diff --git a/lib/util/session.dart b/lib/util/session.dart index 30de85c..4938170 100644 --- a/lib/util/session.dart +++ b/lib/util/session.dart @@ -1,19 +1,20 @@ import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/model/customer_exercise_device.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/service/api.dart'; +import 'package:aitrainer_app/service/customer_exercise_device_service.dart'; import 'package:aitrainer_app/service/customer_service.dart'; +import 'package:aitrainer_app/service/exercise_device_service.dart'; import 'package:aitrainer_app/service/exercise_tree_service.dart'; import 'package:aitrainer_app/service/exercisetype_service.dart'; import 'package:aitrainer_app/service/firebase_api.dart'; import 'package:aitrainer_app/service/property_service.dart'; import 'package:devicelocale/devicelocale.dart'; +import 'package:flurry/flurry.dart'; import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:aitrainer_app/model/cache.dart'; -import 'package:firebase_core/firebase_core.dart'; - -//import '../push_notifications.dart'; class Session { Future _prefs = SharedPreferences.getInstance(); @@ -36,7 +37,6 @@ class Session { // Create the initialization Future outside of `build`: - // PushNotificationsManager().init(); } } @@ -100,15 +100,19 @@ class Session { customerId = prefs.getInt(Cache.customerIdKey); await CustomerApi().getCustomer(customerId); Cache().startPage = "home"; + Flurry.setUserId(customerId.toString()); } } await ExerciseTypeApi().getExerciseTypes(); await ExerciseTreeApi().getExerciseTree(); + final customerDevices = await CustomerExerciseDeviceApi().getDevices(customerId); + Cache().setCustomerDevices(customerDevices); if (customerId > 0) { ExerciseRepository exerciseRepository = ExerciseRepository(); await exerciseRepository.getExercisesByCustomer(customerId); } + await ExerciseDeviceApi().getDevices(); print("--- Session finished"); } } diff --git a/lib/view/account.dart b/lib/view/account.dart index c62bf18..82e76e5 100644 --- a/lib/view/account.dart +++ b/lib/view/account.dart @@ -4,6 +4,7 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/customer.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; +import 'package:badges/badges.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:flutter/material.dart'; @@ -57,7 +58,7 @@ class AccountPage extends StatelessWidget with Trans { ListView accountWidget(BuildContext context, String customerName, AccountBloc accountBloc) { return ListView(padding: EdgeInsets.only(top: 35), children: [ ListTile( - leading: Icon(Icons.perm_identity), + leading: badgedIcon(Colors.grey, Icons.perm_identity, "personalData"), //Icon(Icons.perm_identity), subtitle: Text(t("Profile")), title: FlatButton( child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -74,11 +75,33 @@ class AccountPage extends StatelessWidget with Trans { }, ), ), + devices(context, accountBloc), loginOut(context, accountBloc), getMyTrainees(context, accountBloc), ]); } + ListTile devices(BuildContext context, AccountBloc accountBloc) { + ListTile element = ListTile(); + element = ListTile( + leading: badgedIcon(Colors.grey, Icons.device_hub, "customerDevice"), + title: FlatButton( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [Text(t("Available Devices"), style: TextStyle(color: Colors.orange)), Icon(Icons.arrow_forward_ios)]), + textColor: Colors.orange, + color: Colors.white, + onPressed: () => { + if (accountBloc.customerRepository.customer != null && Cache().userLoggedIn != null) + { + Navigator.of(context).pushNamed('customerExerciseDevicePage'), + } + }, + ), + ); + return element; + } + ListTile loginOut(BuildContext context, AccountBloc accountBloc) { ListTile element = ListTile(); @@ -203,4 +226,24 @@ class AccountPage extends StatelessWidget with Trans { ], )); } + + Widget badgedIcon(Color color, IconData icon, String badgeKey) { + bool show = Cache().getBadges()[badgeKey] != null; + int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0; + return Badge( + position: BadgePosition.topEnd(top: -10, end: -10), + animationDuration: Duration(milliseconds: 500), + animationType: BadgeAnimationType.slide, + badgeColor: Colors.red, + showBadge: show, + badgeContent: Text( + counter.toString(), + style: TextStyle(color: Colors.white), + ), + child: Icon( + icon, + color: color, + ), + ); + } } diff --git a/lib/view/customer_exercise_device.dart b/lib/view/customer_exercise_device.dart new file mode 100644 index 0000000..33c9686 --- /dev/null +++ b/lib/view/customer_exercise_device.dart @@ -0,0 +1,246 @@ +import 'package:aitrainer_app/bloc/customer_exercise_device/customer_exercise_device_bloc.dart'; +import 'package:aitrainer_app/localization/app_language.dart'; +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/model/exercise_device.dart'; +import 'package:aitrainer_app/repository/customer_exercise_device_repository.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:aitrainer_app/widgets/app_bar.dart'; +import 'package:aitrainer_app/widgets/image_button.dart'; +import 'package:aitrainer_app/widgets/splash.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; + +// ignore: must_be_immutable +class CustomerExerciseDevicePage extends StatelessWidget with Trans { + List listDevice; + + @override + Widget build(BuildContext context) { + setContext(context); + double cWidth = MediaQuery.of(context).size.width; + return Scaffold( + appBar: AppBarNav(depth: 0), + body: Container( + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_background.png'), + fit: BoxFit.cover, + alignment: Alignment.center, + ), + ), + child: BlocProvider( + create: (context) => + CustomerExerciseDeviceBloc(repository: CustomerExerciseDeviceRepository(), devices: Cache().getDevices()) + ..add(CustomerExerciseDeviceLoad()), + child: BlocConsumer( + listener: (context, state) { + if (state is CustomerExerciseDeviceLoading) { + return LoadingDialog(); + } else if (state is CustomerExerciseDeviceError) { + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); + } + }, + builder: (context, state) { + final bloc = BlocProvider.of(context); + return getPage(bloc, cWidth); + }, + )))); + } + + Widget getPage(CustomerExerciseDeviceBloc bloc, double cWidth) { + print("width" + cWidth.toString()); + return CustomScrollView(scrollDirection: Axis.vertical, slivers: [ + SliverGrid( + delegate: SliverChildListDelegate([ + Text(t("Available Training Places"), + textAlign: TextAlign.center, + maxLines: 2, + softWrap: true, + style: GoogleFonts.archivoBlack( + fontSize: 24, + color: Colors.white, + shadows: [ + 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, + ), + ], + )), + Text(t("select your places by tapping"), + textAlign: TextAlign.center, + softWrap: true, + maxLines: 2, + style: GoogleFonts.archivoBlack( + fontSize: 14, + color: Colors.white, + shadows: [ + 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, + ), + ], + )), + ]), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 1, + mainAxisSpacing: 0.0, + crossAxisSpacing: 0.0, + childAspectRatio: cWidth > 375 ? 9.1 : 4.1, + ), + ), + SliverGrid( + delegate: SliverChildListDelegate(getDevicesPlace(bloc, cWidth)), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 1, + mainAxisSpacing: 15.0, + crossAxisSpacing: 10.0, + childAspectRatio: 3.0, + ), + ), + SliverGrid( + delegate: SliverChildListDelegate([ + SizedBox( + height: 1, + ), + Text(t("Available Equipments"), + textAlign: TextAlign.center, + maxLines: 2, + style: GoogleFonts.archivoBlack( + fontSize: 24, + color: Colors.white, + shadows: [ + 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, + ), + ], + )), + Text(t("select your equipments by tapping"), + textAlign: TextAlign.center, + maxLines: 2, + style: GoogleFonts.archivoBlack( + fontSize: 14, + color: Colors.white, + shadows: [ + 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, + ), + ], + )), + ]), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 1, + mainAxisSpacing: 2.0, + crossAxisSpacing: 5.0, + childAspectRatio: cWidth > 375 ? 9.1 : 6.1, + ), + ), + SliverGrid( + delegate: SliverChildListDelegate(getDevices(bloc)), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + mainAxisSpacing: 15.0, + crossAxisSpacing: 15.0, + childAspectRatio: 1.0, + ), + ), + ]); + } + + List getDevices(CustomerExerciseDeviceBloc bloc) { + final bool isEnglish = AppLanguage().appLocal.languageCode == "en"; + this.listDevice = List(); + final devices = bloc.devices; + devices.sort((a, b) => a.sort.compareTo(b.sort)); + if (devices != null) { + devices.forEach((element) { + if (element.place == false) { + final String url = "asset/image/" + element.imageUrl.substring(7); + ImageButton button = ImageButton( + width: 178, + height: 175, + textAlignment: Alignment.topCenter, + text: isEnglish ? element.name : element.nameTranslation, + style: GoogleFonts.archivoBlack(fontSize: 14, color: Colors.white, backgroundColor: Colors.black54.withOpacity(0.4)), + image: url, + left: 5, + onTap: () => changeButtonShape(element, bloc), + isLocked: false, + isMarked: bloc.hasCustomerDevice(element.exerciseDeviceId), + buttonIndex: element.exerciseDeviceId, + isShape: false, + ); + listDevice.add(button); + } + }); + } + return listDevice; + } + + List getDevicesPlace(CustomerExerciseDeviceBloc bloc, double cWidth) { + final bool isEnglish = AppLanguage().appLocal.languageCode == "en"; + this.listDevice = List(); + final devices = bloc.devices; + if (devices != null) { + devices.sort((a, b) => a.sort.compareTo(b.sort)); + devices.forEach((element) { + if (element.place) { + ImageButton button = ImageButton( + width: cWidth - 80, + height: 125, + top: 10, + textAlignment: Alignment.topCenter, + text: isEnglish ? element.name : element.nameTranslation, + style: GoogleFonts.archivoBlack(fontSize: 14, color: Colors.white, backgroundColor: Colors.black54.withOpacity(0.4)), + image: element.imageUrl, + left: 35, + onTap: () => changeButtonShape(element, bloc), + isLocked: false, + buttonIndex: element.exerciseDeviceId, + isShape: false, + isMarked: bloc.hasCustomerDevice(element.exerciseDeviceId), + ); + listDevice.add(button); + } + }); + } + return listDevice; + } + + void changeButtonShape(ExerciseDevice device, CustomerExerciseDeviceBloc bloc) { + print("Device clicked: " + device.name); + if (bloc.hasCustomerDevice(device.exerciseDeviceId)) { + bloc.add(CustomerExerciseDeviceRemove(device: device)); + } else { + bloc.add(CustomerExerciseDeviceAdd(device: device)); + } + } +} diff --git a/lib/view/exercise_control_page.dart b/lib/view/exercise_control_page.dart index 5dffd4b..8429c82 100644 --- a/lib/view/exercise_control_page.dart +++ b/lib/view/exercise_control_page.dart @@ -27,43 +27,31 @@ class _ExerciseControlPage extends State with Trans { setContext(context); return BlocProvider( - create: (context) => ExerciseControlBloc( - exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly).. - add(ExerciseControlLoad()), - child: - BlocConsumer( - listener: (context, state) { - + create: (context) => ExerciseControlBloc(exerciseRepository: exerciseRepository, percentToCalculate: percent, readonly: readonly) + ..add(ExerciseControlLoad()), + child: BlocConsumer(listener: (context, state) { if (state is ExerciseControlError) { - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, - content: - Text(state.message, style: TextStyle(color: Colors.white)))); + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } else if (state is ExerciseControlLoading) { return LoadingDialog(); } - }, - builder: (context, state) { - + }, builder: (context, state) { final exerciseBloc = BlocProvider.of(context); if (state is ExerciseControlReady) { return getControlForm(exerciseBloc); } else { return getControlForm(exerciseBloc); } - }) - - ); + })); } Form getControlForm(ExerciseControlBloc exerciseBloc) { - String exerciseName = AppLanguage().appLocal == Locale("en") ? exerciseBloc.exerciseRepository.exerciseType.name : exerciseBloc.exerciseRepository.exerciseType.nameTranslation; return Form( - autovalidate: true, child: Scaffold( resizeToAvoidBottomInset: true, appBar: AppBarNav(depth: 1), @@ -97,8 +85,7 @@ class _ExerciseControlPage extends State with Trans { Icon(Icons.info), Flexible( child: Text(t("Why do you need Exercise Control?"), - style: - TextStyle(color: Colors.blueAccent, fontWeight: FontWeight.normal, fontSize: 14)), + style: TextStyle(color: Colors.blueAccent, fontWeight: FontWeight.normal, fontSize: 14)), ), Icon(Icons.arrow_forward_ios), ]), @@ -137,19 +124,20 @@ class _ExerciseControlPage extends State with Trans { } Widget numberPickForm(ExerciseControlBloc exerciseBloc, int step) { - String strTimes = step == 2 ? exerciseBloc.origQuantity.toString() : "max."; String textInstruction = ""; textInstruction = t("Please repeat with ") + - exerciseBloc.unitQuantity.toStringAsFixed(0) + - " " + - exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + - t("hu_with") + " " + - strTimes + " " + t("times!"); + exerciseBloc.unitQuantity.toStringAsFixed(0) + + " " + + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + + t("hu_with") + + " " + + strTimes + + " " + + t("times!"); String title = step.toString() + ". " + t("Control Exercise:"); - List listWidgets = [ Text( title, @@ -168,75 +156,67 @@ class _ExerciseControlPage extends State with Trans { minValue: 0, maxValue: 200, step: 1, - onChanged: (value) => { - exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step)) - }, + onChanged: (value) => {exerciseBloc.add(ExerciseControlQuantityChange(quantity: value.toDouble(), step: step))}, listViewHeight: 80, //decoration: _decoration, ), RaisedButton( - padding: EdgeInsets.all(0), - textColor: Colors.white, - color: step == exerciseBloc.step ? Colors.blue : Colors.black26, - focusColor: Colors.blueAccent, - onPressed: () => { - exerciseBloc.add(ExerciseControlSubmit(step: step)), - if ( step == 3 ) { - confirmationDialog(exerciseBloc) - } - }, - child: Text( - t("Save"), - style: TextStyle(fontSize: 12), - )), + padding: EdgeInsets.all(0), + textColor: Colors.white, + color: step == exerciseBloc.step ? Colors.blue : Colors.black26, + focusColor: Colors.blueAccent, + onPressed: () => { + exerciseBloc.add(ExerciseControlSubmit(step: step)), + if (step == 3) {confirmationDialog(exerciseBloc)} + }, + child: Text( + t("Save"), + style: TextStyle(fontSize: 12), + )), ], ), - ]; - return - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: listWidgets, - + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: listWidgets, ); } - void confirmationDialog( ExerciseControlBloc bloc ) { - - + void confirmationDialog(ExerciseControlBloc bloc) { String unit = t(bloc.exerciseRepository.exerciseType.unit); showCupertinoDialog( - useRootNavigator: true, - context: context, - //barrierDismissible: false, - builder:(_) => CupertinoAlertDialog( - title: Text(t("Summary of your test")), - content: Column( - - children: [ - - Text(t("Test") + ": " + bloc.repeats[1].toStringAsFixed(0) + "x" + bloc.repeats[0].toStringAsFixed(0) + " " + unit , - style: (TextStyle(color: Colors.blue)),), - Divider(), - Text(t("1st Control") + ": " + bloc.repeats[2].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit , - style: (TextStyle(color: Colors.blue)),), - Text(t("2nd Control") + ": " + bloc.repeats[3].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit , - style: (TextStyle(color: Colors.blue)),), - Text(t("3rd Control") + ": " + bloc.repeats [4].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit , - style: (TextStyle(color: Colors.blue)),), - ]), - actions: [ - FlatButton( - child: Text(t("OK")), - onPressed: () => { - Navigator.of(context).pop(), - Navigator.of(context).pop() - }, - ) - ], - ) - ); + useRootNavigator: true, + context: context, + //barrierDismissible: false, + builder: (_) => CupertinoAlertDialog( + title: Text(t("Summary of your test")), + content: Column(children: [ + Text( + t("Test") + ": " + bloc.repeats[1].toStringAsFixed(0) + "x" + bloc.repeats[0].toStringAsFixed(0) + " " + unit, + style: (TextStyle(color: Colors.blue)), + ), + Divider(), + Text( + t("1st Control") + ": " + bloc.repeats[2].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit, + style: (TextStyle(color: Colors.blue)), + ), + Text( + t("2nd Control") + ": " + bloc.repeats[3].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit, + style: (TextStyle(color: Colors.blue)), + ), + Text( + t("3rd Control") + ": " + bloc.repeats[4].toStringAsFixed(0) + "x" + bloc.unitQuantity.toStringAsFixed(0) + " " + unit, + style: (TextStyle(color: Colors.blue)), + ), + ]), + actions: [ + FlatButton( + child: Text(t("OK")), + onPressed: () => {Navigator.of(context).pop(), Navigator.of(context).pop()}, + ) + ], + )); } } diff --git a/lib/view/exercise_execute_plan_add_page.dart b/lib/view/exercise_execute_plan_add_page.dart index a5c6b3a..22ba5fa 100644 --- a/lib/view/exercise_execute_plan_add_page.dart +++ b/lib/view/exercise_execute_plan_add_page.dart @@ -14,12 +14,11 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; -class ExerciseExecutePlanAddPage extends StatefulWidget{ +class ExerciseExecutePlanAddPage extends StatefulWidget { _ExerciseExecuteAddPage createState() => _ExerciseExecuteAddPage(); } class _ExerciseExecuteAddPage extends State with Trans { - @override Widget build(BuildContext context) { LinkedHashMap arguments = ModalRoute.of(context).settings.arguments; @@ -31,167 +30,151 @@ class _ExerciseExecuteAddPage extends State with Tra setContext(context); return BlocProvider( - create: (context) => - ExerciseExecutePlanAddBloc( - exerciseRepository: exerciseRepository, - exercisePlanRepository: planBloc.exercisePlanRepository, - customerId: customerId, - workoutTree: workoutTree, - planBloc: planBloc), - child: BlocConsumer( - listener: (context, state) { + create: (context) => ExerciseExecutePlanAddBloc( + exerciseRepository: exerciseRepository, + exercisePlanRepository: planBloc.exercisePlanRepository, + customerId: customerId, + workoutTree: workoutTree, + planBloc: planBloc), + child: BlocConsumer(listener: (context, state) { if (state is ExerciseExecutePlanAddError) { - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, - content: - Text(state.message, style: TextStyle(color: Colors.white)))); + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } else if (state is ExerciseExecutePlanAddLoading) { return LoadingDialog(); } - }, - builder: (context, state) { + }, builder: (context, state) { // ignore: close_sinks final exerciseBloc = BlocProvider.of(context); - if ( state is ExerciseExecutePlanAddLoading ) { + if (state is ExerciseExecutePlanAddLoading) { return LoadingDialog(); - } else if ( state is ExerciseExecutePlanAddReady) { + } else if (state is ExerciseExecutePlanAddReady) { return getControlForm(exerciseBloc); } else { return getControlForm(exerciseBloc); } - } - )); + })); } - Form getControlForm( ExerciseExecutePlanAddBloc exerciseBloc) { - String exerciseName = AppLanguage().appLocal == Locale("en") ? - exerciseBloc.exerciseRepository.exerciseType.name : - exerciseBloc.exerciseRepository.exerciseType.nameTranslation; + Form getControlForm(ExerciseExecutePlanAddBloc exerciseBloc) { + String exerciseName = AppLanguage().appLocal == Locale("en") + ? exerciseBloc.exerciseRepository.exerciseType.name + : exerciseBloc.exerciseRepository.exerciseType.nameTranslation; return Form( - autovalidate: true, child: Scaffold( resizeToAvoidBottomInset: true, appBar: AppBarNav(depth: 1), body: Container( - width: MediaQuery - .of(context) - .size - .width, - height: MediaQuery - .of(context) - .size - .height, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), - fit: BoxFit.fill, - alignment: Alignment.center, - ), - ), - child: Container( - padding: const EdgeInsets.only (top: 25, left: 25, right: 25), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - controller: ScrollController( - initialScrollOffset: exerciseBloc.scrollOffset, + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_light_background.png'), + fit: BoxFit.fill, + alignment: Alignment.center, ), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Text(t("Save Exercise")), - Text(exerciseName, - style: TextStyle(fontWeight: FontWeight.bold, - fontSize: 18, - color: Colors.deepOrange), - overflow: TextOverflow.fade, - maxLines: 1, - softWrap: true, + ), + child: Container( + padding: const EdgeInsets.only(top: 25, left: 25, right: 25), + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + controller: ScrollController( + initialScrollOffset: exerciseBloc.scrollOffset, ), - Divider(color: Colors.transparent,), - - Divider(), - Column( - children: repeatExercises(exerciseBloc), - - ), - Divider(), - - - - ]), - ) - ) - ), + child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + Text(t("Save Exercise")), + Text( + exerciseName, + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange), + overflow: TextOverflow.fade, + maxLines: 1, + softWrap: true, + ), + Divider( + color: Colors.transparent, + ), + Divider(), + Column( + children: repeatExercises(exerciseBloc), + ), + Divider(), + ]), + ))), ), ); } List repeatExercises(ExerciseExecutePlanAddBloc exerciseBloc) { List listColumns = List(); - for ( int i = 0; i < exerciseBloc.countSteps; i++) { + for (int i = 0; i < exerciseBloc.countSteps; i++) { Column col = Column( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Divider(color: Colors.transparent,), + Divider( + color: Colors.transparent, + ), Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.baseline, children: [ - Text(t("Execute the") + " ",style: TextStyle(fontWeight: FontWeight.bold),), - Text((i+1).toString() + ". ",style: TextStyle(fontSize:24, fontWeight: FontWeight.bold),), - Text(t("set!"),style: TextStyle(fontWeight: FontWeight.bold),), + Text( + t("Execute the") + " ", + style: TextStyle(fontWeight: FontWeight.bold), + ), + Text( + (i + 1).toString() + ". ", + style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), + ), + Text( + t("set!"), + style: TextStyle(fontWeight: FontWeight.bold), + ), ], ), - - - Divider(color: Colors.transparent,), - Text(t("Please repeat with") + " "+ exerciseBloc.unitQuantity.toStringAsFixed(0) + " " + - exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + " " + - exerciseBloc.exercisePlanRepository.getActualPlanDetail().repeats.toString() + " " + t("times!")), - Row( - children: [ - NumberPicker.horizontal( - highlightSelectedValue: (i + 1) == exerciseBloc.step, - initialValue: exerciseBloc.unitQuantity.toInt(), - minValue: 0, - maxValue: 650, - step: 1, - textStyle: TextStyle(fontWeight: FontWeight.bold), - textStyleHighlighted: TextStyle(fontSize: 24, color: Colors.indigo, fontWeight: FontWeight.bold), - onChanged: (value) => { - exerciseBloc.add(ExerciseExecutePlanAddChangeUnitQuantity(quantity: value.toDouble())) - }, - listViewHeight: 80, - //decoration: _decoration, - ), - Text(exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit), - ] + Divider( + color: Colors.transparent, ), - - Row( - children: [ - NumberPicker.horizontal( - highlightSelectedValue: (i+1) == exerciseBloc.step, - initialValue: exerciseBloc.quantity.toInt(), - minValue: 0, - maxValue: 200, - step: 1, - textStyle: TextStyle(fontWeight: FontWeight.bold), - textStyleHighlighted: TextStyle(fontSize: 24, color: Colors.deepOrange, fontWeight: FontWeight.bold), - onChanged: (value) => { - exerciseBloc.add(ExerciseExecutePlanAddChangeQuantity(quantity: value.toDouble())) - }, - listViewHeight: 80, - //decoration: _decoration, - ), - Text(t("repeat")), - ] - ), - - - + Text(t("Please repeat with") + + " " + + exerciseBloc.unitQuantity.toStringAsFixed(0) + + " " + + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + + " " + + exerciseBloc.exercisePlanRepository.getActualPlanDetail().repeats.toString() + + " " + + t("times!")), + Row(children: [ + NumberPicker.horizontal( + highlightSelectedValue: (i + 1) == exerciseBloc.step, + initialValue: exerciseBloc.unitQuantity.toInt(), + minValue: 0, + maxValue: 650, + step: 1, + textStyle: TextStyle(fontWeight: FontWeight.bold), + textStyleHighlighted: TextStyle(fontSize: 24, color: Colors.indigo, fontWeight: FontWeight.bold), + onChanged: (value) => {exerciseBloc.add(ExerciseExecutePlanAddChangeUnitQuantity(quantity: value.toDouble()))}, + listViewHeight: 80, + //decoration: _decoration, + ), + Text(exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit), + ]), + Row(children: [ + NumberPicker.horizontal( + highlightSelectedValue: (i + 1) == exerciseBloc.step, + initialValue: exerciseBloc.quantity.toInt(), + minValue: 0, + maxValue: 200, + step: 1, + textStyle: TextStyle(fontWeight: FontWeight.bold), + textStyleHighlighted: TextStyle(fontSize: 24, color: Colors.deepOrange, fontWeight: FontWeight.bold), + onChanged: (value) => {exerciseBloc.add(ExerciseExecutePlanAddChangeQuantity(quantity: value.toDouble()))}, + listViewHeight: 80, + //decoration: _decoration, + ), + Text(t("repeat")), + ]), /*TextFieldBlocBuilder( readOnly: exerciseBloc.step != i+1, @@ -239,25 +222,19 @@ class _ExerciseExecuteAddPage extends State with Tra ), ),*/ RaisedButton( - - padding: EdgeInsets.all(0), - textColor: Colors.white, - color: exerciseBloc.step == i+1 ? Colors.blue : Colors.black26, - focusColor: Colors.blueAccent, - onPressed: () => - { - print ("Submit step " + exerciseBloc.step.toString() + " (i) " + i.toString()), - if ( exerciseBloc.step == i+1 ) { - exerciseBloc.add(ExerciseExecutePlanAddSubmit()) - }, - if ( i+1 == exerciseBloc.countSteps) { - Navigator.of(context).pop() - } - }, - child: Text( - t("Save"), - style: TextStyle(fontSize: 12),) - ), + padding: EdgeInsets.all(0), + textColor: Colors.white, + color: exerciseBloc.step == i + 1 ? Colors.blue : Colors.black26, + focusColor: Colors.blueAccent, + onPressed: () => { + print("Submit step " + exerciseBloc.step.toString() + " (i) " + i.toString()), + if (exerciseBloc.step == i + 1) {exerciseBloc.add(ExerciseExecutePlanAddSubmit())}, + if (i + 1 == exerciseBloc.countSteps) {Navigator.of(context).pop()} + }, + child: Text( + t("Save"), + style: TextStyle(fontSize: 12), + )), Divider(), ], ); diff --git a/lib/view/reset_password.dart b/lib/view/reset_password.dart index 3d35778..44935a7 100644 --- a/lib/view/reset_password.dart +++ b/lib/view/reset_password.dart @@ -1,10 +1,6 @@ -import 'package:aitrainer_app/bloc/login_form_bloc.dart'; -import 'package:aitrainer_app/bloc/account/account_bloc.dart'; import 'package:aitrainer_app/bloc/reset_password_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/user_repository.dart'; -import 'package:aitrainer_app/service/firebase_api.dart'; -import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:aitrainer_app/widgets/splash.dart'; @@ -69,68 +65,55 @@ class ResetPasswordPage extends StatelessWidget with Trans { key: _formKey, child: Container( padding: const EdgeInsets.only(left: 25, right: 50), - child: ListView( - shrinkWrap: false, - padding: EdgeInsets.only(top: 150.0), - children: [ - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - new InkWell( - child: new Text( - AppLocalizations.of(context) - .translate('I forgot the password'), - style: TextStyle( - fontWeight: FontWeight.bold, fontSize: 24)), - ), - ], + child: ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 150.0), children: [ + Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + new InkWell( + child: new Text(AppLocalizations.of(context).translate('I forgot the password'), + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)), ), - Divider(), - TextFieldBlocBuilder( - key: LibraryKeys.loginEmailField, - textFieldBloc: formBloc.emailField, - decoration: InputDecoration( - fillColor: Colors.white, - filled: true, - labelText: 'Email', - ), - ), - Divider( - color: Colors.transparent, - ), - Divider( - color: Colors.transparent, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - new FlatButton( - key: LibraryKeys.loginOKButton, - child: Image.asset('asset/image/WT_OK.png', - width: 100, height: 100), - onPressed: () => {formBloc.add(SubmitFormBloc())}), - ]), - Divider( - color: Colors.transparent, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - new InkWell( - child: new Text( - AppLocalizations.of(context).translate('Login')), - onTap: () => Navigator.of(context).pushNamed('login'), - ), - Spacer(flex: 1), - ]), - ])), + ], + ), + Divider(), + TextFieldBlocBuilder( + key: LibraryKeys.loginEmailField, + textFieldBloc: formBloc.emailField, + decoration: InputDecoration( + fillColor: Colors.white, + filled: true, + labelText: 'Email', + ), + ), + Divider( + color: Colors.transparent, + ), + Divider( + color: Colors.transparent, + ), + Row(mainAxisAlignment: MainAxisAlignment.end, children: [ + new FlatButton( + key: LibraryKeys.loginOKButton, + child: Image.asset('asset/image/WT_OK.png', width: 100, height: 100), + onPressed: () => {formBloc.add(SubmitFormBloc())}), + ]), + Divider( + color: Colors.transparent, + ), + Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + new InkWell( + child: new Text(AppLocalizations.of(context).translate('Login')), + onTap: () => Navigator.of(context).pushNamed('login'), + ), + Spacer(flex: 1), + ]), + ])), ); } void showInSnackBar(String error) { - _scaffoldKey.currentState.showSnackBar(SnackBar( - backgroundColor: Colors.orange, - content: Text(error, style: TextStyle(color: Colors.white)))); + _scaffoldKey.currentState + .showSnackBar(SnackBar(backgroundColor: Colors.orange, content: Text(error, style: TextStyle(color: Colors.white)))); } } diff --git a/lib/widgets/app_bar_min.dart b/lib/widgets/app_bar_min.dart index e751cff..35be973 100644 --- a/lib/widgets/app_bar_min.dart +++ b/lib/widgets/app_bar_min.dart @@ -1,21 +1,11 @@ -import 'dart:async'; - -import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; -import 'package:aitrainer_app/model/cache.dart'; -import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:percent_indicator/linear_percent_indicator.dart'; -import 'package:rainbow_color/rainbow_color.dart'; - // ignore: must_be_immutable -class AppBarMin extends StatefulWidget implements PreferredSizeWidget { +class AppBarMin extends StatefulWidget implements PreferredSizeWidget { bool back = false; - AppBarMin({this.back = false }); + AppBarMin({this.back = false}); @override _AppBarNav createState() => _AppBarNav(); @@ -24,7 +14,7 @@ class AppBarMin extends StatefulWidget implements PreferredSizeWidget { Size get preferredSize => const Size.fromHeight(50); } -class _AppBarNav extends State with Common { +class _AppBarNav extends State with Common { @override void initState() { super.initState(); @@ -32,7 +22,6 @@ class _AppBarNav extends State with Common { @override Widget build(BuildContext context) { - return AppBar( backgroundColor: Colors.black, title: Row( @@ -47,19 +36,14 @@ class _AppBarNav extends State with Common { ), leading: IconButton( icon: Icon(Icons.arrow_back, color: widget.back ? Colors.white : Colors.black), - onPressed: () => - { - if ( widget.back ) { - Navigator.of(context).pop() - } + onPressed: () => { + if (widget.back) {Navigator.of(context).pop()} }, - ) - ); + )); } @override void dispose() { super.dispose(); } - } diff --git a/lib/widgets/bmi_widget.dart b/lib/widgets/bmi_widget.dart index 003355f..e4ddc8a 100644 --- a/lib/widgets/bmi_widget.dart +++ b/lib/widgets/bmi_widget.dart @@ -2,6 +2,7 @@ import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:animated_widgets/widgets/rotation_animated.dart'; +import 'package:flurry/flurry.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; @@ -70,6 +71,7 @@ class _BMIState extends State with Trans { @override Widget build(BuildContext context) { setContext(context); + Flurry.logEvent("BMI"); widget.exerciseBloc.getBMI(); return Form( child: Scaffold( @@ -91,7 +93,7 @@ class _BMIState extends State with Trans { child: Column(crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ getWeightInput(), - Text(AppLocalizations.of(context).translate("Body Mass Index"), + Text(t("Body Mass Index"), style: GoogleFonts.archivoBlack( shadows: [ Shadow( diff --git a/lib/widgets/bmr_widget.dart b/lib/widgets/bmr_widget.dart index e6eb547..80f2962 100644 --- a/lib/widgets/bmr_widget.dart +++ b/lib/widgets/bmr_widget.dart @@ -2,6 +2,7 @@ import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/model/fitness_state.dart'; import 'package:aitrainer_app/util/trans.dart'; +import 'package:flurry/flurry.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; @@ -74,6 +75,7 @@ class _BMRState extends State with Trans { @override Widget build(BuildContext context) { setContext(context); + Flurry.logEvent("BMR"); return Form( child: Scaffold( resizeToAvoidBottomInset: true, diff --git a/lib/widgets/bottom_nav.dart b/lib/widgets/bottom_nav.dart index dec6b2b..8294cf0 100644 --- a/lib/widgets/bottom_nav.dart +++ b/lib/widgets/bottom_nav.dart @@ -1,4 +1,8 @@ import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:badges/badges.dart'; +import 'package:flurry/flurry.dart'; import 'package:flutter/material.dart'; import 'package:gradient_bottom_navigation_bar/gradient_bottom_navigation_bar.dart'; @@ -13,7 +17,7 @@ class BottomNavigator extends StatefulWidget { _NawDrawerWidget createState() => _NawDrawerWidget(); } -class _NawDrawerWidget extends State { +class _NawDrawerWidget extends State with Trans { @override void initState() { super.initState(); @@ -25,32 +29,19 @@ class _NawDrawerWidget extends State { final Color bgrColorEnd = Colors.blue; final Color active = Colors.black; final Color inactive = Colors.black26; - - /*final Color bgrColor = Colors.black; - final Color active = Colors.yellowAccent; - final Color inactive = Colors.white60;*/ -// + setContext(context); return GradientBottomNavigationBar( - currentIndex: - widget.bottomNavIndex, // this will be set when a new tab is tapped + currentIndex: widget.bottomNavIndex, // this will be set when a new tab is tapped backgroundColorStart: bgrColorEnd, backgroundColorEnd: bgrColor, fixedColor: active, - //selectedItemColor: active, - //unselectedItemColor: inactive, - //showSelectedLabels: true, - //showUnselectedLabels: true, items: [ BottomNavigationBarItem( backgroundColor: bgrColor, - icon: new Icon(Icons.home, color: inactive), - activeIcon: new Icon( - Icons.home, - color: active, - ), - title: new Text(AppLocalizations.of(context).translate("Home"), - style: TextStyle(fontSize: 9)), + icon: badgedIcon(inactive, Icons.home, "home"), + activeIcon: badgedIcon(active, Icons.home, "home"), + title: new Text(t("Home"), style: TextStyle(fontSize: 12)), ), BottomNavigationBarItem( backgroundColor: bgrColor, @@ -60,8 +51,8 @@ class _NawDrawerWidget extends State { color: active, ), title: new Text( - AppLocalizations.of(context).translate("My Development"), - style: TextStyle(fontSize: 9), + t("My Development"), + style: TextStyle(fontSize: 12), ), ), BottomNavigationBarItem( @@ -72,23 +63,17 @@ class _NawDrawerWidget extends State { color: active, ), title: new Text( - AppLocalizations.of(context).translate("My Training Plan"), - style: TextStyle(fontSize: 9), + t("My Training Plan"), + style: TextStyle(fontSize: 12), ), ), BottomNavigationBarItem( backgroundColor: bgrColor, - icon: Icon( - Icons.person, - color: inactive, - ), - activeIcon: new Icon( - Icons.person, - color: active, - ), + icon: badgedIcon(inactive, Icons.person, "account"), + activeIcon: badgedIcon(active, Icons.person, "account"), title: Text( AppLocalizations.of(context).translate("Account"), - style: TextStyle(fontSize: 9), + style: TextStyle(fontSize: 12), )), BottomNavigationBarItem( backgroundColor: bgrColor, @@ -97,8 +82,7 @@ class _NawDrawerWidget extends State { Icons.settings, color: active, ), - title: Text(AppLocalizations.of(context).translate("Settings"), - style: TextStyle(fontSize: 9))) + title: Text(t("Settings"), style: TextStyle(fontSize: 12))) ], onTap: (index) { setState(() { @@ -106,25 +90,30 @@ class _NawDrawerWidget extends State { switch (index) { case 0: Navigator.of(context).pop(); + Flurry.logEvent("Home"); Navigator.of(context).pushNamed('home'); break; case 1: Navigator.of(context).pop(); + Flurry.logEvent("myDevelopment"); Navigator.of(context).pushNamed('myDevelopment'); break; case 2: Navigator.of(context).pop(); + Flurry.logEvent("myExercisePlan"); Navigator.of(context).pushNamed('myExercisePlan'); break; case 3: Navigator.of(context).pop(); + Flurry.logEvent("Account"); Navigator.of(context).pushNamed('account'); break; case 4: Navigator.of(context).pop(); + Flurry.logEvent("Settings"); Navigator.of(context).pushNamed('settings'); break; @@ -132,4 +121,24 @@ class _NawDrawerWidget extends State { }); }); } + + Widget badgedIcon(Color color, IconData icon, String badgeKey) { + bool show = Cache().getBadges()[badgeKey] != null; + int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0; + return Badge( + position: BadgePosition.topEnd(top: -10, end: -10), + animationDuration: Duration(milliseconds: 500), + animationType: BadgeAnimationType.slide, + badgeColor: Colors.red, + showBadge: show, + badgeContent: Text( + counter.toString(), + style: TextStyle(color: Colors.white), + ), + child: Icon( + icon, + color: color, + ), + ); + } } diff --git a/lib/widgets/image_button.dart b/lib/widgets/image_button.dart index 179d6d4..db561dd 100644 --- a/lib/widgets/image_button.dart +++ b/lib/widgets/image_button.dart @@ -1,7 +1,10 @@ +import 'dart:ui'; + import 'package:aitrainer_app/model/cache.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:bloc/bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; // ignore: must_be_immutable class ImageButton extends StatelessWidget { @@ -10,13 +13,15 @@ class ImageButton extends StatelessWidget { final String image; final double top; final double left; - final double height; - double width = 180; - final bool isShape; + double height; + double width; + bool isShape; final Bloc bloc; final Alignment textAlignment; final VoidCallback onTap; bool isLocked; + bool isMarked; + int buttonIndex; ImageButton( {this.text, @@ -30,20 +35,23 @@ class ImageButton extends StatelessWidget { this.isShape, this.textAlignment, this.onTap, + this.buttonIndex, + this.isMarked, @required this.isLocked}) { width = width ?? 180; - style = style ?? TextStyle(fontSize: 14, fontFamily: "Roboto Mono"); + height = height ?? 180; + isMarked = isMarked ?? false; + style = style ?? + GoogleFonts.archivoBlack( + fontSize: 14, + ); } @override Widget build(BuildContext context) { - double top = width - (style.fontSize - 5) * text.length - 2 * left < 0 - ? width - 2 * style.fontSize - 10 - : width - style.fontSize - 10; - print("Top: " + - top.toStringAsFixed(0) + - " length: " + - ((style.fontSize - 5) * text.length).toString()); + double top = + height - (style.fontSize - 5) * text.length - 2 * left < 0 ? height - 2 * style.fontSize - 22 : height - style.fontSize - 17; + //print("Top: " + top.toStringAsFixed(0) + " length: " + ((style.fontSize - 5) * text.length).toString()); return Stack( //alignment: textAlignment, fit: StackFit.passthrough, @@ -52,24 +60,27 @@ class ImageButton extends StatelessWidget { FlatButton( child: image == null ? _getButtonImage("asset/image/WT_menu_dark.png") - : _getButtonImage(image), + : isMarked + ? Stack( + children: [ + _getButtonImage(image), + Container( + width: width, + height: height, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 1, sigmaY: 1), + child: Container( + color: Colors.black.withOpacity(0.3), + ), + ), + ) + ], + ) + : _getButtonImage(image), padding: EdgeInsets.only(left: 0.0, bottom: 0), shape: getShape(isShape), onPressed: onTap ?? onTap, ), - Stack(alignment: Alignment.topLeft, children: [ - Positioned( - top: 50, - left: 50, - child: this.isLocked - ? Image.asset( - 'asset/image/lock.png', - height: 60, - width: 60, - ) - : Container(), - ) - ]), Positioned( top: top, left: left, @@ -87,6 +98,31 @@ class ImageButton extends StatelessWidget { color: Colors.transparent, ), ), + Stack(alignment: Alignment.topLeft, children: [ + Positioned( + top: height / 2 - 30, + left: width / 2 - 30, + child: this.isLocked + ? GestureDetector( + child: Image.asset( + 'asset/image/lock.png', + height: 60, + width: 60, + ), + onTap: onTap ?? onTap, + ) + : isMarked + ? GestureDetector( + child: Image.asset( + 'asset/image/haken.png', + height: 70, + width: 70, + ), + onTap: onTap ?? onTap, + ) + : Container(), + ) + ]), ] //) // ) @@ -110,12 +146,8 @@ class ImageButton extends StatelessWidget { fit: BoxFit.fitWidth, alignment: Alignment.center, errorBuilder: (context, error, stackTrace) { - String url = Cache.mediaUrl + 'images/' + imageName.substring(11); - Widget image = FadeInImage.assetNetwork( - placeholder: 'asset/image/dots.gif', - image: url, - height: 180, - ); + String url = Cache.mediaUrl + '/' + imageName; //.substring(11); + Widget image = FadeInImage.assetNetwork(placeholder: 'asset/image/dots.gif', image: url, height: this.height); return image; }, ); @@ -124,7 +156,7 @@ class ImageButton extends StatelessWidget { image = FadeInImage.assetNetwork( placeholder: 'asset/image/dots.gif', image: url, - height: 180, + height: 50, ); } diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart index ed00aa0..28da4eb 100644 --- a/lib/widgets/menu_page_widget.dart +++ b/lib/widgets/menu_page_widget.dart @@ -5,6 +5,7 @@ import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/util/trans.dart'; +import 'package:badges/badges.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; @@ -24,15 +25,13 @@ class MenuPageWidget extends StatelessWidget with Trans { MenuBloc menuBloc = BlocProvider.of(context); setContext(context); - return CustomScrollView( - scrollDirection: Axis.vertical, - slivers: [buildMenuColumn(parent, context, menuBloc)]); + return CustomScrollView(scrollDirection: Axis.vertical, slivers: [buildMenuColumn(parent, context, menuBloc)]); } SliverList buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc) { final List _columnChildren = List(); - if ( context != null ) { + if (context != null) { menuBloc.setContext(context); menuBloc.setMenuInfo(); @@ -52,62 +51,50 @@ class MenuPageWidget extends StatelessWidget with Trans { _columnChildren.add(info); } - - menuBloc.menuTreeRepository - .getBranch(menuBloc.parent) - .forEach((treeName, value) { + menuBloc.menuTreeRepository.getBranch(menuBloc.parent).forEach((treeName, value) { WorkoutMenuTree workoutTree = value as WorkoutMenuTree; _columnChildren.add(Container( padding: EdgeInsets.only(top: 16.0), child: Center( - child: Stack( - alignment: Alignment.bottomLeft, - //clipBehavior: Clip.antiAliasWithSaveLayer, - children: [ - FlatButton( - child: _getButtonImage(workoutTree), - padding: EdgeInsets.only(left: 0.0, bottom: 0), - shape: getShape(workoutTree), - onPressed: () => menuClick(workoutTree, menuBloc, context), - ), - Positioned( - top: workoutTree.name.length > 20 ? 130 : 145, - left: 5, - child: Container( - height: 300, - width: 280, - child: InkWell( - onTap:() => menuClick(workoutTree, menuBloc, context), - child: Text( - " " + workoutTree.name, - maxLines: 2, - style: GoogleFonts.archivoBlack( - color: workoutTree.color, - fontSize: workoutTree.fontSize, - ), + child: Stack(alignment: Alignment.bottomLeft, + //clipBehavior: Clip.antiAliasWithSaveLayer, + children: [ + FlatButton( + child: badgedIcon(workoutTree), + padding: EdgeInsets.only(left: 0.0, bottom: 0), + shape: getShape(workoutTree), + onPressed: () => menuClick(workoutTree, menuBloc, context), + ), + Positioned( + top: workoutTree.name.length > 20 ? 130 : 145, + left: 5, + child: Container( + height: 300, + width: 280, + child: InkWell( + onTap: () => menuClick(workoutTree, menuBloc, context), + child: Text( + " " + workoutTree.name, + maxLines: 2, + style: GoogleFonts.archivoBlack( + color: workoutTree.color, + fontSize: workoutTree.fontSize, ), - - highlightColor: workoutTree.color, ), - color: Colors.transparent, + highlightColor: workoutTree.color, ), + color: Colors.transparent, ), - - ] - ) - ) - ) - ); + ), + ])))); }); - SliverList sliverList = - SliverList(delegate: SliverChildListDelegate(_columnChildren)); + SliverList sliverList = SliverList(delegate: SliverChildListDelegate(_columnChildren)); return sliverList; } - void menuClick( - WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) { + void menuClick(WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) { print("Hi!, Menu clicked " + workoutTree.id.toString()); if (workoutTree.child == false) { menuBloc.add(MenuTreeDown(item: workoutTree, parent: workoutTree.id)); @@ -116,16 +103,12 @@ class MenuPageWidget extends StatelessWidget with Trans { if (Cache().userLoggedIn == null) { Scaffold.of(context).showSnackBar(SnackBar( backgroundColor: Colors.orange, - content: Text( - AppLocalizations.of(context).translate('Please log in'), - style: TextStyle(color: Colors.white)))); + content: Text(AppLocalizations.of(context).translate('Please log in'), style: TextStyle(color: Colors.white)))); } else { if (workoutTree.exerciseType.name == "Custom" && Cache().userLoggedIn.admin == 1) { - Navigator.of(context).pushNamed('exerciseCustomPage', - arguments: workoutTree.exerciseType); + Navigator.of(context).pushNamed('exerciseCustomPage', arguments: workoutTree.exerciseType); } else { - Navigator.of(context).pushNamed('exerciseNewPage', - arguments: workoutTree.exerciseType); + Navigator.of(context).pushNamed('exerciseNewPage', arguments: workoutTree.exerciseType); } } } @@ -148,8 +131,7 @@ class MenuPageWidget extends StatelessWidget with Trans { workoutTree.imageName, height: 180, errorBuilder: (context, error, stackTrace) { - String url = - Cache.mediaUrl + 'images/' + workoutTree.imageName.substring(11); + String url = Cache.mediaUrl + 'images/' + workoutTree.imageName.substring(11); Widget image = FadeInImage.assetNetwork( placeholder: 'asset/image/dots.gif', image: url, @@ -169,4 +151,24 @@ class MenuPageWidget extends StatelessWidget with Trans { return image; } + + Widget badgedIcon(WorkoutMenuTree workoutMenuTree) { + String badgeKey = workoutMenuTree.nameEnglish; + bool show = Cache().getBadges()[badgeKey] != null; + int counter = Cache().getBadges()[badgeKey] != null ? Cache().getBadges()[badgeKey] : 0; + return Badge( + padding: EdgeInsets.all(8), + position: BadgePosition.topEnd(top: 3, end: 3), + animationDuration: Duration(milliseconds: 500), + animationType: BadgeAnimationType.slide, + badgeColor: Colors.red, + showBadge: show, + badgeContent: Text(counter.toString(), + style: TextStyle( + color: Colors.white, + fontSize: 16, + )), + child: _getButtonImage(workoutMenuTree), + ); + } } diff --git a/lib/widgets/size_widget.dart b/lib/widgets/size_widget.dart index f18a015..f6ca8e6 100644 --- a/lib/widgets/size_widget.dart +++ b/lib/widgets/size_widget.dart @@ -52,7 +52,7 @@ class _SizeState extends State with Trans { List getSizeFigure() { double mediaWidth = MediaQuery.of(context).size.width * .8; double mediaHeight = MediaQuery.of(context).size.height * .8; - print("w " + mediaWidth.toString() + "h " + mediaHeight.toString()); + //print("w " + mediaWidth.toString() + "h " + mediaHeight.toString()); widget.exerciseBloc.setMediaDimensions(mediaWidth, mediaHeight); List list = List(); list.add(GestureDetector( diff --git a/pubspec.lock b/pubspec.lock index e60be0f..82c2243 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -43,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.5.0-nullsafety.1" + badges: + dependency: "direct main" + description: + name: badges + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.4" bloc: dependency: transitive description: @@ -70,14 +77,14 @@ packages: name: build url: "https://pub.dartlang.org" source: hosted - version: "1.5.0" + version: "1.5.1" build_config: dependency: transitive description: name: build_config url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.3" build_daemon: dependency: transitive description: @@ -98,14 +105,14 @@ packages: name: build_runner url: "https://pub.dartlang.org" source: hosted - version: "1.10.4" + version: "1.10.6" build_runner_core: dependency: transitive description: name: build_runner_core url: "https://pub.dartlang.org" source: hosted - version: "6.0.3" + version: "6.1.1" built_collection: dependency: transitive description: @@ -203,7 +210,7 @@ packages: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "1.3.9" + version: "1.3.10" devicelocale: dependency: "direct main" description: @@ -217,7 +224,7 @@ packages: name: dropdown_search url: "https://pub.dartlang.org" source: hosted - version: "0.4.6" + version: "0.4.8" equatable: dependency: "direct main" description: @@ -246,41 +253,34 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.0.0-nullsafety.2" - firebase: - dependency: transitive - description: - name: firebase - url: "https://pub.dartlang.org" - source: hosted - version: "7.3.2" firebase_auth: dependency: "direct main" description: name: firebase_auth url: "https://pub.dartlang.org" source: hosted - version: "0.18.1+2" + version: "0.18.3" firebase_auth_platform_interface: dependency: transitive description: name: firebase_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.3" firebase_auth_web: dependency: transitive description: name: firebase_auth_web url: "https://pub.dartlang.org" source: hosted - version: "0.3.1+1" + version: "0.3.2" firebase_core: dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "0.5.0+1" + version: "0.5.2" firebase_core_platform_interface: dependency: transitive description: @@ -316,6 +316,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.12.0" + flurry: + dependency: "direct main" + description: + name: flurry + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.7" flutter: dependency: "direct main" description: flutter @@ -333,13 +340,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_facebook_auth: - dependency: "direct main" - description: - name: flutter_facebook_auth - url: "https://pub.dartlang.org" - source: hosted - version: "0.3.3" flutter_form_bloc: dependency: "direct main" description: @@ -492,7 +492,7 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" json_rpc_2: dependency: transitive description: @@ -1001,7 +1001,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "1.7.3" + version: "1.7.4" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 993a38c..a3fe201 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,10 +15,10 @@ 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+2 +version: 1.1.2+34 environment: - sdk: ">=2.7.0 <3.1.0" + sdk: ">=2.10.0 <3.0.0" dependencies: flutter: @@ -28,9 +28,9 @@ dependencies: google_fonts: ^1.1.1 devicelocale: ^0.3.3 sentry: ^3.0.1 - flutter_bloc: ^6.1.0 + flutter_bloc: ^6.1.1 equatable: ^1.2.5 - freezed: ^0.12.1 + freezed: ^0.12.2 flutter_form_bloc: ^0.19.0 spider_chart: ^0.1.5 rainbow_color: ^0.1.1 @@ -40,16 +40,19 @@ dependencies: infinite_listview: ^1.0.1+1 toggle_switch: ^0.1.8 keyboard_actions: ^3.3.1+1 - dropdown_search: ^0.4.6 + dropdown_search: ^0.4.8 + badges: ^1.1.4 - firebase_core: 0.5.0+1 - #firebase_analytics: ^6.0.2 + firebase_core: ^0.5.2 + #firebase_analytics: ^6.2.0 firebase_messaging: ^7.0.3 - firebase_auth: ^0.18.1+2 - flutter_facebook_auth: ^0.3.3 + firebase_auth: ^0.18.3 + #flutter_facebook_auth: ^1.0.1 + flurry: ^0.0.7 + animated_widgets: ^1.0.6 - mockito: ^4.1.1 + mockito: ^4.1.3 flutter_localizations: sdk: flutter @@ -63,9 +66,9 @@ dev_dependencies: build_runner: - http: 0.12.1 - intl: 0.16.1 - shared_preferences: ^0.5.12+2 + http: ^0.12.1 + intl: ^0.16.1 + shared_preferences: ^0.5.12+4 flutter_launcher_icons: ^0.8.1 @@ -126,6 +129,27 @@ flutter: - asset/image/BMI_diagram_b.png - asset/image/BMI_graph_c.png - asset/image/BMI_mutato.png + - asset/image/equipment_specialshome.jpg + - asset/image/equipment_none.jpg + - asset/image/equipment_cables.jpg + - asset/image/equipment_weightplates.jpg + - asset/image/equipment_kettlebells.jpg + - asset/image/equipment_bands.jpg + - asset/image/equipment_ez-baar_.jpg + - asset/image/equipment_exerciseball.jpg + - asset/image/equipment_strap.jpg + - asset/image/equipment_roll.jpg + - asset/image/equipment_instabils.jpg + - asset/image/equipment_medicine.jpg + - asset/image/equipment_rope.jpg + - asset/image/equipment_home.jpg + - asset/image/equipment_baar.jpg + - asset/image/equipment_others.jpg + - asset/image/equipment_barbells.jpg + - asset/image/equipment_machine.jpg + - asset/image/equipment_street.jpg + - asset/image/equipment_dumbbells.jpg + - asset/image/haken.png - asset/menu/1.cardio.png - asset/menu/1.1.aerob.png - asset/menu/1.2.anaerob.png diff --git a/test/exercise_plan_bloc.dart b/test/exercise_plan_bloc.dart index 1c942f0..760c490 100644 --- a/test/exercise_plan_bloc.dart +++ b/test/exercise_plan_bloc.dart @@ -2,6 +2,7 @@ import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; +import 'package:aitrainer_app/model/model_change.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:test/test.dart'; @@ -65,17 +66,14 @@ main() { bloc.customerId = 101; bloc.add(ExercisePlanLoad()); - final expectedResponse = [ - ExercisePlanLoading(), - ExercisePlanReady() - ]; + final expectedResponse = [ExercisePlanLoading(), ExercisePlanReady()]; expectLater( bloc, emitsInOrder(expectedResponse), ).then((_) { expect(bloc.exercisePlanRepository.newPlan, false); - expect(bloc.exercisePlanRepository.exercisePlan.name, "Test Plan2" ); + expect(bloc.exercisePlanRepository.exercisePlan.name, "Test Plan2"); expect(bloc.exercisePlanRepository.exercisePlanDetails[4].weightEquation, "95"); expect(Cache().getMyExercisePlan().name, "Test Plan2"); expect(Cache().getMyExercisePlanDetails()[4].weightEquation, "95"); @@ -93,14 +91,9 @@ main() { detail4.weightEquation = "55"; detail4.serie = 3; - - bloc.add(ExercisePlanAddExercise(exercisePlanDetail: detail4)); - final expectedResponse2 = [ - ExercisePlanLoading(), - ExercisePlanReady() - ]; + final expectedResponse2 = [ExercisePlanLoading(), ExercisePlanReady()]; expectLater( bloc, @@ -110,10 +103,8 @@ main() { expect(bloc.exercisePlanRepository.exercisePlan.customerId, 101); expect(bloc.exercisePlanRepository.exercisePlanDetails.length, 3); expect(bloc.exercisePlanRepository.exercisePlanDetails[5].repeats, 20); - expect(bloc.exercisePlanRepository.exercisePlanDetails[5].change, ExercisePlanDetailChange.add); - expect(Cache() - .getMyExercisePlan() - .name, "Test Plan2"); + expect(bloc.exercisePlanRepository.exercisePlanDetails[5].change, ModelChange.add); + expect(Cache().getMyExercisePlan().name, "Test Plan2"); expect(Cache().getMyExercisePlanDetails()[5].weightEquation, "55"); expect(Cache().getMyExercisePlanDetails()[5].repeats, 20); }); @@ -127,10 +118,7 @@ main() { bloc.add(ExercisePlanAddExercise(exercisePlanDetail: bloc.exercisePlanRepository.exercisePlanDetails[3])); - final expectedResponse2 = [ - ExercisePlanLoading(), - ExercisePlanReady() - ]; + final expectedResponse2 = [ExercisePlanLoading(), ExercisePlanReady()]; expectLater( bloc, @@ -140,7 +128,6 @@ main() { expect(bloc.exercisePlanRepository.exercisePlanDetails[3].repeats, 25); expect(Cache().getMyExercisePlanDetails()[3].repeats, 25); }); - }); test('Delete bloc', () async { bloc.customerId = 101; @@ -148,10 +135,7 @@ main() { bloc.exercisePlanRepository.getExercisePlanDetails(); bloc.add(ExercisePlanRemoveExercise(exercisePlanDetail: bloc.exercisePlanRepository.exercisePlanDetails[3])); - final expectedResponse2 = [ - ExercisePlanLoading(), - ExercisePlanReady() - ]; + final expectedResponse2 = [ExercisePlanLoading(), ExercisePlanReady()]; expectLater( bloc, @@ -164,8 +148,8 @@ main() { }); }); - test('Test Trainee', () async { - /*bloc.customerId = 102; + test('Test Trainee', () async { + /*bloc.customerId = 102; bloc.exercisePlanRepository.customerId = 102; bloc.add(ExercisePlanLoad()); @@ -183,8 +167,6 @@ main() { expect(bloc.exercisePlanRepository.newPlan, true); expect(bloc.exercisePlanRepository.exercisePlanDetails.length, 0); });*/ + }); }); - -}); - -} \ No newline at end of file +} diff --git a/test/exercise_plan_repository_test.dart b/test/exercise_plan_repository_test.dart index df4ef29..2ffbf78 100644 --- a/test/exercise_plan_repository_test.dart +++ b/test/exercise_plan_repository_test.dart @@ -1,16 +1,15 @@ import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; +import 'package:aitrainer_app/model/model_change.dart'; import 'package:test/test.dart'; import 'mocks.dart'; - main() { SimExercisePlanRepository _exercisePlanRepository; int _customerId; Future setUpPlan() async { - final String planName2 = "Test Plan2"; ExercisePlan plan2 = ExercisePlan(planName2, 101); _exercisePlanRepository.setCustomerId(101); @@ -40,8 +39,6 @@ main() { await setUpPlan(); }); - - group('New Plan', () { test('add new plan and plan details and save', () async { final String planName = "Boss Test Plan"; @@ -69,11 +66,8 @@ main() { expect(_exercisePlanRepository.getExercisePlan().name, planName); expect(_exercisePlanRepository.getExercisePlan().exercisePlanId > 0, true); - ExercisePlanDetail detail = - _exercisePlanRepository.getExercisePlanDetailByExerciseId(55); + ExercisePlanDetail detail = _exercisePlanRepository.getExercisePlanDetailByExerciseId(55); expect(detail.exercisePlanId, _exercisePlanRepository.getExercisePlan().exercisePlanId); - - }); test('save new plan and plan details second', () async { int customerId = 100; @@ -104,23 +98,21 @@ main() { ExercisePlanDetail detail = _exercisePlanRepository.getExercisePlanDetailByExerciseId(13); expect(detail.exercisePlanId, _exercisePlanRepository.getExercisePlan().exercisePlanId); expect(detail.repeats, 33); - }); - }); group('Existing Plan', () { test('Get Last Plan and Details from DB', () async { ExercisePlan exercisePlan = await _exercisePlanRepository.getLastExercisePlan(); - expect(exercisePlan.customerId,101); + expect(exercisePlan.customerId, 101); await _exercisePlanRepository.getExercisePlanDetails(); - expect(_exercisePlanRepository.exercisePlanDetails[3].repeats,23 ); - expect(_exercisePlanRepository.exercisePlanDetails[4].weightEquation,"95" ); + expect(_exercisePlanRepository.exercisePlanDetails[3].repeats, 23); + expect(_exercisePlanRepository.exercisePlanDetails[4].weightEquation, "95"); //Test Cache - expect(Cache().getMyExercisePlan().name,"Test Plan2"); - expect(Cache().getMyExercisePlanDetails()[3].weightEquation,"60"); + expect(Cache().getMyExercisePlan().name, "Test Plan2"); + expect(Cache().getMyExercisePlanDetails()[3].weightEquation, "60"); }); test('Add new PlanDetail', () async { @@ -138,20 +130,14 @@ main() { expect(_exercisePlanRepository.getExercisePlan().name, "Test Plan2"); expect(Cache().getMyExercisePlanDetails()[5].weightEquation, "105"); expect(Cache().getMyExercisePlanDetails()[5].repeats, 6); - }); test('Delete from PlanDetails', () async { _exercisePlanRepository.removeExerciseTypeFromPlanByExerciseTypeId(4); _exercisePlanRepository.saveExercisePlan(); - expect(_exercisePlanRepository.exercisePlanDetails[4].change, ExercisePlanDetailChange.delete); + expect(_exercisePlanRepository.exercisePlanDetails[4].change, ModelChange.delete); expect(Cache().getMyExercisePlanDetails()[4], isNull); }); - }); - - - - } diff --git a/test/mocks.dart b/test/mocks.dart index ccbe1eb..4cdb1e8 100644 --- a/test/mocks.dart +++ b/test/mocks.dart @@ -3,6 +3,7 @@ import 'dart:collection'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; +import 'package:aitrainer_app/model/model_change.dart'; import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; import 'package:aitrainer_app/service/exercise_plan_service.dart'; import 'package:mockito/mockito.dart'; @@ -33,7 +34,7 @@ class MockExercisePlanApi extends Mock implements ExercisePlanApi { Future updateExercisePlanDetail(ExercisePlanDetail detail, int planDetailId) async { ExercisePlanDetail updated; memoryExercisePlanDetail.forEach((element) { - if ( element.exercisePlanDetailId == planDetailId ) { + if (element.exercisePlanDetailId == planDetailId) { element = detail; } }); @@ -45,12 +46,12 @@ class MockExercisePlanApi extends Mock implements ExercisePlanApi { int index = -1; int countIndex = 0; memoryExercisePlanDetail.forEach((element) { - if ( element.exercisePlanId == exercisePlanId ) { + if (element.exercisePlanId == exercisePlanId) { index = countIndex; } countIndex++; }); - if ( index > -1) { + if (index > -1) { memoryExercisePlanDetail.removeAt(index); } } @@ -58,7 +59,7 @@ class MockExercisePlanApi extends Mock implements ExercisePlanApi { Future> getExercisePlanDetail(int exercisePlanId) async { List foundList = List(); memoryExercisePlanDetail.forEach((element) { - if ( element.exercisePlanId == exercisePlanId ) { + if (element.exercisePlanId == exercisePlanId) { foundList.add(element); } }); @@ -68,7 +69,7 @@ class MockExercisePlanApi extends Mock implements ExercisePlanApi { Future getLastExercisePlan(int customerId) async { ExercisePlan found; memoryExercisePlan.forEach((element) { - if ( element.customerId == customerId ) { + if (element.customerId == customerId) { found = element; } }); @@ -77,19 +78,18 @@ class MockExercisePlanApi extends Mock implements ExercisePlanApi { } class SimExercisePlanRepository with ExercisePlanRepository { - Future getExercisePlanDetails() async { if (exercisePlan == null) { ExercisePlan exercisePlan = await this.getLastExercisePlan(); - if ( exercisePlan == null ) { + if (exercisePlan == null) { exercisePlanDetails = LinkedHashMap(); return; } } List list = List(); - LinkedHashMap listCache = Cache().getMyExercisePlanDetails(); - if ( listCache.length > 0) { + LinkedHashMap listCache = Cache().getMyExercisePlanDetails(); + if (listCache.length > 0) { exercisePlanDetails = listCache; return; } else { @@ -109,11 +109,11 @@ class SimExercisePlanRepository with ExercisePlanRepository { } Future getLastExercisePlan() async { - if ( customerId == 0) { + if (customerId == 0) { return null; } ExercisePlan myExercisePlan = Cache().getMyExercisePlan(); - if ( myExercisePlan != null ) { + if (myExercisePlan != null) { newPlan = false; return myExercisePlan; } @@ -125,13 +125,13 @@ class SimExercisePlanRepository with ExercisePlanRepository { } Future saveExercisePlan() async { - if ( exercisePlan == null ) { - if ( Cache().userLoggedIn == null ) { + if (exercisePlan == null) { + if (Cache().userLoggedIn == null) { throw Exception("please log in"); } String exercisePlanName; - if ( this.customerId == Cache().userLoggedIn.customerId) { + if (this.customerId == Cache().userLoggedIn.customerId) { exercisePlanName = Cache().userLoggedIn.name + " private"; } else { exercisePlanName = Cache().getTrainee().name + " " + Cache().getTrainee().firstname + " private"; @@ -139,13 +139,11 @@ class SimExercisePlanRepository with ExercisePlanRepository { exercisePlan = ExercisePlan(exercisePlanName, this.customerId); } - if ( newPlan ) { + if (newPlan) { exercisePlan.dateAdd = DateTime.now(); exercisePlan.private = true; - ExercisePlan savedExercisePlan - = await MockExercisePlanApi().saveExercisePlan(exercisePlan); - + ExercisePlan savedExercisePlan = await MockExercisePlanApi().saveExercisePlan(exercisePlan); LinkedHashMap savedExercisePlanDetails = LinkedHashMap(); exercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async { @@ -158,24 +156,20 @@ class SimExercisePlanRepository with ExercisePlanRepository { exercisePlan = savedExercisePlan; } else { - await MockExercisePlanApi().updateExercisePlan(exercisePlan, exercisePlan.exercisePlanId); exercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async { - if ( exercisePlanDetail.change == ExercisePlanDetailChange.delete ) { - await MockExercisePlanApi() - .deleteExercisePlanDetail(exercisePlanDetail.exercisePlanDetailId); + if (exercisePlanDetail.change == ModelChange.delete) { + await MockExercisePlanApi().deleteExercisePlanDetail(exercisePlanDetail.exercisePlanDetailId); Cache().deleteMyExercisePlanDetail(exercisePlanDetail); - } else if ( exercisePlanDetail.change == ExercisePlanDetailChange.update ) { - await MockExercisePlanApi() - .updateExercisePlanDetail(exercisePlanDetail, exercisePlanDetail.exercisePlanDetailId); + } else if (exercisePlanDetail.change == ModelChange.update) { + await MockExercisePlanApi().updateExercisePlanDetail(exercisePlanDetail, exercisePlanDetail.exercisePlanDetailId); Cache().updateMyExercisePlanDetail(exercisePlanDetail); - } else if ( exercisePlanDetail.change == ExercisePlanDetailChange.add ) { - await MockExercisePlanApi() - .saveExercisePlanDetail(exercisePlanDetail); + } else if (exercisePlanDetail.change == ModelChange.add) { + await MockExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail); Cache().addToMyExercisePlanDetails(exercisePlanDetail); } }); } } -} \ No newline at end of file +}