v1.0.0 outsourced from aitrainer_app

This commit is contained in:
Tibor Bossanyi (Freelancer) 2023-01-28 12:53:16 +01:00
commit ca96abf8c0
87 changed files with 7189 additions and 0 deletions

37
.flutter-plugins Normal file
View File

@ -0,0 +1,37 @@
# This is a generated file; do not edit or check into version control.
device_info_plus=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\device_info_plus-8.0.0\\
facebook_auth_desktop=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\facebook_auth_desktop-0.0.8\\
firebase_analytics=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_analytics-10.1.0\\
firebase_analytics_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_analytics_web-0.5.1+8\\
firebase_auth=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_auth-4.2.5\\
firebase_auth_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_auth_web-5.2.4\\
firebase_core=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_core-2.4.1\\
firebase_core_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_core_web-2.1.0\\
firebase_messaging=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_messaging-14.2.1\\
firebase_messaging_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_messaging_web-3.2.11\\
firebase_remote_config=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_remote_config-3.0.9\\
firebase_remote_config_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\firebase_remote_config_web-1.1.18\\
flutter_facebook_auth=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\flutter_facebook_auth-5.0.7\\
flutter_facebook_auth_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\flutter_facebook_auth_web-4.1.1\\
flutter_secure_storage=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\flutter_secure_storage-7.0.1\\
flutter_secure_storage_linux=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\flutter_secure_storage_linux-1.1.2\\
flutter_secure_storage_macos=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\flutter_secure_storage_macos-2.0.1\\
flutter_secure_storage_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\flutter_secure_storage_web-1.1.1\\
flutter_secure_storage_windows=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\flutter_secure_storage_windows-1.1.3\\
google_sign_in=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\google_sign_in-5.4.3\\
google_sign_in_android=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\google_sign_in_android-6.1.5\\
google_sign_in_ios=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\google_sign_in_ios-5.5.1\\
google_sign_in_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\google_sign_in_web-0.10.2+1\\
package_info_plus=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\package_info_plus-3.0.2\\
path_provider_linux=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider_linux-2.1.7\\
path_provider_windows=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider_windows-2.1.3\\
posthog_session=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\git\\posthog_session-0db36d398cc23a7bfab09e0ddb6773525a92107b\\
sentry_flutter=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\sentry_flutter-6.19.0\\
shared_preferences=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\shared_preferences-2.0.17\\
shared_preferences_android=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\shared_preferences_android-2.0.15\\
shared_preferences_foundation=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\shared_preferences_foundation-2.1.2\\
shared_preferences_linux=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\shared_preferences_linux-2.1.3\\
shared_preferences_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\shared_preferences_web-2.0.4\\
shared_preferences_windows=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\shared_preferences_windows-2.1.3\\
sign_in_with_apple=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\sign_in_with_apple-4.3.0\\
sign_in_with_apple_web=C:\\Users\\bossa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\sign_in_with_apple_web-1.0.1\\

File diff suppressed because one or more lines are too long

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/

10
.metadata Normal file
View File

@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 135454af32477f815a7525073027a3ff9eff1bfd
channel: stable
project_type: package

3
CHANGELOG.md Normal file
View File

@ -0,0 +1,3 @@
## 0.0.1
* TODO: Describe initial release.

1
LICENSE Normal file
View File

@ -0,0 +1 @@
TODO: Add your license here.

39
README.md Normal file
View File

@ -0,0 +1,39 @@
<!--
This README describes the package. If you publish this package to pub.dev,
this README's contents appear on the landing page for your package.
For information about how to write a good package README, see the guide for
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
For general information about developing packages, see the Dart guide for
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
and the Flutter guide for
[developing packages and plugins](https://flutter.dev/developing-packages).
-->
TODO: Put a short description of the package here that helps potential users
know whether this package might be useful for them.
## Features
TODO: List what your package can do. Maybe include images, gifs, or videos.
## Getting started
TODO: List prerequisites and provide or point to information on how to
start using the package.
## Usage
TODO: Include short and useful examples for package users. Add longer examples
to `/example` folder.
```dart
const like = 'sample';
```
## Additional information
TODO: Tell users more about the package: where to find more information, how to
contribute to the package, how to file issues, what response they can expect
from the package authors, and more.

4
analysis_options.yaml Normal file
View File

@ -0,0 +1,4 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

801
lib/model/cache.dart Normal file
View File

@ -0,0 +1,801 @@
import 'dart:collection';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:workouttest_util/model/customer.dart';
import 'package:workouttest_util/model/customer_activity.dart';
import 'package:workouttest_util/model/customer_property.dart';
import 'package:workouttest_util/model/customer_training_plan.dart';
import 'package:workouttest_util/model/description.dart';
import 'package:workouttest_util/model/evaluation.dart';
import 'package:workouttest_util/model/exercise_plan.dart';
import 'package:workouttest_util/model/exercise_plan_detail.dart';
import 'package:workouttest_util/model/exercise_plan_template.dart';
import 'package:workouttest_util/model/exercise_tree.dart';
import 'package:workouttest_util/model/exercise.dart';
import 'package:workouttest_util/model/faq.dart';
import 'package:workouttest_util/model/model_change.dart';
import 'package:workouttest_util/model/product.dart' as wt_product;
import 'package:workouttest_util/model/product.dart';
import 'package:workouttest_util/model/property.dart';
import 'package:workouttest_util/model/purchase.dart';
import 'package:workouttest_util/model/split_test.dart';
import 'package:workouttest_util/model/sport.dart';
import 'package:workouttest_util/model/training_plan.dart';
import 'package:workouttest_util/model/training_plan_day.dart';
import 'package:workouttest_util/model/tutorial.dart';
import 'package:workouttest_util/model/workout_menu_tree.dart';
import 'package:workouttest_util/repository/customer_repository.dart';
import 'package:workouttest_util/service/firebase_api.dart';
import 'package:workouttest_util/service/package_service.dart';
import 'package:workouttest_util/util/enums.dart';
import 'package:workouttest_util/util/env.dart';
import 'package:workouttest_util/util/track.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:posthog_session/posthog_session.dart';
// ignore: depend_on_referenced_packages
import 'package:shared_preferences/shared_preferences.dart';
import 'package:workouttest_util/model/exercise_type.dart';
// ignore: depend_on_referenced_packages
import 'package:intl/intl.dart';
import '../util/logging.dart';
import 'customer_exercise_device.dart';
import 'exercise_device.dart';
enum SharePrefsChange {
login,
registration,
logout,
}
/*
Auth flow of the app
1. During the login screen the authentication will be executed
- if not successful: message: Network error, try again later
- if successful
- get the stored shared preferences and customer id
- if customer_id not present -> registration page
- if present, check if the expiration_date > 10 days -> login page
- else get the API customer by the stored customer_id
- After registration / login store the preferences:
- AuthToken
- customer_id
- last_store_date
- is_registered
- is_logged_in
*/
enum ActivityDone {
tutorialExecuteFirstTest,
tutorialBasic,
tutorialBasicChestPress,
tutorialBasicLegPress,
tutorialDevelopment,
isExerciseLogSeen,
isMuscleDevelopmentSeen,
isBodyTypeSeen,
exerciseSaveTestTip,
exerciseSaveTrainingTip,
exerciseSaveTestsetTip
}
extension ActivityDoneExt on ActivityDone {
String toStr() => toString().split(".").last;
bool equalsTo(ActivityDone value) => toString() == value.toString();
bool equalsStringTo(String value) => toStr() == value;
ActivityDone? searchByString(String activityString) {
ActivityDone? activity;
for (var element in ActivityDone.values) {
if (element.equalsStringTo(activityString)) {
activity = element;
}
}
return activity;
}
}
class Cache with Logging {
static final Cache _singleton = Cache._internal();
// Keys to store and fetch data from SharedPreferences
static const String authTokenKey = "auth_token";
static const String customerIdKey = "customer_id";
static const String firebaseUidKey = "firebase_uid";
static const String lastStoreDateKey = "last_date";
static const String isRegisteredKey = "is_registered";
static const String isLoggedInKey = "is_logged_in";
static const String langKey = "lang";
static const String serverKey = "live";
static const String hardwareKey = "hardware";
static const String loginTypeKey = "login_type";
static const String timerDisplayKey = "timer_display";
static const String activeExercisePlanKey = "active_exercise_plan";
static const String activeExercisePlanDateKey = "active_exercise_plan_date";
static const String activeExercisePlanDetailsKey = "active_exercise_details_plan";
static const String myTrainingPlanKey = "myTrainingPlan";
static String baseUrlLive = 'https://api.workouttest.org/api/';
static String baseUrlTest = 'https://apitest.workouttest.org/api/';
late String baseUrl;
static const String mediaUrl = 'https://admin.workouttest.org/media/';
static const String username = 'bosi';
static const String password = 'andio2009';
String authToken = "";
AccessToken? accessTokenFacebook;
Customer? userLoggedIn;
String? firebaseUid;
String? firebaseMessageToken;
LoginType? loginType;
PackageInfo? packageInfo;
bool hasPurchased = false;
bool firstLoad = true;
List<ExerciseType>? _exerciseTypes;
List<ExerciseTree>? _exerciseTree;
List<Evaluation>? _evaluations;
List<Exercise>? _exercises;
ExercisePlan? _myExercisePlan;
List<Property>? _properties;
List<Sport>? _sports;
List<wt_product.Product>? _products;
List<Purchase> _purchases = [];
List<SplitTest> _splitTests = [];
List<TrainingPlanDay> _trainingPlanDays = [];
List<ExercisePlanTemplate> _exercisePlanTemplates = [];
ExercisePlan? activeExercisePlan;
CustomerTrainingPlan? myTrainingPlan;
List<ExercisePlanDetail>? activeExercisePlanDetails;
List<ExerciseDevice>? _devices;
List<CustomerExerciseDevice>? _customerDevices;
List<CustomerActivity>? _customerActivities;
List<CustomerTrainingPlan>? _customerTrainingPlans;
List<CustomerProperty>? _customerPropertyAll;
List<Tutorial>? _tutorials;
List<Description>? _descriptions;
List<Faq>? _faqs;
List<TrainingPlan>? _trainingPlans;
LinkedHashMap<int, ExercisePlanDetail> _myExercisesPlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
LinkedHashMap<String, WorkoutMenuTree> _tree = LinkedHashMap<String, WorkoutMenuTree>();
double _percentExercises = -1;
Customer? _trainee;
List<Exercise>? _exercisesTrainee;
ExercisePlan? _traineeExercisePlan;
FirebaseRemoteConfig? remoteConfig;
LinkedHashMap<String, int> _badges = LinkedHashMap();
List? deviceLanguages;
String startPage = "home";
late String testEnvironment;
bool liveServer = true;
bool? hasHardware = false;
HashMap<String, bool> activitiesDone = HashMap();
factory Cache() {
return _singleton;
}
Cache._internal() {
String testEnv = EnvironmentConfig.test_env;
testEnvironment = testEnv;
print("testEnv $testEnv");
if (testEnv == "1") {
baseUrl = baseUrlTest;
liveServer = false;
}
for (var element in ActivityDone.values) {
activitiesDone[element.toStr()] = false;
}
}
void setTestBaseUrl() {
baseUrl = baseUrlTest;
}
String getAuthToken() {
return authToken;
}
Future<void> deleteCustomerId(int customerId) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
sharedPreferences.remove(Cache.customerIdKey);
}
Future<void> saveActiveExercisePlan(ExercisePlan exercisePlan, List<ExercisePlanDetail> exercisePlanDetails) async {
activeExercisePlan = exercisePlan;
activeExercisePlanDetails = exercisePlanDetails;
String exercisePlanJson = const JsonEncoder().convert(exercisePlan.toJson());
String detailsJson = jsonEncode(exercisePlanDetails.map((i) => i.toJsonWithExerciseList()).toList()).toString();
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
final DateTime now = DateTime.now();
sharedPreferences.setString(Cache.activeExercisePlanKey, exercisePlanJson);
sharedPreferences.setString(Cache.activeExercisePlanDetailsKey, detailsJson);
String savingDay = DateFormat("yyyy-MM-dd HH:mm:ss").format(now);
sharedPreferences.setString(Cache.activeExercisePlanDateKey, savingDay);
}
Future<void> saveMyTrainingPlan() async {
if (myTrainingPlan == null) {
return;
}
String myTrainingPlanJson = const JsonEncoder().convert(myTrainingPlan!.toJsonWithDetails());
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
sharedPreferences.setString(Cache.myTrainingPlanKey, myTrainingPlanJson);
}
Future<void> deleteMyTrainingPlan() async {
if (myTrainingPlan == null) {
return;
}
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
sharedPreferences.remove(Cache.myTrainingPlanKey);
}
Future<void> getMyTrainingPlan() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
final String? savedTrainingPlanJson = sharedPreferences.getString(Cache.myTrainingPlanKey);
if (savedTrainingPlanJson == null) {
return;
}
//String jsonPlan = savedTrainingPlanJson.replaceAllMapped(RegExp(r'[a-zA-Z]+\:'), (Match m) => "\"${m[0]}\"");
Map<String, dynamic> map;
try {
map = JsonDecoder().convert(savedTrainingPlanJson);
//print("Training plan: $savedTrainingPlanJson");
this.myTrainingPlan = CustomerTrainingPlan.fromJsonWithDetails(map);
} on Exception catch (e) {
print(e.toString());
}
}
Future<void> deleteActiveExercisePlan() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
sharedPreferences.remove(Cache.activeExercisePlanDateKey);
this.activeExercisePlan = null;
this.activeExercisePlanDetails = null;
}
Future<void> getActiveExercisePlan() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
final savedPlanDateString = sharedPreferences.getString(Cache.activeExercisePlanDateKey);
if (savedPlanDateString == null) {
return;
}
DateFormat format = DateFormat("yyyy-MM-dd HH:mm:ss");
DateTime savedPlanDate;
savedPlanDate = format.parse(savedPlanDateString);
print("Saved plan: $savedPlanDate");
final DateTime now = DateTime.now();
final DateTime added = savedPlanDate.add(Duration(days: 1));
if (added.isBefore(now)) {
return;
}
String? exercisePlanJson = sharedPreferences.getString(Cache.activeExercisePlanKey);
if (exercisePlanJson != null) {
final Map<String, dynamic> map = JsonDecoder().convert(exercisePlanJson);
this.activeExercisePlan = ExercisePlan.fromJson(map);
}
String? detailsJson = sharedPreferences.getString(Cache.activeExercisePlanDetailsKey);
if (detailsJson != null) {
Iterable json = jsonDecode(detailsJson);
this.activeExercisePlanDetails = json.map((details) => ExercisePlanDetail.fromJsonWithExerciseList(details)).toList();
}
}
Future<void> setServer(bool live) async {
if (this.testEnvironment == "1") {
liveServer = false;
live = false;
}
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
liveServer = live;
sharedPreferences.setBool(Cache.serverKey, live);
}
void getHardware(SharedPreferences prefs) {
final bool? hasHardware = prefs.getBool(Cache.hardwareKey);
this.hasHardware = hasHardware;
if (hasHardware == null) {
this.hasHardware = false;
}
}
Future<bool> selectedHardwareBefore() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
final bool? selectedHardware = sharedPreferences.getBool(Cache.hardwareKey);
return selectedHardware == null;
}
Future<void> setHardware(bool hasHardware) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
sharedPreferences.setBool(Cache.hardwareKey, hasHardware);
this.hasHardware = hasHardware;
}
void setServerAddress(SharedPreferences prefs) {
if (this.testEnvironment == "1") {
baseUrl = baseUrlTest;
print("TestEnv $baseUrl");
return;
}
final bool? live = prefs.getBool(Cache.serverKey);
if (live == null) {
baseUrl = baseUrlLive;
print("Live Env $baseUrl");
liveServer = true;
return;
}
liveServer = live;
if (live) {
baseUrl = baseUrlLive;
} else {
baseUrl = baseUrlTest;
}
print("Env $baseUrl");
}
Future<void> setLoginTypeFromPrefs() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
final String? loginType = sharedPreferences.getString(Cache.loginTypeKey);
LoginType type = LoginType.email;
if (loginType == LoginType.apple.toString()) {
type = LoginType.apple;
} else if (loginType == LoginType.google.toString()) {
type = LoginType.google;
} else if (loginType == LoginType.fb.toString()) {
type = LoginType.fb;
} else if (loginType == LoginType.email.toString()) {
type = LoginType.email;
}
//print("LoginType: " + loginType == null ? "NULL" : loginType);
Cache().setLoginType(type);
}
static String? getToken(SharedPreferences prefs) {
return prefs.getString(authTokenKey);
}
String getBaseUrl() {
return baseUrl;
}
static String getMediaUrl() {
return mediaUrl;
}
afterRegistration(Customer customer) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
userLoggedIn = customer;
final String uid = Cache().firebaseUid!;
SharedPreferences sharedPreferences = await prefs;
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
await setPreferences(prefs, SharePrefsChange.registration, customer.customerId!, uid);
}
afterLogin(Customer customer) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
userLoggedIn = customer;
SharedPreferences sharedPreferences = await prefs;
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
await setPreferences(prefs, SharePrefsChange.login, customer.customerId!, Cache().firebaseUid!);
}
afterFirebaseLogin() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn!.customerId!, Cache().firebaseUid!);
}
afterFacebookLogin() async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn!.customerId!, Cache().firebaseUid!);
}
logout() async {
if (this.accessTokenFacebook != null) {
await FirebaseApi().logOutFacebook();
}
userLoggedIn = null;
firebaseUid = null;
authToken = "";
_trainee = null;
_percentExercises = -1;
_exercisesTrainee = null;
_traineeExercisePlan = null;
_exercises = [];
_myExercisesPlanDetails = LinkedHashMap();
log("Trainees is null? " + (_trainee == null).toString());
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
await setPreferences(prefs, SharePrefsChange.logout, 0, "");
}
Future<void> setPreferences(Future<SharedPreferences> prefs, SharePrefsChange type, int customerId, String firebaseUid) async {
SharedPreferences sharedPreferences;
sharedPreferences = await prefs;
DateTime now = DateTime.now();
sharedPreferences.setString(Cache.lastStoreDateKey, now.toString());
if (type == SharePrefsChange.registration) {
sharedPreferences.setInt(Cache.customerIdKey, customerId);
sharedPreferences.setBool(Cache.isRegisteredKey, true);
sharedPreferences.setBool(Cache.isLoggedInKey, true);
sharedPreferences.setString(Cache.firebaseUidKey, firebaseUid);
await initCustomer(customerId);
} else if (type == SharePrefsChange.login) {
sharedPreferences.setInt(Cache.customerIdKey, customerId);
sharedPreferences.setString(Cache.firebaseUidKey, firebaseUid);
sharedPreferences.setBool(Cache.isLoggedInKey, true);
await initCustomer(customerId);
} else if (type == SharePrefsChange.logout) {
sharedPreferences.setBool(Cache.isLoggedInKey, false);
sharedPreferences.setInt(Cache.customerIdKey, 0);
sharedPreferences.setString(Cache.firebaseUidKey, "");
sharedPreferences.setString(authTokenKey, "");
}
initBadges();
}
void setExerciseTypes(List<ExerciseType> exerciseTypes) {
this._exerciseTypes = exerciseTypes;
}
void setExerciseTree(List<ExerciseTree> exerciseTree) {
this._exerciseTree = exerciseTree;
}
void setExercises(List<Exercise> exercises) => this._exercises = exercises;
void setExercisesTrainee(List<Exercise> exercises) {
this._exercisesTrainee = exercises;
}
void setWorkoutMenuTree(LinkedHashMap<String, WorkoutMenuTree> tree) {
this._tree = tree;
}
List<ExerciseType>? getExerciseTypes() => this._exerciseTypes;
ExerciseType? getExerciseTypeById(int exerciseTypeId) {
ExerciseType? exerciseType;
if (_exerciseTypes != null) {
this._exerciseTypes!.forEach((element) {
if (element.exerciseTypeId == exerciseTypeId) {
exerciseType = element;
}
});
}
return exerciseType;
}
List<ExerciseTree>? getExerciseTree() => this._exerciseTree;
List<Exercise>? getExercises() => this._exercises;
List<Exercise>? getExercisesTrainee() => this._exercisesTrainee;
LinkedHashMap<String, WorkoutMenuTree> getWorkoutMenuTree() => this._tree;
void setPercentExercises(double percent) => this._percentExercises = percent;
double getPercentExercises() => this._percentExercises;
void addExercise(Exercise exercise) => _exercises!.add(exercise);
void addExerciseTrainee(Exercise exercise) => _exercisesTrainee!.add(exercise);
Customer? getTrainee() => this._trainee;
void setTrainee(Customer trainee) => _trainee = trainee;
void setTraineeExercisePlan(ExercisePlan exercisePlan) => this._traineeExercisePlan = exercisePlan;
ExercisePlan? getTraineesExercisePlan() => this._traineeExercisePlan;
void setMyExercisePlan(ExercisePlan exercisePlan) => _myExercisePlan = exercisePlan;
ExercisePlan? getMyExercisePlan() => _myExercisePlan;
void setMyExercisePlanDetails(LinkedHashMap<int, ExercisePlanDetail> listExercisePlanDetail) =>
_myExercisesPlanDetails = listExercisePlanDetail;
void addToMyExercisePlanDetails(ExercisePlanDetail detail) => _myExercisesPlanDetails[detail.exerciseTypeId] = detail;
LinkedHashMap<int, ExercisePlanDetail> getMyExercisePlanDetails() => _myExercisesPlanDetails;
void resetMyExercisePlanDetails() => _myExercisesPlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
void updateMyExercisePlanDetail(ExercisePlanDetail detail) {
this.addToMyExercisePlanDetails(detail);
}
void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => this.deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId);
void deletedMyExercisePlanDetail(ExercisePlanDetail detail) =>
this._myExercisesPlanDetails[detail.exerciseTypeId]!.change = ModelChange.deleted;
void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) {
this._myExercisesPlanDetails[exerciseTypeId]!.change = ModelChange.delete;
}
void setProperties(List<Property> properties) => this._properties = properties;
List<Property>? getProperties() => _properties;
List<Sport>? getSports() => _sports;
void setSports(List<Sport> sports) => this._sports = sports;
void setDevices(List<ExerciseDevice> devices) => this._devices = devices;
List<ExerciseDevice>? getDevices() => this._devices;
void setCustomerDevices(List<CustomerExerciseDevice> devices) => this._customerDevices = devices;
List<CustomerExerciseDevice>? getCustomerDevices() => this._customerDevices;
LinkedHashMap getBadges() => _badges;
void setBadge(String key, bool inc) {
if (inc) {
if (_badges[key] != null) {
_badges[key] = _badges[key]! + 1;
} else {
_badges[key] = 1;
}
} else {
if (_badges[key] != null) {
if (_badges[key] == 1) {
_badges.remove(key);
} else {
_badges[key] = _badges[key]! - 1;
}
}
}
}
void setBadgeNr(String key, int counter) {
if (_badges[key] != null) {
_badges[key] = _badges[key]! + counter;
} else {
_badges[key] = counter;
}
}
void initBadges() {
CustomerRepository customerRepository = CustomerRepository();
_badges = LinkedHashMap();
if (userLoggedIn == null) {
return;
}
customerRepository.setCustomer(userLoggedIn!);
int _ecto = customerRepository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()).toInt();
int _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt();
int _endo = customerRepository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt();
//print("endo " + _endo.toString() + " mezo " + _mezo.toString());
if (this.userLoggedIn != null) {
if (this.userLoggedIn!.birthYear == null || this.userLoggedIn!.birthYear == 0) {
setBadge("personalData", true);
setBadge("account", true);
}
if (this._customerDevices == null || this._customerDevices!.isEmpty) {
setBadge("customerDevice", true);
setBadge("account", true);
}
if (userLoggedIn!.properties.isEmpty) {
setBadge("personalData", true);
setBadge("bodyType", true);
setBadge("Sizes", true);
setBadge("BMI", true);
setBadge("BMR", true);
setBadgeNr("My Body", 3);
setBadgeNr("home", 3);
} else if (customerRepository.getWeight() == 0) {
setBadge("BMI", true);
setBadge("BMR", true);
setBadge("My Body", true);
setBadgeNr("home", 1);
}
if (_ecto == 0 && _mezo == 0 && _endo == 0) {
setBadge("account", true);
setBadge("bodyType", true);
}
if (this._exercises == null || this._exercises!.isEmpty) {
setBadge("home", true);
setBadge("Custom Tests", true);
setBadge("Start Training", true);
}
if (customerRepository.getHeight() == 0) {
setBadge("BMI", true);
setBadge("BMR", true);
setBadge("My Body", true);
setBadgeNr("home", 1);
}
if (userLoggedIn!.goal == null) {
setBadge("Goal", true);
setBadge("account", true);
}
if (userLoggedIn!.fitnessLevel == null) {
setBadge("FitnessLevel", true);
setBadge("account", true);
}
if (this._exercises != null && this._exercises!.isNotEmpty) {
if (!activitiesDone[ActivityDone.isExerciseLogSeen.toStr()]!) {
setBadge("exerciseLog", true);
setBadge("development", true);
}
if (!activitiesDone[ActivityDone.isMuscleDevelopmentSeen.toStr()]!) {
setBadge("muscleDevelopment", true);
setBadge("development", true);
}
}
}
log("Badges: " + _badges.toString());
}
List<Product>? get products => _products;
void setProducts(List<wt_product.Product> value) => _products = value;
List<Purchase> get purchases => _purchases;
setPurchases(List<Purchase> value) => _purchases = value;
Future<void> initCustomer(int customerId) async {
log(" *** initCustomer");
try {
await PackageApi().getCustomerPackage(customerId);
} on Exception catch (_) {
return;
}
if (kReleaseMode) {
//FlurryData.setUserId(customerId.toString());
//FlutterUxcam.setUserProperty("username", customerId.toString());
//FlutterUxcam.setUserIdentity(customerId.toString());
//Smartlook.setUserIdentifier(customerId.toString());
//Smartlook.instance.
Track().track(TrackingEvent.enter);
MatomoTracker.instance.setVisitorUserId(customerId.toString());
MatomoTracker.instance.trackEvent(eventCategory: "wt", action: TrackingEvent.enter.enumToString());
Posthog().identify(userId: customerId.toString());
Posthog().capture(eventName: TrackingEvent.enter.enumToString());
}
await Future.forEach(ActivityDone.values, (element) async {
ActivityDone activity = element as ActivityDone;
await isActivityDonePrefs(activity);
});
print("Firebase token save: $firebaseMessageToken");
if (firebaseMessageToken != null) {
userLoggedIn!.firebaseRegToken = firebaseMessageToken;
CustomerRepository customerRepository = CustomerRepository();
customerRepository.customer = userLoggedIn;
customerRepository.saveCustomer();
}
await getMyTrainingPlan();
Cache().startPage = "home";
}
AccessToken? get getAccessTokenFacebook => accessTokenFacebook;
set setAccessTokenFacebook(AccessToken accessTokenFacebook) => this.accessTokenFacebook = accessTokenFacebook;
LoginType? getLoginType() => loginType;
void setLoginType(LoginType type) => this.loginType = type;
List get exercisePlanTemplates => this._exercisePlanTemplates;
setExercisePlanTemplates(value) => this._exercisePlanTemplates = value;
isActivityDonePrefs(ActivityDone activity) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
if (sharedPreferences.getBool(activity.toStr()) != null) {
activitiesDone[activity.toStr()] = sharedPreferences.getBool(activity.toStr())!;
}
return activitiesDone[activity.toStr()]!;
}
setActivityDonePrefs(ActivityDone activity) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
activitiesDone[activity.toStr()] = true;
sharedPreferences.setBool(activity.toStr(), true);
}
bool isActivityDone(ActivityDone activity) => activitiesDone[activity.toStr()] == true;
List<Evaluation>? get evaluations => this._evaluations;
set evaluations(List<Evaluation>? value) => this._evaluations = value;
List<CustomerActivity>? get customerActivities => this._customerActivities;
setCustomerActivities(List<CustomerActivity>? value) => this._customerActivities = value;
List<Tutorial>? get tutorials => this._tutorials;
setTutorials(List<Tutorial>? value) => this._tutorials = value;
FirebaseRemoteConfig? getRemoteConfig() => this.remoteConfig;
setRemoteConfig(FirebaseRemoteConfig? remoteConfig) => this.remoteConfig = remoteConfig;
List<Description>? getDescriptions() => this._descriptions;
setDescriptions(List<Description>? value) => this._descriptions = value;
List<Faq>? getFaqs() => this._faqs;
setFaqs(List<Faq>? value) => this._faqs = value;
List<TrainingPlan>? getTrainingPlans() => this._trainingPlans;
setTrainingPlans(List<TrainingPlan>? value) => this._trainingPlans = value;
List<CustomerTrainingPlan>? getCustomerTrainingPlans() => this._customerTrainingPlans;
setCustomerTrainingPlans(value) => this._customerTrainingPlans = value;
List<SplitTest> getSplitTests() => this._splitTests;
setSplitTests(value) => this._splitTests = value;
List<TrainingPlanDay> getTrainingPlanDays() => this._trainingPlanDays;
setTrainingPlanDays(value) => this._trainingPlanDays = value;
List<CustomerProperty>? getCustomerPropertyAll() => this._customerPropertyAll;
setCustomerPropertyAll(value) => this._customerPropertyAll = value;
addCustomerProperty(CustomerProperty property) {
if (this._customerPropertyAll == null) {
this._customerPropertyAll = [];
}
this._customerPropertyAll!.add(property);
}
}

128
lib/model/customer.dart Normal file
View File

@ -0,0 +1,128 @@
import 'dart:collection';
import 'package:intl/intl.dart';
import 'customer_property.dart';
class Customer {
String? name;
String? email;
String? firstname;
String? sex;
int? age;
String? active;
int? customerId;
String? password;
int? birthYear;
String? goal;
String? fitnessLevel;
String? bodyType;
int? admin;
int? trainer;
int? dataPolicyAllowed;
String? firebaseUid;
DateTime? dateAdd;
DateTime? dateChange;
int? emailSubscription;
int? sportId;
DateTime? syncedDate;
DateTime? trialDate;
String? firebaseRegToken;
String? lang;
int? lifeLong;
LinkedHashMap<String, CustomerProperty> properties = LinkedHashMap();
Customer(
{this.customerId,
this.name,
this.firstname,
this.email,
this.sex,
this.age,
this.active,
this.password,
this.birthYear,
this.bodyType,
this.fitnessLevel,
this.goal,
this.admin,
this.trainer,
this.dataPolicyAllowed,
this.firebaseUid,
this.dateAdd,
this.dateChange}) {
dateAdd = DateTime.now();
dateChange = DateTime.now();
}
Customer.fromJson(Map json) {
this.customerId = json['customerId'];
this.name = json['name'];
this.firstname = json['firstname'];
this.email = json['email'];
this.sex = json['sex'];
this.age = json['age'];
this.active = json['active'];
this.birthYear = json['birthYear'];
this.bodyType = json['bodyType'];
this.fitnessLevel = json['fitnessLevel'];
this.goal = json['goal'];
this.admin = json['admin'];
this.lifeLong = json['lifeLong'];
this.trainer = json['trainer'];
this.firebaseUid = json['firebaseUid'];
this.firebaseRegToken = json['firebaseRegToken'];
this.lang = json['lang'];
this.dataPolicyAllowed = json['dataPolicyAllowed'];
this.emailSubscription = json['emailSubscription'];
this.sportId = json['sportId'];
this.syncedDate = json['syncedDate'] == null ? null : DateTime.parse(json['syncedDate']);
this.trialDate = json['trialDate'] == null ? null : DateTime.parse(json['trialDate']);
this.dateAdd = json['dateAdd'] == null ? DateTime.parse("0000-00-00") : DateTime.parse(json['dateAdd']);
this.dateChange = json['dateChange'] == null ? DateTime.parse("0000-00-00") : DateTime.parse(json['dateChange']);
}
Map<String, dynamic> toJson() => {
"name": name,
"firstname": firstname,
"email": email,
"age": age,
"sex": sex,
"active": 'Y',
"password": password,
"birthYear": birthYear,
"bodyType": bodyType,
"fitnessLevel": fitnessLevel,
"goal": goal,
"admin": admin,
"trainer": trainer,
"dataPolicyAllowed": dataPolicyAllowed,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
"dateChange": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateChange!),
"emailSubscription": this.emailSubscription,
"sportId": this.sportId,
"syncedDate": this.syncedDate == null ? null : DateFormat('yyyy-MM-dd HH:mm:ss').format(this.syncedDate!),
"trialDate": this.trialDate == null ? null : DateFormat('yyyy-MM-dd HH:mm:ss').format(this.trialDate!),
"firebaseRegToken": this.firebaseRegToken,
"lang": this.lang,
"lifeLong": this.lifeLong,
};
@override
String toString() => this.toJson().toString();
double getProperty(String propertyName) {
if (this.properties[propertyName] == null) {
return 0;
} else {
return this.properties[propertyName]!.propertyValue;
}
}
setProperty(String propertyName, double value) {
this.properties[propertyName]!.propertyValue = value;
}
}

View File

@ -0,0 +1,30 @@
import 'package:intl/intl.dart';
class CustomerActivity {
late int activityId;
late int customerId;
late String type;
late DateTime? dateAdd;
bool? skipped;
CustomerActivity.fromJson(Map json) {
activityId = json['activityId'];
customerId = json['custoemrId'];
type = json['type'];
skipped = json['skipped'];
this.dateAdd = DateTime.parse(json['dateAdd']);
}
Map<String, dynamic> toJson() => {
'activityId': this.activityId,
'customerId': this.customerId,
'type': this.type,
'skipped': this.skipped,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
};
@override
String toString() {
return this.toJson().toString();
}
}

View File

@ -0,0 +1,42 @@
import 'package:intl/intl.dart';
class CustomerExerciseDevice {
int? customerExerciseDeviceId;
late int exerciseDeviceId;
late int customerId;
late bool favourite;
late DateTime dateAdd;
late String change;
CustomerExerciseDevice({required this.exerciseDeviceId, required this.customerId, required 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<String, dynamic> 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),
};
}
}
}

View File

@ -0,0 +1,69 @@
import 'package:intl/intl.dart';
class CustomerProperty {
int? customerPropertyId;
late int propertyId;
late int customerId;
DateTime? dateAdd;
String? dateYmd;
String? dateYm;
String? dateY;
late double propertyValue;
bool newData = false;
CustomerProperty(
{required this.propertyId,
required this.customerId,
required this.dateAdd,
required this.propertyValue});
CustomerProperty.fromJson(Map json) {
this.customerPropertyId = json['customerPropertyId'];
this.propertyId = json['propertyId'];
this.customerId = json['customerId'];
this.dateAdd = DateTime.parse(json['dateAdd']);
if (this.dateAdd != null) {
dateYmd = DateFormat('yyyy-MM-dd').format(this.dateAdd!);
dateYm = DateFormat('yyyy-MM').format(this.dateAdd!);
dateY = DateFormat('yyyy').format(this.dateAdd!);
}
this.propertyValue = json['propertyValue'];
print("Json $json, ${this.toString()}");
}
Map<String, dynamic> toJson() {
if (customerPropertyId != null) {
return {
"customerPropertyId": this.customerPropertyId,
"propertyId": this.propertyId,
"customerId": this.customerId,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
"propertyValue": this.propertyValue
};
} else {
return {
"propertyId": this.propertyId,
"customerId": this.customerId,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
"propertyValue": this.propertyValue
};
}
}
String toString() {
Map<String, dynamic> json = {
"customerPropertyId": this.customerPropertyId,
"propertyId": this.propertyId,
"customerId": this.customerId,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
"propertyValue": this.propertyValue,
"dateYmd": this.dateYmd,
"dateYm": this.dateYm,
"dateY": this.dateY,
};
return json.toString();
}
}

View File

@ -0,0 +1,97 @@
import 'dart:collection';
import 'dart:convert';
// ignore: depend_on_referenced_packages
import 'package:intl/intl.dart';
import 'package:workouttest_util/repository/exercise_type_repository.dart';
import 'package:workouttest_util/model/customer_training_plan_details.dart';
enum CustomerTrainingPlanType { custom, template, none }
extension CustomerTrainingPlanTypeExt on CustomerTrainingPlanType {
String toStr() => toString().split(".").last;
bool equalsTo(CustomerTrainingPlanType type) => toString() == type.toString();
bool equalsStringTo(String type) => toStr() == type;
}
class CustomerTrainingPlan {
int? customerTrainingPlanId;
int? customerId;
int? trainingPlanId;
DateTime? dateAdd;
bool? active;
String? status;
String? name;
CustomerTrainingPlanType type = CustomerTrainingPlanType.none;
CustomerTrainingPlan();
List<CustomerTrainingPlanDetails> details = [];
HashMap<String, List<CustomerTrainingPlanDetails>> days = HashMap();
CustomerTrainingPlan.fromJson(Map json) {
customerTrainingPlanId = json['customerTrainingPlanId'];
customerId = json['customerId'];
trainingPlanId = json['trainingPlanId'];
dateAdd = DateTime.parse(json['dateAdd']);
active = json['active'];
status = json['status'];
name = json['name'];
}
CustomerTrainingPlan.fromJsonWithDetails(Map json) {
customerTrainingPlanId = json['customerTrainingPlanId'];
customerId = json['customerId'];
trainingPlanId = json['trainingPlanId'];
dateAdd = json['dateAdd'] != null ? DateTime.parse(json['dateAdd']) : DateTime.now();
active = json['active'];
status = json['status'];
name = json['name'];
try {
final String details = json['details'];
String jsonDetails = details.replaceAllMapped(RegExp(r'([a-zA-Z]+)\:'), (Match m) => "\"${m[1]}\":");
jsonDetails = jsonDetails.replaceAllMapped(RegExp(r'\: ([a-zA-Z /]+)'), (Match m) => ":\"${m[1]}\"");
jsonDetails =
jsonDetails.replaceAllMapped(RegExp(r'([0-9]{4}\-[0-9]{2}\-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})'), (Match m) => "\"${m[0]}\"");
print("detail: $jsonDetails");
Iterable iterable = jsonDecode(jsonDetails);
this.details = iterable.map((detail) => CustomerTrainingPlanDetails.fromJsonWithExerciseList(detail)).toList();
this.details.forEach((detail) {
detail.alternatives = ExerciseTypeRepository.getExerciseTypeAlternatives(detail.exerciseTypeId);
});
} on Exception catch (e) {
print("JsonDecode error " + e.toString());
}
}
Map<String, dynamic> toJson() => {
"customerTrainingPlanId": customerTrainingPlanId,
"customerId": customerId,
"trainingPlanId": trainingPlanId,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(dateAdd!),
"name": name,
"active": active,
"status": status
};
Map<String, dynamic> toJsonWithDetails() => {
"customerTrainingPlanId": customerTrainingPlanId,
"customerId": customerId,
"trainingPlanId": trainingPlanId,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(dateAdd!).toString(),
"name": name,
"active": active,
"status": status,
'details': details.isEmpty ? [].toString() : details.map((detail) => detail.toJsonWithExercises()).toList().toString(),
};
@override
String toString() => toJson().toString();
}

View File

@ -0,0 +1,162 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/exercise.dart';
import 'package:workouttest_util/model/exercise_plan_detail.dart';
import 'package:workouttest_util/model/exercise_type.dart';
import 'package:workouttest_util/repository/training_plan_day_repository.dart';
class CustomerTrainingPlanDetails {
/// customerTrainingPlanDetails
int? customerTrainingPlanDetailsId;
/// trainingPlanDetailsId
int? trainingPlanDetailsId;
/// exerciseTypeId
int? exerciseTypeId;
/// set
int? set;
/// repeats
int? repeats;
/// weight
double? weight;
int? restingTime;
bool? parallel;
String? day;
int? dayId;
/// exerciseType
ExerciseType? exerciseType;
ExercisePlanDetailState state = ExercisePlanDetailState.start;
List<Exercise> exercises = [];
bool isTest = false;
double baseOneRepMax = -1;
List<ExerciseType> alternatives = [];
CustomerTrainingPlanDetails();
CustomerTrainingPlanDetails.fromJson(Map json) {
this.customerTrainingPlanDetailsId = json['customerTrainingPlanDetailsId'];
this.exerciseTypeId = json['exerciseTypeId'];
this.set = json['set'];
this.repeats = json['repeats'];
this.weight = json['weight'];
this.restingTime = json['restingTime'];
this.parallel = json['parallel'];
this.day = json['day'];
}
CustomerTrainingPlanDetails.fromJsonWithExerciseList(Map json) {
this.customerTrainingPlanDetailsId = json['customerTrainingPlanDetailsId'] == "null" || json['customerTrainingPlanDetailsId'] == null
? 0
: json['customerTrainingPlanDetailsId'];
this.trainingPlanDetailsId = json['trainingPlanDetailsId'] == "null" ? 0 : json['trainingPlanDetailsId'];
this.exerciseTypeId = json['exerciseTypeId'];
this.set = json['set'];
this.repeats = json['repeats'] == "null" ? -1 : json['repeats'];
this.weight = json['weight'] == "null" ? 0 : json['weight'];
this.restingTime = json['restingTime'];
this.parallel = json['parallel'] == "false"
? false
: json['parallel'] == "true"
? true
: null;
this.dayId = json['dayId'] == "null" ? null : json['dayId'];
TrainingPlanDayRepository trainingPlanDayRepository = TrainingPlanDayRepository();
this.day = trainingPlanDayRepository.getNameById(this.dayId);
try {
Iterable iterable = json['exercises'];
this.exercises = iterable.map((exercise) => Exercise.fromJson(exercise)).toList();
} on Exception catch (e) {
print("JsonDecode error " + e.toString());
}
if (json['state'] == ExercisePlanDetailState.finished.toStr()) {
this.state = ExercisePlanDetailState.finished;
} else if (json['state'] == ExercisePlanDetailState.inProgress.toStr()) {
this.state = ExercisePlanDetailState.inProgress;
} else if (json['state'] == ExercisePlanDetailState.skipped.toStr()) {
this.state = ExercisePlanDetailState.skipped;
} else {
this.state = ExercisePlanDetailState.start;
}
this.isTest = json['isTest'] == "true" ? true : false;
this.exerciseType = Cache().getExerciseTypeById(exerciseTypeId!);
this.baseOneRepMax = json['baseOneRepMax'] == null ? 0 : json['baseOneRepMax'];
}
ExerciseType? getExerciseType() => exerciseType;
Map<String, dynamic> toJson() => {
"customerTrainingPlanDetailsId": this.customerTrainingPlanDetailsId,
"exerciseTypeId": this.exerciseTypeId,
"set": this.set,
"repeats": this.repeats,
"weight": this.weight,
"restingTime": this.restingTime,
"parallel": this.parallel,
"day": this.day == null ? '1.' : this.day,
};
Map<String, dynamic> toJsonWithExercises() {
final Map<String, dynamic> jsonMap = {
"customerTrainingPlanDetailsId": this.customerTrainingPlanDetailsId,
"trainingPlanDetailsId": this.trainingPlanDetailsId,
"exerciseTypeId": this.exerciseTypeId,
"set": this.set,
"repeats": this.repeats,
"weight": this.weight,
"restingTime": this.restingTime,
"parallel": this.parallel,
'exercises': exercises.isEmpty ? [].toString() : exercises.map((exercise) => exercise.toJson()).toList().toString(),
'state': this.state.toStr(),
"isTest": this.isTest,
"dayId": this.dayId,
"baseOneRepMax": this.baseOneRepMax,
};
//print("Detail toJson $jsonMap");
return jsonMap;
}
@override
String toString() => this.toJsonWithExercises().toString();
void copy(CustomerTrainingPlanDetails from) {
this.customerTrainingPlanDetailsId = from.customerTrainingPlanDetailsId;
this.trainingPlanDetailsId = from.trainingPlanDetailsId;
this.exerciseTypeId = from.exerciseTypeId;
this.exerciseType = from.exerciseType;
this.set = from.set;
this.repeats = from.repeats;
this.weight = from.weight;
this.restingTime = from.restingTime;
this.parallel = from.parallel;
this.exercises = from.exercises;
this.state = from.state;
this.isTest = from.isTest;
this.day = from.day;
this.dayId = from.dayId;
this.baseOneRepMax = from.baseOneRepMax;
if (from.exercises.length == 0) {
this.exercises = [];
}
if (from.alternatives.length > 0) {
from.alternatives.forEach((alternative) {
this.alternatives.add(alternative);
});
}
}
}

View File

@ -0,0 +1,30 @@
class CustomerTrainingPlanExercise {
int? customerTrainingPlanExerciseId;
int? customerTrainingPlanDetailsId;
int? customerId;
int? exerciseId;
double? weight;
int? repeats;
CustomerTrainingPlanExercise();
CustomerTrainingPlanExercise.fromJson(Map json) {
this.customerTrainingPlanExerciseId = json['customerTrainingPlanExerciseId'];
this.customerTrainingPlanDetailsId = json['customerTrainingPlanDetailsId'];
this.customerId = json['customerId'];
this.exerciseId = json['exerciseId'];
this.repeats = json['repeats'];
this.weight = json['weight'];
}
Map<String, dynamic> toJson() => {
"customerTrainingPlanDetailsId": this.customerTrainingPlanDetailsId,
"customerId": this.customerId,
"exerciseId": this.exerciseId,
"weight": this.weight,
"repeats": this.repeats
};
@override
String toString() => this.toJson().toString();
}

View File

@ -0,0 +1,40 @@
import 'package:workouttest_util/util/app_language.dart';
import 'dart:ui';
class Description {
late int descriptionId;
late String name;
late String description;
int? version;
DateTime? validFrom;
DateTime? validTo;
String? descriptionTranslation;
Description.fromJson(Map json) {
this.descriptionId = json['descriptionId'];
this.name = json['name'];
this.description = json['description'];
this.version = json['version'];
this.validFrom = json['validFrom'];
this.validTo = json['validTo'];
if (json['translations'] != null && json['translations'].length > 0) {
this.descriptionTranslation =
AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['descriptionTranslation'] : json['description'];
}
}
Map<String, dynamic> toJson() => {
"descriptionId": this.descriptionId,
"name": this.name,
"description": this.description,
"version": this.version,
"validFrom": this.validFrom,
"validTo": this.validTo,
"descriptionTranslation": this.descriptionTranslation
};
@override
String toString() => this.toJson().toString();
}

28
lib/model/evaluation.dart Normal file
View File

@ -0,0 +1,28 @@
import 'package:workouttest_util/model/evaluation_attribute.dart';
class Evaluation {
int? evaluationId;
late String name;
int? exerciseTypeId;
String? unit;
late List attributes;
Evaluation.fromJson(Map json) {
evaluationId = json['evaluationId'];
name = json['name'];
exerciseTypeId = json['exerciseTypeId'];
unit = json['unit'];
this.attributes = json['attributes'].map((attr) => EvaluationAttribute.fromJson(attr)).toList();
}
@override
String toString() {
Map<String, dynamic> json = {
'evaluationId': this.evaluationId,
'name': this.name,
'exerciseTypeId': this.exerciseTypeId,
'unit': this.unit
};
return json.toString();
}
}

View File

@ -0,0 +1,41 @@
class EvaluationAttribute {
late int evaluationAttrId;
int? evaluationId;
late String name;
late String sex;
late int ageMin;
late int ageMax;
late double valueMin;
late double valueMax;
late String evaluationText;
String? suggestion;
EvaluationAttribute.fromJson(Map json) {
evaluationAttrId = json['evaluationAttrId'];
evaluationId = json['evaluationId'];
name = json['name'];
sex = json['sex'];
ageMin = json['ageMin'];
ageMax = json['ageMax'];
valueMin = json['valueMin'];
valueMax = json['valueMax'];
evaluationText = json['evaluation_text'];
suggestion = json['suggestion'];
}
@override
String toString() {
Map<String, dynamic> json = {
'evaluationAttrId': this.evaluationAttrId,
'evaluationId': this.evaluationId,
'name': this.name,
'sex': this.sex,
'ageMin': this.ageMin,
'ageMax': this.ageMax,
'valueMin': this.valueMin,
'valueMax': this.valueMax,
'evaluation_text': this.evaluationText,
};
return json.toString();
}
}

68
lib/model/exercise.dart Normal file
View File

@ -0,0 +1,68 @@
import 'package:intl/intl.dart';
class Exercise {
int? exerciseId;
int? exerciseTypeId;
int? customerId;
double? quantity;
String? unit;
double? unitQuantity;
DateTime? dateAdd;
int? exercisePlanDetailId;
int? trainingPlanDetailsId;
String? datePart;
double? calculated;
String? summary;
Exercise({this.exerciseTypeId, this.customerId, this.quantity, this.dateAdd});
Exercise.fromJson(Map json) {
this.exerciseId = json['exerciseId'];
this.exerciseTypeId = json['exerciseTypeId'];
this.customerId = json['customerId'];
this.quantity = json['quantity'];
this.unit = json['unit'];
this.unitQuantity = json['unitQuantity'];
this.dateAdd = DateTime.parse(json['dateAdd']);
this.datePart = DateFormat('yyyy-MM-dd').format(this.dateAdd!);
this.calculated = quantity;
this.exercisePlanDetailId = json['exercisePlanDetailId'] == "null" ? null : json['exercisePlanDetailId'];
this.trainingPlanDetailsId = json['trainingPlanDetailsId'] == "null" ? null : json['trainingPlanDetailsId'];
}
Map<String, dynamic> toJson() => {
"exerciseTypeId": exerciseTypeId,
"customerId": customerId,
"quantity": quantity,
"unit": unit,
"unitQuantity": unitQuantity,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
"exercisePlanDetailId": exercisePlanDetailId,
"trainingPlanDetailsId": trainingPlanDetailsId,
};
Map<String, dynamic> toJsonDatePart() => {
"exerciseTypeId": exerciseTypeId,
"customerId": customerId,
"quantity": quantity,
'calculated': calculated,
"unit": unit,
"unitQuantity": unitQuantity,
"datePart": this.datePart,
};
Exercise copy() {
Exercise newExercise =
Exercise(exerciseTypeId: this.exerciseTypeId, customerId: this.customerId, quantity: this.quantity, dateAdd: this.dateAdd);
newExercise.unit = this.unit;
newExercise.unitQuantity = this.unitQuantity;
newExercise.exercisePlanDetailId = this.exercisePlanDetailId;
return newExercise;
}
@override
String toString() {
return this.toJson().toString();
}
}

View File

@ -0,0 +1,25 @@
enum ExerciseAbility { oneRepMax, endurance, running, mini_test_set, paralell_test, training, training_execute, none }
extension ExerciseAbilityExt on ExerciseAbility {
String enumToString() => this.toString().split(".").last;
bool equalsTo(ExerciseAbility ability) => this.toString() == ability.toString();
bool equalsStringTo(String ability) => this.enumToString() == ability;
String get description {
switch (this) {
case ExerciseAbility.endurance:
return "Endurance";
case ExerciseAbility.oneRepMax:
return "One Rep Max";
case ExerciseAbility.running:
return "Running";
case ExerciseAbility.mini_test_set:
return "Compact Test";
case ExerciseAbility.paralell_test:
return "Custom Test";
case ExerciseAbility.training:
return "Training";
default:
return "Compact Test";
}
}
}

View File

@ -0,0 +1,21 @@
class ExerciseDevice {
late int exerciseDeviceId;
late String name;
late String description;
late String imageUrl;
late String nameTranslation;
late int sort;
late bool place;
bool? isGym;
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;
}
}

View File

@ -0,0 +1,70 @@
import 'package:intl/intl.dart';
class ExercisePlan {
int? exercisePlanId;
late int customerId;
late String name;
String? description;
late bool private;
late DateTime? dateAdd;
late DateTime dateUpd;
String? type;
int? exercisePlanTemplateId;
ExercisePlan(String name, int customerId) {
this.customerId = customerId;
this.name = name;
this.dateUpd = DateTime.now();
}
ExercisePlan.fromJson(Map json) {
this.exercisePlanId = json['exercisePlanId'];
this.customerId = json['customerId'];
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.type = json['type'];
this.exercisePlanTemplateId = json['exercisePlanTemplateId'];
}
Map<String, dynamic> toJson() {
String? formattedDateAdd;
if (dateAdd != null) {
formattedDateAdd = DateFormat('yyyy-MM-dd HH:mm').format(dateAdd!);
}
String formattedDateUpd = DateFormat('yyyy-MM-dd HH:mm').format(dateUpd);
if (exercisePlanId == null) {
return {
"customerId": customerId,
"name": name,
"description": description,
"private": private,
"dateAdd": formattedDateAdd,
"dateUpd": formattedDateUpd,
"type": type,
"exercisePlanTemplateId": exercisePlanTemplateId
};
} else {
return {
"exercisePlanId": exercisePlanId,
"customerId": customerId,
"name": name,
"description": description,
"private": private,
"dateAdd": formattedDateAdd,
"dateUpd": formattedDateUpd,
"type": type,
"exercisePlanTemplateId": exercisePlanTemplateId
};
}
}
@override
String toString() {
Map<String, dynamic> json = toJson();
return json.toString();
}
}

View File

@ -0,0 +1,91 @@
import 'dart:convert';
import 'package:workouttest_util/model/exercise.dart';
import 'package:workouttest_util/model/exercise_type.dart';
enum ExercisePlanDetailState { start, inProgress, skipped, finished, extra }
extension ExericisePlanDetailStateExt on ExercisePlanDetailState {
bool equalsTo(ExercisePlanDetailState state) => this.toString() == state.toString();
bool equalsStringTo(String state) => this.toString() == state;
String toStr() => this.toString().split(".").last;
}
class ExercisePlanDetail {
int? exercisePlanDetailId;
int? exercisePlanId;
late int exerciseTypeId;
int? serie;
int? repeats;
String? weightEquation;
/// List<Exercise>
List<Exercise>? exercises;
/// bool finished
bool? finished;
ExercisePlanDetailState state = ExercisePlanDetailState.start;
ExerciseType? exerciseType;
String? change; // 1: update -1:delete 0: new
ExercisePlanDetail(int exerciseTypeId) {
this.exerciseTypeId = exerciseTypeId;
}
ExercisePlanDetail.fromJson(Map json) {
this.exercisePlanDetailId = json['exercisePlanDetailId'];
this.exercisePlanId = json['exercisePlanId'];
this.exerciseTypeId = json['exerciseTypeId'];
this.serie = json['serie'];
this.repeats = json['repeats'];
this.weightEquation = json['weightEquation'];
}
ExercisePlanDetail.fromJsonWithExerciseList(Map json) {
this.exercisePlanDetailId = json['exercisePlanDetailId'];
this.exercisePlanId = json['exercisePlanId'];
this.exerciseTypeId = json['exerciseTypeId'];
this.serie = json['serie'];
this.repeats = json['repeats'];
this.weightEquation = json['weightEquation'];
try {
final String exercises = json['exercises'];
String jsonExercises = exercises.replaceAllMapped(
RegExp(r'([a-zA-Z]+|[0-9]{4}\-[0-9]{2}\-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})'), (Match m) => "\"${m[0]}\"");
jsonExercises = jsonExercises.replaceAll(r'\"null\"', 'null');
//print("Exercises $jsonExercises");
Iterable iterable = jsonDecode(jsonExercises);
this.exercises = iterable.map((exercise) => Exercise.fromJson(exercise)).toList();
} on Exception catch (e) {
print("JsonDecode error " + e.toString());
}
}
Map<String, dynamic> toJson() => {
"exercisePlanId": exercisePlanId == null ? 0 : exercisePlanId,
"exerciseTypeId": exerciseTypeId,
"serie": serie,
"repeats": repeats,
"weightEquation": weightEquation
};
Map<String, dynamic> toJsonWithExerciseList() => {
"exercisePlanDetailId": exercisePlanDetailId,
"exercisePlanId": exercisePlanId,
"exerciseTypeId": exerciseTypeId,
"serie": serie,
"repeats": repeats,
"weightEquation": weightEquation,
'exercises': exercises == null ? [].toString() : exercises!.map((exercise) => exercise.toJson()).toList().toString(),
};
@override
String toString() {
Map<String, dynamic> json = toJsonWithExerciseList();
return json.toString();
}
}

View File

@ -0,0 +1,50 @@
import 'dart:ui';
import 'package:workouttest_util/util/app_language.dart';
class ExercisePlanTemplate {
late int? exercisePlanTemplateId;
late String name;
late String description;
late String templateType;
late String nameTranslation;
late String descriptionTranslation;
List<int> exerciseTypes = [];
ExercisePlanTemplate.fromJson(Map json) {
this.exercisePlanTemplateId = json['exercisePlanId'];
this.name = json['name'];
this.description = json['description'];
this.templateType = json['templateType'];
if (json['translations'].length > 0) {
this.nameTranslation = AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['name'] : json['name'];
this.descriptionTranslation = AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['description'] : json['description'];
}
if (json['details'] != null && (json['details']).length > 0) {
final List details = json['details'];
details.sort((a, b) {
if (a['sort'] == null || b['sort'] == null) {
return a['exercisePlanTemplateDetailId'] < b['exercisePlanTemplateDetailId'] ? -1 : 1;
} else {
return a['sort'] < b['sort'] ? -1 : 1;
}
});
details.forEach((element) {
exerciseTypes.add(element['exerciseTypeId']);
});
}
}
Map<String, dynamic> toJson() {
return {
"exercisePlanTemplateId": exercisePlanTemplateId,
"name": name,
"description": "description",
"templateType": templateType,
"nameTranslation": nameTranslation,
"descriptionTranslation": descriptionTranslation,
"exerciseTypes": exerciseTypes.toString()
};
}
}

View File

@ -0,0 +1,46 @@
import 'package:workouttest_util/model/result.dart';
import 'package:intl/intl.dart';
class ExerciseResult {
late int? exerciseResultId;
late int customerId;
late int exerciseId;
late int exercisePlanId;
late String resultType;
late double value;
late DateTime dateFrom;
late DateTime? dateTo;
ResultExt? resultExtension;
ExerciseResult();
Map<String, dynamic> toJson() {
String? formattedDateTo;
if (dateTo != null) {
formattedDateTo = DateFormat('yyyy-MM-dd HH:mm').format(dateTo!);
}
return {
"customerId": customerId,
"exerciseId": exerciseId,
"exercisePlanId": exercisePlanId,
"resultType": resultType,
"value": value,
"dateFrom": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateFrom),
"dateTo": formattedDateTo,
};
}
ExerciseResult.fromJson(Map json) {
this.exerciseResultId = json['exerciseResultId'];
this.exerciseId = json['exerciseId'];
this.exercisePlanId = json['exercisePlanId'];
this.customerId = json['customerId'];
this.resultType = json['resultType'];
this.value = json["value"];
this.dateFrom = DateTime.parse(json['dateFrom']);
this.dateTo = DateTime.parse(json['dateTo']);
this.resultExtension = ResultExt(itemString: this.resultType);
}
}

View File

@ -0,0 +1,76 @@
class ExerciseTree {
/// treeId
late int treeId;
/// parentId
late int parentId;
/// name
late String name;
/// imageUrl
late String imageUrl;
/// active
late bool active;
/// nameTranslation
late String nameTranslation;
/// sort
int? sort;
String? internalName;
String? description;
String? descriptionTranslation;
ExerciseTree();
ExerciseTree.fromJson(Map json) {
this.treeId = json['treeId'];
this.name = json['name'];
this.parentId = 0;
this.imageUrl = json['imageUrl'];
this.active = json['active'];
this.nameTranslation = json['translations'] != null && (json['translations']).length > 0 ? json['translations'][0]['name'] : this.name;
this.descriptionTranslation =
json['translations'] != null && (json['translations']).length > 0 && json['translations'][0]['description'] != null
? json['translations'][0]['description']
: this.description;
this.sort = 99;
this.internalName = json['internalName'];
}
Map<String, dynamic> toJson() {
return {
"treeId": treeId,
"parentId": parentId,
"name": name,
"description": description,
"imageUrl": imageUrl,
"active": active.toString(),
"nameTranslation": nameTranslation,
"descriptionTranslation": descriptionTranslation,
"sort": sort,
};
}
@override
String toString() => this.toJson().toString();
ExerciseTree copy(int parentId) {
ExerciseTree newTree = ExerciseTree();
newTree.treeId = this.treeId;
newTree.name = this.name;
newTree.imageUrl = this.imageUrl;
newTree.nameTranslation = this.nameTranslation;
if (parentId != -1) {
newTree.parentId = parentId;
}
newTree.active = this.active;
newTree.sort = this.sort == null ? 99 : this.sort;
return newTree;
}
}

View File

@ -0,0 +1,13 @@
class ExerciseTreeParents {
late int exerciseTreeParentsId;
late int exerciseTreeParentId;
late int exerciseTreeChildId;
late int sort;
ExerciseTreeParents.fromJson(Map json) {
this.exerciseTreeParentsId = json['exerciseTreeParentsId'];
this.exerciseTreeParentId = json['exerciseTreeParentId'];
this.exerciseTreeChildId = json['exerciseTreeChildId'];
this.sort = json['sort'];
}
}

View File

@ -0,0 +1,134 @@
import 'package:workouttest_util/model/exercise_ability.dart';
import 'package:workouttest_util/util/app_language.dart';
import 'package:workouttest_util/util/enums.dart';
import 'package:flutter/material.dart';
class ExerciseType {
///exerciseTypeId
late int exerciseTypeId;
/// name
late String name;
/// description
late String description;
/// unit
late String unit;
/// unitQuantity
String? unitQuantity;
/// unitQuantityUnit
String? unitQuantityUnit;
///active
late bool active;
/// base
late bool base;
late bool buddyWarning;
/// imageUrl
String imageUrl = "";
/// nameTranslation
String nameTranslation = "";
/// descriptionTranslation
String descriptionTranslation = "";
/// devices[]
List<int> devices = [];
/// parents[]
List<int> parents = [];
/// alternatives []
List<int> alternatives = [];
/// ability
ExerciseAbility? ability;
/// TrainingPlanState - whether the exercise_type exists in the
/// custom training plan
ExerciseTypeTrainingPlanState trainingPlanState = ExerciseTypeTrainingPlanState.none;
ExerciseType({required this.name, required this.description});
ExerciseType.fromJson(Map json) {
this.exerciseTypeId = json['exerciseTypeId'];
//this.treeId = json['treeId'];
this.name = json['name'];
this.description = json['description'];
this.unit = json['unit'];
this.unitQuantity = json['unitQuantity'];
this.unitQuantityUnit = json['unitQuantityUnit'];
this.active = json['active'];
this.base = json['base'];
this.buddyWarning = json['buddyWarning'];
if (json['images'].length > 0) {
this.imageUrl = json['images'][0]['url'];
}
if (json['translations'].length > 0) {
this.nameTranslation = AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['name'] : json['name'];
this.descriptionTranslation = AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['description'] : json['description'];
}
if (json['devices'].length > 0) {
final List jsonDevices = json['devices'];
jsonDevices.forEach((device) {
this.devices.add(device['exerciseDeviceId']);
});
}
if (json['parents'].length > 0) {
final List jsonParents = json['parents'];
jsonParents.forEach((parent) {
this.parents.add(parent['exerciseTreeId']);
});
}
if (json['alternatives'].length > 0) {
final List jsonAlternatives = json['alternatives'];
jsonAlternatives.forEach((alternative) {
this.alternatives.add(alternative['exerciseTypeChildId']);
});
}
}
Map<String, dynamic> toJson() => {
"name": name,
"description": description,
"unit": unit,
"unitQuantity": unitQuantity,
"unitQuantityUnit": unitQuantityUnit,
"active": active,
"base": base,
"buddyWarning": buddyWarning,
"devices": this.devices.toString(),
"nameTranslation": this.nameTranslation,
"parents": this.parents.toString()
};
void setAbility(ExerciseAbility ability) {
this.ability = ability;
}
ExerciseAbility getAbility() {
return this.ability!;
}
bool is1RM() {
return this.ability!.equalsTo(ExerciseAbility.oneRepMax);
}
@override
String toString() {
return this.toJson().toString();
}
}

View File

@ -0,0 +1,11 @@
class ExerciseTypeDevice {
late int exerciseTypeDeviceId;
late int exerciseDeviceId;
ExerciseTypeDevice();
ExerciseTypeDevice.fromJson(Map json) {
this.exerciseTypeDeviceId = json['exerciseTypeDeviceId'];
this.exerciseDeviceId = json['exerciseDeviceId'];
}
}

37
lib/model/faq.dart Normal file
View File

@ -0,0 +1,37 @@
import 'dart:collection';
class Faq {
late int faqId;
late String name;
late String description;
int? sort;
HashMap<String, String> nameTranslations = HashMap();
HashMap<String, String> descriptionTranslations = HashMap();
Faq.fromJson(Map json) {
this.faqId = json['faqId'];
this.name = json['name'];
this.description = json['description'];
this.sort = json['sort'];
nameTranslations['en'] = name;
descriptionTranslations['en'] = description;
if (json['translations'] != null && json['translations'].length > 0) {
json['translations'].forEach((translation) {
nameTranslations[translation['languageCode']] = translation['nameTranslation'];
descriptionTranslations[translation['languageCode']] = translation['descriptionTranslation'];
});
}
}
Map<String, dynamic> toJson() => {
"faqId": this.faqId,
"name": this.name,
"description": this.description,
"nameTranslation": this.nameTranslations.toString(),
};
@override
String toString() => this.toJson().toString();
}

View File

@ -0,0 +1,67 @@
class FitnessState {
late final String value;
late final String stateText;
late final String explanation;
static String beginner = "beginner";
static String intermediate = "intermediate";
static String advanced = "advanced";
static String professional = "professional";
FitnessState({required this.value, required this.stateText, required this.explanation});
bool isEqual(FitnessState? state) {
if (state == null) {
return false;
}
return state.value == this.value;
}
@override
String toString() {
return stateText;
}
}
class FitnessItem {
static final FitnessItem _singleton = FitnessItem._internal();
List<FitnessState> elements = [];
factory FitnessItem() {
return _singleton;
}
FitnessItem._internal() {
elements.add(FitnessState(
value: FitnessState.beginner, stateText: _capitalize(FitnessState.beginner), explanation: "I am " + FitnessState.beginner));
elements.add(FitnessState(
value: FitnessState.intermediate,
stateText: _capitalize(FitnessState.intermediate),
explanation: "I am " + FitnessState.intermediate));
elements.add(FitnessState(
value: FitnessState.advanced, stateText: _capitalize(FitnessState.advanced), explanation: "I am " + FitnessState.advanced));
elements.add(FitnessState(
value: FitnessState.professional,
stateText: _capitalize(FitnessState.professional),
explanation: "I am " + FitnessState.professional));
}
String _capitalize(String value) {
return "${value[0].toUpperCase()}${value.substring(1)}";
}
List<FitnessState> toList() => elements;
FitnessState? getItem(String? value) {
if (value == null || value.length == 0) {
return elements[0];
}
FitnessState? selected;
elements.forEach((element) {
if (element.value == value) {
selected = element;
}
});
return selected;
}
}

46
lib/model/mautic.dart Normal file
View File

@ -0,0 +1,46 @@
class Mautic {
late int formId;
String? firstname;
String? lastname;
String? email;
String? fitnessLevel;
String? goal;
int? databaseId;
String? subscriptionDate;
String? language;
String? purchaseDate;
String? exerciseDate;
String? trialDate;
Map<String, dynamic> toJson() => {
"formId": formId,
"firstname": firstname,
"lastname": lastname,
"email": email,
"fitnessLevel": fitnessLevel,
"goal": goal,
"databaseId": databaseId,
"subscriptionDate": subscriptionDate,
"lang": language
};
String toForm() {
String form = "mauticform[formId]=$formId";
form += email == null ? "" : "&mauticform[email]=$email";
form += lastname == null ? "" : "&mauticform[f_name]=$lastname";
form += firstname == null ? "" : "&mauticform[firstname]=$firstname";
form += fitnessLevel == null ? "" : "&mauticform[fitness_level]=$fitnessLevel";
form += goal == null ? "" : "&mauticform[goal]=$goal";
form += subscriptionDate == null ? "" : "&mauticform[subscribed]=$subscriptionDate";
form += databaseId == null ? "" : "&mauticform[databaseid]=$databaseId";
form += language == null ? "" : "&mauticform[lang]=$language";
form += purchaseDate == null ? "" : "&mauticform[purchase_date]=$purchaseDate";
form += exerciseDate == null ? "" : "&mauticform[last_exercise]=$exerciseDate";
form += trialDate == null ? "" : "&mauticform[trialdate]=$trialDate";
return form;
}
@override
String toString() => this.toJson().toString();
}

View File

@ -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";
}

53
lib/model/product.dart Normal file
View File

@ -0,0 +1,53 @@
class Product {
late int productId;
late String name;
late String description;
late String type;
late String appVersion;
late int sort;
late int productSet;
late DateTime validFrom;
late DateTime? validTo;
late String? productIdIos;
late String? productIdAndroid;
late double? priceIos;
late double? priceAndroid;
String? localizedPrice;
Product.fromJson(Map json) {
this.productId = json['productId'];
this.name = json['name'];
this.description = json['description'];
this.type = json['type'];
this.appVersion = json['appVersion'];
this.sort = json['sort'];
this.productSet = json['productSet'];
this.validFrom = (json['validFrom'] == null ? null : DateTime.parse(json['validFrom']))!;
this.validTo = json['validTo'] == null ? null : DateTime.parse(json['validTo']);
this.productIdIos = json['productIdIos'];
this.productIdAndroid = json['productIdAndroid'];
this.priceIos = json['priceIos'];
this.priceAndroid = json['priceAndroid'];
}
@override
String toString() {
Map<String, dynamic> json = {
'productId': this.productId,
'name': this.name,
'description': this.description,
'type': this.type,
'appVersion': this.appVersion,
'sort': this.sort,
'productSet': this.productSet,
'validFrom': this.validFrom,
'validTo': validTo,
'productIdIos': this.productIdIos,
'productIdAndroid': this.productIdAndroid,
'priceIos': this.priceIos,
'priceAndroid': this.priceAndroid,
'localizedPrice': this.localizedPrice
};
return json.toString();
}
}

28
lib/model/property.dart Normal file
View File

@ -0,0 +1,28 @@
class Property {
late int propertyId;
late String propertyName;
late String propertyUnit;
late String propertyNameTranslation;
int? top;
int? left;
double? value;
Property.fromJson(Map json) {
this.propertyId = json['propertyId'];
this.propertyName = json['propertyName'];
this.propertyUnit = json['propertyUnit'];
this.propertyNameTranslation =
json['translations'] != null && (json['translations']).length > 0
? json['translations'][0]['propertyName']
: this.propertyName;
}
String toString() {
Map<String, dynamic> json = {
"propertyId": propertyId,
"propertyName": propertyName,
"propertyUnit": propertyUnit
};
return json.toString();
}
}

31
lib/model/purchase.dart Normal file
View File

@ -0,0 +1,31 @@
import 'package:intl/intl.dart';
class Purchase {
int? purchaseId;
late int customerId;
late int productId;
late DateTime dateAdd;
late double purchaseSum;
late String currency;
Purchase({required this.customerId, required this.productId});
Purchase.fromJson(Map json) {
this.purchaseId = json['purchaseId'];
this.customerId = json['customerId'];
this.productId = json['productId'];
this.dateAdd = DateTime.parse(json['dateAdd']);
this.purchaseSum = json['purchaseSum'];
this.currency = json['currency'];
}
Map<String, dynamic> toJson() => {
"purchaseId": purchaseId,
"customerId": customerId,
"productId": productId,
"purchaseSum": purchaseSum,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
"currency": currency,
};
}

101
lib/model/result.dart Normal file
View File

@ -0,0 +1,101 @@
enum ResultItem {
calorie,
development_percent_bodypart,
distance,
fatburn_percent,
bpm_avg,
bpm_min,
bpm_max,
speed_max,
reps_volume,
steps,
//time,
weight_volume
}
extension ResultItemExt on ResultItem {
static const ResultItemDesc = {
ResultItem.calorie: "Calorie",
ResultItem.development_percent_bodypart: "Development in %",
ResultItem.distance: "Distance",
ResultItem.bpm_avg: "Average BPM",
ResultItem.bpm_min: "Min BPM",
ResultItem.bpm_max: "Max BPM",
ResultItem.speed_max: "Max speed",
ResultItem.reps_volume: "Repeats volume",
ResultItem.steps: "Steps",
//ResultItem.time: "Time",
ResultItem.weight_volume: "Weight volume",
ResultItem.fatburn_percent: "Fatburn %",
};
static const ResultItemImg = {
ResultItem.calorie: "pict_calorie.png",
ResultItem.development_percent_bodypart: "pic_development_by_bodypart_percent.png",
ResultItem.distance: "pict_distance_m.png",
ResultItem.bpm_avg: "pict_hravg_bpm.png",
ResultItem.bpm_min: "pict_hrmin_bpm.png",
ResultItem.bpm_max: "pict_hrmax_bpm.png",
ResultItem.speed_max: "pict_maxspeed_kmh.png",
ResultItem.reps_volume: "pict_reps_volumen_db.png",
ResultItem.steps: "pict_steps.png",
//ResultItem.time: "pict_time_h.png",
ResultItem.weight_volume: "pict_weight_volumen_tonna.png",
ResultItem.fatburn_percent: "pict_fatburn_percent.png",
};
static const HardwareData = {
ResultItem.calorie: true,
ResultItem.development_percent_bodypart: false,
ResultItem.distance: true,
ResultItem.bpm_avg: true,
ResultItem.bpm_min: true,
ResultItem.bpm_max: true,
ResultItem.speed_max: true,
ResultItem.reps_volume: false,
ResultItem.steps: true,
//ResultItem.time: false,
ResultItem.weight_volume: false,
ResultItem.fatburn_percent: true,
};
bool equals(ResultItem item) => this.toString() == item.toString();
bool equalsString(String item) => this.description == item;
String? get description => ResultItemDesc[this];
String? get image => ResultItemImg[this];
bool? get isHardware => HardwareData[this];
String? displayString() => description;
}
class ResultExt {
late final String itemString;
late ResultItem item;
double data = 0;
int? exerciseId;
DateTime? dateFrom;
DateTime? dateTo;
ResultExt({required this.itemString}) {
ResultItem.values.forEach((element) {
if (element.equalsString(itemString)) {
item = element;
}
});
}
String? getDescription() => item.description;
String getImage() => "asset/image/" + item.image!;
bool? isHardware() => item.isHardware;
int? get getExerciseId => exerciseId;
set setExerciseId(int exerciseId) => this.exerciseId = exerciseId;
set setDateFrom(DateTime dateFrom) => this.dateFrom = dateFrom;
DateTime? get getDateFrom => dateFrom;
set setDateTo(DateTime dateTo) => this.dateTo = dateTo;
DateTime? get getDateTo => dateTo;
bool equals(ResultItem item) => this.item.equals(item);
bool equalsString(String item) => this.item.equalsString(item);
}

36
lib/model/split_test.dart Normal file
View File

@ -0,0 +1,36 @@
class SplitTest {
late int testId;
late String name;
late String remoteConfigKey;
late String remoteConfigValue;
late String testValue;
String? source;
late bool active;
DateTime? validTo;
SplitTest.fromJson(Map json) {
this.testId = json['testId'];
this.name = json['name'];
this.remoteConfigKey = json['remoteConfigKey'];
this.remoteConfigValue = json['remoteConfigValue'];
this.testValue = json['testValue'];
this.source = json['source'];
this.active = json['active'];
this.validTo = json['validTo'] == null ? null : DateTime.parse(json['validTo']);
}
@override
String toString() {
Map<String, dynamic> json = {
'productId': this.testId,
'name': this.name,
'remoteConfigKey': this.remoteConfigKey,
'remoteConfigValue': this.remoteConfigValue,
'testValue': this.testValue,
'source': this.source,
'active': this.active,
'validTo': validTo,
};
return json.toString();
}
}

30
lib/model/sport.dart Normal file
View File

@ -0,0 +1,30 @@
import 'dart:collection';
class Sport {
late int sportId;
late String name;
HashMap<String, String> nameTranslations = HashMap();
Sport.fromJson(Map json) {
this.sportId = json['sportId'];
this.name = json['name'];
nameTranslations['en'] = name;
if (json['translations'] != null && json['translations'].length > 0) {
json['translations'].forEach((translation) {
nameTranslations[translation['languageCode']] = translation['sportName'];
});
}
}
Map<String, dynamic> toJson() => {
"sportId": sportId,
"name": name,
};
@override
String toString() {
return this.toJson().toString();
}
}

24
lib/model/tracking.dart Normal file
View File

@ -0,0 +1,24 @@
import 'dart:io';
import 'package:workouttest_util/model/cache.dart';
import 'package:intl/intl.dart';
class Tracking {
late int customerId;
late DateTime dateAdd;
late String event;
String? eventValue;
late String area;
late String platform;
late String version;
Map<String, dynamic> toJson() => {
"customerId": customerId,
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
"event": event,
"eventValue": eventValue,
"area": Platform.localeName,
"platform": Platform.isAndroid ? "Android" : "iOS",
"version": Cache().packageInfo != null ? Cache().packageInfo!.version + "+" + Cache().packageInfo!.buildNumber : ""
};
}

View File

@ -0,0 +1,33 @@
import 'package:workouttest_util/model/exercise_plan_detail.dart';
import 'package:workouttest_util/model/exercise_type.dart';
import 'package:flutter/material.dart';
enum TrainingEvaluationExerciseType { weightBased, repeatBased, secondBased }
extension TrainingEvaluationExerciseTypeExt on TrainingEvaluationExerciseType {
String toStr() => this.toString().split(".").last;
bool equalsTo(TrainingEvaluationExerciseType value) => this.toString() == value.toString();
bool equalsStringTo(String value) => this.toString() == value;
}
class TrainingEvaluationExercise {
late int exerciseTypeId;
late String name;
late TrainingEvaluationExerciseType type;
late ExerciseType exerciseType;
int? repeats;
int? maxRepeats;
double? totalLift;
double? maxTotalLift;
double? oneRepMax;
double? max1RM;
late double? trend;
late String trendText;
late Color trendColor;
late ExercisePlanDetailState state;
}

View File

@ -0,0 +1,74 @@
import 'dart:collection';
import 'package:workouttest_util/model/training_plan_detail.dart';
class TrainingPlan {
late int trainingPlanId;
String? type;
late String name;
String? internalName;
String? description;
late bool free;
late bool active;
int? treeId;
HashMap<String, String> nameTranslations = HashMap();
HashMap<String, String> descriptionTranslations = HashMap();
List<TrainingPlanDetail>? details;
TrainingPlan.fromJson(Map<String, dynamic> json) {
this.trainingPlanId = json['trainingPlanId'];
this.name = json['name'];
this.type = json['type'];
this.internalName = json['internalName'];
this.description = json['description'];
this.free = json['free'];
this.active = json['active'];
this.treeId = json['treeId'];
nameTranslations['en'] = name;
descriptionTranslations['en'] = description ?? "";
if (json['translations'] != null && json['translations'].length > 0) {
json['translations'].forEach((translation) {
nameTranslations[translation['languageCode']] = translation['nameTranslation'];
descriptionTranslations[translation['languageCode']] = translation['descriptionTranslation'];
});
}
if (json['details'] != null && json['details'].length > 0) {
details = json['details'].map<TrainingPlanDetail>((detail) => TrainingPlanDetail.fromJson(detail)).toList();
if (details != null && details!.isNotEmpty) {
details!.sort((a, b) {
if (a.sort == 0 || b.sort == 0) {
if (a.trainingPlanDetailId <= b.trainingPlanDetailId) {
return -1;
} else {
return 1;
}
}
if (a.sort <= b.sort) {
return -1;
} else {
return 1;
}
});
}
}
}
Map<String, dynamic> toJson() => {
"trainingPlanId": this.trainingPlanId,
"treeId": this.treeId,
"name": this.name,
"type": this.type,
"internalName": this.internalName,
"free": this.free,
"active": this.active,
"description": this.description,
"nameTranslation": this.nameTranslations.toString(),
};
@override
String toString() => this.toJson().toString();
}

View File

@ -0,0 +1,29 @@
import 'dart:collection';
class TrainingPlanDay {
late int dayId;
late String name;
HashMap<String, String> nameTranslations = HashMap();
TrainingPlanDay.fromJson(Map json) {
this.dayId = json['dayId'];
this.name = json['name'];
nameTranslations['en'] = name;
if (json['translations'] != null && json['translations'].length > 0) {
json['translations'].forEach((translation) {
nameTranslations[translation['languageCode']] = translation['nameTranslation'];
});
}
}
Map<String, dynamic> toJson() => {
"dayId": this.dayId,
"name": this.name,
"nameTranslation": this.nameTranslations.toString(),
};
@override
String toString() => this.toJson().toString();
}

View File

@ -0,0 +1,44 @@
class TrainingPlanDetail {
late int trainingPlanDetailId;
int? trainingPlanId;
late int exerciseTypeId;
late int sort;
late int set;
int? repeats;
double? weight;
int? restingTime;
bool? parallel;
int? dayId;
String? day;
String? summary;
TrainingPlanDetail.fromJson(Map<String, dynamic> json) {
this.trainingPlanDetailId = json['trainingPlanDetailId'];
this.trainingPlanId = json['trainingPlanId'];
this.exerciseTypeId = json['exerciseTypeId'];
this.sort = json['sort'];
this.set = json['set'];
this.repeats = json['repeats'];
this.weight = json['weight'];
this.restingTime = json['restingTime'];
this.parallel = json['parallel'];
this.dayId = json['dayId'];
}
Map<String, dynamic> toJson() => {
"trainingPlanDetailId": this.trainingPlanDetailId,
"trainingPlanId": this.trainingPlanId,
"exerciseType": this.exerciseTypeId,
"sort": this.sort,
"repeats": this.repeats,
"weight": this.weight,
"restingTime": this.restingTime,
"parallel": this.parallel,
"dayId": this.dayId,
"day": this.day,
"summary": this.summary,
};
@override
String toString() => this.toJson().toString();
}

View File

@ -0,0 +1,29 @@
import 'package:workouttest_util/model/exercise.dart';
import 'package:flutter/material.dart';
class TrainingResult {
final Exercise? exercise;
final String eventName;
final DateTime from;
final DateTime to;
Color background;
Color color;
final bool isAllDay;
final bool isTest;
final bool isExercise;
String? summary;
bool search = false;
TrainingResult({
required this.eventName,
required this.from,
required this.to,
required this.background,
required this.color,
required this.isAllDay,
required this.exercise,
required this.isTest,
required this.isExercise,
this.summary,
});
}

37
lib/model/tutorial.dart Normal file
View File

@ -0,0 +1,37 @@
import 'package:workouttest_util/model/tutorial_step.dart';
enum TutorialEnum { basic, development, training }
class Tutorial {
late int tutorialId;
late String name;
List<TutorialStep>? steps;
Tutorial.fromJson(Map<String, dynamic> json) {
this.tutorialId = json['tutorialId'];
this.name = json['name'];
if (json['steps'] != null && json['steps'].length > 0) {
steps = json['steps'].map<TutorialStep>((step) => TutorialStep.fromJson(step)).toList();
if (steps != null) {
steps!.sort((a, b) {
if (a.step == null || b.step == null) {
return -1;
} else {
if (a.step! <= b.step!) {
return -1;
} else {
return 1;
}
}
});
}
}
}
Map<String, dynamic> toJson() => {'tutorialId': this.tutorialId, 'name': this.name, 'steps': steps.toString()};
@override
String toString() => this.toJson().toString();
}

View File

@ -0,0 +1,98 @@
import 'dart:ui';
import 'dart:convert';
import 'package:workouttest_util/util/app_language.dart';
enum TutorialEnum { basic, development, training }
class TutorialStepAction {
late String direction;
late int top;
late int left;
late bool showBubble;
late int bubbleX;
late int bubbleY;
late int bubbleWidth;
late int bubbleHeight;
late bool showCheckText;
late int parent;
TutorialStepAction.fromJson(Map json) {
this.direction = json['direction'];
this.top = json['top'];
this.left = json['left'];
this.showBubble = json['show_bubble'];
this.bubbleX = json['bubble_x'];
this.bubbleY = json['bubble_y'];
this.bubbleWidth = json['bubble_width'];
this.bubbleHeight = json['bubble_height'];
this.showCheckText = json['show_check_text'];
this.parent = json['parent'];
}
Map<String, dynamic> toJson() => {
"direction": this.direction,
"top": this.top,
"left": this.left,
"showBubble": this.showBubble,
"bubbleX": this.bubbleX,
"bubbleY": this.bubbleY,
"bubbleWidth": this.bubbleWidth,
"bubbleHeight": this.bubbleHeight,
"showCheckText": this.showCheckText,
"parent": this.parent,
};
@override
String toString() => this.toJson().toString();
}
class TutorialStep {
int? tutorialStepId;
int? tutorialId;
int? step;
String? tutorialText;
String? direction;
String? checkText;
String? condition;
String? branch;
int? parentId;
TutorialStepAction? action;
String? tutorialTextTranslation;
String? errorTextTranslation;
TutorialStep.fromJson(Map json) {
this.tutorialStepId = json['tutorialStepId'];
this.tutorialId = json['tutorialId'];
this.step = json['step'];
this.tutorialText = json['tutorialText'];
this.checkText = json['checkText'];
this.condition = json['condition'];
if (this.condition != null) {
this.condition = condition!.replaceAll(r'\\', "replace");
this.action = TutorialStepAction.fromJson(jsonDecode(condition!));
}
if (json['translations'] != null && json['translations'].length > 0) {
this.tutorialTextTranslation =
AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['tutorialText'] : json['tutorialText'];
this.errorTextTranslation = AppLanguage().appLocal == Locale('hu') ? json['translations'][0]['errorText'] : json['errorText'];
}
}
Map<String, dynamic> toJson() => {
"tutorialStepId": this.tutorialStepId,
"tutorialId": this.tutorialId,
"step": this.step,
"tutorialText": this.tutorialText,
"checkText": this.checkText,
"tutorialTextTranslation": this.tutorialTextTranslation,
"errorTextTranslation": this.errorTextTranslation,
"condition": this.condition,
"action": this.action != null ? this.action!.toJson() : ""
};
@override
String toString() => this.toJson().toString();
}

14
lib/model/user.dart Normal file
View File

@ -0,0 +1,14 @@
class User {
String? email;
String? password;
int? customerId;
String? firebaseUid;
User();
Map<String, dynamic> toJson() => {
"username": email,
"password": password,
"firebaseUid": firebaseUid,
};
}

View File

@ -0,0 +1,86 @@
import 'dart:ui';
import 'exercise_type.dart';
enum WorkoutType { endurance, oneRepMax, cardio, staticExercise }
extension WorkoutTypeExt on WorkoutType {
static const WorkoutTypeMenu = {
WorkoutType.endurance: "Endurance",
WorkoutType.cardio: "Cardio",
WorkoutType.oneRepMax: "One Rep Max",
WorkoutType.staticExercise: "Static"
};
bool equals(WorkoutType type) => this.toString() == type.toString();
bool equalsString(String type) => this.toString() == type;
String? get menu => WorkoutTypeMenu[this];
}
class WorkoutMenuTree {
late int id;
late int parent;
late String name;
late String imageName;
late Color color;
late double fontSize;
late bool child;
late int exerciseTypeId;
ExerciseType? exerciseType;
late bool base;
late bool is1RM;
late bool isRunning;
List<WorkoutType> workoutTypes = [];
bool selected = false;
bool executed = false;
late String exerciseDetail;
late String nameEnglish;
late String parentName;
late String parentNameEnglish;
late int sort;
late String internalName;
WorkoutMenuTree(
this.id,
this.parent,
this.name,
this.imageName,
this.color,
this.fontSize,
this.child,
this.exerciseTypeId,
this.exerciseType,
this.base,
this.is1RM,
this.isRunning,
this.nameEnglish,
this.parentName,
this.parentNameEnglish,
this.sort,
this.internalName);
Map<String, dynamic> toJson() {
return {
"id": id,
"parent": parent,
"name": name,
"imageName": imageName,
"color": color.toString(),
"fontSize": fontSize.toString(),
"child": child.toString(),
"exerciseTypeId": exerciseTypeId.toString(),
"base": base.toString(),
"is1RM": is1RM.toString(),
"isRunning": isRunning.toString(),
"sort": sort,
"internalName": internalName,
};
}
@override
String toString() {
return this.toJson().toString();
}
}

View File

@ -0,0 +1,74 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/customer_exercise_device.dart';
import 'package:workouttest_util/model/exercise_device.dart';
import 'package:workouttest_util/model/model_change.dart';
import 'package:workouttest_util/service/customer_exercise_device_service.dart';
class CustomerExerciseDeviceRepository {
List<CustomerExerciseDevice> _devices = [];
List<CustomerExerciseDevice> getDevices() => this._devices;
void setDevices(List<CustomerExerciseDevice> devices) => this._devices = devices;
Future<List<CustomerExerciseDevice>?> getDBDevices() async {
if (Cache().userLoggedIn != null) {
final int customerId = Cache().userLoggedIn!.customerId!;
this._devices = await CustomerExerciseDeviceApi().getDevices(customerId);
}
return this._devices;
}
Future<void> addDevice(ExerciseDevice device) async {
CustomerExerciseDevice? found;
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;
CustomerExerciseDevice saved = await CustomerExerciseDeviceApi().addDevice(newDevice);
this._devices.add(saved);
Cache().setCustomerDevices(_devices);
}
}
Future<void> removeDevice(ExerciseDevice device) async {
CustomerExerciseDevice? found;
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;
this._devices.forEach((element) {
if (element.exerciseDeviceId == exerciseDeviceId) {
found = true;
}
});
return found;
}
}

View File

@ -0,0 +1,573 @@
import 'dart:collection';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/customer.dart';
import 'package:workouttest_util/model/customer_property.dart';
import 'package:workouttest_util/model/property.dart';
import 'package:workouttest_util/model/purchase.dart';
import 'package:workouttest_util/model/sport.dart';
import 'package:workouttest_util/repository/property_repository.dart';
import 'package:workouttest_util/service/customer_service.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:workouttest_util/service/purchase_service.dart';
import 'package:workouttest_util/util/enums.dart';
class GenderItem {
GenderItem(this.dbValue, this.name);
final String dbValue;
String name;
}
class CustomerRepository with Logging {
Customer? customer;
Customer? _trainee;
List<Customer>? _trainees;
List<CustomerProperty>? _properties;
//List<CustomerProperty>? _allCustomerProperties;
final PropertyRepository propertyRepository = PropertyRepository();
final List<Property> womanSizes = [];
final List<Property> manSizes = [];
final double baseWidth = 312;
final double baseHeight = 675.2;
double mediaWidth = 0;
double mediaHeight = 0;
bool isMan = true;
//List<CustomerRepository> customerList = List<CustomerRepository>();
bool visibleDetails = false;
late List<GenderItem> genders;
CustomerRepository() {
customer = Customer();
if (Cache().userLoggedIn != null) {
isMan = (Cache().userLoggedIn!.sex == "m");
}
//_allCustomerProperties = Cache().getCustomerPropertyAll();
}
String? getGenderByName(String name) {
String? dbValue;
genders.forEach((element) {
if (element.name == name) {
dbValue = element.dbValue;
}
});
return dbValue;
}
String? getGenderByDBValue(String dbValue) {
String? name;
genders.forEach((element) {
if (element.dbValue == dbValue) {
name = element.name;
}
});
return name;
}
String? get name {
return this.customer != null && this.customer!.name != null ? this.customer!.name : "";
}
String? get firstName {
return this.customer != null && this.customer!.firstname != null ? this.customer!.firstname : "";
}
String get sex {
if (this.customer == null) throw Exception("Initialize the customer object");
return this.customer!.sex == "m" ? "Man" : "Woman";
}
int? get birthYear {
if (this.customer == null) throw Exception("Initialize the customer object");
return this.customer!.birthYear;
}
String? get goal {
if (this.customer == null) throw Exception("Initialize the customer object");
return this.customer!.goal;
}
String? getSportString() {
if (this.customer == null) throw Exception("Initialize the customer object");
String? sport;
List<Sport>? sports = Cache().getSports();
if (sports != null) {
for (Sport sportObject in sports) {
if (sportObject.sportId == this.customer!.sportId) {
sport = sportObject.name;
break;
}
}
}
return sport;
}
Sport? getSport() {
if (this.customer == null) throw Exception("Initialize the customer object");
Sport? sport;
List<Sport>? sports = Cache().getSports();
if (sports != null) {
for (Sport sportObject in sports) {
if (sportObject.sportId == this.customer!.sportId) {
sport = sportObject;
break;
}
}
}
return sport;
}
String? get fitnessLevel {
if (this.customer == null) throw Exception("Initialize the customer object");
return this.customer!.fitnessLevel;
}
String? get bodyType {
if (this.customer == null) throw Exception("Initialize the customer object");
return this.customer!.bodyType;
}
setName(String name) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.name = name;
}
setFirstName(String firstName) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.firstname = firstName;
}
setPassword(String password) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.password = password;
}
setEmail(String email) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.email = email;
}
setSex(String sex) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.sex = sex;
}
setWeight(double weight) {
final propertyName = "Weight";
this.setCustomerProperty(propertyName, weight);
}
setHeight(int height) {
final propertyName = "Height";
this.setCustomerProperty(propertyName, height.toDouble());
}
setCustomerProperty(String propertyName, double value, {id = 0}) {
if (this.customer == null) {
throw Exception("Initialize the customer object");
}
if (this.customer!.properties[propertyName] == null) {
this.customer!.properties[propertyName] = CustomerProperty(
propertyId: propertyRepository.getPropertyByName("Height")!.propertyId,
customerId: this.customer!.customerId == null ? 0 : this.customer!.customerId!,
propertyValue: value,
dateAdd: DateTime.now());
} else {
this.customer!.properties[propertyName]!.propertyValue = value;
}
this.customer!.properties[propertyName]!.dateAdd = DateTime.now();
this.customer!.properties[propertyName]!.newData = true;
if (id > 0) {
this.customer!.properties[propertyName]!.customerPropertyId = id;
}
Cache().addCustomerProperty(this.customer!.properties[propertyName]!);
}
double getWeight() {
return getCustomerPropertyValue("Weight");
}
double getHeight() {
return getCustomerPropertyValue("Height");
}
double getCustomerPropertyValue(String propertyName) {
if (this.customer == null || this.customer!.properties[propertyName] == null) {
return 0.0;
} else {
return this.customer!.properties[propertyName]!.propertyValue;
}
}
CustomerProperty? getCustomerProperty(String propertyName) {
if (this.customer == null) throw Exception("Initialize the customer object");
return this.customer!.properties[propertyName];
}
setBirthYear(int birthYear) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.birthYear = birthYear;
}
setFitnessLevel(String level) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.fitnessLevel = level;
}
setGoal(String goal) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.goal = goal;
}
setSportString(String selectedSport) {
if (this.customer == null) throw Exception("Initialize the customer object");
List<Sport>? sports = Cache().getSports();
if (sports != null) {
for (Sport sportObject in sports) {
if (sportObject.name == selectedSport) {
this.customer!.sportId = sportObject.sportId;
break;
}
}
}
}
setBodyType(String bodyType) {
if (this.customer == null) throw Exception("Initialize the customer object");
this.customer!.bodyType = bodyType;
}
createNew() {
this.customer = Customer();
}
Customer getCustomer() {
if (this.customer == null) throw Exception("Initialize the customer object");
return this.customer!;
}
void setCustomer(Customer customer) {
this.customer = customer;
}
Future<void> addCustomer() async {
if (this.customer == null) throw Exception("Initialize the customer object");
final Customer modelCustomer = customer!;
await CustomerApi().addCustomer(modelCustomer);
}
Future<void> saveCustomer() async {
if (this.customer == null) throw Exception("Initialize the customer object");
final Customer modelCustomer = customer!;
if (modelCustomer.sex == null) {
modelCustomer.sex = "m";
}
if (modelCustomer.fitnessLevel == null) {
modelCustomer.fitnessLevel = "beginner";
}
await CustomerApi().saveCustomer(modelCustomer);
await this.saveProperties(modelCustomer.properties);
}
Future<void> saveProperties(LinkedHashMap<String, CustomerProperty> properties) async {
properties.forEach((propertyName, property) async {
if (property.newData == true) {
await CustomerApi().addProperty(property);
property.newData = false;
}
});
}
Future<void> savePropertyByName(String name) async {
await Future.forEach(this._properties!, (element) async {
final CustomerProperty customerProperty = element as CustomerProperty;
final Property? property = propertyRepository.getPropertyByName(name);
if (property != null) {
if (property.propertyId == customerProperty.propertyId) {
await CustomerApi().updateProperty(customerProperty);
}
}
});
}
Future<Customer?> getTraineeAsCustomer() async {
this._trainee = await CustomerApi().getTrainee(Cache().userLoggedIn!.customerId!);
return _trainee;
}
Future<List<Customer?>?> getTrainees() async {
int trainerId = Cache().userLoggedIn!.customerId!;
final results = await CustomerApi().getTrainees(trainerId);
this._trainees = results;
return results;
}
Future<List<CustomerProperty>> getAllCustomerProperties() async {
int customerId = Cache().userLoggedIn!.customerId!;
final results = await CustomerApi().getAllProperties(customerId);
this._properties = results;
return results;
}
List<CustomerProperty>? getAllProperties() {
return this._properties;
}
List<Customer>? getTraineesList() {
return _trainees;
}
void setTrainee(int traineeId) {
if (_trainees == null) {
return;
}
_trainees!.forEach((element) {
if (traineeId == element.customerId) {
this._trainee = element;
}
});
}
void emptyTrainees() {
_trainees = null;
_trainee = null;
}
Customer? getTrainee() {
return this._trainee;
}
Customer? getTraineeById(int customerId) {
if (_trainees == null) {
return null;
}
_trainees!.forEach((element) {
if (customerId == element.customerId) {
this._trainee = element;
}
});
return _trainee;
}
Future<List<Purchase>> getPurchase() async {
int customerId = Cache().userLoggedIn!.customerId!;
List<Purchase> purchases = await PurchaseApi().getPurchasesByCustomer(customerId);
return purchases;
}
Future<void> addPurchase(Purchase purchase) async {
await PurchaseApi().savePurchase(purchase);
}
void setMediaDimensions(double width, double height) {
this.mediaHeight = height;
this.mediaWidth = width;
this.addSizes(this.sex);
}
void addSizes(String sex) {
if (this.customer == null) throw Exception("Initialize the customer object");
List<Property>? properties = Cache().getProperties();
if (properties == null) {
return;
}
final double distortionWidth = mediaWidth / baseWidth;
final double distortionHeight = mediaHeight / baseHeight;
if (isMan) {
properties.forEach((element) {
if (element.propertyName == "Shoulder") {
element.top = (122 * distortionHeight).toInt();
element.left = (130 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Shoulder");
manSizes.add(element);
} else if (element.propertyName == "Neck") {
element.top = (68 * distortionHeight).toInt();
element.left = (130 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Neck");
manSizes.add(element);
} else if (element.propertyName == "Biceps") {
element.top = (178 * distortionHeight).toInt();
element.left = (208 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Biceps");
manSizes.add(element);
} else if (element.propertyName == "Chest") {
element.top = (154 * distortionHeight).toInt();
element.left = (130 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Chest");
manSizes.add(element);
} else if (element.propertyName == "Belly") {
element.top = (244 * distortionHeight).toInt();
element.left = (130 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Belly");
manSizes.add(element);
} else if (element.propertyName == "Hip") {
element.top = (308 * distortionHeight).toInt();
element.left = (130 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Hip");
manSizes.add(element);
} else if (element.propertyName == "Thigh Top") {
element.top = (332 * distortionHeight).toInt();
element.left = (165 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Thigh Top");
manSizes.add(element);
} else if (element.propertyName == "Thigh Middle") {
element.top = (382 * distortionHeight).toInt();
element.left = (100 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Thigh Middle");
manSizes.add(element);
} else if (element.propertyName == "Knee") {
element.top = (464 * distortionHeight).toInt();
element.left = (97 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Knee");
manSizes.add(element);
} else if (element.propertyName == "Calf") {
element.top = (520 * distortionHeight).toInt();
element.left = (97 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Calf");
manSizes.add(element);
} else if (element.propertyName == "Ankle") {
element.top = (620 * distortionHeight).toInt();
element.left = (150 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Ankle");
manSizes.add(element);
} else if (element.propertyName == "Weight") {
element.top = (402 * distortionHeight).toInt();
element.left = (240 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Weight");
manSizes.add(element);
}
});
} else {
properties.forEach((element) {
if (element.propertyName == "Shoulder") {
element.top = (122 * distortionHeight).toInt();
element.left = (151 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Shoulder");
manSizes.add(element);
} else if (element.propertyName == "Neck") {
element.top = (78 * distortionHeight).toInt();
element.left = (151 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Neck");
manSizes.add(element);
} else if (element.propertyName == "Biceps") {
element.top = (178 * distortionHeight).toInt();
element.left = (212 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Biceps");
manSizes.add(element);
} else if (element.propertyName == "Chest") {
element.top = (154 * distortionHeight).toInt();
element.left = (151 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Chest");
manSizes.add(element);
} else if (element.propertyName == "Belly") {
element.top = (230 * distortionHeight).toInt();
element.left = (151 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Belly");
manSizes.add(element);
} else if (element.propertyName == "Hip") {
element.top = (294 * distortionHeight).toInt();
element.left = (151 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Hip");
manSizes.add(element);
} else if (element.propertyName == "Thigh Top") {
element.top = (335 * distortionHeight).toInt();
element.left = (185 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Thigh Top");
manSizes.add(element);
} else if (element.propertyName == "Thigh Middle") {
element.top = (377 * distortionHeight).toInt();
element.left = (125 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Thigh Middle");
manSizes.add(element);
} else if (element.propertyName == "Knee") {
element.top = (468 * distortionHeight).toInt();
element.left = (129 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Knee");
manSizes.add(element);
} else if (element.propertyName == "Calf") {
element.top = (525 * distortionHeight).toInt();
element.left = (129 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Calf");
manSizes.add(element);
} else if (element.propertyName == "Ankle") {
element.top = (620 * distortionHeight).toInt();
element.left = (162 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Ankle");
manSizes.add(element);
} else if (element.propertyName == "Weight") {
element.top = (402 * distortionHeight).toInt();
element.left = (240 * distortionWidth).toInt();
element.value = this.customer!.getProperty("Weight");
manSizes.add(element);
}
});
}
}
int? getWeightCoordinate(isMan, {isTop = false, isLeft = false}) {
int? value = 0;
this.manSizes.forEach((element) {
if (element.propertyName == SizesEnum.Weight.toStr()) {
if (isTop == true) {
value = element.top;
} else if (isLeft == true) {
value = element.left;
}
}
});
return value;
}
Property? getPropertyByName(String propertyName) {
Property? property;
List<Property> sizes;
if (this.sex == "m") {
sizes = this.manSizes;
} else {
sizes = this.womanSizes;
}
sizes.forEach((element) {
if (element.propertyName == propertyName) {
property = element;
}
});
return property;
}
void updateSizes(String propertyName, double value) {
List<Property> sizes;
if (this.sex == "m") {
sizes = this.manSizes;
} else {
sizes = this.womanSizes;
}
sizes.forEach((element) {
if (element.propertyName == propertyName) {
element.value = value;
}
});
}
List<CustomerProperty> getAllCustomerPropertyByName(String propertyName) {
List<CustomerProperty> allProperties = [];
Property? property = propertyRepository.getPropertyByName(propertyName);
print(property);
if (property == null || Cache().getCustomerPropertyAll() == null) {
return allProperties;
}
Cache().getCustomerPropertyAll()!.forEach((element) {
if (element.propertyId == property.propertyId) {
allProperties.add(element);
}
});
return allProperties;
}
}

View File

@ -0,0 +1,52 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/exercise_device.dart';
import 'package:workouttest_util/service/exercise_device_service.dart';
class ExerciseDeviceRepository {
List<ExerciseDevice> _devices = [];
List<ExerciseDevice> getDevices() {
return this._devices;
}
void setDevices(List<ExerciseDevice> list) {
_devices = list;
}
Future<List<ExerciseDevice>> getDBDevices() async {
this._devices = await ExerciseDeviceApi().getDevices();
return this._devices;
}
bool isGym(int deviceId) {
bool isGym = false;
_devices.forEach((element) {
isGym = isGymElement(element.name);
});
return isGym;
}
bool isGymElement(String name) {
return name == "Cable" ||
name == "Baar" ||
name == "Gym Machine" ||
name == "Dumbbells" ||
name == "Barbell" ||
name == "HOME" ||
name == "STREET";
}
List<ExerciseDevice> getGymDevices() {
if (Cache().getDevices() == null) return [];
final List<ExerciseDevice> gymDevices = [];
if (_devices.isEmpty) {
_devices = Cache().getDevices()!;
}
_devices.forEach((element) {
if (isGymElement(element.name)) {
gymDevices.add(element);
}
});
return gymDevices;
}
}

View File

@ -0,0 +1,538 @@
import 'dart:collection';
import 'package:workouttest_util/util/app_language.dart';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/customer.dart';
import 'package:workouttest_util/model/exercise.dart';
import 'package:workouttest_util/model/exercise_type.dart';
import 'package:workouttest_util/model/workout_menu_tree.dart';
import 'package:workouttest_util/service/exercise_service.dart';
// ignore: depend_on_referenced_packages
import 'package:intl/intl.dart';
class ExerciseRepository {
Exercise? exercise;
Customer? customer;
ExerciseType? exerciseType;
List<Exercise>? exerciseList;
List<Exercise>? exerciseLogList = [];
List<Exercise>? actualExerciseList = [];
bool noRegistration = false;
double rmWendler = 0;
double rmMcglothlin = 0;
double rmLombardi = 0;
double rmMayhew = 0;
double rmOconner = 0;
double rmWathen = 0;
DateTime? start;
DateTime? end;
ExerciseRepository() {
this.createNew();
}
createNew() {
this.exercise = Exercise();
exercise!.dateAdd = DateTime.now();
}
setQuantity(double quantity) {
if (this.exercise == null) {
this.createNew();
}
this.exercise!.quantity = quantity;
}
setUnitQuantity(double unitQuantity) {
if (this.exercise == null) {
this.createNew();
}
this.exercise!.unitQuantity = unitQuantity;
}
setUnit(String unit) {
if (this.exercise == null) {
this.createNew();
}
this.exercise!.unit = unit;
}
setDatetimeExercise(DateTime datetimeExercise) {
if (this.exercise == null) {
this.createNew();
}
this.exercise!.dateAdd = datetimeExercise;
}
double? get unitQuantity => this.exercise!.unitQuantity;
double? get quantity => this.exercise!.quantity;
Exercise? getExercise() => this.exercise;
Future<Exercise> addExercise() async {
if (this.customer == null) {
throw Exception("Please log in");
}
final Exercise modelExercise = this.exercise!;
modelExercise.customerId = this.customer!.customerId;
modelExercise.exerciseTypeId = this.exerciseType!.exerciseTypeId;
if (exerciseType!.unitQuantity != "1") {
modelExercise.unitQuantity = null;
}
Exercise copy = modelExercise.copy();
this.actualExerciseList!.add(copy);
//final int index = this.actualExerciseList.length - 1;
//print("$index. actual exercise " + this.actualExerciseList[index].toJson().toString());
Exercise savedExercise = await ExerciseApi().addExercise(modelExercise);
//this.actualExerciseList[index].exerciseId = savedExercise.exerciseId;
if (customer!.customerId == Cache().userLoggedIn!.customerId) {
Cache().addExercise(savedExercise);
} else if (Cache().getTrainee() != null && customer!.customerId == Cache().getTrainee()!.customerId) {
Cache().addExerciseTrainee(savedExercise);
}
return savedExercise;
}
void addExerciseNoRegistration() {
final Exercise modelExercise = this.exercise!;
modelExercise.exerciseTypeId = this.exerciseType!.exerciseTypeId;
if (exerciseType!.unitQuantity != "1") {
modelExercise.unitQuantity = null;
}
Exercise copy = modelExercise.copy();
this.actualExerciseList!.add(copy);
this.exerciseList = [];
this.exerciseList!.add(copy);
this.noRegistration = true;
}
void initExercise() {
this.createNew();
this.exerciseType = exerciseType;
this.setUnit(exerciseType!.unit);
exercise!.exerciseTypeId = this.exerciseType!.exerciseTypeId;
this.setQuantity(12);
this.setUnitQuantity(30);
this.exercise!.exercisePlanDetailId = 0;
exercise!.exerciseId = 0;
this.start = DateTime.now();
}
Future<void> deleteExercise(Exercise exercise) async {
await ExerciseApi().deleteExercise(exercise);
}
setCustomer(Customer customer) => this.customer = customer;
setExerciseType(ExerciseType exerciseType) => this.exerciseType = exerciseType;
Future<List<Exercise>> getExercisesByCustomer(int customerId) async {
final results = await ExerciseApi().getExercisesByCustomer(customerId);
this.exerciseList = results;
if (Cache().userLoggedIn != null) {
if (customerId == Cache().userLoggedIn!.customerId) {
Cache().setExercises(exerciseList!);
} else if (Cache().getTrainee() != null && customerId == Cache().getTrainee()!.customerId) {
Cache().setExercisesTrainee(exerciseList!);
}
}
return this.exerciseList!;
}
List<Exercise>? getExerciseList() {
this.exerciseList = Cache().getExercises();
return this.exerciseList;
}
List<Exercise>? getExerciseListTrainee() {
this.exerciseList = Cache().getExercisesTrainee();
return this.exerciseList;
}
String? nextMissingBaseExercise(SplayTreeMap sortedTree) {
if (exerciseList == null) {
exerciseList = Cache().getExercises();
}
if (exerciseList == null) {
return null;
}
String? missingTreeName;
String? foundTreeName;
bool isBreak = false;
sortedTree.forEach((key, list) {
List<WorkoutMenuTree> listByMuscle = list as List<WorkoutMenuTree>;
String treeName = key as String;
treeName = treeName.substring(3);
foundTreeName = null;
listByMuscle.forEach((exercise) {
if (missingTreeName == null) {
missingTreeName = treeName;
}
if (exercise.base) {
if (exerciseList != null) {
exerciseList!.forEach((element) {
if (element.exerciseTypeId == exercise.exerciseTypeId) {
foundTreeName = treeName;
//print("Found " + foundTreeName + " Missing actual: " + missingTreeName);
isBreak = true;
}
});
}
}
});
if (foundTreeName == null && !isBreak) {
missingTreeName = treeName;
isBreak = true;
}
});
return missingTreeName;
}
void getBaseExerciseFinishedPercent() {
List<int> checkedExerciseTypeId = [];
List<int> baseTreeItem = [];
List<int> checkedBaseTreeItem = [];
int count1RMExercises = 0;
LinkedHashMap<String, WorkoutMenuTree> tree = Cache().getWorkoutMenuTree();
if (tree.isEmpty) {
return;
}
tree.forEach((key, value) {
WorkoutMenuTree treeItem = value;
if (treeItem.exerciseType != null && treeItem.exerciseType!.base == true && !baseTreeItem.contains(treeItem.parent)) {
baseTreeItem.add(treeItem.parent);
}
});
if (exerciseList == null) {
exerciseList = Cache().getExercises();
}
if (exerciseList == null) {
return;
}
exerciseList!.forEach((element) {
Exercise exercise = element;
if (!checkedExerciseTypeId.contains(exercise.exerciseTypeId)) {
checkedExerciseTypeId.add(exercise.exerciseTypeId!);
tree.forEach((key, value) {
WorkoutMenuTree treeItem = value;
if (treeItem.exerciseType != null &&
treeItem.exerciseType!.base == true &&
exercise.exerciseTypeId == treeItem.exerciseType!.exerciseTypeId &&
!checkedBaseTreeItem.contains(treeItem.parent)) {
//print ("id: " + exercise.exerciseTypeId.toString());
checkedBaseTreeItem.add(treeItem.parent);
count1RMExercises++;
}
});
}
});
//print ("checkedExerciseTypeid: " + checkedExerciseTypeId.toString());
//print ("baseTreeItem: " + baseTreeItem.toString());
//print ("count1RMExercises: " + count1RMExercises.toString());
final double percent = count1RMExercises / baseTreeItem.length;
Cache().setPercentExercises(percent);
}
void getLastExercise() {
List<Exercise>? exercises = this.getExerciseList();
Exercise? lastExercise = exercises == null ? null : exercises[0];
if (exercises != null) {
exercises.forEach((element) {
Exercise actualExercise = element;
if (actualExercise.dateAdd!.compareTo(lastExercise!.dateAdd!) > 0) {
lastExercise = actualExercise;
}
});
}
this.exercise = lastExercise;
this.customer = Cache().userLoggedIn!;
this.exerciseType = getExerciseTypeById(exercise!.exerciseTypeId!);
return;
}
ExerciseType? getExerciseTypeById(int exerciseTypeId) {
ExerciseType? actualExerciseType;
List<ExerciseType>? exercises = Cache().getExerciseTypes();
if (exercises != null) {
exercises.forEach((element) {
ExerciseType exerciseType = element;
if (exerciseType.exerciseTypeId == exerciseTypeId) {
actualExerciseType = exerciseType;
}
});
}
if (actualExerciseType == null) {
throw Exception("Data error, no ExerciseType for exerciseTypeId $exerciseTypeId");
}
return actualExerciseType;
}
void getSameExercise(int exerciseTypeId, String day) {
if (!this.noRegistration) {
this.actualExerciseList = [];
}
if (exerciseList != null) {
int index = 0;
for (int i = 0; i < this.exerciseList!.length; i++) {
Exercise exercise = exerciseList![i];
final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
if (exerciseTypeId == exercise.exerciseTypeId && exerciseDate == day && index < 4) {
this.actualExerciseList!.add(exercise);
index++;
}
}
}
}
double calculate1RM(Exercise exercise) {
double weight = exercise.unitQuantity!;
double repeat = exercise.quantity!;
if (weight == 0 || repeat == 0) {
return 0;
}
double rmWendler = weight * repeat * 0.0333 + weight;
double rmOconner = weight * (1 + repeat / 40);
double average = (rmWendler + rmOconner) / 2;
return average;
}
double getBest1RM(Exercise exercise) {
double result = 0;
if (this.exerciseList == null || this.exerciseList!.isEmpty) {
this.exerciseList = Cache().getExercises();
}
final int exerciseTypeId = exercise.exerciseTypeId!;
double toCompare = this.calculate1RM(exercise);
result = toCompare;
final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(DateTime.now());
List<Exercise> oldExercises = [];
if (exerciseList == null) {
return toCompare;
}
this.exerciseList!.forEach((exercise) {
final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) {
oldExercises.add(exercise);
}
});
if (oldExercises.isNotEmpty) {
oldExercises.sort((a, b) {
double sumA = 0;
double sumB = 0;
if (a.unitQuantity != null && b.unitQuantity != null) {
sumA = a.quantity! * a.unitQuantity!;
sumB = b.quantity! * b.unitQuantity!;
} else {
sumA = a.quantity!;
sumB = b.quantity!;
}
return sumA >= sumB ? 1 : -1;
});
double withCompare = this.calculate1RM(oldExercises.last);
//result = toCompare >= withCompare ? (1 - toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100;
result = toCompare >= withCompare ? toCompare : withCompare;
}
return result;
}
double getLast1RMPercent(Exercise exercise) {
double result = 0;
if (this.exerciseList == null || this.exerciseList!.isEmpty) {
this.exerciseList = Cache().getExercises();
}
final int exerciseTypeId = exercise.exerciseTypeId!;
double toCompare = this.calculate1RM(exercise);
final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
List<Exercise> oldExercises = [];
if (exerciseList == null) {
return result;
}
this.exerciseList!.forEach((exercise) {
final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) {
oldExercises.add(exercise);
}
});
if (oldExercises.isNotEmpty) {
double withCompare = this.calculate1RM(oldExercises.first);
result = toCompare >= withCompare ? (toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100;
}
return result;
}
double getBestVolume(Exercise exercise) {
double result = 0;
if (this.exerciseList == null || this.exerciseList!.isEmpty) {
this.exerciseList = Cache().getExercises();
}
final int exerciseTypeId = exercise.exerciseTypeId!;
double toCompare = exercise.unitQuantity != null ? exercise.quantity! * exercise.unitQuantity! : exercise.quantity!;
result = toCompare;
final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(DateTime.now());
List<Exercise> oldExercises = [];
if (exerciseList == null) {
return toCompare;
}
this.exerciseList!.forEach((exercise) {
final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) {
oldExercises.add(exercise);
}
});
if (oldExercises.isNotEmpty) {
oldExercises.sort((a, b) {
double sumA = 0;
double sumB = 0;
if (a.unitQuantity != null && b.unitQuantity != null) {
sumA = a.quantity! * a.unitQuantity!;
sumB = b.quantity! * b.unitQuantity!;
} else {
sumA = a.quantity!;
sumB = b.quantity!;
}
return sumA >= sumB ? 1 : -1;
});
double withCompare =
oldExercises.last.unitQuantity != null ? oldExercises.last.quantity! * oldExercises.last.unitQuantity! : oldExercises.last.quantity!;
//result = toCompare >= withCompare ? (1 - toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100;
//print("Last Best: ${oldExercises.last} - result: $result");
result = toCompare >= withCompare ? toCompare : withCompare;
}
return result;
}
double getLastExercisePercent(Exercise exercise) {
double result = 0;
if (this.exerciseList == null || this.exerciseList!.isEmpty) {
this.exerciseList = Cache().getExercises();
}
final int exerciseTypeId = exercise.exerciseTypeId!;
double toCompare = exercise.unitQuantity != null ? exercise.quantity! * exercise.unitQuantity! : exercise.quantity!;
final String today = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
List<Exercise> oldExercises = [];
if (exerciseList == null) {
return result;
}
this.exerciseList!.forEach((exercise) {
final String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
if (exercise.exerciseTypeId == exerciseTypeId && exerciseDate.compareTo(today) < 0) {
oldExercises.add(exercise);
}
});
if (oldExercises.isNotEmpty) {
double withCompare =
oldExercises.first.unitQuantity != null ? oldExercises.first.quantity! * oldExercises.first.unitQuantity! : oldExercises.first.quantity!;
result = toCompare >= withCompare ? (toCompare / withCompare) * 100 : (1 - toCompare / withCompare) * -100;
print("Last Last: ${oldExercises.first} vs. $exercise - - result: $result");
}
return result;
}
void sortByDate() {
if (exerciseList == null || exerciseList!.isEmpty) {
return;
}
exerciseList!.sort((a, b) {
final String datePartA = DateFormat('yyyyMMdd', AppLanguage().appLocal.toString()).format(a.dateAdd!);
String aId = datePartA + "_" + a.exerciseTypeId.toString();
final String datePartB = DateFormat('yyyyMMdd', AppLanguage().appLocal.toString()).format(b.dateAdd!);
String bId = datePartB + "_" + b.exerciseTypeId.toString();
return bId.compareTo(aId);
});
this.exerciseLogList = [];
String summary = "";
String prevDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exerciseList![0].dateAdd!);
int prevExerciseTypeId = exerciseList![0].exerciseTypeId!;
Exercise prevExercise = exerciseList![0];
int prevCount = 0;
for (int i = 0; i < this.exerciseList!.length; i++) {
Exercise exercise = exerciseList![i];
int exerciseTypeId = exercise.exerciseTypeId!;
String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd!);
//print(" -- $prevExerciseTypeId - '$prevDate' against $exerciseTypeId - '$exerciseDate'");
if (exerciseTypeId != prevExerciseTypeId || prevDate != exerciseDate) {
ExerciseType? exerciseType = Cache().getExerciseTypeById(prevExercise.exerciseTypeId!);
String unit = exerciseType != null && exerciseType.unitQuantityUnit != null ? exerciseType.unitQuantityUnit! : prevExercise.unit!;
prevExercise.summary = summary + " " + unit;
exerciseLogList!.add(prevExercise);
//print("Log add " + exercise.toJson().toString());
summary = "";
prevCount = 0;
}
String delimiter = "";
if (prevCount > 0) delimiter = ", ";
double quantity = exercise.quantity == null ? 0 : exercise.quantity!;
summary += delimiter + quantity.toStringAsFixed(0);
ExerciseType? exerciseType = Cache().getExerciseTypeById(exercise.exerciseTypeId!);
//print("exerciseType " + (exerciseType == null ? "NULL" : exerciseType.name) + " ID " + exercise.exerciseTypeId.toString());
if (exerciseType != null) {
if (exerciseType.unitQuantity == "1") {
summary += "x" + exercise.unitQuantity!.toStringAsFixed(0);
}
//print(" --- sum " + exerciseType.name + " $summary");
}
prevExerciseTypeId = exerciseTypeId;
prevDate = exerciseDate;
prevExercise = exercise;
prevCount++;
}
prevExercise.summary = summary;
exerciseLogList!.add(prevExercise);
}
List<Exercise> getExercisesByExerciseTypeId(int exerciseTypeId) {
List<Exercise> list = [];
List<Exercise>? allExercise = Cache().getExercises();
if (allExercise == null) {
return list;
}
allExercise.forEach((element) {
if (element.exerciseTypeId == exerciseTypeId) {
list.add(element);
}
});
return list;
}
}

View File

@ -0,0 +1,26 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/exercise_type.dart';
import 'package:workouttest_util/util/logging.dart';
class ExerciseTypeRepository with Logging {
static List<ExerciseType> getExerciseTypeAlternatives(int? exerciseTypeId) {
if (exerciseTypeId == null || exerciseTypeId <= 0) {
return [];
}
List<ExerciseType> list = [];
List<ExerciseType>? exerciseTypes = Cache().getExerciseTypes();
if (exerciseTypes != null) {
exerciseTypes.forEach((exerciseType) {
if (exerciseType.alternatives.isNotEmpty) {
exerciseType.alternatives.forEach((childId) {
if (childId == exerciseTypeId) {
list.add(exerciseType);
}
});
}
});
}
return list;
}
}

View File

@ -0,0 +1,93 @@
// ignore: depend_on_referenced_packages
import 'package:intl/intl.dart';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/mautic.dart';
import 'package:workouttest_util/repository/customer_repository.dart';
import 'package:workouttest_util/service/mautic.dart';
import 'package:workouttest_util/util/app_language.dart';
class MauticRepository {
final CustomerRepository customerRepository;
const MauticRepository({required this.customerRepository});
Future<void> sendMauticSubscription() async {
Mautic mautic = Mautic();
mautic.formId = 2;
mautic.databaseId = Cache().userLoggedIn!.customerId!;
mautic.firstname = customerRepository.customer!.firstname == null ? "" : customerRepository.customer!.firstname!;
mautic.lastname = customerRepository.customer!.name == null ? "" : customerRepository.customer!.name!;
mautic.email = customerRepository.customer!.email == null ? "" : customerRepository.customer!.email!;
if (mautic.email == null || mautic.email!.contains("privaterelay.appleid.com")) {
return;
}
mautic.fitnessLevel = customerRepository.customer!.fitnessLevel == null ? "" : customerRepository.customer!.fitnessLevel!;
mautic.goal = customerRepository.customer!.goal == null ? "" : customerRepository.customer!.goal!;
mautic.subscriptionDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
mautic.language = AppLanguage().appLocal.languageCode;
await MauticApi().sendMauticForm(mautic);
customerRepository.customer!.syncedDate = DateTime.now();
await customerRepository.saveCustomer();
}
Future<void> sendMauticDataChange() async {
Mautic mautic = Mautic();
mautic.formId = 3;
mautic.databaseId = Cache().userLoggedIn!.customerId!;
mautic.firstname = customerRepository.customer!.firstname == null ? "" : customerRepository.customer!.firstname!;
mautic.lastname = customerRepository.customer!.name == null ? "" : customerRepository.customer!.name!;
mautic.email = customerRepository.customer!.email == null ? "" : customerRepository.customer!.email!;
if (mautic.email == null || mautic.email!.contains("privaterelay.appleid.com")) {
return;
}
mautic.fitnessLevel = customerRepository.customer!.fitnessLevel == null ? "" : customerRepository.customer!.fitnessLevel!;
mautic.goal = customerRepository.customer!.goal == null ? "" : customerRepository.customer!.goal!;
mautic.language = AppLanguage().appLocal.languageCode;
await MauticApi().sendMauticForm(mautic);
}
Future<void> sendMauticPurchase() async {
Mautic mautic = Mautic();
mautic.formId = 4;
mautic.firstname = customerRepository.customer!.firstname == null ? "" : customerRepository.customer!.firstname!;
mautic.lastname = customerRepository.customer!.name == null ? "" : customerRepository.customer!.name!;
mautic.email = customerRepository.customer!.email == null ? "" : customerRepository.customer!.email!;
if (mautic.email == null || mautic.email!.contains("privaterelay.appleid.com")) {
return;
}
mautic.purchaseDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
await MauticApi().sendMauticForm(mautic);
}
Future<void> sendMauticExercise() async {
Mautic mautic = Mautic();
mautic.formId = 5;
mautic.firstname = customerRepository.customer!.firstname == null ? "" : customerRepository.customer!.firstname!;
mautic.lastname = customerRepository.customer!.name == null ? "" : customerRepository.customer!.name!;
mautic.email = customerRepository.customer!.email == null ? "" : customerRepository.customer!.email!;
if (mautic.email == null || mautic.email!.contains("privaterelay.appleid.com")) {
return;
}
mautic.exerciseDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
mautic.databaseId = Cache().userLoggedIn!.customerId!;
await MauticApi().sendMauticForm(mautic);
}
Future<void> sendMauticTrial() async {
Mautic mautic = Mautic();
mautic.formId = 6;
mautic.email = customerRepository.customer!.email == null ? "" : customerRepository.customer!.email!;
if (mautic.email == null || mautic.email!.contains("privaterelay.appleid.com")) {
return;
}
mautic.trialDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(DateTime.now());
mautic.databaseId = Cache().userLoggedIn!.customerId!;
await MauticApi().sendMauticForm(mautic);
}
}

View File

@ -0,0 +1,31 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/property.dart';
import 'package:workouttest_util/service/property_service.dart';
class PropertyRepository {
List<Property>? _properties;
Future<List<Property>?> getDBProperties() async {
this._properties = await PropertyApi().getProperties();
return this._properties;
}
List<Property>? getProperties() {
return this._properties;
}
Property? getPropertyByName(String name) {
Property? property;
if (_properties == null) {
_properties = Cache().getProperties();
}
if (_properties != null) {
this._properties!.forEach((element) {
if (name == element.propertyName) {
property = element;
}
});
}
return property;
}
}

View File

@ -0,0 +1,35 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/training_plan.dart';
import 'package:workouttest_util/util/app_language.dart';
class TrainingPlanDayRepository {
const TrainingPlanDayRepository();
void assignTrainingPlanDays() {
List<TrainingPlan>? plans = Cache().getTrainingPlans();
if (plans == null) {
return;
}
plans.forEach((plan) {
if (plan.details != null) {
plan.details!.forEach((element) {
element.day = this.getNameById(element.dayId);
});
}
});
}
String? getNameById(int? dayId) {
if (dayId == null) {
return "";
}
String? name;
for (var day in Cache().getTrainingPlanDays()) {
if (day.dayId == dayId) {
name = day.nameTranslations[AppLanguage().appLocal.languageCode];
break;
}
}
return name;
}
}

View File

@ -0,0 +1,448 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/customer_training_plan.dart';
import 'package:workouttest_util/model/customer_training_plan_details.dart';
import 'package:workouttest_util/model/exercise.dart';
import 'package:workouttest_util/model/exercise_plan_detail.dart';
import 'package:workouttest_util/model/exercise_tree.dart';
import 'package:workouttest_util/model/fitness_state.dart';
import 'package:workouttest_util/model/training_plan.dart';
import 'package:workouttest_util/model/training_plan_detail.dart';
import 'package:workouttest_util/repository/exercise_type_repository.dart';
import 'package:workouttest_util/repository/training_plan_day_repository.dart';
import 'package:workouttest_util/util/app_language.dart';
import 'package:workouttest_util/util/common.dart';
class TrainingPlanRepository with Common {
ExerciseTree? parentTree;
List<TrainingPlan> getPlansByParent(String parent) {
final List<TrainingPlan> resultList = [];
final List<ExerciseTree>? exerciseTree = Cache().getExerciseTree();
int? parentId;
if (exerciseTree != null) {
exerciseTree.forEach((element) {
if (element.internalName == parent) {
parentId = element.treeId;
parentTree = element;
}
});
}
final List<TrainingPlan>? plans = Cache().getTrainingPlans();
if (plans != null && parentId != null) {
plans.forEach((element) {
if (element.treeId == parentId) {
resultList.add(element);
}
});
}
return resultList;
}
/// 1. deactivate old training plans - update all
/// 2. calculate customer_training_plan_details weights / repleats
/// 3. create new customer_training_plan
CustomerTrainingPlan? activateTrainingPlan(int trainingPlanId) {
print(" **** Activate Plan: $trainingPlanId");
// 1. deactivate
if (Cache().getCustomerTrainingPlans() != null) {
Cache().getCustomerTrainingPlans()!.forEach((plan) {
plan.active = false;
if (plan.customerTrainingPlanId != null) {
//TrainingPlanApi().updateCustomerTrainingPlan(plan, plan.customerTrainingPlanId!);
}
});
}
CustomerTrainingPlan plan = CustomerTrainingPlan();
plan.customerId = Cache().userLoggedIn!.customerId;
plan.trainingPlanId = trainingPlanId;
plan.active = true;
plan.status = "open";
plan.dateAdd = DateTime.now();
TrainingPlan? trainingPlan = this.getTrainingPlanById(trainingPlanId);
if (trainingPlan == null || trainingPlan.details == null) {
print("trainingPlan null");
return null;
}
plan.name = trainingPlan.nameTranslations[AppLanguage().appLocal.toString()];
// 3 calculate weights
int index = 0;
int exerciseTypeIdOrig = 0;
trainingPlan.details!.forEach((elem) {
List<CustomerTrainingPlanDetails> list = createDetail(plan, elem, exerciseTypeIdOrig, index);
exerciseTypeIdOrig = elem.exerciseTypeId;
list.forEach((element) {
plan.details.add(element);
index++;
});
});
Cache().myTrainingPlan = plan;
return plan;
}
CustomerTrainingPlanDetails? getDetailById(CustomerTrainingPlan? plan, int customerTrainingPlanDetailsId) {
CustomerTrainingPlanDetails? foundDetail;
if (plan == null || plan.details.length == 0 || customerTrainingPlanDetailsId == 0) {
return foundDetail;
}
for (var detail in plan.details) {
if (detail.customerTrainingPlanDetailsId == customerTrainingPlanDetailsId) {
foundDetail = detail;
break;
}
}
return foundDetail;
}
CustomerTrainingPlanDetails createAlternativeDetail(
CustomerTrainingPlan plan, CustomerTrainingPlanDetails detail, TrainingPlanDetail elem, int exerciseTypeId) {
CustomerTrainingPlanDetails alternativeDetail = CustomerTrainingPlanDetails();
alternativeDetail.copy(detail);
alternativeDetail.exerciseTypeId = exerciseTypeId;
alternativeDetail.exerciseType = Cache().getExerciseTypeById(exerciseTypeId);
if (elem.weight == -1) {
if (alternativeDetail.exerciseType!.unitQuantityUnit != null) {
alternativeDetail = getCalculatedWeightRepeats(elem.exerciseTypeId, alternativeDetail);
} else {
alternativeDetail.weight = 0;
}
} else if (elem.weight == -2) {
final CustomerTrainingPlanDetails calculated = this.isWeightCalculatedByExerciseType(elem.exerciseTypeId, alternativeDetail, plan);
if (calculated.weight != -1) {
alternativeDetail.weight = calculated.weight;
} else {
alternativeDetail.weight = -2;
}
} else {
alternativeDetail.weight = elem.weight;
}
//print("Detail $alternativeDetail exerciseType: ${alternativeDetail.exerciseType!.exerciseTypeId}");
return alternativeDetail;
}
List<CustomerTrainingPlanDetails> createDetail(CustomerTrainingPlan plan, TrainingPlanDetail elem, int exerciseTypeIdOrig, int index,
{bool changeExerciseType = false}) {
List<CustomerTrainingPlanDetails> list = [];
CustomerTrainingPlanDetails detail = CustomerTrainingPlanDetails();
detail.customerTrainingPlanDetailsId = ++index;
detail.trainingPlanDetailsId = elem.trainingPlanDetailId;
detail.exerciseTypeId = changeExerciseType ? exerciseTypeIdOrig : elem.exerciseTypeId;
detail.repeats = elem.repeats;
detail.set = elem.set;
detail.dayId = elem.dayId;
TrainingPlanDayRepository trainingPlanDayRepository = TrainingPlanDayRepository();
detail.day = trainingPlanDayRepository.getNameById(elem.dayId);
detail.parallel = elem.parallel;
detail.restingTime = elem.restingTime;
detail.exerciseType = Cache().getExerciseTypeById(detail.exerciseTypeId!);
detail.alternatives = ExerciseTypeRepository.getExerciseTypeAlternatives(detail.exerciseTypeId);
if (elem.weight == -1) {
if (detail.exerciseType!.unitQuantityUnit != null) {
detail = getCalculatedWeightRepeats(elem.exerciseTypeId, detail);
} else {
detail.weight = 0;
}
} else if (elem.weight == -2) {
final CustomerTrainingPlanDetails calculated = this.isWeightCalculatedByExerciseType(elem.exerciseTypeId, detail, plan);
if (calculated.weight != -1) {
detail.weight = calculated.weight;
} else {
detail.weight = -2;
}
} else {
detail.weight = elem.weight;
}
print("Detail $detail exerciseType: ${detail.exerciseType!.exerciseTypeId}");
detail.state = ExercisePlanDetailState.start;
if (detail.weight != null && detail.weight! > 0) {
detail.baseOneRepMax = calculate1RM(detail.weight!, detail.repeats!.toDouble());
}
// first repeat: 50% more
if (detail.weight != null && detail.weight! > 0 && exerciseTypeIdOrig != detail.exerciseTypeId && detail.repeats! > 0) {
CustomerTrainingPlanDetails firstDetail = CustomerTrainingPlanDetails();
firstDetail.copy(detail);
firstDetail.repeats = (detail.repeats! * 1.5).round();
firstDetail.baseOneRepMax = calculate1RM(firstDetail.weight!, firstDetail.repeats!.toDouble());
firstDetail.set = 1;
detail.set = detail.set! - 1;
if (detail.set! > 0) {
index++;
}
detail.customerTrainingPlanDetailsId = index;
list.add(firstDetail);
}
if (detail.set! > 0) {
list.add(detail);
}
return list;
}
CustomerTrainingPlanDetails isWeightCalculatedByExerciseType(int exerciseTypeId, CustomerTrainingPlanDetails detail, CustomerTrainingPlan plan) {
CustomerTrainingPlanDetails calculated = detail;
for (var element in plan.details) {
if (element.exerciseTypeId == exerciseTypeId) {
calculated = element;
break;
}
}
return calculated;
}
TrainingPlan? getTrainingPlanById(int trainingPlanId) {
TrainingPlan? plan;
if (Cache().getTrainingPlans() == null) {
return plan;
}
for (var trainingPlan in Cache().getTrainingPlans()!) {
if (trainingPlan.trainingPlanId == trainingPlanId) {
plan = trainingPlan;
break;
}
}
return plan;
}
int? getTrainingPlanByInternalName(String internalName) {
int? id;
if (Cache().getTrainingPlans() == null) {
return id;
}
for (var trainingPlan in Cache().getTrainingPlans()!) {
//print("internal ${trainingPlan.internalName}");
if (trainingPlan.internalName == internalName) {
id = trainingPlan.trainingPlanId;
break;
}
}
return id;
}
CustomerTrainingPlanDetails getCalculatedWeightRepeats(int exerciseTypeId, CustomerTrainingPlanDetails detail) {
double weight = -1;
if (Cache().getExercises() == null) {
detail.weight = weight;
detail.isTest = true;
return detail;
}
Exercise? lastExercise1RM;
DateTime dt = DateTime.now().subtract(Duration(days: 30));
List<Exercise> exercises = Cache().getExercises()!;
exercises.sort((a, b) {
// reverse
return a.dateAdd!.compareTo(b.dateAdd!);
});
exercises.forEach((exercise) {
if (exercise.exerciseTypeId == exerciseTypeId && exercise.dateAdd!.compareTo(dt) >= 0) {
detail.weight = weight;
lastExercise1RM = exercise;
//print("last exercise: $exercise");
}
});
if (lastExercise1RM == null || lastExercise1RM!.unitQuantity == null) {
detail.weight = weight;
detail.isTest = true;
return detail;
}
double oneRepMax = calculateMax1RMSameDay(lastExercise1RM!);
// Common.calculate1RM(lastExercise1RM!.unitQuantity!, lastExercise1RM!.quantity!);
//print("Exercise $exerciseTypeId - 1RM : $oneRepMax");
weight = oneRepMax * Common.get1RMPercent(detail.repeats!);
//print("Exercise $exerciseTypeId - weight : $weight");
//weight = Common.roundWeight(weight);
//detail.weight = Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), lastExercise1RM!.quantity!);
//weight = lastExercise1RM!.unitQuantity! * detail.repeats! / lastExercise1RM!.quantity!;
weight = Common.roundWeight(weight);
//print("Recaluclated weight ${detail.weight} - repeat: ${detail.repeats}");
//detail.repeats = Common.calculateQuantityByChangedWeight(oneRepMax, weight, detail.repeats!.toDouble());
detail.weight = weight;
return detail;
}
double calculateMax1RMSameDay(Exercise actual) {
List<Exercise> exercises = Cache().getExercises()!;
double max1RM = 0.0;
exercises.forEach((exercise) {
if (actual.exerciseTypeId == exercise.exerciseTypeId &&
actual.dateAdd!.year == exercise.dateAdd!.year &&
actual.dateAdd!.month == exercise.dateAdd!.month &&
actual.dateAdd!.day == exercise.dateAdd!.day) {
double oneRepMax = calculate1RM(exercise.unitQuantity!, exercise.quantity!);
if (max1RM < oneRepMax) {
max1RM = oneRepMax;
}
}
});
return max1RM;
}
int getOriginalRepeats(int trainingPlanId, CustomerTrainingPlanDetails detail) {
TrainingPlan? plan = getTrainingPlanById(trainingPlanId);
if (plan == null) {
return 0;
}
int originalRepeats = 0;
plan.details!.forEach((element) {
if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) {
originalRepeats = element.repeats ?? 0;
}
});
return originalRepeats;
}
double getOriginalWeight(int trainingPlanId, CustomerTrainingPlanDetails detail) {
TrainingPlan? plan = getTrainingPlanById(trainingPlanId);
if (plan == null) {
return 0;
}
double originalWeight = 0;
plan.details!.forEach((element) {
if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) {
originalWeight = element.weight ?? 0;
}
});
return originalWeight;
}
CustomerTrainingPlanDetails recalculateDetailFixRepeats(int trainingPlanId, CustomerTrainingPlanDetails detail) {
TrainingPlan? plan = getTrainingPlanById(trainingPlanId);
if (plan == null) {
return detail;
}
int originalRepeats = getOriginalRepeats(trainingPlanId, detail);
detail.weight = Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), originalRepeats.toDouble());
detail.weight = Common.roundWeight(detail.weight!);
print("Recalculated weight: ${detail.weight}");
detail.repeats = originalRepeats;
return detail;
}
CustomerTrainingPlanDetails recalculateDetailFixRepeatsSet1(
int trainingPlanId, CustomerTrainingPlanDetails detail, CustomerTrainingPlanDetails detailWithData) {
TrainingPlan? plan = getTrainingPlanById(trainingPlanId);
if (plan == null) {
return detail;
}
int originalRepeats = getOriginalRepeats(trainingPlanId, detail);
detail.weight = Common.calculateWeigthByChangedQuantity(detailWithData.weight!, detailWithData.repeats!.toDouble(), originalRepeats.toDouble());
detail.weight = Common.roundWeight(detail.weight!);
print("Recalculated weight: ${detail.weight}");
detail.repeats = originalRepeats;
return detail;
}
CustomerTrainingPlanDetails recalculateDetail(int trainingPlanId, CustomerTrainingPlanDetails detail, CustomerTrainingPlanDetails nextDetail) {
CustomerTrainingPlanDetails recalculatedDetail = nextDetail;
// 1. get original repeats
// 1a get original plan
TrainingPlan? plan = getTrainingPlanById(trainingPlanId);
if (plan == null) {
return recalculatedDetail;
}
// 1.b get the original detail's repeat
int originalRepeats = detail.repeats!;
plan.details!.forEach((element) {
if (element.trainingPlanDetailId == detail.trainingPlanDetailsId) {
originalRepeats = element.repeats ?? 0;
}
});
// 2 get recalculated repeats
recalculatedDetail.weight = Common.calculateWeigthByChangedQuantity(detail.weight!, detail.repeats!.toDouble(), originalRepeats.toDouble());
recalculatedDetail.weight = Common.roundWeight(recalculatedDetail.weight!);
print("recalculated repeats for $originalRepeats: ${recalculatedDetail.weight}");
//recalculatedDetail.repeats = originalRepeats;
return recalculatedDetail;
}
void generateTrainingPlan() {
int? trainingPlanId;
if (Cache().userLoggedIn == null) {
return;
}
bool isWoman = Cache().userLoggedIn!.sex == "w";
if (Cache().userLoggedIn!.goal == "shape_forming") {
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L1") : getTrainingPlanByInternalName("man_routine1");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L2") : getTrainingPlanByInternalName("man_routine3");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L3") : getTrainingPlanByInternalName("man_routine4");
} else {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("women_shape_L4") : getTrainingPlanByInternalName("man_routine2");
}
} else if (Cache().userLoggedIn!.goal == "muscle_endurance") {
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l1") : getTrainingPlanByInternalName("man_se_l1");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l2") : getTrainingPlanByInternalName("man_se_l2");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l3") : getTrainingPlanByInternalName("man_se_l3");
} else {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_se_l4") : getTrainingPlanByInternalName("man_se_l4");
}
} else if (Cache().userLoggedIn!.goal == "gain_strength") {
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l1") : getTrainingPlanByInternalName("man_power_l1");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l2") : getTrainingPlanByInternalName("man_power_l2");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l3") : getTrainingPlanByInternalName("man_power_l3");
} else {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_power_l4") : getTrainingPlanByInternalName("man_power_l4");
}
} else if (Cache().userLoggedIn!.goal == "gain_muscle") {
if (Cache().userLoggedIn!.fitnessLevel == FitnessState.beginner) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner") : getTrainingPlanByInternalName("beginner_man");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.intermediate) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_beginner_split") : getTrainingPlanByInternalName("man_foundation");
} else if (Cache().userLoggedIn!.fitnessLevel == FitnessState.advanced) {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("woman_advanced") : getTrainingPlanByInternalName("basic_mass_building");
} else {
trainingPlanId = isWoman ? getTrainingPlanByInternalName("man_routine2") : getTrainingPlanByInternalName("mass_building");
}
}
print("Generated plan $trainingPlanId fitness ${Cache().userLoggedIn!.fitnessLevel} - ${FitnessState.beginner}");
if (trainingPlanId != null) {
CustomerTrainingPlan? customerTrainingPlan = activateTrainingPlan(trainingPlanId);
if (customerTrainingPlan != null) {
Cache().myTrainingPlan = customerTrainingPlan;
Cache().saveMyTrainingPlan();
}
}
}
}

View File

@ -0,0 +1,224 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/user.dart';
import 'package:workouttest_util/service/customer_service.dart';
import 'package:workouttest_util/service/firebase_api.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:workouttest_util/util/not_found_exception.dart';
import 'package:firebase_auth/firebase_auth.dart' as auth;
class UserRepository with Logging {
late User user;
UserRepository() {
this.createNewUser();
}
setEmail(String email) {
this.user.email = email;
}
setPassword(String password) {
this.user.password = password;
}
createNewUser() {
this.user = User();
}
Future<void> addUser() async {
final User modelUser = this.user;
try {
String rc = await FirebaseApi().registerEmail(modelUser.email!, modelUser.password!);
if (rc == FirebaseApi.SIGN_IN_OK) {
modelUser.firebaseUid = Cache().firebaseUid;
await CustomerApi().addUser(modelUser);
}
} catch (e) {
final String message = e.toString();
log(message);
if (message.contains("CERT_ALREADY_IN_HASH_TABLE")) {
} else {
throw new Exception(e);
}
}
}
Future<void> addUserFB() async {
final User modelUser = this.user;
try {
Map<String, dynamic> userData = await FirebaseApi().registerWithFacebook();
modelUser.email = userData['email'];
if (modelUser.email == null) {
throw new Exception("Facebook signup was not successful. Please try another method");
}
modelUser.password = Cache().firebaseUid;
modelUser.firebaseUid = Cache().firebaseUid;
await CustomerApi().addUser(modelUser);
} on auth.FirebaseAuthException catch (e) {
if (e.code == 'email-already-in-use') {
log('The account already exists for that email.');
throw Exception("The email address has been registered already");
} else if (e.code == 'weak-password') {
log('The password provided is too weak.');
throw Exception("Password too short");
} else if (e.code == 'account-exists-with-different-credential') {
log(e.code);
throw Exception("The account exists with different credential");
} else {
print(e.code);
throw Exception(e);
}
} on WorkoutTestException catch (ex) {
if (ex.code == WorkoutTestException.CUSTOMER_EXISTS) {
log('The account already exists for that email.');
throw Exception("The email address has been registered already");
}
} on Exception catch (ex) {
log("FB exception: " + ex.toString());
throw Exception("Facebook Sign In failed");
}
}
Future<void> addUserGoogle() async {
final User modelUser = this.user;
try {
Map<String, dynamic> userData = await FirebaseApi().registerWithGoogle();
modelUser.email = userData['email'];
if (modelUser.email == null) {
throw new Exception("Google signup was not successful. Please try another method");
}
modelUser.password = Cache().firebaseUid;
modelUser.firebaseUid = Cache().firebaseUid;
await CustomerApi().addUser(modelUser);
} on auth.FirebaseAuthException catch (e) {
if (e.code == 'email-already-in-use') {
log('The account already exists for that email.');
throw Exception("The email address has been registered already");
} else {
throw Exception(e);
}
} on WorkoutTestException catch (ex) {
if (ex.code == WorkoutTestException.CUSTOMER_EXISTS) {
log('The account already exists for that email.');
throw Exception("The email address has been registered already");
}
} on Exception catch (ex) {
log("Google exception: " + ex.toString());
throw Exception("Google Sign In failed");
}
}
Future<void> addUserApple() async {
final User modelUser = this.user;
try {
Map<String, dynamic> userData = await FirebaseApi().registerWithApple();
modelUser.email = userData['email'];
if (modelUser.email == null) {
throw new Exception("Apple signup was not successful. Please try another method");
}
modelUser.password = Cache().firebaseUid;
modelUser.firebaseUid = Cache().firebaseUid;
await CustomerApi().addUser(modelUser);
} on auth.FirebaseAuthException catch (e) {
if (e.code == 'email-already-in-use') {
log('The account already exists for that email.');
throw Exception("The email address has been registered already");
}
} on WorkoutTestException catch (ex) {
if (ex.code == WorkoutTestException.CUSTOMER_EXISTS) {
log('The account already exists for that email.');
throw Exception("The email address has been registered already");
}
} on Exception catch (ex) {
log("Apple exception: " + ex.toString());
throw Exception(ex);
}
}
Future<void> getUserByFB() async {
final User modelUser = this.user;
try {
Map<String, dynamic> userData = await FirebaseApi().signInWithFacebook();
modelUser.email = userData['email'];
await CustomerApi().getUserByEmail(modelUser.email!);
await Cache().afterFirebaseLogin();
} /* on FacebookAuthException catch (e) {
switch (e.errorCode) {
case FacebookAuthErrorCode.OPERATION_IN_PROGRESS:
throw Exception("You have a previous Facebook login operation in progress");
break;
case FacebookAuthErrorCode.CANCELLED:
throw Exception("Facebook login cancelled");
break;
case FacebookAuthErrorCode.FAILED:
throw Exception("Facebook login failed");
break;
}
} */
on NotFoundException catch (ex) {
log("FB exception: " + ex.toString());
throw Exception("Customer does not exist or the password is wrong");
} on Exception catch (e) {
log(e.toString());
throw new Exception(e);
}
}
Future<void> getUserByGoogle() async {
final User modelUser = this.user;
try {
Map<String, dynamic> userData = await FirebaseApi().signInWithGoogle();
if (userData['email'] == null) {
throw new Exception("Google login was not successful");
}
modelUser.email = userData['email'];
await CustomerApi().getUserByEmail(modelUser.email!);
await Cache().afterFirebaseLogin();
} on Exception catch (ex) {
log("Google exception: " + ex.toString());
throw Exception(ex);
}
}
Future<void> getUserByApple() async {
final User modelUser = this.user;
Map<String, dynamic> userData = await FirebaseApi().signInWithApple();
if (userData['email'] == null) {
throw new Exception("Apple login was not successful");
}
modelUser.email = userData['email'];
try {
await CustomerApi().getUserByEmail(modelUser.email!);
await Cache().afterFirebaseLogin();
} on Exception catch (ex) {
log("Apple exception: " + ex.toString());
throw Exception("Customer does not exist or the password is wrong");
}
}
Future<void> getUser() async {
final User modelUser = this.user;
String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password);
try {
if (rc == FirebaseApi.SIGN_IN_OK) {
await CustomerApi().getUserByEmail(modelUser.email!);
await Cache().afterFirebaseLogin();
} else {
log("Exception: user not found or password is wrong");
throw Exception("Customer does not exist or the password is wrong");
}
} on NotFoundException catch (_) {
throw Exception("Customer does not exist or the password is wrong");
}
}
Future<void> resetPassword() async {
final User modelUser = this.user;
await FirebaseApi().resetPassword(modelUser.email!);
}
}

141
lib/service/api.dart Normal file
View File

@ -0,0 +1,141 @@
import 'dart:convert';
import 'dart:io';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:workouttest_util/util/common.dart';
import 'package:workouttest_util/util/not_found_exception.dart';
import 'package:flutter/services.dart';
import 'package:workouttest_util/model/cache.dart';
class APIClient with Common, Logging {
static final APIClient _singleton = APIClient._internal();
late bool cert;
factory APIClient() {
return _singleton;
}
APIClient._internal() {
cert = false;
}
dynamic authenticateUser(String email, String password) async {
var url = Cache().getBaseUrl() + "authenticate";
try {
ByteData data = await rootBundle.load('asset/data/aitrainer_server.crt.pem');
SecurityContext context = SecurityContext.defaultContext;
if (cert == false) {
print("Set CERT $cert");
context.setTrustedCertificatesBytes(data.buffer.asUint8List(), password: "[xxxx]");
cert = true;
}
HttpClient client = new HttpClient(); //context: context Todo provide the right certificate
client.badCertificateCallback = ((X509Certificate cert, String host, int port) {
print("Host: $host Port: $port");
return true;
});
var uri = Uri.parse(url);
final HttpClientRequest request = await client.postUrl(uri);
request.headers.set('Content-Type', 'application/json');
request.headers.set('Authorization', '1');
final body = '{"username":"$email", "password":"$password"}';
request.write(body);
HttpClientResponse result = await request.close();
client.close();
if (result.statusCode != 200) {
trace("authentication response: ${result.statusCode} with URL: $url");
throw Exception("Authentication error: ${result.statusCode}");
}
return jsonDecode(await result.transform(utf8.decoder).join());
} catch (exception) {
print(exception.toString());
try {
await Sentry.captureException(exception);
} on Exception catch (e) {
print(e);
}
throw Exception("Network error, try again later!");
}
}
Future<String> post(String endPoint, String body) async {
final url = Cache().getBaseUrl() + endPoint;
trace(" ------------ http/post body $body - url: $url ");
try {
String authToken = Cache().getAuthToken();
if (authToken.length == 0) {
var responseJson = await this.authenticateUser(Cache.username, Cache.password);
authToken = responseJson['token'];
Cache().authToken = authToken;
}
var uri = Uri.parse(url);
HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
final HttpClientRequest request = await client.postUrl(uri);
request.headers.contentType = new ContentType("application", "json", charset: "utf-8");
request.headers.set('Authorization', 'Bearer $authToken');
//request.contentLength = body.length;
request.write(body);
HttpClientResponse result = await request.close();
client.close();
trace(" ------------post response code: " + result.statusCode.toString());
if (result.statusCode == 200) {
return await result.transform(utf8.decoder).join();
} else if (result.statusCode == 404) {
throw NotFoundException(message: "Not Found");
} else {
throw Exception("Network Error, please try again later");
}
} on NotFoundException catch(e) {
throw NotFoundException(message: "Not Found");
} on Exception catch (e) {
print("Post Exception: $e");
await Sentry.captureException(e);
throw Exception("Network Error, please try again later");
}
}
Future<String> get(String endPoint, String param) async {
final url = Cache().getBaseUrl() + endPoint + param;
try {
trace("-------- API get " + url);
String authToken = Cache().getAuthToken();
if (authToken.length == 0) {
var responseJson = await this.authenticateUser(Cache.username, Cache.password);
authToken = responseJson['token'];
Cache().authToken = authToken;
}
var uri = Uri.parse(url);
HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
final HttpClientRequest request = await client.getUrl(uri);
request.headers.set('Content-Type', 'application/json');
request.headers.set('Authorization', 'Bearer $authToken');
HttpClientResponse result = await request.close();
client.close();
trace(" ------------get response code: " + result.statusCode.toString());
if (result.statusCode == 200) {
return await result.transform(utf8.decoder).join();
} else if (result.statusCode == 404) {
throw NotFoundException(message: "Not Found");
} else {
throw Exception("Network Error, please try again later");
}
} on NotFoundException catch(e) {
throw NotFoundException(message: "Not Found");
} on Exception catch (e) {
print("Post Exception: $e");
await Sentry.captureException(e);
throw Exception("Network Error, please try again later");
}
}
}

View File

@ -0,0 +1,47 @@
import 'package:workouttest_util/model/customer_exercise_device.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:workouttest_util/util/not_found_exception.dart';
import 'dart:convert';
import 'api.dart';
class CustomerExerciseDeviceApi with Logging {
final APIClient _client = APIClient();
Future<List<CustomerExerciseDevice>> getDevices(int customerId) async {
List<CustomerExerciseDevice> devices = [];
try {
log(" --- get customer_exercise_devices: ");
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 (_) {
log("No devices found");
devices = [];
}
return devices;
}
Future<CustomerExerciseDevice> addDevice(CustomerExerciseDevice device) async {
CustomerExerciseDevice savedDevice;
try {
final String body = JsonEncoder().convert(device.toJson());
log(" --- 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<void> removeDevice(int id) async {
try {
log(" --- 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;
}
}

View File

@ -0,0 +1,240 @@
import 'dart:collection';
import 'dart:convert';
import 'package:workouttest_util/model/customer.dart';
import 'package:workouttest_util/model/customer_property.dart';
import 'package:workouttest_util/model/property.dart';
import 'package:workouttest_util/model/user.dart';
import 'package:workouttest_util/service/api.dart';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:workouttest_util/util/not_found_exception.dart';
class CustomerApi with Logging {
final APIClient _client = APIClient();
Future<List<Customer>> getRealCustomers(String param) async {
final body = await _client.get("customers/", param);
final Iterable json = jsonDecode(body);
final List<Customer> customers = json.map((customer) => Customer.fromJson(customer)).toList();
return customers;
}
Future<void> saveCustomer(Customer customer) async {
customer.dateChange = DateTime.now();
String body = JsonEncoder().convert(customer.toJson());
log(" ===== saving customer id: " + customer.customerId.toString() + ":" + body);
await _client.post("customers/" + customer.customerId.toString(), body);
}
Future<void> updateFirebaseUid(int customerId, String uid) async {
log(" ===== update Firebase uid : " + customerId.toString() + ": " + uid);
await _client.post("customers/update_firebase_uid/" + customerId.toString(), uid);
}
Future<void> deactivateCustomer(int customerId) async {
log(" ===== deactivate : $customerId");
await _client.post("customers/deactivate/$customerId", "");
}
Future<void> addCustomer(Customer customer) async {
customer.dateAdd = DateTime.now();
customer.dateChange = DateTime.now();
String body = JsonEncoder().convert(customer.toJson());
log(" ===== add new customer: " + body);
await _client.post("customers", body);
}
Future<void> addUser(User user) async {
String body = JsonEncoder().convert(user.toJson());
log(" ===== add new user: " + body);
final String responseBody = await _client.post("registration", body);
Customer customer;
try {
int? status = jsonDecode(responseBody)['status'];
if (status != null) {
String error = jsonDecode(responseBody)['error'];
throw new Exception(error);
} else {
customer = Customer.fromJson(jsonDecode(responseBody));
await Cache().afterRegistration(customer);
}
} on FormatException {
if (responseBody == "Customer exists") {
throw WorkoutTestException(code: WorkoutTestException.CUSTOMER_EXISTS, message: responseBody);
}
throw new Exception(responseBody);
}
}
Future<void> getUser(User user) async {
String body = JsonEncoder().convert(user.toJson());
log(" ===== login the user: " + body);
final String responseBody = await _client.post("login", body);
Customer customer;
try {
customer = Customer.fromJson(jsonDecode(responseBody));
await Cache().afterLogin(customer);
} on FormatException {
throw new Exception(responseBody);
}
}
Future<void> getUserByEmail(String email) async {
log(" ===== User getByEmail : " + email);
final String responseBody = await _client.get("customers/find_by_email/" + email, "");
Customer customer;
try {
customer = Customer.fromJson(jsonDecode(responseBody));
if (customer.firebaseUid == null) {
await this.updateFirebaseUid(customer.customerId!, Cache().firebaseUid!);
}
Cache().userLoggedIn = customer;
final List<CustomerProperty>? properties = await this.getActualProperties(customer.customerId!);
if (properties != null) {
this.initProperties(properties);
}
} on FormatException {
throw new Exception(responseBody);
}
}
Future<void> getCustomer(int customerId) async {
String body = "";
log(" ===== get the customer by id: " + customerId.toString());
try {
final String responseBody = await _client.get("customers/" + customerId.toString(), body);
Customer customer = Customer.fromJson(jsonDecode(responseBody));
log(" --- Customer: " + customer.toJson().toString());
Cache().userLoggedIn = customer;
final List<CustomerProperty>? properties = await this.getActualProperties(customerId);
//log(" ---- Props: " + properties.toJson().toString());
//await Cache().initCustomer(customerId);
if (properties != null) {
this.initProperties(properties);
}
} on Exception catch (exception) {
log("Exception: " + exception.toString());
log(" === go to registration ");
Cache().logout();
Cache().startPage = "registration";
}
}
void initProperties(final List<CustomerProperty>? customerProperties) {
List<Property>? properties = Cache().getProperties();
Customer customer = Cache().userLoggedIn!;
customer.properties = LinkedHashMap<String, CustomerProperty>();
if (properties != null) {
// reset Properties
properties.forEach((property) {
CustomerProperty customerProperty =
CustomerProperty(propertyId: property.propertyId, customerId: customer.customerId!, dateAdd: DateTime.now(), propertyValue: 0);
customer.properties[property.propertyName] = customerProperty;
});
customerProperties!.forEach((customerProperty) {
properties.forEach((property) {
if (customerProperty.propertyId == property.propertyId) {
customer.properties[property.propertyName] = customerProperty;
}
});
});
}
}
Future<Customer> getTrainee(int customerId) async {
String body = "";
Customer customer;
log(" ===== get Trainee customer by id: " + customerId.toString());
try {
final String responseBody = await _client.get("customers/" + customerId.toString(), body);
customer = Customer.fromJson(jsonDecode(responseBody));
log(" --- Trainee: " + customer.toJson().toString());
} catch (exception) {
log("Exception: " + exception.toString());
throw Exception(exception);
}
return customer;
}
Future<List<Customer>> getTrainees(int trainerId) async {
List<Customer> trainees = [];
log("Get trainees list");
try {
String body = "";
final String responseBody = await _client.get("customers/trainees/" + trainerId.toString(), body);
final Iterable json = jsonDecode(responseBody);
trainees = json.map((customer) => Customer.fromJson(customer)).toList();
} catch (exception) {
log("Exception: " + exception.toString());
throw Exception(exception);
}
return trainees;
}
Future<List<CustomerProperty>> getAllProperties(int customerId) async {
final body = await _client.get("customer_property/", customerId.toString());
final Iterable json = jsonDecode(body);
final List<CustomerProperty> properties = json.map((property) => CustomerProperty.fromJson(property)).toList();
return properties;
}
Future<List<CustomerProperty>?> getActualProperties(int customerId) async {
List<CustomerProperty>? properties;
try {
final body = await _client.get("customer_property/last/", customerId.toString());
final Iterable json = jsonDecode(body);
properties = json.map((property) => CustomerProperty.fromJson(property)).toList();
} on Exception catch (ex) {
log(ex.toString());
}
return properties;
}
Future<CustomerProperty> addProperty(CustomerProperty property) async {
String body = JsonEncoder().convert(property.toJson());
log(" ===== add new customer property: " + body);
CustomerProperty customerProperty;
String? responseBody;
try {
responseBody = await _client.post("customer_property", body);
log(" responseBody: " + responseBody);
int? status = jsonDecode(responseBody)['status'];
if (status != null) {
throw new Exception(jsonDecode(responseBody)['error']);
} else {
customerProperty = CustomerProperty.fromJson(jsonDecode(responseBody));
}
} on FormatException {
throw new Exception(responseBody);
} on Exception catch (e) {
throw new Exception(e);
}
return customerProperty;
}
Future<CustomerProperty> updateProperty(CustomerProperty property) async {
String body = JsonEncoder().convert(property.toJson());
CustomerProperty? customerProperty;
log(" ===== update customer property: " + body);
String? responseBody;
try {
responseBody = await _client.post("customer_property/update/" + property.customerPropertyId.toString(), body);
log(" responseBody: " + responseBody);
int? status = jsonDecode(responseBody)['status'];
if (status != null) {
throw new Exception(jsonDecode(responseBody)['error']);
} else {
customerProperty = CustomerProperty.fromJson(jsonDecode(responseBody));
}
} on FormatException {
throw new Exception(responseBody);
} on Exception catch (e) {
throw new Exception(e);
}
return customerProperty;
}
}

View File

@ -0,0 +1,17 @@
import 'package:workouttest_util/model/cache.dart';
import 'dart:convert';
import 'package:workouttest_util/model/exercise_device.dart';
import 'api.dart';
class ExerciseDeviceApi {
final APIClient _client = APIClient();
Future<List<ExerciseDevice>> getDevices() async {
final body = await _client.get("exercise_device/", "");
final Iterable json = jsonDecode(body);
final List<ExerciseDevice> devices = json.map((device) => ExerciseDevice.fromJson(device)).toList();
Cache().setDevices(devices);
return devices;
}
}

View File

@ -0,0 +1,44 @@
import 'dart:convert';
import 'package:workouttest_util/model/exercise.dart';
import 'package:workouttest_util/service/api.dart';
import 'package:workouttest_util/util/logging.dart';
class ExerciseApi with Logging {
final APIClient _client = APIClient();
Future<void> saveExercise(Exercise exercise) async {
String body = JsonEncoder().convert(exercise.toJson());
log(" ===== saving exercise id: " + exercise.exerciseId.toString() + ":" + body);
await _client.post("exercises/" + exercise.exerciseId.toString(), body);
}
Future<List<Exercise>> getExercisesByCustomer(int customerId) async {
final body = await _client.get("exercises/customer/", customerId.toString());
final Iterable json = jsonDecode(body);
final List<Exercise> exercises = json.map((exercise) {
Exercise item = Exercise.fromJson(exercise);
return item;
}).toList();
//exercises.sort( (a, b) => b.dateAdd.compareTo(a.dateAdd) );
return exercises;
}
Future<Exercise> addExercise(Exercise exercise) async {
String body = JsonEncoder().convert(exercise.toJson());
log(" ===== add new exercise: " + body);
final String response = await _client.post("exercises", body);
final Exercise savedExercise = Exercise.fromJson(jsonDecode(response));
return savedExercise;
}
Future<void> deleteExercise(Exercise exercise) async {
if (exercise.exerciseId == null) {
return;
}
int exerciseId = exercise.exerciseId!;
log(" ===== delete exercise: " + exerciseId.toString());
await _client.post("exercises/" + exerciseId.toString(), "");
return;
}
}

View File

@ -0,0 +1,82 @@
import 'dart:convert';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/exercise_tree.dart';
import 'package:workouttest_util/model/exercise_tree_parents.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:flutter/services.dart';
import 'api.dart';
class ExerciseTreeApi with Logging {
final APIClient _client = APIClient();
Future<List<ExerciseTree>> getExerciseTree() async {
final String body = await _client.get("exercise_tree", "");
Iterable json = jsonDecode(body);
List<ExerciseTree>? exerciseTrees = json.map((exerciseTree) => ExerciseTree.fromJson(exerciseTree)).toList();
exerciseTrees = await getExerciseTreeParents(exerciseTrees);
await Future.forEach(exerciseTrees, (element) async {
ExerciseTree exerciseTree = element as ExerciseTree;
exerciseTree.imageUrl = await buildImage(exerciseTree.imageUrl, exerciseTree.treeId);
});
exerciseTrees = await getExerciseTreeParents(exerciseTrees);
log("ExerciseTree downloaded $exerciseTrees");
Cache().setExerciseTree(exerciseTrees);
return exerciseTrees;
}
Future<String> buildImage(String imageUrl, int treeId) async {
String assetImage = 'asset/menu/' + imageUrl.substring(7);
print("asset image $assetImage");
return await rootBundle.load(assetImage).then((value) {
return assetImage;
}).catchError((_) {
String imagePath = assetImage.substring(10);
String url = Cache.mediaUrl + 'images' + imagePath;
return url;
});
}
Future<List<ExerciseTree>> getExerciseTreeParents(List<ExerciseTree> exerciseTree) async {
List<ExerciseTree> copyList = this.copyList(exerciseTree);
final String body = await _client.get("exercise_tree_parents", "");
Iterable json = jsonDecode(body);
final List<ExerciseTreeParents> exerciseTreeParents =
json.map((exerciseTreeParent) => ExerciseTreeParents.fromJson(exerciseTreeParent)).toList();
int treeIndex = 0;
copyList.forEach((element) async {
int index = 0;
exerciseTreeParents.forEach((parent) {
if (parent.exerciseTreeChildId == element.treeId) {
if (index > 0) {
ExerciseTree newElement = element.copy(parent.exerciseTreeParentId);
newElement.sort = parent.sort;
exerciseTree.add(newElement);
} else {
element.parentId = parent.exerciseTreeParentId;
element.sort = parent.sort;
exerciseTree[treeIndex].parentId = parent.exerciseTreeParentId;
}
index++;
}
});
treeIndex++;
});
return exerciseTree;
}
List<ExerciseTree> copyList(List<ExerciseTree> tree) {
final List<ExerciseTree> copyList = [];
tree.forEach((element) {
final ExerciseTree copy = element.copy(-1);
copyList.add(copy);
});
return copyList;
}
}

View File

@ -0,0 +1,40 @@
import 'dart:convert';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/exercise_type.dart';
import 'package:workouttest_util/service/api.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:flutter/services.dart';
class ExerciseTypeApi with Logging {
final APIClient _client = APIClient();
Future<List<ExerciseType>> getExerciseTypes() async {
final body = await _client.get("exercise_type", "");
final Iterable json = jsonDecode(body);
final List<ExerciseType> exerciseTypes = json.map((exerciseType) => ExerciseType.fromJson(exerciseType)).toList();
await Future.forEach(exerciseTypes, (element) async {
ExerciseType exerciseType = element as ExerciseType;
exerciseType.imageUrl = await buildImage(exerciseType.imageUrl, exerciseType.exerciseTypeId);
});
log("ExerciseTypes downloaded");
Cache().setExerciseTypes(exerciseTypes);
return exerciseTypes;
}
Future<String> buildImage(String imageUrl, int exerciseTypeId) async {
if (imageUrl.length > 8) {
String assetImage = 'asset/menu/' + imageUrl.substring(7);
return rootBundle.load(assetImage).then((value) {
return assetImage;
}).catchError((_) {
String imagePath = assetImage.substring(10);
String url = Cache.mediaUrl + 'images' + imagePath;
return url;
});
} else {
return imageUrl;
}
}
}

View File

@ -0,0 +1,403 @@
import 'dart:math' as math;
import 'dart:convert';
// ignore: depend_on_referenced_packages
import 'package:crypto/crypto.dart';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/util/logging.dart' as logger;
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:firebase_auth/firebase_auth.dart';
// ignore: depend_on_referenced_packages
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class FirebaseApi with logger.Logging {
bool appleSignInAvailable = false;
static final FirebaseAuth auth = FirebaseAuth.instance;
static const String SIGN_IN_OK = "OK";
static const String SIGN_IN_NOT_FOUND = "user-not-found";
static const String SIGN_IN_WRONG_PWD = "wrong-password";
static const String REGISTER_WEAK_PWD = "weak-password";
static const String REGISTER_EMAIL_IN_USE = "email-already-in-use";
late UserCredential userCredential;
String? firebaseRegToken;
factory FirebaseApi() => FirebaseApi._internal();
FirebaseApi._internal();
// Define an async function to initialize FlutterFire
Future<void> initializeFlutterFire() async {
try {
// Wait for Firebase to initialize and set `_initialized` state to true
await Firebase.initializeApp();
this.appleSignInAvailable = await SignInWithApple.isAvailable();
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true, // Required to display a heads up notification
badge: true,
sound: true,
);
this.firebaseRegToken = await FirebaseMessaging.instance.getToken();
Cache().firebaseMessageToken = firebaseRegToken;
log("FirebaseMessaging token $firebaseRegToken");
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
if (message.notification != null) {
print('Message also contained a notification: ${message.notification}');
}
});
} catch (e) {
// Set `_error` state to true if Firebase initialization fails
Sentry.captureException(e);
log("Error initializing Firebase");
}
}
Future<String> signInEmail(String? email, String? password) async {
if (email == null) {
throw Exception("Please type an email address");
}
if (password == null) {
throw Exception("Password too short");
}
String rc = SIGN_IN_OK;
try {
userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password);
Cache().firebaseUid = userCredential.user!.uid;
} on FirebaseAuthException catch (e) {
Sentry.captureException(e);
if (e.code == 'user-not-found') {
log('No user found for that email.');
rc = SIGN_IN_NOT_FOUND;
} else if (e.code == 'wrong-password') {
log('Wrong password provided for that user.');
rc = SIGN_IN_WRONG_PWD;
throw Exception("Customer does not exist or the password is wrong");
}
return e.code;
}
return rc;
}
Future<String> registerEmail(String email, String password) async {
String rc = SIGN_IN_OK;
try {
userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password);
Cache().firebaseUid = userCredential.user!.uid;
} on FirebaseAuthException catch (e) {
Sentry.captureException(e);
if (e.code == 'weak-password') {
log('The password provided is too weak.');
rc = REGISTER_WEAK_PWD;
throw Exception("Password too short");
} else if (e.code == 'email-already-in-use') {
log('The account already exists for that email.');
rc = REGISTER_EMAIL_IN_USE;
throw Exception("The email address has been registered already");
}
} catch (e) {
log(e.toString());
Sentry.captureException(e);
throw Exception(e.toString());
}
return rc;
}
String generateNonce([int length = 32]) {
final charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
final random = math.Random.secure();
return List.generate(length, (_) => charset[random.nextInt(charset.length)]).join();
}
/// Returns the sha256 hash of [input] in hex notation.
String sha256ofString(String input) {
final bytes = utf8.encode(input);
final digest = sha256.convert(bytes);
return digest.toString();
}
Future<Map<String, dynamic>> signInWithApple() async {
Map<String, dynamic> userData = Map();
// To prevent replay attacks with the credential returned from Apple, we
// include a nonce in the credential request. When signing in with
// Firebase, the nonce in the id token returned by Apple, is expected to
// match the sha256 hash of `rawNonce`.
final rawNonce = generateNonce();
final nonce = sha256ofString(rawNonce);
// Request credential for the currently signed in Apple account.
final appleCredential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
nonce: nonce,
);
// Create an `OAuthCredential` from the credential returned by Apple.
final oauthCredential = OAuthProvider("apple.com").credential(
idToken: appleCredential.identityToken,
rawNonce: rawNonce,
);
UserCredential? userCredential;
try {
// Sign in the user with Firebase. If the nonce we generated earlier does
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
} on FirebaseAuthException catch(e) {
Sentry.captureException(e);
throw Exception(e);
}
Cache().firebaseUid = userCredential.user!.uid;
log("userCredential: " + userCredential.toString());
log("Apple Credentials: ${appleCredential.userIdentifier} state ${appleCredential.state} email ${userCredential.user!.email!}");
userData['email'] = userCredential.user!.email;
return userData;
}
Future<Map<String, dynamic>> registerWithApple() async {
Map<String, dynamic> userData = Map();
final rawNonce = generateNonce();
final nonce = sha256ofString(rawNonce);
// Request credential for the currently signed in Apple account.
final appleCredential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
nonce: nonce,
);
final oauthCredential = OAuthProvider("apple.com").credential(
idToken: appleCredential.identityToken,
rawNonce: rawNonce,
);
UserCredential? userCredential;
try {
// Sign in the user with Firebase. If the nonce we generated earlier does
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
} on FirebaseAuthException catch(e) {
Sentry.captureException(e);
throw Exception(e);
}
Cache().firebaseUid = userCredential.user!.uid;
userData['email'] = userCredential.user!.email;
return userData;
}
Future<Map<String, dynamic>> signInWithGoogle() async {
Map<String, dynamic> userData = Map();
// Trigger the authentication flow
GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: [
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
Sentry.captureException(new Exception("Google Sign In failed"));
throw Exception("Google Sign In failed");
}
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
// Create a new credential
final OAuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(credential);
Cache().firebaseUid = userCredential.user!.uid;
log("GoogleUser: " + googleUser.toString());
userData['email'] = googleUser.email;
userData['id'] = googleUser.id;
userData['name'] = googleUser.displayName;
return userData;
}
Future<Map<String, dynamic>> registerWithGoogle() async {
Map<String, dynamic> userData = Map();
// Trigger the authentication flow
GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: [
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
Sentry.captureException(new Exception("Google Sign In failed"));
throw Exception("Google Sign In failed");
}
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
// Create a new credential
final OAuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final userCredential = await FirebaseAuth.instance.signInWithCredential(credential);
log("Google credentials: " + credential.toString() + " GoogleUser: " + googleUser.toString());
Cache().firebaseUid = userCredential.user!.uid;
userData['email'] = googleUser.email;
return userData;
}
Future<Map<String, dynamic>> signInWithFacebook() async {
Map<String, dynamic> userData;
// by default the login method has the next permissions ['email','public_profile']
final LoginResult result = await FacebookAuth.instance.login();
if (result.status == LoginStatus.success) {
final AccessToken accessToken = result.accessToken!;
log(accessToken.toJson().toString());
Cache().accessTokenFacebook = accessToken;
// get the user data
userData = await FacebookAuth.instance.getUserData();
Cache().firebaseUid = userData['id'];
log(userData.toString());
} else {
Sentry.captureException(new Exception(result.message));
throw Exception("Facebook login was not successful");
}
return userData;
}
Future<Map<String, dynamic>> registerWithFacebook() async {
Map<String, dynamic> userData;
// by default the login method has the next permissions ['email','public_profile']
final LoginResult result = await FacebookAuth.instance.login();
if (result.status == LoginStatus.success) {
final AccessToken accessToken = result.accessToken!;
Cache().accessTokenFacebook = accessToken;
// get the user data
userData = await FacebookAuth.instance.getUserData();
log("FB user data: " + userData.toString());
// Create a credential from the access token
final OAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(accessToken.token);
// Once signed in, return the UserCredential
final userCredential = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
log("Email by FB: " + userData['email'] + " FB credential: " + userCredential.toString());
Cache().firebaseUid = userCredential.user!.uid;
} else {
Sentry.captureException(new Exception(result.message));
throw Exception("Facebook login was not successful");
}
return userData;
}
Future<void> logOutFacebook() async {
await FacebookAuth.instance.logOut();
Cache().accessTokenFacebook = null;
}
Future<void> signOut() async {
await FirebaseAuth.instance.signOut();
}
Future<void> resetPassword(String email) async {
await FirebaseAuth.instance.sendPasswordResetEmail(email: email);
}
Future<void> setupRemoteConfig() async {
//initializeFlutterFire();
FirebaseRemoteConfig? remoteConfig;
try {
remoteConfig = FirebaseRemoteConfig.instance;
await remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(seconds: 10),
minimumFetchInterval: const Duration(seconds: 1),
));
//RemoteConfigValue(null, ValueSource.valueStatic);
//Cache().setRemoteConfig(remoteConfig);
} on Exception catch (e) {
print('Unable to fetch remote config. Cached or default values will be used: $e');
if (remoteConfig != null) {
await remoteConfig.setDefaults(<String, dynamic>{
'sales_page_text_a': '',
'product_set_2': '',
'registration_skip_color': '',
'email_checkbox': '',
});
Cache().setRemoteConfig(remoteConfig);
}
}
}
}
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
print('Handling a background message ${message.messageId}');
}
/* Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
print('Handling a background message: ${message.messageId}');
if (!StringUtils.isNullOrEmpty(message.notification?.title, considerWhiteSpaceAsEmpty: true) ||
!StringUtils.isNullOrEmpty(message.notification?.body, considerWhiteSpaceAsEmpty: true)) {
print('message also contained a notification: ${message.notification}');
String? imageUrl;
imageUrl ??= message.notification!.android?.imageUrl;
imageUrl ??= message.notification!.apple?.imageUrl;
Map<String, dynamic> notificationAdapter = {
NOTIFICATION_CHANNEL_KEY: 'basic_channel',
NOTIFICATION_ID: message.data[NOTIFICATION_CONTENT]?[NOTIFICATION_ID] ?? message.messageId ?? math.Random().nextInt(2147483647),
NOTIFICATION_TITLE: message.data[NOTIFICATION_CONTENT]?[NOTIFICATION_TITLE] ?? message.notification?.title,
NOTIFICATION_BODY: message.data[NOTIFICATION_CONTENT]?[NOTIFICATION_BODY] ?? message.notification?.body,
NOTIFICATION_LAYOUT: StringUtils.isNullOrEmpty(imageUrl) ? 'Default' : 'BigPicture',
NOTIFICATION_BIG_PICTURE: imageUrl
};
AwesomeNotifications().createNotificationFromJsonData(notificationAdapter);
} else {
AwesomeNotifications().createNotificationFromJsonData(message.data);
}
} */

29
lib/service/mautic.dart Normal file
View File

@ -0,0 +1,29 @@
import 'dart:io';
import 'package:workouttest_util/model/mautic.dart';
import 'package:workouttest_util/util/logging.dart';
class MauticApi with Logging {
final String mauticUrl = "https://mautic.workouttest.org/form/submit?formId=";
Future<void> sendMauticForm(Mautic model) async {
final String body = model.toForm();
log(" ===== mautic subscription: $body");
HttpClient client = HttpClient();
String url = mauticUrl + model.formId.toString();
var uri = Uri.parse(url);
final HttpClientRequest request = await client.postUrl(uri);
request.headers.set('Content-Type', 'application/x-www-form-urlencoded');
request.headers.set('cache-control', 'no-cache');
request.write(body);
HttpClientResponse result = await request.close();
client.close();
if (!(result.statusCode == 200 || result.statusCode == 302)) {
trace("mautic response: ${result.statusCode}");
//throw Exception("Network error, try again later!");
}
}
}

View File

@ -0,0 +1,210 @@
import 'dart:convert';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/customer.dart';
import 'package:workouttest_util/model/customer_activity.dart';
import 'package:workouttest_util/model/customer_exercise_device.dart';
import 'package:workouttest_util/model/customer_property.dart';
import 'package:workouttest_util/model/description.dart';
import 'package:workouttest_util/model/evaluation.dart';
import 'package:workouttest_util/model/exercise.dart';
import 'package:workouttest_util/model/exercise_device.dart';
import 'package:workouttest_util/model/exercise_plan_template.dart';
import 'package:workouttest_util/model/exercise_tree.dart';
import 'package:workouttest_util/model/exercise_tree_parents.dart';
import 'package:workouttest_util/model/exercise_type.dart';
import 'package:workouttest_util/model/faq.dart';
import 'package:workouttest_util/model/product.dart';
import 'package:workouttest_util/model/property.dart';
import 'package:workouttest_util/model/purchase.dart';
import 'package:workouttest_util/model/split_test.dart';
import 'package:workouttest_util/model/training_plan.dart';
import 'package:workouttest_util/model/training_plan_day.dart';
import 'package:workouttest_util/model/tutorial.dart';
import 'package:workouttest_util/repository/training_plan_day_repository.dart';
import 'package:workouttest_util/service/api.dart';
import 'package:workouttest_util/service/exercise_type_service.dart';
import 'package:workouttest_util/util/not_found_exception.dart';
import '../model/sport.dart';
import 'customer_service.dart';
import 'exercise_tree_service.dart';
class PackageApi {
final APIClient _client = APIClient();
Future<void> getPackage() async {
late List<ExerciseTree> exerciseTree;
late List<ExerciseTreeParents> exerciseTreeParents;
final body = await _client.get("app_package/", "");
final List<String> models = body.split("|||");
await Future.forEach(models, (elem) async {
final String element = elem as String;
final List<String> headRecord = element.split("***");
final Iterable json = jsonDecode(headRecord[1]);
if (headRecord[0] == "ExerciseDevice") {
final List<ExerciseDevice> devices = json.map((device) => ExerciseDevice.fromJson(device)).toList();
Cache().setDevices(devices);
} else if (headRecord[0] == "Product") {
final List<Product> products = json.map((product) => Product.fromJson(product)).toList();
Cache().setProducts(products);
} else if (headRecord[0] == "Property") {
final List<Property> properties = json.map((property) => Property.fromJson(property)).toList();
Cache().setProperties(properties);
} else if (headRecord[0] == "ExerciseTree") {
exerciseTree = json.map((exerciseTree) => ExerciseTree.fromJson(exerciseTree)).toList();
} else if (headRecord[0] == "ExerciseType") {
final List<ExerciseType> exerciseTypes = json.map((exerciseType) => ExerciseType.fromJson(exerciseType)).toList();
await Future.forEach(exerciseTypes, (elem) async {
final ExerciseType exerciseType = elem as ExerciseType;
exerciseType.imageUrl = await ExerciseTypeApi().buildImage(exerciseType.imageUrl, exerciseType.exerciseTypeId);
});
Cache().setExerciseTypes(exerciseTypes);
} else if (headRecord[0] == "ExerciseAbility") {
} else if (headRecord[0] == "ExercisePlanTemplate") {
final List<ExercisePlanTemplate> exercisePlanTemplates =
json.map((exercisePlanTemplate) => ExercisePlanTemplate.fromJson(exercisePlanTemplate)).toList();
Cache().setExercisePlanTemplates(exercisePlanTemplates);
} else if (headRecord[0] == "ExerciseTreeParents") {
exerciseTreeParents = json.map((exerciseTreeParent) => ExerciseTreeParents.fromJson(exerciseTreeParent)).toList();
} else if (headRecord[0] == "Evaluation") {
final List<Evaluation> evaluations = json.map((evaluation) => Evaluation.fromJson(evaluation)).toList();
Cache().evaluations = evaluations;
} else if (headRecord[0] == "Sport") {
final List<Sport> sports = json.map((sport) => Sport.fromJson(sport)).toList();
Cache().setSports(sports);
} else if (headRecord[0] == "Tutorial") {
final Iterable json = jsonDecode(headRecord[1]);
final List<Tutorial> tutorials = json.map((tutorial) => Tutorial.fromJson(tutorial)).toList();
Cache().setTutorials(tutorials);
} else if (headRecord[0] == "Description") {
final Iterable json = jsonDecode(headRecord[1]);
final List<Description>? descriptions = json.map((description) => Description.fromJson(description)).toList();
//print("Description: $descriptions");
Cache().setDescriptions(descriptions);
} else if (headRecord[0] == "Faq") {
final Iterable json = jsonDecode(headRecord[1]);
final List<Faq>? faqs = json.map((faq) => Faq.fromJson(faq)).toList();
//print("Faq: $faqs");
Cache().setFaqs(faqs);
} else if (headRecord[0] == "TrainingPlan") {
final Iterable json = jsonDecode(headRecord[1]);
final List<TrainingPlan>? plans = json.map((plan) => TrainingPlan.fromJson(plan)).toList();
List<TrainingPlan> activePlans = [];
if (plans != null) {
plans.forEach((element) {
if (element.active) {
activePlans.add(element);
}
});
}
Cache().setTrainingPlans(activePlans);
} else if (headRecord[0] == "SplitTests") {
final Iterable json = jsonDecode(headRecord[1]);
final List<SplitTest>? tests = json.map((test) => SplitTest.fromJson(test)).toList();
//print("A/B tests: $tests");
Cache().setSplitTests(tests);
} else if (headRecord[0] == "TrainingPlanDay") {
final Iterable json = jsonDecode(headRecord[1]);
final List<TrainingPlanDay>? days = json.map((day) => TrainingPlanDay.fromJson(day)).toList();
Cache().setTrainingPlanDays(days);
}
});
exerciseTree = this.getExerciseTreeParents(exerciseTree, exerciseTreeParents);
await Future.forEach(exerciseTree, (element) async {
ExerciseTree tree = element as ExerciseTree;
tree.imageUrl = await ExerciseTreeApi().buildImage(tree.imageUrl, tree.treeId);
});
Cache().setExerciseTree(exerciseTree);
TrainingPlanDayRepository trainingPlanDayRepository = TrainingPlanDayRepository();
trainingPlanDayRepository.assignTrainingPlanDays();
return;
}
List<ExerciseTree> getExerciseTreeParents(final List<ExerciseTree> exerciseTree, final List<ExerciseTreeParents> exerciseTreeParents) {
List<ExerciseTree> copyList = ExerciseTreeApi().copyList(exerciseTree);
int treeIndex = 0;
copyList.forEach((element) async {
int index = 0;
exerciseTreeParents.forEach((parent) {
if (parent.exerciseTreeChildId == element.treeId) {
if (index > 0) {
ExerciseTree newElement = element.copy(parent.exerciseTreeParentId);
newElement.sort = parent.sort;
exerciseTree.add(newElement);
} else {
element.parentId = parent.exerciseTreeParentId;
element.sort = parent.sort;
exerciseTree[treeIndex].parentId = parent.exerciseTreeParentId;
exerciseTree[treeIndex].sort = parent.sort;
}
index++;
}
});
treeIndex++;
});
return exerciseTree;
}
Future<void> getCustomerPackage(int customerId) async {
try {
final body = await _client.get("app_customer_package/" + customerId.toString(), "");
final List<String> models = body.split("|||");
await Future.forEach(models, (elem) async {
final String element = elem as String;
final List<String> headRecord = element.split("***");
//print("Class " + headRecord[0]);
if (headRecord[0] == "Customer") {
Customer customer = Customer.fromJson(jsonDecode(headRecord[1]));
Cache().userLoggedIn = customer;
} else if (headRecord[0] == "CustomerExerciseDevice") {
final Iterable json = jsonDecode(headRecord[1]);
final List<CustomerExerciseDevice> devices = json.map((device) => CustomerExerciseDevice.fromJson(device)).toList();
Cache().setCustomerDevices(devices);
// ToDo
} else if (headRecord[0] == "Exercises") {
final Iterable json = jsonDecode(headRecord[1]);
final List<Exercise> exercises = json.map((exerciseType) => Exercise.fromJson(exerciseType)).toList();
Cache().setExercises(exercises);
} else if (headRecord[0] == "Purchase") {
final Iterable json = jsonDecode(headRecord[1]);
final List<Purchase> purchases = json.map((purchase) => Purchase.fromJson(purchase)).toList();
Cache().setPurchases(purchases);
} else if (headRecord[0] == "CustomerProperty") {
final Iterable json = jsonDecode(headRecord[1]);
final List<CustomerProperty> customerProperties = json.map((property) => CustomerProperty.fromJson(property)).toList();
CustomerApi().initProperties(customerProperties);
} else if (headRecord[0] == "CustomerPropertyAll") {
final Iterable json = jsonDecode(headRecord[1]);
final List<CustomerProperty> allCustomerProperties = json.map((property) => CustomerProperty.fromJson(property)).toList();
print(" All Properties ---- $allCustomerProperties");
Cache().setCustomerPropertyAll(allCustomerProperties);
} else if (headRecord[0] == "ExerciseResult") {
/*final Iterable json = jsonDecode(headRecord[1]);
final List<ExerciseResult> exerciseResults = json.map((exerciseResult) {
ExerciseResult item = ExerciseResult.fromJson(exerciseResult);
return item;
}).toList();
// ToDo */
} else if (headRecord[0] == "CustomerActivity") {
final Iterable json = jsonDecode(headRecord[1]);
final List<CustomerActivity> customerActivities = json.map((activity) => CustomerActivity.fromJson(activity)).toList();
Cache().setCustomerActivities(customerActivities);
}
});
} on NotFoundException catch (e) {
throw Exception("Please log in $e");
}
}
}

View File

@ -0,0 +1,17 @@
import 'dart:convert';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/product.dart';
import 'package:workouttest_util/service/api.dart';
class ProductApi {
final APIClient _client = APIClient();
Future<List<Product>> getProducts() async {
final body = await _client.get("product/", "");
final Iterable json = jsonDecode(body);
final List<Product> products = json.map((product) => Product.fromJson(product)).toList();
Cache().setProducts(products);
return products;
}
}

View File

@ -0,0 +1,18 @@
import 'dart:convert';
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/service/api.dart';
import 'package:workouttest_util/model/property.dart';
class PropertyApi {
final APIClient _client = APIClient();
Future<List<Property>> getProperties() async {
final body = await _client.get("property/", "");
final Iterable json = jsonDecode(body);
final List<Property> properties = json.map((property) => Property.fromJson(property)).toList();
Cache().setProperties(properties);
return properties;
}
}

View File

@ -0,0 +1,29 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/model/purchase.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:workouttest_util/util/not_found_exception.dart';
import 'dart:convert';
import 'api.dart';
class PurchaseApi with Logging {
final APIClient _client = APIClient();
Future<List<Purchase>> getPurchasesByCustomer(int customerId) async {
List<Purchase> purchases = [];
try {
final body = await _client.get("purchase/customer/" + customerId.toString(), "");
final Iterable json = jsonDecode(body);
final List<Purchase> purchases = json.map((purchase) => Purchase.fromJson(purchase)).toList();
Cache().setPurchases(purchases);
} on NotFoundException catch (_) {
log("No purchases found");
}
return purchases;
}
Future<void> savePurchase(Purchase purchase) async {
String body = JsonEncoder().convert(purchase.toJson());
log(" ===== saving purchase:" + body);
await _client.post("purchase/", body);
}
}

View File

@ -0,0 +1,18 @@
import 'package:workouttest_util/model/tracking.dart';
import 'package:workouttest_util/util/logging.dart';
import 'dart:convert';
import 'api.dart';
class TrackingApi with Logging {
final APIClient _client = APIClient();
Future<void> saveTracking(Tracking tracking) async {
try {
String body = const JsonEncoder().convert(tracking.toJson());
log(" ===== saving tracking: $body");
await _client.post("tracking/", body);
} catch (exception) {
log("exception in tracking: ${exception.toString()}");
}
}
}

View File

@ -0,0 +1,34 @@
import 'dart:convert';
import 'package:workouttest_util/model/customer_training_plan.dart';
import 'package:workouttest_util/model/customer_training_plan_exercise.dart';
import 'package:workouttest_util/service/api.dart';
import 'package:workouttest_util/util/logging.dart';
class TrainingPlanApi with Logging {
final APIClient _client = APIClient();
Future<CustomerTrainingPlan> saveCustomerTrainingPlan(CustomerTrainingPlan plan) async {
String body = JsonEncoder().convert(plan.toJson());
log(" ===== saving customer training plan:" + body);
final String response = await _client.post("customer_training_plan/", body);
final CustomerTrainingPlan saved = CustomerTrainingPlan.fromJson(jsonDecode(response));
return saved;
}
Future<CustomerTrainingPlanExercise> saveCustomerTrainingPlanExercise(CustomerTrainingPlanExercise planExercise) async {
String body = JsonEncoder().convert(planExercise.toJson());
log(" ===== saving customer training plan exercise:" + body);
final String response = await _client.post("customer_training_plan_exercise/", body);
final CustomerTrainingPlanExercise saved = CustomerTrainingPlanExercise.fromJson(jsonDecode(response));
return saved;
}
Future<CustomerTrainingPlan> updateCustomerTrainingPlan(CustomerTrainingPlan plan, int customerTrainingPlanId) async {
String body = JsonEncoder().convert(plan.toJson());
log(" ===== update customer training plan:" + body);
final String response = await _client.post("customer_training_plan/update/$customerTrainingPlanId", body);
final CustomerTrainingPlan saved = CustomerTrainingPlan.fromJson(jsonDecode(response));
return saved;
}
}

View File

@ -0,0 +1,68 @@
import 'dart:io';
import 'package:workouttest_util/util/logging.dart';
import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AppLanguage with Logging {
static final AppLanguage _singleton = AppLanguage._internal();
Locale? _appLocale = Locale('en');
factory AppLanguage() {
return _singleton;
}
AppLanguage._internal();
static Future<AppLanguage> getInstance() async {
return _singleton;
}
Locale get appLocal => _appLocale ?? Locale("en");
Future<void> fetchLocale() async {
var prefs = await SharedPreferences.getInstance();
String? langCode = prefs.getString('language_code');
log(" ---- lang code $langCode");
if (langCode == null) {
_appLocale = Locale('en');
} else {
_appLocale = Locale(langCode);
}
log(" ---- Fetched lang: " + _appLocale.toString());
}
getLocale(SharedPreferences prefs) {
String? langCode = prefs.getString('language_code');
if (langCode == null) {
final String localName = Platform.localeName;
if (localName.endsWith("HU")) {
_appLocale = Locale('hu');
langCode = "hu";
} else {
_appLocale = Locale('en');
langCode = "en";
}
}
_appLocale = Locale(langCode);
log(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode");
}
void changeLanguage(Locale type) async {
var prefs = await SharedPreferences.getInstance();
if (_appLocale == type) {
return;
}
if (type == Locale("hu")) {
_appLocale = Locale("hu");
await prefs.setString('language_code', 'hu');
await prefs.setString('countryCode', 'HU');
} else {
_appLocale = Locale("en");
await prefs.setString('language_code', 'en');
await prefs.setString('countryCode', 'US');
}
log(" ---- Stored lang: " + _appLocale.toString());
}
}

View File

@ -0,0 +1,78 @@
import 'dart:convert';
import 'package:workouttest_util/util/logging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
class AppLocalizations with Logging {
late Locale locale;
bool isTest;
late Map<String, String> _localizedStrings;
AppLocalizations(this.locale, {this.isTest = false});
// Helper method to keep the code in the widgets concise
// Localizations are accessed using an InheritedWidget "of" syntax
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
// Static member to have a simple access to the delegate from the MaterialApp
static const LocalizationsDelegate<AppLocalizations> delegate = AppLocalizationsDelegate();
setLocale(Locale locale) {
this.locale = locale;
}
Future<bool> load() async {
// Load the language JSON file from the "lang" folder
log(" -- load language pieces " + locale.languageCode);
String jsonString = await rootBundle.loadString('i18n/${locale.languageCode}.json');
Map<String, dynamic> jsonMap = json.decode(jsonString);
_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});
return true;
}
Future<AppLocalizations> loadTest(Locale locale) async {
return AppLocalizations(locale);
}
// This method will be called from every widget which needs a localized text
String translate(String key) {
if (isTest) return key;
String? translated = _localizedStrings[key];
return translated != null ? translated : key;
}
}
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
final bool isTest;
// This delegate instance will never change (it doesn't even have fields!)
// It can provide a constant constructor.
const AppLocalizationsDelegate({this.isTest = false});
@override
bool isSupported(Locale locale) {
// Include all of your supported language codes here
return ['en', 'hu'].contains(locale.languageCode);
}
@override
Future<AppLocalizations> load(Locale locale) async {
// AppLocalizations class is where the JSON loading actually runs
AppLocalizations localizations = new AppLocalizations(locale, isTest: this.isTest);
if (isTest) {
await localizations.loadTest(locale);
} else {
await localizations.load();
}
return localizations;
}
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}

176
lib/util/common.dart Normal file
View File

@ -0,0 +1,176 @@
import 'dart:convert';
import 'package:workouttest_util/util/app_language.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class DateRate {
static String daily = "daily";
static String weekly = "weekly";
static String monthly = "monthly";
static String yearly = "yearly";
}
mixin Common {
final emailError = "Please type a right email address here.";
final passwordError = "The password must have at least 8 characters.";
String toJson(Map<String, String> map) {
String rc = "{";
map.forEach((key, value) {
rc += "'$key':'$value'";
});
rc += "}";
return rc;
}
String getDateLocale(DateTime datetime, bool timeDisplay) {
var date = datetime;
String dateName = DateFormat(DateFormat.YEAR_NUM_MONTH_DAY, AppLanguage().appLocal.toString()).format(date.toUtc());
if (timeDisplay) {
dateName += " " + DateFormat(DateFormat.HOUR_MINUTE, AppLanguage().appLocal.toString()).format(date.toUtc());
}
return dateName;
}
String utf8convert(String text) {
List<int> bytes = text.toString().codeUnits;
return utf8.decode(bytes);
}
double mediaSizeWidth(BuildContext context) {
return MediaQuery.of(context).size.width;
}
/// Calculates week number from a date as per https://en.wikipedia.org/wiki/ISO_week_date#Calculation
int weekNumber(DateTime date) {
int dayOfYear = int.parse(DateFormat("D").format(date));
return ((dayOfYear - date.weekday + 10) / 7).floor();
}
static String? emailValidation(String? email) {
final String error = "Please type an email address";
if (email == null) {
return error;
}
bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email);
return emailValid ? null : error;
}
static String? passwordValidation(String? value) {
final String error = "Password too short";
if (value == null || value.length == 0) {
return error;
}
bool valid = 8 < value.length;
return valid ? null : error;
}
static normalizeDecimal(String value) {
if (value.isEmpty) {
return 0;
}
value = value.replaceFirst(",", ".");
value = value.replaceAll(RegExp(r'[^0-9.]'), "");
return value;
}
double calculate1RM(double weight, double repeat) {
if (weight == 0 || repeat == 0) {
return 0;
}
double rmWendler = weight * repeat * 0.0333 + weight;
double rmOconner = weight * (1 + repeat / 40);
//print("Weight: $weight repeat: $repeat, $rmWendler, Oconner: $rmOconner");
double average = (rmWendler + rmOconner) / 2;
return average;
}
double getRepeatByOneRepMax(double oneRepMax, double weight) {
double repeats = ( 80 * oneRepMax - 80 * weight ) / ( weight * ( 40 * 0.0333 + 1) );
//print("getRepeatsByOneRepMax: $repeats");
return repeats;
}
int calculateRepeatBy1RMPercent(double oneRepMax, double weight, double percent) {
return getRepeatByOneRepMax(oneRepMax , weight * percent).round();
}
double calculate1RMPercentByRepeat(double oneRepMax, double weight, double repeat) {
double percent = 80 * oneRepMax / (weight * ( repeat * ( 40 * 0.0333 + 1 ) + 80));
return percent;
}
static double get1RMPercent(int repeats) {
double percent = 1;
if (repeats >= 35) {
percent = 0.50;
} else if (repeats > 12) {
percent = (100 - 2 * repeats) / 100;
} else {
percent = (100.0 - 2 * repeats) / 100;
}
//print("1RM Percent: $percent repeats: $repeats");
return percent;
}
static double roundWeight(double weight) {
double rounded = weight.round().toDouble();
if (weight > 35) {
final double remainder = weight % 5;
if (remainder < 1) {
rounded = ((weight / 5).floor() * 5).toDouble();
} else if (remainder > 1 && remainder <= 2.5) {
rounded = (weight / 5).floor() * 5 + 2.5;
} else if (remainder > 2.5 && remainder < 3.25) {
rounded = (weight / 5).floor() * 5 + 2.5;
} else {
rounded = (((weight / 5).ceil() * 5)).toDouble();
}
}
return rounded;
}
static int calculateQuantityByChangedWeight(double initialRM, double weight, double repeat) {
final double repeatWendler = (initialRM - weight) / 0.0333 / weight;
final double repeatOconner = (initialRM / weight - 1) * 40;
final newRepeat = ((repeatOconner + repeatWendler) / 2).ceil();
print("Initial 1RM: $initialRM Weight: $weight repeatWendler: $repeatWendler repeat Oconner: $repeatOconner. NEW REPEAT: $newRepeat");
return newRepeat;
}
static int reCalculateRepeatsByChangedWeight(double weight, double repeat, double changedWeight) {
final double rmWendler = weight * repeat * 0.0333 + weight;
final double rmOconner = weight * (1 + repeat / 40);
final double repeatWendler = (rmWendler - changedWeight) / 0.0333 / changedWeight;
final double repeatOconner = (rmOconner / changedWeight - 1) * 40;
final newRepeat = ((repeatOconner + repeatWendler) / 2).ceil();
print("Weight: $weight changedWeight: $changedWeight repeatWendler: $repeatWendler repeat Oconner: $repeatOconner. NEW REPEAT: $newRepeat");
return newRepeat;
}
static double calculateWeigthByChangedQuantity(double weight, double repeat, double changedRepeats) {
final double rmWendler = weight * repeat * 0.0333 + weight;
final double rmOconner = weight * (1 + repeat / 40);
final double initialRM = (rmWendler + rmOconner) / 2;
final double weightWendler = rmWendler / (changedRepeats * 0.0333 + 1);
final double weightOconner = rmOconner / (1 + changedRepeats / 40);
final double newWeight = ((weightWendler + weightOconner) / 2);
print(
"Initial 1RM: $initialRM repeat: $repeat changedRepeat: $changedRepeats Weight: $weight weightWendler: $weightWendler weight Oconner: $weightOconner. NEW WEIGHT: $newWeight");
return newWeight;
}
}
class CommonHoldingClass with Common {}

129
lib/util/enums.dart Normal file
View File

@ -0,0 +1,129 @@
import 'package:workouttest_util/util/string_extension.dart';
enum LoginType { email, fb, google, apple }
extension LoginTypeExt on LoginType {
bool equalsTo(LoginType type) => this.toString() == type.toString();
bool equalsStringTo(String type) => this.toString() == type;
}
enum TrackingEvent {
enter,
login,
logout,
registration,
login_skip,
home,
sizes,
sizes_save,
my_development,
my_exerciseplan,
account,
settings,
sales_page,
purchase_request,
purchase_successful,
exercise_new,
exercise_new_no_registration,
exercise_new_paralell,
result,
exercise_log,
exercise_log_open,
exercise_log_delete,
exercise_log_result,
my_body_development,
my_muscle_development,
my_size_development,
my_custom_exercise_plan,
my_custom_exercise_plan_save,
my_exercise_plan_execute_open,
my_exercise_plan_execute_save,
my_special_plan,
my_suggested_plan,
prediction,
search,
exercise_device,
customer_change,
settings_lang,
settings_server,
test_set_edit,
test_set_new,
tutorial_step,
tutorial_finished,
tutorial_activate,
terms_of_use,
data_privacy,
delete_account,
faq,
training_plan_open,
training_plan_start,
training_plan_execute,
training_plan_finished,
training_plan_custom,
trial,
feedback_email,
}
T enumFromString<T>(Iterable<T> values, String value) {
return values.firstWhere((type) => type.toString().split(".").last == value);
}
extension TrackingEventExt on TrackingEvent {
String enumToString() => this.toString().split(".").last;
bool equalsTo(TrackingEvent event) => this.toString() == event.toString();
bool equalsStringTo(String event) => this.toString() == event;
}
enum PropertyEnum { Ectomorph, Mesomorph, Endomorph }
extension PropertyExt on PropertyEnum {
String toStr() => this.toString().split(".").last;
bool equalsTo(PropertyEnum event) => this.toString() == event.toString();
bool equalsStringTo(String event) => this.toString() == event;
}
enum SizesEnum { Weight, Height, Shoulder, Neck, Biceps, Chest, Belly, Hip, ThighTop, ThighMiddle, Knee, Calf, Ankle, Underarm, Lowerarm }
extension SizesExt on SizesEnum {
String toStr() => this.toString().split(".").last;
bool equalsTo(SizesEnum event) => this.toString() == event.toString();
bool equalsStringTo(String event) => this.toString() == event;
}
enum EvaluationText { very_poor, poor, fair, below_average, average, above_average, good, excellent, elite }
extension EvaluationTextExt on EvaluationText {
String toStr() => this.toString().split(".").last;
bool equalsTo(EvaluationText eval) => this.toString() == eval.toString();
bool equalsStringTo(String eval) => this.toStr() == eval;
}
enum ExerciseTypeTrainingPlanState { none, added, executed }
extension ExerciseTypeTrainingPlanStateExt on ExerciseTypeTrainingPlanState {
String toStr() => this.toString().split(".").last;
bool equalsTo(ExerciseTypeTrainingPlanState state) => this.toString() == state.toString();
bool equalsStringTo(String state) => this.toStr() == state;
}
enum ExerciseSaveType { test, training, test_set }
extension ExerciseSaveTypeExt on ExerciseSaveType {
String toStr() => this.toString().split(".").last;
bool equalsTo(ExerciseSaveType type) => this.toString() == type.toString();
bool equalsStringTo(String type) => this.toStr() == type;
}
enum MuscleGroup { chest, biceps, triceps, back, shoulders, core, thigh, calf }
extension MuscleGroupExt on MuscleGroup {
String toStr() => this.toString().split(".").last;
String toText() => this.toString().split(".").last.capitalize();
bool equalsTo(MuscleGroup type) => this.toString() == type.toString();
bool equalsStringTo(String type) => this.toStr() == type;
String getStrByIndex(int index) => MuscleGroup.values.elementAt(index).toStr();
MuscleGroup getByIndex(int index) => MuscleGroup.values.elementAt(index);
String getTextByIndex(int index) => MuscleGroup.values.elementAt(index).toText();
}

3
lib/util/env.dart Normal file
View File

@ -0,0 +1,3 @@
class EnvironmentConfig {
static const test_env = String.fromEnvironment('test_env');
}

16
lib/util/logging.dart Normal file
View File

@ -0,0 +1,16 @@
import 'package:workouttest_util/util/env.dart';
import 'package:intl/intl.dart';
mixin Logging {
void log(String message) {
DateTime time = DateTime.now();
print(DateFormat('yyyy-MM-dd HH:mm:ss ').format(time) + message);
}
void trace(String message) {
String testEnv = EnvironmentConfig.test_env;
if (testEnv == "1") {
log(message);
}
}
}

View File

@ -0,0 +1,13 @@
class NotFoundException implements Exception {
final String message;
const NotFoundException({required this.message});
}
class WorkoutTestException implements Exception {
static const String CUSTOMER_EXISTS = "customer-exists";
static const String LOGIN_CANCELLED = "login-cancelled";
final String message;
final String code;
const WorkoutTestException({required this.message, required this.code});
}

View File

@ -0,0 +1,5 @@
extension StringExtension on String {
String capitalize() {
return "${this[0].toUpperCase()}${this.substring(1).toLowerCase()}";
}
}

53
lib/util/track.dart Normal file
View File

@ -0,0 +1,53 @@
import 'package:workouttest_util/model/cache.dart';
import 'package:workouttest_util/util/logging.dart';
import 'package:workouttest_util/service/tracking_service.dart';
import 'package:workouttest_util/util/enums.dart';
import 'package:workouttest_util/model/tracking.dart' as model;
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:posthog_session/posthog_session.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:flutter/foundation.dart';
class Track with Logging {
static final Track _singleton = Track._internal();
static FirebaseAnalytics analytics = FirebaseAnalytics.instance;
factory Track() {
return _singleton;
}
Track._internal();
void track(TrackingEvent event, {String eventValue = ""}) {
model.Tracking tracking = model.Tracking();
tracking.customerId = Cache().userLoggedIn == null ? 0 : Cache().userLoggedIn!.customerId!;
if (kReleaseMode) {
tracking.event = event.enumToString();
if (eventValue.isNotEmpty) {
tracking.eventValue = eventValue;
}
tracking.dateAdd = DateTime.now();
TrackingApi().saveTracking(tracking);
FirebaseMessaging.instance.subscribeToTopic(event.enumToString());
analytics.logEvent(name: event.enumToString(), parameters: {"value": eventValue});
if (eventValue.isNotEmpty) {
MatomoTracker.instance.trackEvent(eventCategory: "wt", action: event.enumToString(), eventName: eventValue);
} else {
MatomoTracker.instance.trackEvent(eventCategory: "wt", action: event.enumToString());
}
Posthog().capture(
eventName: event.enumToString(),
properties: {
'eventValue': eventValue,
'customer': tracking.customerId,
},
);
}
}
}

View File

@ -0,0 +1 @@
library workouttest_util;

73
pubspec.yaml Normal file
View File

@ -0,0 +1,73 @@
name: workouttest_util
description: Workout Test app and web functions.
version: 0.0.1
homepage:
environment:
sdk: '>=2.18.6 <3.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
firebase_auth: ^4.2.5
firebase_analytics: ^10.1.0
firebase_messaging: ^14.2.1
firebase_remote_config: ^3.0.9
flutter_facebook_auth: ^5.0.7
google_sign_in: ^5.4.3
sign_in_with_apple: ^4.3.0
matomo_tracker: ^2.0.0
package_info_plus: ^3.0.2
sentry_flutter: ^6.9.1
posthog_session:
git: https://bossanyit@git.workouttest.org/bossanyit/posthog_session.git
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
intl: ^0.17.0
shared_preferences: ^2.0.5
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# To add assets to your package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# To add custom fonts to your package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages

View File

@ -0,0 +1,9 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:workouttest_util/workouttest_util.dart';
void main() {
test('adds one to input values', () {
});
}