diff --git a/.gitignore b/.gitignore index f3c2053..a69360e 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,7 @@ app.*.map.json # Exceptions to above rules. !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +local.properties +.gitignore +.vscode/launch.json +.vscode/settings.json diff --git a/README.md b/README.md index e793e44..16bc94f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # aitrainer_app -The AITRAINER Mobile Application +The WorkoutTest Mobile Application -Prototye 1.1.0s +Prototye 1.1.2f diff --git a/asset/image/WT_black_backround.png b/asset/image/WT_black_backround.png deleted file mode 100644 index 6bdc65b..0000000 Binary files a/asset/image/WT_black_backround.png and /dev/null differ diff --git a/i18n/en.json b/i18n/en.json index 757d0be..f5ac39b 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -69,7 +69,7 @@ "The number of the exercise done with": "The number of the exercise done with", "Please repeat with": "Please repeat with", "Execute the": "Execute the", - ". set!":". set!", + "set!":"set!", "repeat": "repeat", @@ -97,6 +97,8 @@ "Gain Muscle": "Gain Muscle", "Loose Weight": "Loose Weight", "Your Fitness State": "Your Fitness State", + "Fitness level": "Fizikai állapot", + "Fitness Activity":"Fitness Activity", "Beginner": "Beginner", "I am beginner": "I am beginner", "Intermediate": "Intermediate", @@ -105,6 +107,7 @@ "I am advanced": "4+ times a week", "Professional": "Professional", "I am professional": "I am a professional", + "No item selected":"No item selected", "Your Body Type": "Your Body Type", "Ectomorph": "Ectomorph", "Endomorph": "Endomorph", @@ -207,5 +210,18 @@ "Are you sure to delete this exercise?": "Are you sure to delete this exercise?", "I forgot the password":"I forgot the password", - "Exception: Instance of 'NotFoundException'": "Customer with the email not found. Please register or reset your password" + "Exception: Instance of 'NotFoundException'": "Customer with the email not found. Please register or reset your password", + "More »": "More »", + "Done": "Done", + "Height":"Height", + "Actual Height":"Actual Height", + "Actual Weight":"Actual Weight", + "Based on your weight and height your goal for BMI and weight:":"Based on your weight and height your goal for BMI and weight:", + "Body Mass Index":"Body Mass Index", + "Basal Metabolic Rate":"Basal Metabolic Rate", + "Based on your weight, height and activity your BMR value":"Based on your weight, height and activity this is your daily calory demand.", + "Your Sizes":"Your Sizes", + "Size Of Your":"Size Of Your", + "Please type the following data:":"Please type the following data:", + "Cancel": "Cancel" } \ No newline at end of file diff --git a/i18n/hu.json b/i18n/hu.json index 2594d60..7b0f319 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -58,7 +58,7 @@ "The number of the exercise done with": "Írd be, mennyivel csináltad a gyakorlatot", "Please repeat with": "Kérlek ismételd", "Execute the": "Hajtsd végre a(z)", - ". set!":". sorozatot!", + "set!":"sorozatot!", "Name": "Név", "Exercise": "Gyakorlat", @@ -97,6 +97,8 @@ "Gain Muscle": "Izomépítés", "Loose Weight": "Fogyás", "Your Fitness State": "Milyen a fizikai állapotod?", + "Fitness level": "Fizikai állapot", + "Fitness Activity":"Fizikai aktivitás", "Beginner": "Kezdő", "I am beginner": "Kezdő / Újrakezdő vagyok", "Intermediate": "Középhaladó", @@ -106,6 +108,7 @@ "Professional": "Professzionális", "I am professional": "Professzionális sportoló vagyok", "Your Body Type": "Milyen a testtípusod?", + "No item selected":"Nincs kiválasztott elem", "Ectomorph": "Ectomorf", "Endomorph":"Endomorf", "Mesomorph":"Mezomorf", @@ -126,7 +129,7 @@ "Please add an exercise plan": "Kérlek add meg az edzéstervet a gyakorlathoz", - "Serie": "Széria", + "Serie": "Sorozat", "Repeats": "Ismétlés", "Save The Exercise To The Exercise Plan": "Gyakorlat mentése az edzéstervhez", "The number of the serie done with":"Mennyi szériát csinálsz", @@ -194,7 +197,6 @@ "Calf": "vádli", "Bring me there": "Vigyél oda", - "My Body Development": "Testem fejlődése", "You see here your whole body development by muscle groups.": "Itt láthatod a tested fejlődését izomcsoportonként", @@ -209,5 +211,18 @@ "Are you sure to delete this exercise?": "Biztos, hogy törlöd a gyakorlatot?", "I forgot the password":"Elfelejtett jelszó", - "Exception: Instance of 'NotFoundException'": "Ezzel az email címmel nem található felhasználó. Kérlek regisztálj vagy kérj jelszóemlékeztetőt" + "Exception: Instance of 'NotFoundException'": "Ezzel az email címmel nem található felhasználó. Kérlek regisztálj vagy kérj jelszóemlékeztetőt", + "More »": "Részletek »", + "Done": "Kész", + "Height":"Magasság", + "Actual Height":"Akt. magasság", + "Actual Weight":"Aktuális tömeg", + "Based on your weight and height your goal for BMI and weight:":"A jelenlegi tömeged és magasságod alapján kiszámoltuk, hogy mennyi legyen a célod a BMI (testtömegindex) és tömeg elérésben:", + "Body Mass Index":"Testtömegindex", + "Basal Metabolic Rate":"Alapanyagcsere érték", + "Based on your weight, height and activity your BMR value":"A tömeged, magasságod és aktivitásod alapján megközelítőleg ennyi a napi kalóriaszükségleted.", + "Your Sizes":"Méreteid", + "Size Of Your":"Testméret:", + "Please type the following data:":"Kérlek írd be a következő adatot:", + "Cancel": "Mégsem" } \ No newline at end of file diff --git a/lib/bloc/customer_change/customer_change_bloc.dart b/lib/bloc/customer_change/customer_change_bloc.dart index 13516ca..1320060 100644 --- a/lib/bloc/customer_change/customer_change_bloc.dart +++ b/lib/bloc/customer_change/customer_change_bloc.dart @@ -10,29 +10,105 @@ part 'customer_change_state.dart'; class CustomerChangeBloc extends Bloc { final CustomerRepository customerRepository; - CustomerChangeBloc({this.customerRepository}) : super(CustomerChangeInitial()); + bool visiblePassword = false; + int year = 1990; + double weight = 60; + double height = 170; + CustomerChangeBloc({this.customerRepository}) : super(CustomerChangeInitial()) { + year = this.customerRepository.customer.birthYear; + weight = this.customerRepository.getWeight(); + height = this.customerRepository.getHeight(); + } @override Stream mapEventToState( CustomerChangeEvent event, ) async* { try { - if (event is CustomerGoalChange) { + if (event is CustomerLoad) { + yield CustomerChangeLoading(); + yield CustomerDataChanged(); + } else if (event is CustomerGoalChange) { customerRepository.setGoal(event.goal); yield CustomerDataChanged(); + } else if (event is CustomerChangePasswordObscure) { + visiblePassword = !visiblePassword; + yield CustomerDataChanged(); } else if (event is CustomerFitnessChange) { customerRepository.setFitnessLevel(event.fitness); yield CustomerDataChanged(); + } else if (event is CustomerBirthYearChange) { + yield CustomerChangeLoading(); + customerRepository.setBirthYear(event.year); + year = event.year; + yield CustomerDataChanged(); + } else if (event is CustomerWeightChange) { + yield CustomerChangeLoading(); + customerRepository.setWeight(event.weight); + weight = event.weight.toDouble(); + yield CustomerDataChanged(); + } else if (event is CustomerHeightChange) { + yield CustomerChangeLoading(); + customerRepository.setHeight(event.height); + height = event.height.toDouble(); + yield CustomerDataChanged(); } else if (event is CustomerBodyTypeChange) { customerRepository.setBodyType(event.bodyType); yield CustomerDataChanged(); + } else if (event is CustomerEmailChange) { + customerRepository.setEmail(event.email); + yield CustomerDataChanged(); + } else if (event is CustomerPasswordChange) { + customerRepository.setPassword(event.password); + yield CustomerDataChanged(); + } else if (event is CustomerFirstNameChange) { + customerRepository.setFirstName(event.firstName); + yield CustomerDataChanged(); + } else if (event is CustomerNameChange) { + customerRepository.setName(event.name); + yield CustomerDataChanged(); + } else if (event is CustomerGenderChange) { + customerRepository.setSex(event.gender == 0 ? "m" : "w"); + yield CustomerDataChanged(); } else if (event is CustomerSave) { yield CustomerSaving(); - await customerRepository.saveCustomer(); - yield CustomerSaveSuccess(); + if (validation()) { + await customerRepository.saveCustomer(); + yield CustomerSaveSuccess(); + } else { + yield CustomerSaveError(message: "Please provide the necessary information"); + } } - } on Exception catch(e) { + } on Exception catch (e) { yield CustomerSaveError(message: e.toString()); } } + + bool validation() { + print("f " + customerRepository.customer.firstname); + return (emailValidation(customerRepository.customer.email) == null) && + (passwordValidation(customerRepository.customer.password) == null) && + (nameValidation(customerRepository.customer.firstname) == null) && + (nameValidation(customerRepository.customer.name) == null); + } + + String emailValidation(String email) { + bool emailValid = RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+").hasMatch(email); + return emailValid ? null : "Please type an email address"; + } + + String passwordValidation(String value) { + if (value == null || value.length == 0) { + return null; + } + bool valid = 8 < value.length; + return valid ? null : "Password too short"; + } + + String nameValidation(String value) { + if (value == null || value.length == 0) { + return "Name too short"; + } + return null; + } } diff --git a/lib/bloc/customer_change/customer_change_event.dart b/lib/bloc/customer_change/customer_change_event.dart index 7ae94b0..ec3d7f4 100644 --- a/lib/bloc/customer_change/customer_change_event.dart +++ b/lib/bloc/customer_change/customer_change_event.dart @@ -31,6 +31,78 @@ class CustomerBodyTypeChange extends CustomerChangeEvent { List get props => [bodyType]; } +class CustomerBirthYearChange extends CustomerChangeEvent { + final int year; + const CustomerBirthYearChange({this.year}); + + @override + List get props => [year]; +} + +class CustomerWeightChange extends CustomerChangeEvent { + final int weight; + const CustomerWeightChange({this.weight}); + + @override + List get props => [weight]; +} + +class CustomerHeightChange extends CustomerChangeEvent { + final int height; + const CustomerHeightChange({this.height}); + + @override + List get props => [height]; +} + +class CustomerGenderChange extends CustomerChangeEvent { + final int gender; + const CustomerGenderChange({this.gender}); + + @override + List get props => [gender]; +} + +class CustomerEmailChange extends CustomerChangeEvent { + final String email; + const CustomerEmailChange({this.email}); + + @override + List get props => [email]; +} + +class CustomerFirstNameChange extends CustomerChangeEvent { + final String firstName; + const CustomerFirstNameChange({this.firstName}); + + @override + List get props => [firstName]; +} + +class CustomerNameChange extends CustomerChangeEvent { + final String name; + const CustomerNameChange({this.name}); + + @override + List get props => [name]; +} + +class CustomerPasswordChange extends CustomerChangeEvent { + final String password; + const CustomerPasswordChange({this.password}); + + @override + List get props => [password]; +} + +class CustomerChangePasswordObscure extends CustomerChangeEvent { + const CustomerChangePasswordObscure(); +} + +class CustomerLoad extends CustomerChangeEvent { + const CustomerLoad(); +} + class CustomerSave extends CustomerChangeEvent { const CustomerSave(); } diff --git a/lib/bloc/customer_change/customer_change_state.dart b/lib/bloc/customer_change/customer_change_state.dart index 5506468..461f66d 100644 --- a/lib/bloc/customer_change/customer_change_state.dart +++ b/lib/bloc/customer_change/customer_change_state.dart @@ -11,6 +11,10 @@ class CustomerChangeInitial extends CustomerChangeState { const CustomerChangeInitial(); } +class CustomerChangeLoading extends CustomerChangeState { + const CustomerChangeLoading(); +} + class CustomerSaving extends CustomerChangeState { const CustomerSaving(); } diff --git a/lib/bloc/customer_change_form_bloc.dart b/lib/bloc/customer_change_form_bloc.dart index 4c497bf..9829849 100644 --- a/lib/bloc/customer_change_form_bloc.dart +++ b/lib/bloc/customer_change_form_bloc.dart @@ -4,6 +4,9 @@ import 'package:flutter_form_bloc/flutter_form_bloc.dart'; class CustomerChangeFormBloc extends FormBloc { final CustomerRepository customerRepository; + int weight = 60; + int birthYear = 1990; + final emailField = TextFieldBloc( validators: [ FieldBlocValidators.required, @@ -22,31 +25,32 @@ class CustomerChangeFormBloc extends FormBloc { //FieldBlocValidators.confirmPassword(passwordField), ], ); - final birthYearField = TextFieldBloc(); - final weightField = TextFieldBloc(); - final genderField = SelectFieldBloc(); + final birthYearField = InputFieldBloc(initialValue: 1990); + final weightField = InputFieldBloc(initialValue: 60); + final genderField = InputFieldBloc(initialValue: 0); final goalField = TextFieldBloc(); CustomerChangeFormBloc({this.customerRepository}) { addFieldBlocs(fieldBlocs: [ - emailField, - firstNameField, - nameField, - passwordField, - birthYearField, - weightField, - genderField, - - goalField, - ]); + emailField, + firstNameField, + nameField, + passwordField, + birthYearField, + weightField, + genderField, + goalField, + ]); emailField.updateInitialValue(customerRepository.customer.email); firstNameField.updateInitialValue(customerRepository.customer.firstname); nameField.updateInitialValue(customerRepository.customer.name); - birthYearField.updateInitialValue(customerRepository.customer.birthYear.toString()); - weightField.updateInitialValue(customerRepository.customer.weight.toString()); - genderField.updateInitialValue(customerRepository.getGenderByDBValue(customerRepository.sex)); + birthYearField.updateInitialValue(customerRepository.customer.birthYear); + weightField.updateInitialValue(customerRepository.customer.getProperty("weight").toInt()); + + int initialGender = customerRepository.getGenderByDBValue(customerRepository.sex) == "m" ? 0 : 1; + genderField.updateInitialValue(initialGender); firstNameField.onValueChanges(onData: (previous, current) async* { customerRepository.setFirstName(current.value); @@ -54,7 +58,7 @@ class CustomerChangeFormBloc extends FormBloc { nameField.onValueChanges(onData: (previous, current) async* { customerRepository.setName(current.value); }); - birthYearField.onValueChanges(onData: (previous, current) async* { + /*birthYearField.onValueChanges(onData: (previous, current) async* { customerRepository.setBirthYear(current.valueToInt); }); weightField.onValueChanges(onData: (previous, current) async* { @@ -63,24 +67,49 @@ class CustomerChangeFormBloc extends FormBloc { customerRepository.genders.forEach((element) { genderField.addItem(element.name); - }); + });*/ genderField.onValueChanges(onData: (previous, current) async* { - String dbValue = customerRepository.getGenderByName(current.value); + String dbValue = customerRepository.getGenderByName(current.value.toString()); customerRepository.setSex(dbValue); }); + } + int getGender() { + return customerRepository.customer.sex == "M" ? 0 : 1; + } + void switchGender(int index) { + String dbValue; + if (index == 0) { + dbValue = customerRepository.getGenderByName("Man"); + } else if (index == 1) { + dbValue = customerRepository.getGenderByName("Woman"); + } + customerRepository.setSex(dbValue); + genderField.add(UpdateFieldBlocValue(dbValue)); + } + + void changeWeight(int value) { + customerRepository.setWeight(value); + weight = value; + weightField.updateValue(value); + } + + changeBirthYear(int value) { + customerRepository.setBirthYear(value); + birthYear = value; + birthYearField.updateValue(value); } @override void onSubmitting() async { - print("on Submitting Custom form"); + print("on Submitting Customer Change form"); try { emitLoading(progress: 30); // Emit either Loaded or Error await customerRepository.saveCustomer(); - emitSuccess(canSubmitAgain: false); + emitSuccess(canSubmitAgain: true); } on Exception catch (ex) { emitFailure(failureResponse: ex.toString()); } @@ -98,5 +127,4 @@ class CustomerChangeFormBloc extends FormBloc { goalField.close(); return super.close(); } - -} \ No newline at end of file +} diff --git a/lib/bloc/exercise_new/exercise_new_bloc.dart b/lib/bloc/exercise_new/exercise_new_bloc.dart index 27ade8a..57006a3 100644 --- a/lib/bloc/exercise_new/exercise_new_bloc.dart +++ b/lib/bloc/exercise_new/exercise_new_bloc.dart @@ -1,25 +1,212 @@ import 'dart:async'; import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; +import 'package:aitrainer_app/model/cache.dart'; +import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; +import 'package:aitrainer_app/model/fitness_state.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:flutter/animation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; import 'package:meta/meta.dart'; part 'exercise_new_event.dart'; - part 'exercise_new_state.dart'; class ExerciseNewBloc extends Bloc { final ExerciseRepository exerciseRepository; + final CustomerRepository customerRepository; final MenuBloc menuBloc; + AnimationController bmiAnimationController; double quantity = 12; double unitQuantity = 30; + double bmi = 0; + double bmr = 0; + double goalBMI = 0; + double goalWeight = 0; + double bmiAngle = 0; + double bmiTop = 0; + double bmiLeft = 0; + double weight; + double height; + String fitnessLevel; + bool changedWeight = false; + bool changedSizes = false; + final List womanSizes = List(); + final List manSizes = List(); + + double mediaWidth = 0; + double mediaHeight = 0; @override - ExerciseNewBloc({this.exerciseRepository, this.menuBloc, ExerciseType exerciseType}) : super(ExerciseNewInitial()) { + ExerciseNewBloc({this.exerciseRepository, this.menuBloc, this.customerRepository, ExerciseType exerciseType}) + : super(ExerciseNewInitial()) { exerciseRepository.setUnit(exerciseType.unit); + exerciseRepository.setQuantity(quantity); + exerciseRepository.setUnitQuantity(unitQuantity); + if (Cache().userLoggedIn != null) { + customerRepository.customer = Cache().userLoggedIn; + weight = customerRepository.customer.getProperty("Weight"); + height = customerRepository.customer.getProperty("Height"); + fitnessLevel = customerRepository.customer.fitnessLevel; + } + } + + void setMediaDimensions(double width, double height) { + this.mediaHeight = height; + this.mediaWidth = width; + this.addSizes(customerRepository.sex); + } + + void addSizes(String sex) { + List properties = Cache().getProperties(); + if (sex == "Man") { + properties.forEach((element) { + if (element.propertyName == "Shoulder") { + element.top = (mediaHeight * 0.131).toInt(); + element.left = (mediaWidth * 0.23).toInt(); + element.value = customerRepository.customer.getProperty("Shoulder"); + manSizes.add(element); + } else if (element.propertyName == "Neck") { + element.top = (mediaHeight * 0.069).toInt(); + element.left = (mediaWidth * 0.23).toInt(); + element.value = customerRepository.customer.getProperty("Neck"); + manSizes.add(element); + } else if (element.propertyName == "Biceps") { + element.top = (mediaHeight * 0.199).toInt(); + element.left = (mediaWidth * 0.44).toInt(); + element.value = customerRepository.customer.getProperty("Biceps"); + manSizes.add(element); + } else if (element.propertyName == "Chest") { + element.top = (mediaHeight * 0.171).toInt(); + element.left = (mediaWidth * 0.23).toInt(); + element.value = customerRepository.customer.getProperty("Chest"); + manSizes.add(element); + } else if (element.propertyName == "Belly") { + element.top = (mediaHeight * 0.275).toInt(); + element.left = (mediaWidth * 0.23).toInt(); + element.value = customerRepository.customer.getProperty("Belly"); + manSizes.add(element); + } else if (element.propertyName == "Hip") { + element.top = (mediaHeight * 0.355).toInt(); + element.left = (mediaWidth * 0.23).toInt(); + element.value = customerRepository.customer.getProperty("Hip"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Top") { + element.top = (mediaHeight * 0.38).toInt(); + element.left = (mediaWidth * 0.32).toInt(); + element.value = customerRepository.customer.getProperty("Thigh Top"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Middle") { + element.top = (mediaHeight * 0.438).toInt(); + element.left = (mediaWidth * 0.14).toInt(); + element.value = customerRepository.customer.getProperty("Thigh Middle"); + manSizes.add(element); + } else if (element.propertyName == "Knee") { + element.top = (mediaHeight * 0.535).toInt(); + element.left = (mediaWidth * 0.14).toInt(); + element.value = customerRepository.customer.getProperty("Knee"); + manSizes.add(element); + } else if (element.propertyName == "Calf") { + element.top = (mediaHeight * 0.60).toInt(); + element.left = (mediaWidth * 0.14).toInt(); + element.value = customerRepository.customer.getProperty("Calf"); + manSizes.add(element); + } else if (element.propertyName == "Ankle") { + element.top = (mediaHeight * 0.72).toInt(); + element.left = (mediaWidth * 0.28).toInt(); + element.value = customerRepository.customer.getProperty("Ankle"); + manSizes.add(element); + } else if (element.propertyName == "Weight") { + element.top = (mediaHeight * 0.44).toInt(); + element.left = (mediaWidth * 0.54).toInt(); + element.value = customerRepository.customer.getProperty("Weight"); + manSizes.add(element); + } + }); + } else { + properties.forEach((element) { + if (element.propertyName == "Shoulder") { + element.top = (mediaHeight * 0.131).toInt(); + element.left = (mediaWidth * 0.195).toInt(); + element.value = customerRepository.customer.getProperty("Shoulder"); + manSizes.add(element); + } else if (element.propertyName == "Neck") { + element.top = (mediaHeight * 0.081).toInt(); + element.left = (mediaWidth * 0.195).toInt(); + element.value = customerRepository.customer.getProperty("Neck"); + manSizes.add(element); + } else if (element.propertyName == "Biceps") { + element.top = (mediaHeight * 0.199).toInt(); + element.left = (mediaWidth * 0.36).toInt(); + element.value = customerRepository.customer.getProperty("Biceps"); + manSizes.add(element); + } else if (element.propertyName == "Chest") { + element.top = (mediaHeight * 0.168).toInt(); + element.left = (mediaWidth * 0.195).toInt(); + element.value = customerRepository.customer.getProperty("Chest"); + manSizes.add(element); + } else if (element.propertyName == "Belly") { + element.top = (mediaHeight * 0.26).toInt(); + element.left = (mediaWidth * 0.195).toInt(); + element.value = customerRepository.customer.getProperty("Belly"); + manSizes.add(element); + } else if (element.propertyName == "Hip") { + element.top = (mediaHeight * 0.335).toInt(); + element.left = (mediaWidth * 0.195).toInt(); + element.value = customerRepository.customer.getProperty("Hip"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Top") { + element.top = (mediaHeight * 0.385).toInt(); + element.left = (mediaWidth * 0.28).toInt(); + element.value = customerRepository.customer.getProperty("Thigh Top"); + manSizes.add(element); + } else if (element.propertyName == "Thigh Middle") { + element.top = (mediaHeight * 0.433).toInt(); + element.left = (mediaWidth * 0.12).toInt(); + element.value = customerRepository.customer.getProperty("Thigh Middle"); + manSizes.add(element); + } else if (element.propertyName == "Knee") { + element.top = (mediaHeight * 0.543).toInt(); + element.left = (mediaWidth * 0.14).toInt(); + element.value = customerRepository.customer.getProperty("Knee"); + manSizes.add(element); + } else if (element.propertyName == "Calf") { + element.top = (mediaHeight * 0.608).toInt(); + element.left = (mediaWidth * 0.14).toInt(); + element.value = customerRepository.customer.getProperty("Calf"); + manSizes.add(element); + } else if (element.propertyName == "Ankle") { + element.top = (mediaHeight * 0.725).toInt(); + element.left = (mediaWidth * 0.23).toInt(); + element.value = customerRepository.customer.getProperty("Ankle"); + manSizes.add(element); + } else if (element.propertyName == "Weight") { + element.top = (mediaHeight * 0.44).toInt(); + element.left = (mediaWidth * 0.54).toInt(); + element.value = customerRepository.customer.getProperty("Weight"); + manSizes.add(element); + } + }); + } + } + + void updateSizes(String propertyName, double value) { + List sizes; + if (customerRepository.sex == "Man") { + sizes = this.manSizes; + } else { + sizes = this.womanSizes; + } + + sizes.forEach((element) { + if (element.propertyName == propertyName) { + element.value = value; + } + }); } @override @@ -28,26 +215,131 @@ class ExerciseNewBloc extends Bloc { if (event is ExerciseNewLoad) { yield ExerciseNewLoading(); yield ExerciseNewReady(); - } else if ( event is ExerciseNewQuantityChange ) { + } else if (event is ExerciseNewQuantityChange) { yield ExerciseNewLoading(); exerciseRepository.setQuantity(event.quantity); quantity = event.quantity; yield ExerciseNewReady(); - } else if ( event is ExerciseNewQuantityUnitChange ) { + } else if (event is ExerciseNewQuantityUnitChange) { yield ExerciseNewLoading(); exerciseRepository.setUnitQuantity(event.quantity); unitQuantity = event.quantity; yield ExerciseNewReady(); - } else if ( event is ExerciseNewSubmit ) { + } else if (event is ExerciseNewWeightChange) { + yield ExerciseNewLoading(); + customerRepository.setWeight(event.value.toInt()); + changedWeight = true; + weight = event.value; + getBMI(); + getBMR(); + yield ExerciseNewReady(); + } else if (event is ExerciseNewFitnessLevelChange) { + yield ExerciseNewLoading(); + customerRepository.setFitnessLevel(event.value); + fitnessLevel = event.value; + changedWeight = true; + getBMR(); + yield ExerciseNewReady(); + } else if (event is ExerciseNewHeightChange) { + yield ExerciseNewLoading(); + customerRepository.setHeight(event.value.toInt()); + changedWeight = true; + height = event.value; + getBMI(); + getBMR(); + yield ExerciseNewReady(); + } else if (event is ExerciseNewSaveWeight) { + yield ExerciseNewLoading(); + customerRepository.saveCustomer(); + changedWeight = false; + this.changedSizes = false; + yield ExerciseNewReady(); + } else if (event is ExerciseNewSizeChange) { + yield ExerciseNewLoading(); + this.changedSizes = true; + this.updateSizes(event.propertyName, event.value); + customerRepository.setCustomerProperty(event.propertyName, event.value); + yield ExerciseNewReady(); + } else if (event is ExerciseNewSubmit) { yield ExerciseNewLoading(); await exerciseRepository.addExercise(); menuBloc.add(MenuTreeDown(parent: 0)); yield ExerciseNewReady(); + } else if (event is ExerciseNewBMIAnimate) { + yield ExerciseNewLoading(); + yield ExerciseNewReady(); } } on Exception catch (e) { yield ExerciseNewError(message: e.toString()); } } + + double getBMI() { + this.bmi = weight / (height * height / 10000); + this.getGoalBMI(); + return this.bmi; + } + + double getBMR() { + var date = DateTime.now(); + + int year = int.parse(DateFormat(DateFormat.YEAR).format(date)); + + if (customerRepository.customer.sex == "m") { + //66.47 + ( 13.75 × tömeg kg-ban ) + ( 5.003 × magasság cm-ben ) − ( 6.755 × életkor évben kifejezve ) + bmr = 66.47 + (13.75 * weight) + (5.003 * height) - (6.755 * (year - customerRepository.customer.birthYear)); + } else { + //BMR = 655.1 + ( 9.563 × ömeg kg-ban ) + ( 1.85 × magasság cm-ben) − ( 4.676 × életkor évben kifejezve ) + bmr = 655.1 + (9.563 * weight) + (1.85 * height) - (4.676 * (year - customerRepository.customer.birthYear)); + } + + if (customerRepository.customer.fitnessLevel == FitnessState.beginner) { + bmr *= 1.2; + } else if (customerRepository.customer.fitnessLevel == FitnessState.intermediate) { + bmr *= 1.375; + } else if (customerRepository.customer.fitnessLevel == FitnessState.advanced) { + bmr *= 1.55; + } else if (customerRepository.customer.fitnessLevel == FitnessState.professional) { + bmr *= 1.9; + } + return bmr; + } + + double getGoalBMI() { + if (this.bmi == 0) { + getBMI(); + } + //bmi = 15; + this.bmiAngle = (bmi * 90 / 25) - 90; + if (bmi < 18.5) { + goalBMI = 19; + this.bmiTop = 99; + this.bmiLeft = 72; + bmiAngle = -62; + } else if (bmi < 25 && 18.5 < bmi) { + goalBMI = bmi; + this.bmiTop = 46; + this.bmiLeft = 130; + bmiAngle = -21; + } else if (bmi < 30 && 24.9 < bmi) { + goalBMI = 24; + this.bmiTop = 38.0; + this.bmiLeft = 186.0; + } else if (bmi < 34.9 && 29.9 < bmi) { + goalBMI = 29; + bmiTop = 48; + bmiLeft = 211; + } else if (bmi > 35) { + goalBMI = 34; + bmiTop = 94; + bmiLeft = 260; + bmiAngle = 59; + } + + this.goalWeight = goalBMI * (height * height / 10000); + + //print("Angle: " + bmiAngle.toStringAsFixed(1)); + + return goalBMI; + } } - - diff --git a/lib/bloc/exercise_new/exercise_new_event.dart b/lib/bloc/exercise_new/exercise_new_event.dart index 9d60cb4..15013c3 100644 --- a/lib/bloc/exercise_new/exercise_new_event.dart +++ b/lib/bloc/exercise_new/exercise_new_event.dart @@ -28,7 +28,50 @@ class ExerciseNewQuantityUnitChange extends ExerciseNewEvent { List get props => [quantity]; } +class ExerciseNewWeightChange extends ExerciseNewEvent { + final double value; + const ExerciseNewWeightChange({this.value}); + @override + List get props => [value]; +} + +class ExerciseNewHeightChange extends ExerciseNewEvent { + final double value; + const ExerciseNewHeightChange({this.value}); + + @override + List get props => [value]; +} + +class ExerciseNewFitnessLevelChange extends ExerciseNewEvent { + final String value; + const ExerciseNewFitnessLevelChange({this.value}); + + @override + List get props => [value]; +} + +class ExerciseNewSizeChange extends ExerciseNewEvent { + final String propertyName; + final double value; + const ExerciseNewSizeChange({this.propertyName, this.value}); + + @override + List get props => [propertyName, value]; +} + +class ExerciseNewSaveWeight extends ExerciseNewEvent { + const ExerciseNewSaveWeight(); +} + +class ExerciseNewBMIAnimate extends ExerciseNewEvent { + final dynamic value; + const ExerciseNewBMIAnimate({this.value}); + + @override + List get props => [value]; +} + class ExerciseNewSubmit extends ExerciseNewEvent { const ExerciseNewSubmit(); } - diff --git a/lib/library/tree_view.dart b/lib/library/tree_view.dart index a9a832e..580fbbd 100644 --- a/lib/library/tree_view.dart +++ b/lib/library/tree_view.dart @@ -126,8 +126,8 @@ class TreeViewChildState extends State with Common, SingleTicker child: Container( child: AnimatedSwitcher( - duration: Duration(milliseconds:900), - reverseDuration: Duration(milliseconds:500), + duration: Duration(milliseconds:200), + reverseDuration: Duration(milliseconds:200), switchInCurve: Curves.easeIn, child: isExpanded ? Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/model/cache.dart b/lib/model/cache.dart index 5fc1f82..64e518d 100644 --- a/lib/model/cache.dart +++ b/lib/model/cache.dart @@ -4,6 +4,7 @@ import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart'; import 'package:aitrainer_app/model/exercise_tree.dart'; import 'package:aitrainer_app/model/exercise.dart'; +import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/service/exercise_tree_service.dart'; @@ -62,6 +63,7 @@ class Cache { List _exercises; ExercisePlan _myExercisePlan; + List _properties; LinkedHashMap _myExercisesPlanDetails = LinkedHashMap(); @@ -82,7 +84,7 @@ class Cache { Cache._internal() { String testEnv = EnvironmentConfig.test_env; - if ( testEnv == "1") { + if (testEnv == "1") { baseUrl = 'http://aitrainer.app:8899/api/'; } } @@ -136,22 +138,19 @@ class Cache { _traineeExercisePlan = null; _exercises = List(); _myExercisesPlanDetails = LinkedHashMap(); - print("Trainees is null? " + (_trainee == null).toString() ); + print("Trainees is null? " + (_trainee == null).toString()); Future prefs = SharedPreferences.getInstance(); await setPreferences(prefs, SharePrefsChange.logout, 0, ""); } - setPreferences(Future prefs, - SharePrefsChange type, - int customerId, - String firebaseUid) async { + setPreferences(Future prefs, SharePrefsChange type, int customerId, String firebaseUid) async { SharedPreferences sharedPreferences; sharedPreferences = await prefs; DateTime now = DateTime.now(); sharedPreferences.setString(Cache.lastStoreDateKey, now.toString()); ExerciseRepository exerciseRepository = ExerciseRepository(); - if ( type == SharePrefsChange.registration ) { + if (type == SharePrefsChange.registration) { Cache().startPage = "home"; sharedPreferences.setInt(Cache.customerIdKey, customerId); sharedPreferences.setBool(Cache.isRegisteredKey, true); @@ -160,7 +159,7 @@ class Cache { await ExerciseTypeApi().getExerciseTypes(); await ExerciseTreeApi().getExerciseTree(); await exerciseRepository.getExercisesByCustomer(customerId); - } else if ( type == SharePrefsChange.login ) { + } else if (type == SharePrefsChange.login) { Cache().startPage = "home"; sharedPreferences.setInt(Cache.customerIdKey, customerId); sharedPreferences.setString(Cache.firebaseUidKey, firebaseUid); @@ -168,7 +167,7 @@ class Cache { await ExerciseTypeApi().getExerciseTypes(); await ExerciseTreeApi().getExerciseTree(); await exerciseRepository.getExercisesByCustomer(customerId); - } else if ( type == SharePrefsChange.logout ) { + } else if (type == SharePrefsChange.logout) { sharedPreferences.setBool(Cache.isLoggedInKey, false); sharedPreferences.setInt(Cache.customerIdKey, 0); sharedPreferences.setString(Cache.firebaseUidKey, null); @@ -176,23 +175,23 @@ class Cache { } } - void setExerciseTypes( List exerciseTypes) { + void setExerciseTypes(List exerciseTypes) { this._exerciseTypes = exerciseTypes; } - void setExerciseTree( List exerciseTree) { + void setExerciseTree(List exerciseTree) { this._exerciseTree = exerciseTree; } - void setExercises( List exercises ) { + void setExercises(List exercises) { this._exercises = exercises; } - void setExercisesTrainee( List exercises ) { + void setExercisesTrainee(List exercises) { this._exercisesTrainee = exercises; } - void setWorkoutMenuTree( LinkedHashMap tree) { + void setWorkoutMenuTree(LinkedHashMap tree) { this._tree = tree; } @@ -218,7 +217,7 @@ class Cache { void setTrainee(Customer trainee) => _trainee = trainee; - void setTraineeExercisePlan(ExercisePlan exercisePlan) => this._traineeExercisePlan = exercisePlan; + void setTraineeExercisePlan(ExercisePlan exercisePlan) => this._traineeExercisePlan = exercisePlan; ExercisePlan getTraineesExercisePlan() => this._traineeExercisePlan; @@ -226,8 +225,8 @@ class Cache { ExercisePlan getMyExercisePlan() => _myExercisePlan; - void setMyExercisePlanDetails(LinkedHashMap listExercisePlanDetail) - => _myExercisesPlanDetails = listExercisePlanDetail; + void setMyExercisePlanDetails(LinkedHashMap listExercisePlanDetail) => + _myExercisesPlanDetails = listExercisePlanDetail; void addToMyExercisePlanDetails(ExercisePlanDetail detail) => _myExercisesPlanDetails[detail.exerciseTypeId] = detail; @@ -239,16 +238,16 @@ class Cache { this.addToMyExercisePlanDetails(detail); } - void deleteMyExercisePlanDetail(ExercisePlanDetail detail) - => this.deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId); + void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => this.deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId); - void deletedMyExercisePlanDetail(ExercisePlanDetail detail) - => this._myExercisesPlanDetails[detail.exerciseTypeId].change = ExercisePlanDetailChange.deleted; + void deletedMyExercisePlanDetail(ExercisePlanDetail detail) => + this._myExercisesPlanDetails[detail.exerciseTypeId].change = ExercisePlanDetailChange.deleted; void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) { this._myExercisesPlanDetails[exerciseTypeId].change = ExercisePlanDetailChange.delete; } + void setProperties(List properties) => this._properties = properties; - -} \ No newline at end of file + List getProperties() => _properties; +} diff --git a/lib/model/customer.dart b/lib/model/customer.dart index 5e55dd8..8da85f3 100644 --- a/lib/model/customer.dart +++ b/lib/model/customer.dart @@ -1,24 +1,29 @@ +import 'dart:collection'; +import 'customer_property.dart'; + class Customer { - String name; - String email; - String firstname; - String sex; - int age; - String active; - int customerId; - String password; - int birthYear; - int weight; - String goal; - String fitnessLevel; - String bodyType; - int admin; - int trainer; - int dataPolicyAllowed; - String firebaseUid; + String name; + String email; + String firstname; + String sex; + int age; + String active; + int customerId; + String password; + int birthYear; + //int weight; + String goal; + String fitnessLevel; + String bodyType; + int admin; + int trainer; + int dataPolicyAllowed; + String firebaseUid; + LinkedHashMap properties = LinkedHashMap(); - Customer({this.customerId, + Customer({ + this.customerId, this.name, this.firstname, this.email, @@ -30,7 +35,7 @@ class Customer { this.bodyType, this.fitnessLevel, this.goal, - this.weight, + //this.weight, this.admin, this.trainer, this.dataPolicyAllowed, @@ -49,28 +54,39 @@ class Customer { this.bodyType = json['bodyType']; this.fitnessLevel = json['fitnessLevel']; this.goal = json['goal']; - this.weight = json['weight']; + //this.weight = json['weight']; this.admin = json['admin']; this.trainer = json['trainer']; this.firebaseUid = json['firebaseUid']; } - Map toJson() => - { - "name": name, - "firstname": firstname, - "email": email, - "age": age, - "sex": sex, - "active": 'Y', - "password": password, - "birthYear": birthYear, - "bodyType": bodyType, - "fitnessLevel": fitnessLevel, - "goal": goal, - "weight": weight, - "admin": admin, - "trainer": trainer, - "dataPolicyAllowed": dataPolicyAllowed, - }; + Map toJson() => { + "name": name, + "firstname": firstname, + "email": email, + "age": age, + "sex": sex, + "active": 'Y', + "password": password, + "birthYear": birthYear, + "bodyType": bodyType, + "fitnessLevel": fitnessLevel, + "goal": goal, + //"weight": weight, + "admin": admin, + "trainer": trainer, + "dataPolicyAllowed": dataPolicyAllowed, + }; + + 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; + } } diff --git a/lib/model/customer_property.dart b/lib/model/customer_property.dart index e16af67..7f7a61d 100644 --- a/lib/model/customer_property.dart +++ b/lib/model/customer_property.dart @@ -1,3 +1,5 @@ +import 'package:flutter_form_bloc/flutter_form_bloc.dart'; + class CustomerProperty { int propertyId; int customerId; @@ -14,6 +16,10 @@ class CustomerProperty { this.propertyValue = json['propertyValue']; } - Map toJson() => - {"propertyId": this.propertyId, "customerId": this.customerId, "dateAdd": this.dateAdd, "propertyValue": this.propertyValue}; + Map toJson() => { + "propertyId": this.propertyId, + "customerId": this.customerId, + "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), + "propertyValue": this.propertyValue + }; } diff --git a/lib/model/product.dart b/lib/model/product.dart index 417190e..f8a4778 100644 --- a/lib/model/product.dart +++ b/lib/model/product.dart @@ -1,20 +1,17 @@ -class ExerciseTree { - int treeId; - int parentId; +class Product { + int productId; String name; - String imageUrl; - bool active; - String nameTranslation; + String description; + String type; + DateTime validFrom; + DateTime validTo; - ExerciseTree.fromJson(Map json) { - this.treeId = json['treeId']; + Product.fromJson(Map json) { + this.productId = json['productId']; this.name = json['name']; - this.parentId = json['parentId']; - this.imageUrl = json['imageUrl']; - this.active = json['active']; - this.nameTranslation = - json['translations'] != null && (json['translations']).length > 0 - ? json['translations'][0]['name'] - : this.name; + this.description = json['description']; + this.type = json['type']; + this.validFrom = json['validFrom']; + this.validTo = json['validTo']; } } diff --git a/lib/model/product_test.dart b/lib/model/product_test.dart index f8a4778..7a6d788 100644 --- a/lib/model/product_test.dart +++ b/lib/model/product_test.dart @@ -1,17 +1,16 @@ -class Product { +class ProductTest { + int productTestId; + int customerId; int productId; - String name; - String description; - String type; - DateTime validFrom; - DateTime validTo; - Product.fromJson(Map json) { + DateTime dateView; + bool purchaseClick; + + ProductTest.fromJson(Map json) { + this.productTestId = json['productTestId']; + this.customerId = json['customerId']; this.productId = json['productId']; - this.name = json['name']; - this.description = json['description']; - this.type = json['type']; - this.validFrom = json['validFrom']; - this.validTo = json['validTo']; + this.dateView = json['dateView']; + this.purchaseClick = json['purchaseClick']; } } diff --git a/lib/model/property.dart b/lib/model/property.dart index 0752e39..3e63225 100644 --- a/lib/model/property.dart +++ b/lib/model/property.dart @@ -3,14 +3,15 @@ class Property { String propertyName; String propertyUnit; 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; + json['translations'] != null && (json['translations']).length > 0 ? json['translations'][0]['propertyName'] : this.propertyName; } } diff --git a/lib/model/purchase.dart b/lib/model/purchase.dart index f8a4778..57b782a 100644 --- a/lib/model/purchase.dart +++ b/lib/model/purchase.dart @@ -1,17 +1,30 @@ -class Product { - int productId; - String name; - String description; - String type; - DateTime validFrom; - DateTime validTo; +import 'package:flutter_form_bloc/flutter_form_bloc.dart'; - Product.fromJson(Map json) { +class Purchase { + int purchaseId; + int customerId; + int productId; + + DateTime dateAdd; + double purchaseSum; + String currency; + + Purchase.fromJson(Map json) { + this.purchaseId = json['purchaseId']; + this.customerId = json['customerId']; this.productId = json['productId']; - this.name = json['name']; - this.description = json['description']; - this.type = json['type']; - this.validFrom = json['validFrom']; - this.validTo = json['validTo']; + this.dateAdd = json['dateAdd']; + this.purchaseSum = json['purchaseSum']; + this.customerId = json['currency']; } + + Map toJson() => + { + "purchaseId": purchaseId, + "customerId": customerId, + "productId": productId, + "purchaseSum": purchaseSum, + "dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd), + "currency": currency, + }; } diff --git a/lib/repository/customer_repository.dart b/lib/repository/customer_repository.dart index 4c0b520..73bfeeb 100644 --- a/lib/repository/customer_repository.dart +++ b/lib/repository/customer_repository.dart @@ -1,9 +1,13 @@ +import 'dart:collection'; + import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/customer.dart'; +import 'package:aitrainer_app/model/customer_property.dart'; +import 'package:aitrainer_app/repository/property_repository.dart'; import 'package:aitrainer_app/service/customer_service.dart'; class GenderItem { - GenderItem(this.dbValue,this.name); + GenderItem(this.dbValue, this.name); final String dbValue; String name; } @@ -12,6 +16,8 @@ class CustomerRepository { Customer customer; Customer _trainee; List _trainees; + List _allProperties; + final PropertyRepository propertyRepository = PropertyRepository(); //List customerList = List(); bool visibleDetails = false; @@ -76,11 +82,12 @@ class CustomerRepository { setName(String name) { this.customer.name = name; } + setFirstName(String firstName) { this.customer.firstname = firstName; } - setPassword( String password ) { + setPassword(String password) { this.customer.password = password; } @@ -88,24 +95,58 @@ class CustomerRepository { this.customer.email = email; } - setSex(String sex) { this.customer.sex = sex; } - setWeight( int weight) { - this.customer.weight = weight; + setWeight(int weight) { + final propertyName = "Weight"; + this.setCustomerProperty(propertyName, weight.toDouble()); } - setBirthYear( int birthYear ) { + setHeight(int height) { + final propertyName = "Height"; + this.setCustomerProperty(propertyName, height.toDouble()); + } + + setCustomerProperty(String propertyName, double value) { + if (this.customer.properties[propertyName] == null) { + this.customer.properties[propertyName] = CustomerProperty( + propertyId: propertyRepository.getPropertyByName("Height").propertyId, + customerId: this.customer.customerId, + propertyValue: value); + } else { + this.customer.properties[propertyName].propertyValue = value; + } + this.customer.properties[propertyName].dateAdd = DateTime.now(); + this.customer.properties[propertyName].newData = true; + } + + double getWeight() { + return getCustomerProperty("Weight"); + } + + double getHeight() { + return getCustomerProperty("Height"); + } + + double getCustomerProperty(String propertyName) { + if (this.customer.properties[propertyName] == null) { + return 0.0; + } else { + return this.customer.properties[propertyName].propertyValue; + } + } + + setBirthYear(int birthYear) { this.customer.birthYear = birthYear; } - setFitnessLevel( String level ) { + setFitnessLevel(String level) { this.customer.fitnessLevel = level; } - setGoal( String goal ) { + setGoal(String goal) { this.customer.goal = goal; } @@ -121,7 +162,7 @@ class CustomerRepository { return this.customer; } - void setCustomer ( Customer customer ) { + void setCustomer(Customer customer) { this.customer = customer; } @@ -133,32 +174,51 @@ class CustomerRepository { Future saveCustomer() async { final Customer modelCustomer = customer; await CustomerApi().saveCustomer(modelCustomer); + await this.saveProperties(modelCustomer.properties); + } + + Future saveProperties(LinkedHashMap properties) async { + properties.forEach((propertyName, property) async { + if (property.newData == true) { + await CustomerApi().addProperty(property); + property.newData = false; + } + }); } Future getTraineeAsCustomer() async { - this._trainee = await CustomerApi().getTrainee( - Cache().userLoggedIn.customerId - ); + this._trainee = await CustomerApi().getTrainee(Cache().userLoggedIn.customerId); return _trainee; } - Future> getTrainees() async { + Future> getTrainees() async { int trainerId = Cache().userLoggedIn.customerId; - final results = await CustomerApi().getTrainees(trainerId); + final results = await CustomerApi().getTrainees(trainerId); this._trainees = results; return results; - } + } + + Future> getAllCustomerProperties() async { + int customerId = Cache().userLoggedIn.customerId; + final results = await CustomerApi().getAllProperties(customerId); + this._allProperties = results; + return results; + } + + List getAllProperties() { + return this._allProperties; + } List getTraineesList() { return _trainees; } - void setTrainee(int traineeId ) { - if ( _trainees == null ) { + void setTrainee(int traineeId) { + if (_trainees == null) { return; } _trainees.forEach((element) { - if ( traineeId == element.customerId) { + if (traineeId == element.customerId) { this._trainee = element; } }); @@ -178,7 +238,7 @@ class CustomerRepository { return null; } _trainees.forEach((element) { - if ( customerId == element.customerId) { + if (customerId == element.customerId) { this._trainee = element; } }); diff --git a/lib/repository/user_repository.dart b/lib/repository/user_repository.dart index 61666db..266b3a9 100644 --- a/lib/repository/user_repository.dart +++ b/lib/repository/user_repository.dart @@ -34,13 +34,13 @@ class UserRepository { Future getUser() async { final User modelUser = this.user; String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password); - if ( rc == FirebaseApi.SIGN_IN_NOT_FOUND ) { - rc = await FirebaseApi().registerEmail(modelUser.email, modelUser.password); - } + if ( rc == FirebaseApi.SIGN_IN_OK ) { print("Firebase login ok"); await CustomerApi().getUserByEmail(modelUser.email); Cache().afterFirebaseLogin(); + } else { + throw Exception("Exception: Customer does not exist or the password is wrong"); } } diff --git a/lib/service/customer_service.dart b/lib/service/customer_service.dart index 03ba511..453fd3b 100644 --- a/lib/service/customer_service.dart +++ b/lib/service/customer_service.dart @@ -1,5 +1,8 @@ +import 'dart:collection'; import 'dart:convert'; import 'package:aitrainer_app/model/customer.dart'; +import 'package:aitrainer_app/model/customer_property.dart'; +import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/model/user.dart'; import 'package:aitrainer_app/service/api.dart'; import 'package:aitrainer_app/model/cache.dart'; @@ -10,43 +13,32 @@ class CustomerApi { Future> getRealCustomers(String param) async { final body = await _client.get("customers/", param); final Iterable json = jsonDecode(body); - final List customers = json.map((customer) => - Customer.fromJson(customer)).toList(); + final List customers = json.map((customer) => Customer.fromJson(customer)).toList(); return customers; } Future saveCustomer(Customer customer) async { String body = JsonEncoder().convert(customer.toJson()); - print(" ===== saving customer id: " + customer.customerId.toString() + ":" + - body); - await _client.post( - "customers/" + customer.customerId.toString(), - body); + print(" ===== saving customer id: " + customer.customerId.toString() + ":" + body); + await _client.post("customers/" + customer.customerId.toString(), body); } Future updateFirebaseUid(int customerId, String uid) async { - print(" ===== update Firebase uid : " + customerId.toString() + ": " + - uid); - await _client.post( - "customers/update_firebase_uid/" + customerId.toString(), - uid); + print(" ===== update Firebase uid : " + customerId.toString() + ": " + uid); + await _client.post("customers/update_firebase_uid/" + customerId.toString(), uid); } Future addCustomer(Customer customer) async { String body = JsonEncoder().convert(customer.toJson()); print(" ===== add new customer: " + body); - await _client.post( - "customers", - body); + await _client.post("customers", body); } Future addUser(User user) async { String body = JsonEncoder().convert(user.toJson()); print(" ===== add new user: " + body); - final String responseBody = await _client.post( - "registration", - body); + final String responseBody = await _client.post("registration", body); Customer customer; try { int status = jsonDecode(responseBody)['status']; @@ -64,9 +56,7 @@ class CustomerApi { Future getUser(User user) async { String body = JsonEncoder().convert(user.toJson()); print(" ===== login the user: " + body); - final String responseBody = await _client.post( - "login", - body); + final String responseBody = await _client.post("login", body); Customer customer; try { customer = Customer.fromJson(jsonDecode(responseBody)); @@ -78,13 +68,11 @@ class CustomerApi { Future getUserByEmail(String email) async { print(" ===== User getByEmail : " + email); - final String responseBody = await _client.get( - "customers/find_by_email/" + email, - ""); + final String responseBody = await _client.get("customers/find_by_email/" + email, ""); Customer customer; try { customer = Customer.fromJson(jsonDecode(responseBody)); - if ( customer.firebaseUid == null ) { + if (customer.firebaseUid == null) { await this.updateFirebaseUid(customer.customerId, Cache().firebaseUid); } Cache().userLoggedIn = customer; @@ -93,17 +81,17 @@ class CustomerApi { } } - Future getCustomer(int customerId) async { String body = ""; print(" ===== get the customer by id: " + customerId.toString()); try { - final String responseBody = await _client.get( - "customers/" + customerId.toString(), - body); + final String responseBody = await _client.get("customers/" + customerId.toString(), body); Customer customer = Customer.fromJson(jsonDecode(responseBody)); print(" --- Customer: " + customer.toJson().toString()); + final List properties = await this.getActualProperties(customerId); + print(" ---- Props: " + properties.toString()); Cache().afterRegistration(customer); + this._initProperties(properties); } catch (exception) { print("Exception: " + exception.toString()); print(" === go to registration "); @@ -112,14 +100,33 @@ class CustomerApi { } } + void _initProperties(List customerProperties) { + List properties = Cache().getProperties(); + Customer customer = Cache().userLoggedIn; + customer.properties = LinkedHashMap(); + + // reset Properties + properties.forEach((property) { + CustomerProperty customerProperty = + CustomerProperty(propertyId: property.propertyId, customerId: customer.customerId, dateAdd: null, propertyValue: 0); + customer.properties[property.propertyName] = customerProperty; + }); + + customerProperties.forEach((customerProperty) { + properties.forEach((property) { + if (customerProperty.propertyId == property.propertyId) { + customer.properties[property.propertyName] = customerProperty; + } + }); + }); + } + Future getTrainee(int customerId) async { String body = ""; Customer customer; print(" ===== get Trainee customer by id: " + customerId.toString()); try { - final String responseBody = await _client.get( - "customers/" + customerId.toString(), - body); + final String responseBody = await _client.get("customers/" + customerId.toString(), body); customer = Customer.fromJson(jsonDecode(responseBody)); print(" --- Trainee: " + customer.toJson().toString()); } catch (exception) { @@ -134,10 +141,7 @@ class CustomerApi { print("Get trainees list"); try { String body = ""; - final String responseBody = await _client.get( - "customers/trainees/" + trainerId.toString(), - 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) { @@ -146,4 +150,39 @@ class CustomerApi { } return trainees; } -} \ No newline at end of file + + Future> getAllProperties(int customerId) async { + final body = await _client.get("customer_property/", customerId.toString()); + final Iterable json = jsonDecode(body); + final List properties = json.map((property) => CustomerProperty.fromJson(property)).toList(); + + return properties; + } + + Future> getActualProperties(int customerId) async { + final body = await _client.get("customer_property/last/", customerId.toString()); + final Iterable json = jsonDecode(body); + final List properties = json.map((property) => CustomerProperty.fromJson(property)).toList(); + + return properties; + } + + Future addProperty(CustomerProperty property) async { + String body = JsonEncoder().convert(property.toJson()); + print(" ===== add new customer property: " + body); + final String responseBody = await _client.post("customer_property", body); + try { + int status = jsonDecode(responseBody)['status']; + if (status != null) { + throw new Exception(jsonDecode(responseBody)['error']); + } else { + CustomerProperty customerProperty = CustomerProperty.fromJson(jsonDecode(responseBody)); + if (customerProperty == null) { + throw new Exception("Property Insert was not successful"); + } + } + } on FormatException { + throw new Exception(responseBody); + } + } +} diff --git a/lib/service/firebase_api.dart b/lib/service/firebase_api.dart index 09747fa..ec72675 100644 --- a/lib/service/firebase_api.dart +++ b/lib/service/firebase_api.dart @@ -22,8 +22,6 @@ class FirebaseApi { _instance = this; } - - // Define an async function to initialize FlutterFire Future initializeFlutterFire() async { try { @@ -38,10 +36,7 @@ class FirebaseApi { Future signInEmail(String email, String password) async { String rc = SIGN_IN_OK; try { - userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword( - email: email, - password: password - ); + userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password); Cache().firebaseUid = userCredential.user.uid; } on FirebaseAuthException catch (e) { if (e.code == 'user-not-found') { @@ -60,10 +55,7 @@ class FirebaseApi { Future registerEmail(String email, String password) async { String rc = SIGN_IN_OK; try { - userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: email, - password: password - ); + userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password); Cache().firebaseUid = userCredential.user.uid; } on FirebaseAuthException catch (e) { if (e.code == 'weak-password') { @@ -73,12 +65,9 @@ class FirebaseApi { } else if (e.code == 'email-already-in-use') { print('The account already exists for that email.'); rc = REGISTER_EMAIL_IN_USE; - userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword( - email: email, - password: password - ); - if ( rc != null ) { - String rc = SIGN_IN_OK; + userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password); + if (rc != null) { + rc = SIGN_IN_OK; } } } catch (e) { @@ -93,8 +82,7 @@ class FirebaseApi { final LoginResult result = await FacebookAuth.instance.login(); // Create a credential from the access token - final FacebookAuthCredential facebookAuthCredential = - FacebookAuthProvider.credential(result.accessToken.token); + final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(result.accessToken.token); // Once signed in, return the UserCredential return await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential); @@ -107,4 +95,4 @@ class FirebaseApi { Future resetPassword(String email) async { await FirebaseAuth.instance.sendPasswordResetEmail(email: email); } -} \ No newline at end of file +} diff --git a/lib/util/session.dart b/lib/util/session.dart index 27b0511..f35fc5f 100644 --- a/lib/util/session.dart +++ b/lib/util/session.dart @@ -6,6 +6,7 @@ import 'package:aitrainer_app/service/customer_service.dart'; import 'package:aitrainer_app/service/exercise_tree_service.dart'; import 'package:aitrainer_app/service/exercisetype_service.dart'; import 'package:aitrainer_app/service/firebase_api.dart'; +import 'package:aitrainer_app/service/property_service.dart'; import 'package:devicelocale/devicelocale.dart'; import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -14,34 +15,29 @@ import 'package:firebase_core/firebase_core.dart'; //import '../push_notifications.dart'; -class Session { - +class Session { Future _prefs = SharedPreferences.getInstance(); SharedPreferences _sharedPreferences; - fetchSessionAndNavigate( ) async { - print (" -- Session: await prefs.."); + fetchSessionAndNavigate() async { + print(" -- Session: await prefs.."); _sharedPreferences = await _prefs; - - if ( Cache().firstLoad ) { - - print (" -- Session: fetch locale.."); + if (Cache().firstLoad) { + print(" -- Session: fetch locale.."); await AppLanguage().getLocale(_sharedPreferences); await AppLocalizations.delegate.load(AppLanguage().appLocal); - print (" -- Session: fetch token.."); + print(" -- Session: fetch token.."); await _fetchToken(_sharedPreferences); - print (" -- FireBase init.."); + print(" -- FireBase init.."); await FirebaseApi().initializeFlutterFire(); //initDeviceLocale(); // Create the initialization Future outside of `build`: - - // PushNotificationsManager().init(); + // PushNotificationsManager().init(); } - } Future initDeviceLocale() async { @@ -53,7 +49,6 @@ class Session { languages = await Devicelocale.preferredLanguages; Cache().deviceLanguages = languages; print("device langs " + languages.toString()); - } on PlatformException { print("Error obtaining preferred languages"); } @@ -69,14 +64,10 @@ class Session { Auth flow of the user, see auth.dart */ _fetchToken(SharedPreferences prefs) async { - - var responseJson = await APIClient.authenticateUser( - Cache.username, - Cache.password - ); + var responseJson = await APIClient.authenticateUser(Cache.username, Cache.password); int customerId = 0; print("--- Lang: " + AppLanguage().appLocal.toString()); - if(responseJson['error'] != null) { + if (responseJson['error'] != null) { print("************** Here big error - no authentication"); } else if (responseJson['token'] != null) { prefs.setString(Cache.authTokenKey, responseJson['token']); @@ -89,8 +80,7 @@ class Session { Cache().startPage = "registration"; } else { DateTime now = DateTime.now(); - DateTime lastStoreDate = DateTime.parse( - prefs.get(Cache.lastStoreDateKey)); + DateTime lastStoreDate = DateTime.parse(prefs.get(Cache.lastStoreDateKey)); DateTime minStoreDate = now.add(Duration(days: -10)); if (lastStoreDate == null || @@ -100,14 +90,14 @@ class Session { print("************* Login"); Cache().startPage = "login"; } else { - // only - if ( Cache().firebaseUid == null) { + if (Cache().firebaseUid == null) { print("************* firebaseUid is null, Login"); Cache().startPage = "login"; } else { // get API customer customerId = prefs.getInt(Cache.customerIdKey); + await PropertyApi().getProperties(); await CustomerApi().getCustomer(customerId); Cache().startPage = "home"; } @@ -115,13 +105,12 @@ class Session { await ExerciseTypeApi().getExerciseTypes(); await ExerciseTreeApi().getExerciseTree(); - if ( customerId > 0) { + if (customerId > 0) { ExerciseRepository exerciseRepository = ExerciseRepository(); await exerciseRepository.getExercisesByCustomer(customerId); } print("--- Session finished"); - } } } -} \ No newline at end of file +} diff --git a/lib/util/trans.dart b/lib/util/trans.dart index 6b4e5c0..c2313ed 100644 --- a/lib/util/trans.dart +++ b/lib/util/trans.dart @@ -10,4 +10,6 @@ mixin Trans { String t(String text) { return AppLocalizations.of(context).translate(text); } + + } \ No newline at end of file diff --git a/lib/view/account.dart b/lib/view/account.dart index 049cc07..07529fc 100644 --- a/lib/view/account.dart +++ b/lib/view/account.dart @@ -2,6 +2,7 @@ import 'package:aitrainer_app/bloc/account/account_bloc.dart'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/model/customer.dart'; import 'package:aitrainer_app/util/trans.dart'; +import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:flutter/material.dart'; @@ -17,17 +18,8 @@ class AccountPage extends StatelessWidget with Trans { setContext(context); accountBloc = BlocProvider.of(context); return Scaffold( - appBar: AppBar( - title: Text(t('Account')), - backgroundColor: Colors.transparent, - ), + appBar: AppBarMin(), body: Container( - foregroundDecoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_long_logo.png'), - alignment: Alignment.topRight, - ), - ), decoration: BoxDecoration( image: DecorationImage( image: AssetImage('asset/image/WT_light_background.png'), @@ -35,79 +27,64 @@ class AccountPage extends StatelessWidget with Trans { alignment: Alignment.center, ), ), - child: BlocConsumer( - listener: (context, state) { - if (state is AccountError) { - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, - content: - Text(state.message, style: TextStyle(color: Colors.white)))); - } else if (state is AccountLoading) { - - } - }, - builder: (context, state) { - if ( state is AccountInitial ) { - String customerName = accountBloc.customerRepository.firstName + - " " + accountBloc.customerRepository.name; - return accountWidget(context, customerName, accountBloc); - } else if ( state is AccountLoggedIn ) { - String customerName = accountBloc.customerRepository.firstName + - " " + accountBloc.customerRepository.name; - return accountWidget(context, customerName, accountBloc); - } else if ( state is AccountLoggedOut ) { - String customerName = ""; - return accountWidget(context, customerName, accountBloc); - } else if ( state is AccountReady ) { - String customerName = accountBloc.customerRepository.firstName + - " " + accountBloc.customerRepository.name; - return accountWidget(context, customerName, accountBloc); - } else { - return accountWidget(context, "", accountBloc); - } - + child: BlocConsumer(listener: (context, state) { + if (state is AccountError) { + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); + } else if (state is AccountLoading) {} + }, builder: (context, state) { + if (state is AccountInitial) { + String customerName = accountBloc.customerRepository.firstName + " " + accountBloc.customerRepository.name; + return accountWidget(context, customerName, accountBloc); + } else if (state is AccountLoggedIn) { + String customerName = accountBloc.customerRepository.firstName + " " + accountBloc.customerRepository.name; + return accountWidget(context, customerName, accountBloc); + } else if (state is AccountLoggedOut) { + String customerName = ""; + return accountWidget(context, customerName, accountBloc); + } else if (state is AccountReady) { + String customerName = accountBloc.customerRepository.firstName + " " + accountBloc.customerRepository.name; + return accountWidget(context, customerName, accountBloc); + } else { + return accountWidget(context, "", accountBloc); } - ), + }), ), bottomNavigationBar: BottomNavigator(bottomNavIndex: 3)); } ListView accountWidget(BuildContext context, String customerName, AccountBloc accountBloc) { - return ListView(padding: EdgeInsets.only(top: 135), children: [ + return ListView(padding: EdgeInsets.only(top: 35), children: [ ListTile( leading: Icon(Icons.perm_identity), - subtitle: - Text(t("Profile")), + subtitle: Text(t("Profile")), title: FlatButton( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(customerName, - style: TextStyle(color: Colors.blue)), - Icon(Icons.arrow_forward_ios), - ]), + child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(customerName, style: TextStyle(color: Colors.blue)), + Icon(Icons.arrow_forward_ios), + ]), textColor: Colors.grey, color: Colors.white, onPressed: () => { - if (accountBloc.customerRepository.customer != null) { - Navigator.of(context).pushNamed('customerModifyPage'), - print("Profile"), - } + if (accountBloc.customerRepository.customer != null) + { + Navigator.of(context).pushNamed('customerModifyPage'), + } }, ), ), - loginOut( context, accountBloc ), + loginOut(context, accountBloc), getMyTrainees(context, accountBloc), ]); } - ListTile loginOut( BuildContext context, AccountBloc accountBloc ) { + ListTile loginOut(BuildContext context, AccountBloc accountBloc) { ListTile element = ListTile(); String text = "Logout"; Color buttonColor = Colors.orange; - if ( accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer.email == null) { + if (accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer.email == null) { text = "Login"; buttonColor = Colors.blue; } @@ -116,25 +93,22 @@ class AccountPage extends StatelessWidget with Trans { enabled: true, leading: Icon(Icons.input), title: FlatButton( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(t(text), - style: TextStyle( - color: buttonColor - )), - Icon(Icons.arrow_forward_ios), - ]), + child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(t(text), style: TextStyle(color: buttonColor)), + Icon(Icons.arrow_forward_ios), + ]), textColor: buttonColor, color: Colors.white, onPressed: () => { - if ( accountBloc.loggedIn ) { - confirmationDialog( accountBloc ), - } else { - accountBloc.add(AccountLogin()), - Navigator.of(context).pushNamed('login'), - } - + if (accountBloc.loggedIn) + { + confirmationDialog(accountBloc), + } + else + { + accountBloc.add(AccountLogin()), + Navigator.of(context).pushNamed('login'), + } }, ), ); @@ -142,17 +116,17 @@ class AccountPage extends StatelessWidget with Trans { return element; } - Widget getMyTrainees( BuildContext context, AccountBloc accountBloc ) { - if ( accountBloc.customerRepository.customer == null ) { + Widget getMyTrainees(BuildContext context, AccountBloc accountBloc) { + if (accountBloc.customerRepository.customer == null) { return Container(); } - if ( accountBloc.customerRepository.customer.trainer == 0 ) { + if (accountBloc.customerRepository.customer.trainer == 0) { return ListTile( title: Container(), ); } - if (accountBloc.customerRepository.getTraineesList() == null ) { + if (accountBloc.customerRepository.getTraineesList() == null) { return ListTile( leading: Icon(Icons.people), title: RaisedButton( @@ -161,7 +135,6 @@ class AccountPage extends StatelessWidget with Trans { child: Text("See my trainees"), ), ); - } List elements = List(); @@ -169,74 +142,64 @@ class AccountPage extends StatelessWidget with Trans { Customer trainee = element; String name = trainee.name; String firstName = trainee.firstname; - String nodeName = AppLanguage().appLocal == Locale("en") ? - firstName + " " + name : name + " " + firstName; + String nodeName = AppLanguage().appLocal == Locale("en") ? firstName + " " + name : name + " " + firstName; bool selected = accountBloc.traineeId == trainee.customerId; Widget widget = FlatButton( padding: EdgeInsets.all(10), - shape:RoundedRectangleBorder( + shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(8)), - side: BorderSide(width: 2, color: selected ? Colors.blue : Colors.black26 ), + side: BorderSide(width: 2, color: selected ? Colors.blue : Colors.black26), ), onPressed: () { accountBloc.add(AccountSelectTrainee(traineeId: trainee.customerId)); //Navigator.of(context).pushNamed('login'); }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(nodeName, style: - TextStyle( - color: selected ? Colors.blue : Colors.black54, - fontWeight: selected ? FontWeight.bold : FontWeight.normal - ), - ), - Icon(Icons.arrow_forward_ios), - ]), + child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text( + nodeName, + style: TextStyle(color: selected ? Colors.blue : Colors.black54, fontWeight: selected ? FontWeight.bold : FontWeight.normal), + ), + Icon(Icons.arrow_forward_ios), + ]), ); elements.add(widget); }); return ListTile( - leading: Icon(Icons.people), - subtitle: Text("My Trainees"), - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: elements, - ) - ); + leading: Icon(Icons.people), + subtitle: Text("My Trainees"), + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: elements, + )); } void confirmationDialog(AccountBloc accountBloc) { showCupertinoDialog( - useRootNavigator: true, - context: context, - //barrierDismissible: false, - builder:(_) => CupertinoAlertDialog( - title: Text(t("Are you sure to logout?")), - content: Column( - - children: [ - Divider(), - ]), - actions: [ - FlatButton( - child: Text(t("No")), - onPressed: () => Navigator.pop(context), - ), - FlatButton( - child: Text(t("Yes")), - onPressed: () => { - accountBloc.add(AccountLogout()), - Navigator.pop(context), - }, - ) - ], - ) - ); + useRootNavigator: true, + context: context, + //barrierDismissible: false, + builder: (_) => CupertinoAlertDialog( + title: Text(t("Are you sure to logout?")), + content: Column(children: [ + Divider(), + ]), + actions: [ + FlatButton( + child: Text(t("No")), + onPressed: () => Navigator.pop(context), + ), + FlatButton( + child: Text(t("Yes")), + onPressed: () => { + accountBloc.add(AccountLogout()), + Navigator.pop(context), + }, + ) + ], + )); } - } diff --git a/lib/view/customer_fitness_page.dart b/lib/view/customer_fitness_page.dart index e71bc77..04c63f7 100644 --- a/lib/view/customer_fitness_page.dart +++ b/lib/view/customer_fitness_page.dart @@ -1,6 +1,7 @@ import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/repository/customer_repository.dart'; +import 'package:aitrainer_app/model/fitness_state.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -16,13 +17,13 @@ class CustomerFitnessPage extends StatefulWidget { } } -class FitnessItem { +/* class FitnessItem { static String beginner = "beginner"; static String intermediate = "intermediate"; static String advanced = "advanced"; static String professional = "professional"; } - + */ //TODO // dropbox for professional sport @@ -32,8 +33,7 @@ class _CustomerFitnessPageState extends State { @override Widget build(BuildContext context) { final double cWidth = MediaQuery.of(context).size.width * 0.75; - final CustomerRepository customerRepository = - ModalRoute.of(context).settings.arguments; + final CustomerRepository customerRepository = ModalRoute.of(context).settings.arguments; selected = customerRepository.customer.fitnessLevel; return Scaffold( appBar: AppBar( @@ -50,12 +50,10 @@ class _CustomerFitnessPageState extends State { backgroundColor: Colors.transparent, ), body: BlocProvider( - create: (context) => - CustomerChangeBloc(customerRepository: customerRepository), + create: (context) => CustomerChangeBloc(customerRepository: customerRepository), child: Builder(builder: (context) { // ignore: close_sinks - CustomerChangeBloc changeBloc = - BlocProvider.of(context); + CustomerChangeBloc changeBloc = BlocProvider.of(context); return SingleChildScrollView( scrollDirection: Axis.vertical, @@ -77,14 +75,9 @@ class _CustomerFitnessPageState extends State { alignment: WrapAlignment.center, children: [ Text( - AppLocalizations.of(context) - .translate("Your Fitness State"), + AppLocalizations.of(context).translate("Your Fitness State"), textAlign: TextAlign.center, - style: TextStyle( - color: Colors.orange, - fontSize: 42, - fontFamily: 'Arial', - fontWeight: FontWeight.w900), + style: TextStyle(color: Colors.orange, fontSize: 42, fontFamily: 'Arial', fontWeight: FontWeight.w900), ) ]), Divider(), @@ -93,33 +86,20 @@ class _CustomerFitnessPageState extends State { width: cWidth, child: Column( children: [ + Text(AppLocalizations.of(context).translate("Beginner"), + textWidthBasis: TextWidthBasis.longestLine, + style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900)), Text( - AppLocalizations.of(context) - .translate("Beginner"), - textWidthBasis: - TextWidthBasis.longestLine, - style: TextStyle( - color: Colors.blue, - fontSize: 32, - fontFamily: 'Arial', - fontWeight: FontWeight.w900)), - Text( - AppLocalizations.of(context) - .translate("I am beginner"), - style: TextStyle( - color: Colors.black, - fontSize: 20, - fontFamily: 'Arial', - fontWeight: FontWeight.w100), + AppLocalizations.of(context).translate("I am beginner"), + style: TextStyle(color: Colors.black, fontSize: 20, fontFamily: 'Arial', fontWeight: FontWeight.w100), ), ], )), padding: EdgeInsets.all(10.0), - shape: getShape( - customerRepository, FitnessItem.beginner), + shape: getShape(customerRepository, FitnessState.beginner), onPressed: () => { setState(() { - selected = FitnessItem.beginner; + selected = FitnessState.beginner; changeBloc.add(CustomerFitnessChange(fitness: selected)); print(selected); }), @@ -132,25 +112,15 @@ class _CustomerFitnessPageState extends State { children: [ InkWell( child: Text( - AppLocalizations.of(context) - .translate("Intermediate"), - style: TextStyle( - color: Colors.blue, - fontSize: 32, - fontFamily: 'Arial', - fontWeight: FontWeight.w900), + AppLocalizations.of(context).translate("Intermediate"), + style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), ), highlightColor: Colors.white, ), InkWell( child: Text( - AppLocalizations.of(context) - .translate("I am intermediate"), - style: TextStyle( - color: Colors.black, - fontSize: 20, - fontFamily: 'Arial', - fontWeight: FontWeight.w100), + AppLocalizations.of(context).translate("I am intermediate"), + style: TextStyle(color: Colors.black, fontSize: 20, fontFamily: 'Arial', fontWeight: FontWeight.w100), ), highlightColor: Colors.white, ), @@ -158,11 +128,10 @@ class _CustomerFitnessPageState extends State { ), ), padding: EdgeInsets.all(10.0), - shape: getShape( - customerRepository, FitnessItem.intermediate), + shape: getShape(customerRepository, FitnessState.intermediate), onPressed: () => { setState(() { - selected = FitnessItem.intermediate; + selected = FitnessState.intermediate; changeBloc.add(CustomerFitnessChange(fitness: selected)); print(selected); }), @@ -175,25 +144,15 @@ class _CustomerFitnessPageState extends State { children: [ InkWell( child: Text( - AppLocalizations.of(context) - .translate("Advanced"), - style: TextStyle( - color: Colors.blue, - fontSize: 32, - fontFamily: 'Arial', - fontWeight: FontWeight.w900), + AppLocalizations.of(context).translate("Advanced"), + style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), ), highlightColor: Colors.white, ), InkWell( child: Text( - AppLocalizations.of(context) - .translate("I am advanced"), - style: TextStyle( - color: Colors.black, - fontSize: 20, - fontFamily: 'Arial', - fontWeight: FontWeight.w100), + AppLocalizations.of(context).translate("I am advanced"), + style: TextStyle(color: Colors.black, fontSize: 20, fontFamily: 'Arial', fontWeight: FontWeight.w100), ), highlightColor: Colors.white, ), @@ -201,11 +160,10 @@ class _CustomerFitnessPageState extends State { ), ), padding: EdgeInsets.all(10.0), - shape: getShape( - customerRepository, FitnessItem.advanced), + shape: getShape(customerRepository, FitnessState.advanced), onPressed: () => { setState(() { - selected = FitnessItem.advanced; + selected = FitnessState.advanced; changeBloc.add(CustomerFitnessChange(fitness: selected)); print(selected); }), @@ -218,25 +176,15 @@ class _CustomerFitnessPageState extends State { children: [ InkWell( child: Text( - AppLocalizations.of(context) - .translate("Professional"), - style: TextStyle( - color: Colors.blue, - fontSize: 32, - fontFamily: 'Arial', - fontWeight: FontWeight.w900), + AppLocalizations.of(context).translate("Professional"), + style: TextStyle(color: Colors.blue, fontSize: 32, fontFamily: 'Arial', fontWeight: FontWeight.w900), ), highlightColor: Colors.white, ), InkWell( child: Text( - AppLocalizations.of(context) - .translate("I am professional"), - style: TextStyle( - color: Colors.black, - fontSize: 20, - fontFamily: 'Arial', - fontWeight: FontWeight.w100), + AppLocalizations.of(context).translate("I am professional"), + style: TextStyle(color: Colors.black, fontSize: 20, fontFamily: 'Arial', fontWeight: FontWeight.w100), ), highlightColor: Colors.white, ), @@ -244,11 +192,10 @@ class _CustomerFitnessPageState extends State { ), ), padding: EdgeInsets.all(10.0), - shape: getShape( - customerRepository, FitnessItem.professional), + shape: getShape(customerRepository, FitnessState.professional), onPressed: () => { setState(() { - selected = FitnessItem.professional; + selected = FitnessState.professional; changeBloc.add(CustomerFitnessChange(fitness: selected)); print(selected); }), @@ -257,15 +204,11 @@ class _CustomerFitnessPageState extends State { RaisedButton( color: Colors.orange, textColor: Colors.white, - child: InkWell( - child: Text(AppLocalizations.of(context) - .translate("Next"))), + child: InkWell(child: Text(AppLocalizations.of(context).translate("Next"))), onPressed: () => { changeBloc.add(CustomerSave()), Navigator.of(context).pop(), - Navigator.of(context).pushNamed( - "customerBodyTypePage", - arguments: customerRepository) + Navigator.of(context).pushNamed("customerBodyTypePage", arguments: customerRepository) }, ) ], diff --git a/lib/view/customer_modify_page.dart b/lib/view/customer_modify_page.dart index a1e7d13..6a38d4f 100644 --- a/lib/view/customer_modify_page.dart +++ b/lib/view/customer_modify_page.dart @@ -1,17 +1,21 @@ import 'package:aitrainer_app/bloc/account/account_bloc.dart'; -import 'package:aitrainer_app/bloc/customer_change_form_bloc.dart'; +import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart'; +import 'package:aitrainer_app/library/numberpicker.dart'; import 'package:aitrainer_app/util/trans.dart'; +import 'package:aitrainer_app/widgets/app_bar_min.dart'; +import 'package:aitrainer_app/widgets/splash.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; -import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_form_bloc/flutter_form_bloc.dart'; + +import 'package:toggle_switch/toggle_switch.dart'; import '../library_keys.dart'; // ignore: must_be_immutable class CustomerModifyPage extends StatelessWidget with Trans { - final _formKey = GlobalKey(); + final GlobalKey _scaffoldKey = new GlobalKey(); @override Widget build(BuildContext context) { @@ -20,180 +24,268 @@ class CustomerModifyPage extends StatelessWidget with Trans { final accountBloc = BlocProvider.of(context); return BlocProvider( - create: (context) => CustomerChangeFormBloc(customerRepository: accountBloc.customerRepository), + create: (context) => CustomerChangeBloc(customerRepository: accountBloc.customerRepository)..add(CustomerLoad()), child: Builder(builder: (context) { // ignore: close_sinks - final customerBloc = BlocProvider.of(context); + final customerBloc = BlocProvider.of(context); return Scaffold( resizeToAvoidBottomInset: true, - appBar: AppBar( - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("Profil"), - Image.asset( - 'asset/image/WT_long_logo.png', - fit: BoxFit.cover, - height: 65.0, - ), - ], - ), - //title: Text(AppLocalizations.of(context).translate('Settings')), - backgroundColor: Colors.transparent, + appBar: AppBarMin( + back: true, ), body: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('asset/image/WT_light_background.png'), - fit: BoxFit.cover, + fit: BoxFit.fill, alignment: Alignment.center, ), ), - child: Form( - key: _formKey, - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 40, left: 25, right: 45, bottom: 100), - child: Container( - alignment: Alignment.center, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFieldBlocBuilder( - key: LibraryKeys.loginEmailField, - style: TextStyle(fontSize: 12), - textFieldBloc: customerBloc.emailField, - decoration: InputDecoration( - fillColor: Colors.white24, - filled: true, - labelText: t('Email'), - ), - ), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFieldBlocBuilder( - style: TextStyle(fontSize: 12), - textFieldBloc: customerBloc.passwordField, - suffixButton: SuffixButton.obscureText, - decoration: InputDecoration( - fillColor: Colors.white24, - filled: true, - labelText: t('Password (Leave empty if no change)'), - ), - ), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFieldBlocBuilder( - style: TextStyle(fontSize: 12), - textFieldBloc: customerBloc.nameField, - decoration: InputDecoration( - fillColor: Colors.white24, - filled: true, - labelText: t('Name'), - ), - ), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFieldBlocBuilder( - style: TextStyle(fontSize: 12), - textFieldBloc: customerBloc.firstNameField, - decoration: InputDecoration( - fillColor: Colors.white24, - filled: true, - labelText: t('First Name'), - ), - ), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFieldBlocBuilder( - style: TextStyle(fontSize: 12), - textFieldBloc: customerBloc.birthYearField, - inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d]"))], - decoration: InputDecoration( - fillColor: Colors.white24, - filled: true, - labelText: t('Birth Year'), - ), - ), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: TextFieldBlocBuilder( - style: TextStyle(fontSize: 12), - textFieldBloc: customerBloc.weightField, - inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d]"))], - decoration: InputDecoration( - fillColor: Colors.white24, - filled: true, - labelText: t('Weight'), - ), - ), - ) - ], - ), - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: DropdownFieldBlocBuilder( - selectFieldBloc: customerBloc.genderField, - itemBuilder: (context, item) => item, - decoration: InputDecoration( - labelText: t('Select a gender'), - )), - ) - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Expanded( - child: RaisedButton( - color: Colors.orange, - textColor: Colors.white, - child: InkWell(child: Text(t("Next"))), - onPressed: () => { - customerBloc.add(SubmitFormBloc()), - Navigator.of(context) - .pushNamed("customerGoalPage", arguments: customerBloc.customerRepository) - }, - )) - ], - ), - ], - ), - ), - ), + child: BlocConsumer( + listener: (context, state) { + if (state is CustomerChangeLoading) { + LoadingDialog(); + } else if (state is CustomerSaveError) { + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); + } else if (state is CustomerSaveSuccess) { + Navigator.of(context).pushNamed("customerGoalPage", arguments: customerBloc.customerRepository); + } + }, + builder: (context, state) { + return loadForm(customerBloc); + }, ))); })); } + + Widget loadForm(CustomerChangeBloc customerBloc) { + return Form( + key: _scaffoldKey, + autovalidateMode: AutovalidateMode.always, + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + padding: EdgeInsets.only(top: 40, left: 25, right: 25, bottom: 250), + child: Container( + alignment: Alignment.center, + child: Column( + children: [ + TextFormField( + key: LibraryKeys.loginEmailField, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + labelText: t('Email'), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 4.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + initialValue: customerBloc.customerRepository.customer.email, + autovalidateMode: AutovalidateMode.always, + validator: (val) { + return customerBloc.emailValidation(val); + }, + keyboardType: TextInputType.emailAddress, + style: new TextStyle(fontSize: 16, color: Colors.indigo), + ), + Divider( + color: Colors.transparent, + ), + TextFormField( + key: LibraryKeys.loginPasswordField, + obscureText: true, + decoration: InputDecoration( + labelStyle: TextStyle(fontSize: 14), + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + suffixIcon: IconButton( + onPressed: () => {customerBloc.add(CustomerChangePasswordObscure())}, + icon: Icon(Icons.remove_red_eye), + ), + labelText: t('Password (Leave empty if no change)'), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 1.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + initialValue: customerBloc.customerRepository.customer.password, + autovalidateMode: AutovalidateMode.always, + validator: (val) { + return customerBloc.passwordValidation(val); + }, + keyboardType: TextInputType.visiblePassword, + style: new TextStyle(fontSize: 16, color: Colors.indigo), + ), + Divider( + color: Colors.transparent, + ), + TextFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + labelText: t('Name'), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 1.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + initialValue: customerBloc.customerRepository.customer.name, + autovalidateMode: AutovalidateMode.always, + validator: (val) { + return customerBloc.nameValidation(val); + }, + keyboardType: TextInputType.name, + style: new TextStyle(fontSize: 16, color: Colors.indigo), + onChanged: (value) => {customerBloc.add(CustomerNameChange(name: value))}), + Divider( + color: Colors.transparent, + ), + TextFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 15, bottom: 15), + labelText: t('First Name'), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 2.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + initialValue: customerBloc.customerRepository.customer.firstname, + autovalidateMode: AutovalidateMode.always, + validator: (val) { + return customerBloc.nameValidation(val); + }, + keyboardType: TextInputType.name, + style: new TextStyle(fontSize: 16, color: Colors.indigo), + onChanged: (value) => {customerBloc.add(CustomerFirstNameChange(firstName: value))}), + Divider( + color: Colors.transparent, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 4, + child: Text(t("Birth Year"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14)), + ), + Flexible( + fit: FlexFit.tight, + flex: 8, + child: NumberPicker.horizontal( + highlightSelectedValue: true, + initialValue: customerBloc.year, + minValue: 1930, + maxValue: 2100, + + step: 1, + textStyle: TextStyle(fontWeight: FontWeight.bold), + textStyleHighlighted: TextStyle(fontSize: 16, color: Colors.indigo, fontWeight: FontWeight.bold), + onChanged: (value) => {customerBloc.add(CustomerBirthYearChange(year: value))}, + listViewHeight: 60, + //decoration: _decoration, + ), + ), + SizedBox(width: 80), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 4, + child: Text(t("Weight"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14)), + ), + Flexible( + fit: FlexFit.tight, + flex: 8, + child: NumberPicker.horizontal( + highlightSelectedValue: true, + initialValue: customerBloc.weight.toInt(), + minValue: 0, + maxValue: 200, + step: 1, + textStyle: TextStyle(fontWeight: FontWeight.bold), + textStyleHighlighted: TextStyle(fontSize: 18, color: Colors.indigo, fontWeight: FontWeight.bold), + onChanged: (value) => {customerBloc.add(CustomerWeightChange(weight: value))}, + listViewHeight: 60, + ), + ), + SizedBox(width: 80), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + flex: 4, + child: Text(t("Height"), style: TextStyle(fontWeight: FontWeight.normal, fontSize: 14)), + ), + Flexible( + fit: FlexFit.tight, + flex: 8, + child: NumberPicker.horizontal( + highlightSelectedValue: true, + initialValue: customerBloc.height.toInt(), + minValue: 0, + maxValue: 230, + step: 1, + textStyle: TextStyle(fontWeight: FontWeight.bold), + textStyleHighlighted: TextStyle(fontSize: 18, color: Colors.indigo, fontWeight: FontWeight.bold), + onChanged: (value) => {customerBloc.add(CustomerHeightChange(height: value))}, + listViewHeight: 60, + ), + ), + SizedBox(width: 80), + ], + ), + Divider(), + ToggleSwitch( + minWidth: 50.0, + minHeight: 50.0, + fontSize: 14.0, + initialLabelIndex: customerBloc.customerRepository.customer.sex == "m" ? 0 : 1, + activeBgColor: Colors.indigo, + activeFgColor: Colors.white, + inactiveBgColor: Colors.white30, + inactiveFgColor: Colors.grey[900], + labels: [t('Man'), t('Woman')], + onToggle: (index) { + customerBloc.add(CustomerGenderChange(gender: index)); + }, + ), + Divider(), + FlatButton( + onPressed: () => {customerBloc.add(CustomerSave())}, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_orange_a.png', width: 140, height: 60), + Text( + t("Next"), + style: TextStyle(fontSize: 16, color: Colors.white), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + void showInSnackBar(String error) { + _scaffoldKey.currentState + .showSnackBar(SnackBar(backgroundColor: Colors.orange, content: Text(error, style: TextStyle(color: Colors.white)))); + } } diff --git a/lib/view/customer_welcome_page.dart b/lib/view/customer_welcome_page.dart index 918e15a..34de59b 100644 --- a/lib/view/customer_welcome_page.dart +++ b/lib/view/customer_welcome_page.dart @@ -1,8 +1,9 @@ import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter/material.dart'; // ignore: must_be_immutable -class CustomerWelcomePage extends StatefulWidget{ +class CustomerWelcomePage extends StatefulWidget { _CustomerWelcomePageState _state; _CustomerWelcomePageState createState() { @@ -14,9 +15,9 @@ class CustomerWelcomePage extends StatefulWidget{ class _CustomerWelcomePageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( + appBar: AppBarMin(), +/* title: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ @@ -28,40 +29,34 @@ class _CustomerWelcomePageState extends State { ), ], ), - backgroundColor: Colors.transparent, - ), - body: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_welcome.png'), - fit: BoxFit.cover, - alignment: Alignment.center, - ), +*/ + //backgroundColor: Colors.transparent, + //), + body: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_welcome.png'), + fit: BoxFit.fill, + alignment: Alignment.center, ), - child: Center( - child: Column( - children: [ - Divider(color: Colors.transparent,), - Divider(color: Colors.transparent,), - Divider(color: Colors.transparent,), - Divider(color: Colors.transparent,), - RaisedButton( - - color: Colors.orange, - textColor: Colors.white, - child: InkWell( - child: Text(AppLocalizations.of(context).translate("Next"))), - onPressed: () => { - - Navigator.of(context).pop(), - Navigator.of(context).pushNamed("home") - }, - ) - ], - ), - ) ), + child: SafeArea( + bottom: false, + child: Center( + child: Column( + children: [ + Divider( + color: Colors.transparent, + ), + RaisedButton( + color: Colors.orange, + textColor: Colors.white, + child: InkWell(child: Text(AppLocalizations.of(context).translate("Next"))), + onPressed: () => {Navigator.of(context).pop(), Navigator.of(context).pushNamed("home")}, + ) + ], + ), + ))), ); } - -} \ No newline at end of file +} diff --git a/lib/view/exercise_execute_page.dart b/lib/view/exercise_execute_page.dart index ca67016..5e0193e 100644 --- a/lib/view/exercise_execute_page.dart +++ b/lib/view/exercise_execute_page.dart @@ -12,6 +12,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; class ExerciseExecutePage extends StatefulWidget { @override @@ -109,7 +110,8 @@ class _ExerciseExecutePage extends State with Trans { child: Text( t("Execute your active Exercise Plan!"), - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + style: GoogleFonts.archivoBlack(fontSize: 20,), + maxLines: 2, ), ), @@ -167,13 +169,17 @@ class _ExerciseExecutePage extends State with Trans { ), SizedBox(width: 20), Flexible( + fit:FlexFit.tight, child: InkWell( child: Text( element.name, textAlign: TextAlign.start, - style: TextStyle(fontSize: 12, color: Colors.black), + style: GoogleFonts.inter( + fontSize: 17, + color: Colors.black), + ), onTap: () => { addExerciseByPlanEvent(bloc, element) diff --git a/lib/view/exercise_execute_plan_add_page.dart b/lib/view/exercise_execute_plan_add_page.dart index 2782cfa..a5c6b3a 100644 --- a/lib/view/exercise_execute_plan_add_page.dart +++ b/lib/view/exercise_execute_plan_add_page.dart @@ -135,8 +135,17 @@ class _ExerciseExecuteAddPage extends State with Tra crossAxisAlignment: CrossAxisAlignment.start, children: [ Divider(color: Colors.transparent,), - Text(t("Execute the") + " " + (i+1).toString() + t(". set!"), - style: TextStyle(),), + Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.baseline, + children: [ + Text(t("Execute the") + " ",style: TextStyle(fontWeight: FontWeight.bold),), + Text((i+1).toString() + ". ",style: TextStyle(fontSize:24, fontWeight: FontWeight.bold),), + Text(t("set!"),style: TextStyle(fontWeight: FontWeight.bold),), + ], + ), + + Divider(color: Colors.transparent,), Text(t("Please repeat with") + " "+ exerciseBloc.unitQuantity.toStringAsFixed(0) + " " + exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + " " + diff --git a/lib/view/exercise_new_page.dart b/lib/view/exercise_new_page.dart index f8b85e4..188a6b7 100644 --- a/lib/view/exercise_new_page.dart +++ b/lib/view/exercise_new_page.dart @@ -5,21 +5,73 @@ import 'package:aitrainer_app/bloc/menu/menu_bloc.dart'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/exercise_type.dart'; +import 'package:aitrainer_app/repository/customer_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; +import 'package:aitrainer_app/widgets/bmi_widget.dart'; +import 'package:aitrainer_app/widgets/bmr_widget.dart'; +import 'package:aitrainer_app/widgets/size_widget.dart'; import 'package:aitrainer_app/widgets/splash.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; -import 'package:aitrainer_app/library/numberpicker.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:keyboard_actions/keyboard_actions.dart'; -class ExerciseNewPage extends StatefulWidget{ +class ExerciseNewPage extends StatefulWidget { _ExerciseNewPageState createState() => _ExerciseNewPageState(); } -class _ExerciseNewPageState extends State with Trans{ +class _ExerciseNewPageState extends State with Trans { + final FocusNode _nodeText1 = FocusNode(); + final FocusNode _nodeText2 = FocusNode(); + + KeyboardActionsConfig _buildConfig(BuildContext context) { + return KeyboardActionsConfig( + keyboardActionsPlatform: KeyboardActionsPlatform.ALL, + keyboardBarColor: Colors.grey[200], + keyboardSeparatorColor: Colors.black26, + nextFocus: true, + actions: [ + KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [ + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + padding: EdgeInsets.all(8.0), + color: Colors.orange[500], + child: Text( + t("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ]), + KeyboardActionsItem( + focusNode: _nodeText1, + toolbarButtons: [ + //button 2 + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + color: Colors.orange, + padding: EdgeInsets.all(8.0), + child: Text( + t("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ], + ), + ], + ); + } @override Widget build(BuildContext context) { @@ -29,251 +81,267 @@ class _ExerciseNewPageState extends State with Trans{ setContext(context); return BlocProvider( - create: (context) => ExerciseNewBloc(exerciseRepository: ExerciseRepository(), menuBloc: menuBloc, exerciseType: exerciseType).. - add(ExerciseNewLoad()), - child: BlocConsumer( - listener: (context, state) { - if ( state is ExerciseNewLoading ) { - return LoadingDialog(); - } else if ( state is ExerciseNewError ) { - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, - content: - Text(state.message, style: TextStyle(color: Colors.white)))); - } - }, - builder: (context, state) { - final exerciseBloc = BlocProvider.of(context); - if ( state is ExerciseNewReady ) { + create: (context) => ExerciseNewBloc( + exerciseRepository: ExerciseRepository(), + menuBloc: menuBloc, + customerRepository: CustomerRepository(), + exerciseType: exerciseType) + ..add(ExerciseNewLoad()), + child: BlocConsumer( + listener: (context, state) { + if (state is ExerciseNewLoading) { + return LoadingDialog(); + } else if (state is ExerciseNewError) { + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); + } + }, + builder: (context, state) { + final exerciseBloc = BlocProvider.of(context); + double width = MediaQuery.of(context).size.width; + double height = MediaQuery.of(context).size.height; + exerciseBloc.setMediaDimensions(width, height); return getExerciseWidget(exerciseBloc, exerciseType); - } else { - return getExerciseWidget(exerciseBloc, exerciseType); - } - }, - ) - ); + }, + )); } Widget getExerciseWidget(ExerciseNewBloc exerciseBloc, ExerciseType exerciseType) { - exerciseBloc.exerciseRepository.setExerciseType(exerciseType); - String exerciseName = AppLanguage().appLocal == Locale("en") ? - exerciseBloc.exerciseRepository.exerciseType.name : - exerciseBloc.exerciseRepository.exerciseType.nameTranslation; + final String exerciseName = AppLanguage().appLocal == Locale("en") + ? exerciseBloc.exerciseRepository.exerciseType.name + : exerciseBloc.exerciseRepository.exerciseType.nameTranslation; + + String exerciseDescription = AppLanguage().appLocal == Locale("en") + ? exerciseBloc.exerciseRepository.exerciseType.description + : exerciseBloc.exerciseRepository.exerciseType.descriptionTranslation; + if (exerciseDescription == null) { + exerciseDescription = ""; + } + + print(exerciseBloc.exerciseRepository.exerciseType.name); + + if (exerciseBloc.exerciseRepository.exerciseType.name == "BMR") { + return BMR(exerciseBloc: exerciseBloc); + } + if (exerciseBloc.exerciseRepository.exerciseType.name == "BMI") { + return BMI(exerciseBloc: exerciseBloc); + } + if (exerciseBloc.exerciseRepository.exerciseType.name == "Sizes") { + return SizeWidget(exerciseBloc: exerciseBloc); + } return Form( - child: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBarNav(depth: 1), - body: Container( - width: MediaQuery - .of(context) - .size - .width, - height: MediaQuery - .of(context) - .size - .height, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), - fit: BoxFit.fill, - alignment: Alignment.center, - ), + //autovalidateMode: AutovalidateMode.disabled, + child: Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBarNav(depth: 1), + body: Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_background.png'), + fit: BoxFit.fill, + alignment: Alignment.center, ), - child: Container( - padding: const EdgeInsets.only (top: 25, left: 25, right: 25), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - /*Divider(color: Colors.transparent,), - Divider(color: Colors.transparent,),*/ - Text(t('Save Exercise'), - style: TextStyle(fontSize: 14, color: Colors.blueAccent)), - Text(exerciseName, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange), - overflow: TextOverflow.fade, - maxLines: 1, - softWrap: true, - ), - - - //Divider(color: Colors.transparent,), - FlatButton( - child: Row( - - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Icon(Icons.description), - Text(t("Description"), - style: TextStyle( - color: Colors.blueAccent, fontWeight: FontWeight.normal, fontSize: 14)), - Icon(Icons.arrow_forward_ios), - ]), - textColor: Colors.blueAccent, - color: Colors.transparent, - onPressed: () => - { - Navigator.of(context).pushNamed( - 'exerciseTypeDescription', arguments: exerciseBloc.exerciseRepository), - }, - ), - //Divider(color: Colors.transparent,), - columnQuantityUnit(exerciseBloc), - Divider(color: Colors.transparent,), - - - columnQuantity(exerciseBloc), - Divider(), - Divider(color: Colors.transparent,), - Divider(color: Colors.transparent,), - Divider(color: Colors.transparent,), - RaisedButton( - textColor: Colors.white, - color: Colors.deepOrange, - focusColor: Colors.white, - onPressed: () => - { - confirmationDialog(exerciseBloc), - }, - child: Text(t("Save"), style: TextStyle(fontSize: 16),) - ), - ]), - ) - ) ), + child: KeyboardActions( + config: _buildConfig(context), + child: Container( + padding: const EdgeInsets.only(top: 5, left: 75, right: 75), + child: SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(t('Save Exercise'), style: TextStyle(fontSize: 14, color: Colors.blue[200])), + Divider(), + Text( + exerciseName, + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.orange), + overflow: TextOverflow.fade, + maxLines: 2, + softWrap: true, + textAlign: TextAlign.center, + ), + SizedBox( + height: 15, + ), + Text( + exerciseDescription, + style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[300]), + maxLines: 8, + overflow: TextOverflow.fade, + softWrap: true, + ), + InkWell( + child: Text( + t("More »"), + style: GoogleFonts.inter(fontSize: 12, color: Colors.blue[200]), + ), + onTap: () => { + Navigator.of(context).pushNamed('exerciseTypeDescription', arguments: exerciseBloc.exerciseRepository), + }, + ), + Divider( + color: Colors.transparent, + ), + columnQuantityUnit(exerciseBloc), + Divider( + color: Colors.transparent, + ), + columnQuantity(exerciseBloc), + Divider(), + Divider( + color: Colors.transparent, + ), + Divider( + color: Colors.transparent, + ), + Divider( + color: Colors.transparent, + ), + FlatButton( + onPressed: () => { + confirmationDialog(exerciseBloc), + }, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_orange_a.png', width: 140, height: 60), + Text( + t("Save"), + style: TextStyle(fontSize: 16, color: Colors.white), + ), + ], + )), + ]), + ))), ), - ); + )); } - Row columnQuantityUnit( ExerciseNewBloc bloc ) { - Row row = Row(); - if ( bloc.exerciseRepository.exerciseType != null && - bloc.exerciseRepository.exerciseType.unitQuantity == "1") { - row = Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: bloc.unitQuantity.toInt(), - minValue: 0, - maxValue: 200, - step: 1, - onChanged: (value) => { - bloc.add(ExerciseNewQuantityUnitChange(quantity: value.toDouble())) - }, - listViewHeight: 80, - textStyle: TextStyle(fontSize: 24), - textStyleHighlighted: TextStyle(fontSize: 38, color: Colors.orange, fontWeight: FontWeight.bold), - //decoration: _decoration, - ), - - new InkWell( - child: new Text(t(bloc.exerciseRepository.exerciseType.unitQuantityUnit), - style: TextStyle(fontSize: 16)), - ), - - ]); + Column columnQuantityUnit(ExerciseNewBloc bloc) { + Column row = Column(); + if (bloc.exerciseRepository.exerciseType != null && bloc.exerciseRepository.exerciseType.unitQuantity == "1") { + row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + TextFormField( + focusNode: _nodeText1, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + labelText: t(bloc.exerciseRepository.exerciseType.unitQuantityUnit), + labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), + fillColor: Colors.black38, + filled: true, + border: OutlineInputBorder( + gapPadding: 8.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.white12, width: 0.4), + ), + ), + initialValue: "30", + keyboardType: TextInputType.numberWithOptions(decimal: true), + textInputAction: TextInputAction.done, + style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.yellow[300]), + onChanged: (value) => {bloc.add(ExerciseNewQuantityUnitChange(quantity: double.parse(value)))}), + //] ), + ]); } return row; } - Row columnQuantity( ExerciseNewBloc bloc ) { - Row row = Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: bloc.quantity.toInt(), - minValue: 0, - maxValue: 200, - step: 1, - onChanged: (value) => { - bloc.add(ExerciseNewQuantityChange(quantity: value.toDouble())) - }, - listViewHeight: 80, - textStyle: TextStyle(fontSize: 24), - textStyleHighlighted: TextStyle(fontSize: 38, color: Colors.orange, fontWeight: FontWeight.bold), - //decoration: _decoration, - ), - - Text(t(bloc.exerciseRepository.exerciseType.unit), - style: TextStyle(fontSize: 16)), - ]); + Column columnQuantity(ExerciseNewBloc bloc) { + Column row = Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + TextFormField( + focusNode: _nodeText2, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + labelText: t(bloc.exerciseRepository.exerciseType.unit), + labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.orange[50], decorationColor: Colors.black12), + fillColor: Colors.black38, + filled: true, + border: OutlineInputBorder( + gapPadding: 8.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.black26, width: 0.4), + ), + ), + initialValue: "12", + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + style: GoogleFonts.archivoBlack(fontSize: 80, color: Colors.orange[200]), + onChanged: (value) => {bloc.add(ExerciseNewQuantityChange(quantity: double.parse(value)))}, + ), + ]); return row; } - void confirmationDialog( ExerciseNewBloc bloc ) { + void confirmationDialog(ExerciseNewBloc bloc) { LinkedHashMap args = LinkedHashMap(); print("exercise validated " + bloc.exerciseRepository.exercise.quantity.toString()); - if ( bloc.exerciseRepository.exercise.quantity == null) { + if (bloc.exerciseRepository.exercise.quantity == null) { return; } - String quantity = bloc.exerciseRepository.exercise.quantity % 1 == 0? - bloc.exerciseRepository.exercise.quantity.round().toString() : - bloc.exerciseRepository.exercise.quantity.toString(); + String quantity = bloc.exerciseRepository.exercise.quantity % 1 == 0 + ? bloc.exerciseRepository.exercise.quantity.round().toString() + : bloc.exerciseRepository.exercise.quantity.toString(); String unitQuantity = ""; - if ( bloc.exerciseRepository.exercise.unitQuantity != null ) { - unitQuantity = bloc.exerciseRepository.exercise.unitQuantity % 1 == 0 ? - bloc.exerciseRepository.exercise.unitQuantity.round().toString() : - bloc.exerciseRepository.exercise.unitQuantity.toString(); + if (bloc.exerciseRepository.exercise.unitQuantity != null) { + unitQuantity = bloc.exerciseRepository.exercise.unitQuantity % 1 == 0 + ? bloc.exerciseRepository.exercise.unitQuantity.round().toString() + : bloc.exerciseRepository.exercise.unitQuantity.toString(); } - showCupertinoDialog( - useRootNavigator: true, - context: context, - //barrierDismissible: false, - builder:(_) => CupertinoAlertDialog( - title: Text(t("Do you save this exercise with these parameters?")), - content: Column( - - children: [ - Divider(), - Text(t("Exercise") + ": " + - bloc.exerciseRepository.exerciseType.name, - style: (TextStyle(color: Colors.blue)),), - Text(quantity + " " + - t(bloc.exerciseRepository.exerciseType.unit), - style: (TextStyle(color: Colors.deepOrange)),), - Text(bloc.exerciseRepository.exerciseType.unitQuantity == "1" ? - t("with") + " " - + unitQuantity + " " - + t(bloc.exerciseRepository.exerciseType.unitQuantityUnit) : - "", - style: (TextStyle(color: Colors.deepOrange)), - ), - - ]), - actions: [ - FlatButton( - child: Text(t("No")), - onPressed: () => Navigator.pop(context), - ), - FlatButton( - child: Text(t("Yes")), - onPressed: () => { - bloc.exerciseRepository.setCustomer(Cache().userLoggedIn), - bloc.exerciseRepository.addExercise(), - Navigator.pop(context), - Navigator.pop(context), - if ( bloc.exerciseRepository.exerciseType.is1RM ) { - args['exerciseRepository'] = bloc.exerciseRepository, - args['percent'] = 0.75, - args['readonly'] = false, - Navigator.of(context).pushNamed('exerciseControlPage', - arguments: args ) - } - }, - ) - ], - ) - ); + useRootNavigator: true, + context: context, + //barrierDismissible: false, + builder: (_) => CupertinoAlertDialog( + title: Text(t("Do you save this exercise with these parameters?")), + content: Column(children: [ + Divider(), + Text( + t("Exercise") + ": " + bloc.exerciseRepository.exerciseType.name, + style: (TextStyle(color: Colors.blue)), + ), + Text( + quantity + " " + t(bloc.exerciseRepository.exerciseType.unit), + style: (TextStyle(color: Colors.deepOrange)), + ), + Text( + bloc.exerciseRepository.exerciseType.unitQuantity == "1" + ? t("with") + " " + unitQuantity + " " + t(bloc.exerciseRepository.exerciseType.unitQuantityUnit) + : "", + style: (TextStyle(color: Colors.deepOrange)), + ), + ]), + actions: [ + FlatButton( + child: Text(t("No")), + onPressed: () => Navigator.pop(context), + ), + FlatButton( + child: Text(t("Yes")), + onPressed: () => { + bloc.exerciseRepository.setCustomer(Cache().userLoggedIn), + bloc.exerciseRepository.addExercise(), + Navigator.pop(context), + Navigator.pop(context), + if (bloc.exerciseRepository.exerciseType.is1RM) + { + args['exerciseRepository'] = bloc.exerciseRepository, + args['percent'] = 0.75, + args['readonly'] = false, + Navigator.of(context).pushNamed('exerciseControlPage', arguments: args) + } + }, + ) + ], + )); } } diff --git a/lib/view/exercise_plan_custom_detail_add_page.dart b/lib/view/exercise_plan_custom_detail_add_page.dart index 0a76a64..dd04363 100644 --- a/lib/view/exercise_plan_custom_detail_add_page.dart +++ b/lib/view/exercise_plan_custom_detail_add_page.dart @@ -2,7 +2,6 @@ import 'dart:collection'; import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart'; import 'package:aitrainer_app/bloc/exercise_plan_custom_add/exercise_plan_custom_add_bloc.dart'; -import 'package:aitrainer_app/library/numberpicker.dart'; import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; @@ -13,6 +12,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:keyboard_actions/keyboard_actions.dart'; +import 'package:keyboard_actions/keyboard_actions_config.dart'; +import 'package:keyboard_actions/keyboard_actions_item.dart'; class ExercisePlanDetailAddPage extends StatefulWidget { @override @@ -20,6 +23,73 @@ class ExercisePlanDetailAddPage extends StatefulWidget { } class _ExercisePlanDetailAddPage extends State with Trans { + final FocusNode _nodeText1 = FocusNode(); + final FocusNode _nodeText2 = FocusNode(); + final FocusNode _nodeText3 = FocusNode(); + + KeyboardActionsConfig _buildConfig(BuildContext context) { + return KeyboardActionsConfig( + keyboardActionsPlatform: KeyboardActionsPlatform.ALL, + keyboardBarColor: Colors.grey[200], + nextFocus: true, + actions: [ + KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [ + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + padding: EdgeInsets.all(8.0), + color: Colors.orange[500], + child: Text( + t("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ]), + KeyboardActionsItem( + focusNode: _nodeText1, + toolbarButtons: [ + //button 2 + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + color: Colors.orange, + padding: EdgeInsets.all(8.0), + child: Text( + t("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ], + ), + KeyboardActionsItem( + focusNode: _nodeText3, + toolbarButtons: [ + //button 2 + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + color: Colors.orange, + padding: EdgeInsets.all(8.0), + child: Text( + t("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ], + ), + ], + ); + } + @override Widget build(BuildContext context) { LinkedHashMap args = ModalRoute.of(context).settings.arguments; @@ -38,8 +108,8 @@ class _ExercisePlanDetailAddPage extends State with T if (state is ExercisePlanCustomAddLoading) { return LoadingDialog(); } else if (state is ExercisePlanCustomAddError) { - Scaffold.of(context).showSnackBar(SnackBar( - backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); + Scaffold.of(context).showSnackBar( + SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white)))); } }, builder: (context, state) { @@ -50,8 +120,6 @@ class _ExercisePlanDetailAddPage extends State with T )); } - - Widget getForm(ExercisePlanCustomAddBloc bloc, WorkoutMenuTree workoutMenuTree) { String exerciseName = ""; if (bloc != null) { @@ -60,162 +128,158 @@ class _ExercisePlanDetailAddPage extends State with T : bloc.exercisePlanRepository.getActualPlanDetail().exerciseType.nameTranslation; } return Form( - autovalidate: true, - child: Scaffold( - resizeToAvoidBottomInset: true, - appBar: AppBarNav(depth: 1), - body: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_light_background.png'), - fit: BoxFit.fill, - alignment: Alignment.center, - ), + child: Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBarNav(depth: 1), + body: Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_background.png'), + fit: BoxFit.fill, + alignment: Alignment.center, ), - child: Container( - padding: const EdgeInsets.only(top: 25, left: 25, right: 25), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Text(t('Save The Exercise To The Exercise Plan'), - style: TextStyle(fontSize: 14, color: Colors.blueAccent)), - Text( - exerciseName, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange), - overflow: TextOverflow.fade, - maxLines: 1, - softWrap: true, - ), - Divider(color: Colors.transparent,height: 30,), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Flexible( - fit: FlexFit.tight, - flex: 8, - child: + ), + child: KeyboardActions( + config: _buildConfig(context), + child: Container( + child: SingleChildScrollView( + padding: const EdgeInsets.only(top: 25, left: 95, right: 95), + scrollDirection: Axis.vertical, + child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ + Text(t('Save The Exercise To The Exercise Plan'), + textAlign: TextAlign.center, + style: GoogleFonts.inter( + fontSize: 14, + color: Colors.white, + )), + Text( + exerciseName, + textAlign: TextAlign.center, + style: GoogleFonts.archivoBlack(fontSize: 18, color: Colors.deepOrange), + overflow: TextOverflow.fade, + maxLines: 3, + softWrap: true, + ), + + Divider( + color: Colors.transparent, + height: 30, + ), + + TextFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + labelText: t('Serie'), + labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50], decorationColor: Colors.black12), + fillColor: Colors.white24, + filled: true, + border: OutlineInputBorder( + gapPadding: 8.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.black26, width: 0.4), + ), + ), + initialValue: bloc.serie.toStringAsFixed(0), + focusNode: _nodeText1, + keyboardType: TextInputType.number, + style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), + onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeSerie(quantity: double.parse(value)))}), + //] ), + Divider(), + + TextFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + labelText: t('Repeats'), + fillColor: Colors.white24, + labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), + filled: true, + border: OutlineInputBorder( + gapPadding: 4.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + focusNode: _nodeText2, + initialValue: bloc.quantity.toStringAsFixed(0), + keyboardType: TextInputType.number, + style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), + onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeQuantity(quantity: double.parse(value)))}), + //]), + Divider(), + + TextFormField( + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + labelText: t('Weight'), + fillColor: Colors.white24, + labelStyle: GoogleFonts.inter(fontSize: 20, color: Colors.yellow[50]), + filled: true, + border: OutlineInputBorder( + gapPadding: 2.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.green[50], width: 0.4), + ), + ), + focusNode: _nodeText3, + initialValue: bloc.quantityUnit.toStringAsFixed(0), + keyboardType: TextInputType.numberWithOptions(decimal: true), + style: GoogleFonts.archivoBlack(fontSize: 60, color: Colors.yellow[200]), + onChanged: (value) => {bloc.add(ExercisePlanCustomAddChangeQuantityUnit(quantity: double.parse(value)))}), + //]), + + Divider(), + Text( + bloc.serie.toStringAsFixed(0) + + " x " + + bloc.quantity.toStringAsFixed(0) + + " x " + + bloc.quantityUnit.toStringAsFixed(0) + + " kg", + style: TextStyle(fontSize: 24, fontWeight: FontWeight.normal, color: Colors.yellow[50]), + ), + Divider(), + + Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + FlatButton( + onPressed: () => { + bloc.add(ExercisePlanCustomAddRemove()), + Navigator.of(context).pop(), + }, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_pink_b.png', width: 140, height: 60), Text( - t("Serie"), - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - + t("Delete"), + style: TextStyle(fontSize: 16, color: Colors.white), ), + ], ), - NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: bloc.serie.toInt(), - itemExtent: 85, - minValue: 1, - maxValue: 20, - //decoration: _decoration, - step: 1, - onChanged: (value) => { - bloc.add(ExercisePlanCustomAddChangeSerie(quantity: value.toDouble())) - }, - listViewHeight: 80, - textStyle: TextStyle(fontSize: 24), - textStyleHighlighted: TextStyle(fontSize: 36, color: Colors.orange, fontWeight: FontWeight.bold), - //decoration: _decoration, - ), - - ] - ), - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Flexible( - fit: FlexFit.tight, - flex: 8, - child: - Text(t("Repeats"), - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),), - ), - NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: bloc.quantity.toInt(), - itemExtent: 85, - minValue: 0, - maxValue: 200, - step: 1, - onChanged: (value) => { - bloc.add(ExercisePlanCustomAddChangeQuantity(quantity: value.toDouble())) - }, - listViewHeight: 80, - textStyle: TextStyle(fontSize: 24), - textStyleHighlighted: TextStyle(fontSize: 36, color: Colors.orange, fontWeight: FontWeight.bold), - //decoration: _decoration, - ), - ]), - Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Flexible( - fit: FlexFit.tight, - flex: 8, - child: - Text(t("Weight") + " (" + bloc.exercisePlanRepository.getActualPlanDetail().exerciseType.unitQuantityUnit + ")", - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),), - ), - NumberPicker.horizontal( - highlightSelectedValue: true, - initialValue: bloc.quantityUnit.toInt(), - //decoration: _decoration, - itemExtent: 85, - minValue: 0, - maxValue: 650, - step: 1, - onChanged: (value) => { - bloc.add(ExercisePlanCustomAddChangeQuantityUnit(quantity: value.toDouble())) - }, - listViewHeight: 80, - textStyle: TextStyle(fontSize: 24), - textStyleHighlighted: TextStyle(fontSize: 36, color: Colors.orange, fontWeight: FontWeight.bold), - //decoration: _decoration, - ), - ]), - - - Divider(), - Text( - bloc.serie.toStringAsFixed(0) + " x " + bloc.quantity.toStringAsFixed(0) + " x " + bloc.quantityUnit.toStringAsFixed(0) + " kg" , - style: TextStyle(fontSize: 28, fontWeight: FontWeight.normal), - ), - Divider(), - - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - RaisedButton( - textColor: Colors.white, - color: Colors.red.shade300, - focusColor: Colors.white, + ), + FlatButton( onPressed: () => { - bloc.add(ExercisePlanCustomAddRemove()), - Navigator.of(context).pop(), - }, - child: Text(t( - "Delete")), //Text(AppLocalizations.of(context).translate("Delete"), style: TextStyle(fontSize: 16),) - ), - RaisedButton( - textColor: Colors.white, - color: Colors.blueAccent, - focusColor: Colors.white, - onPressed: () => { - bloc.add(ExercisePlanCustomAddSubmit()), - Navigator.of(context).pop(), - }, - child: Text( - t("Save"), - style: TextStyle(fontSize: 16), - )), - ], - ), - ]), - ))), - ), - ); + bloc.add(ExercisePlanCustomAddSubmit()), + Navigator.of(context).pop(), + }, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset('asset/icon/gomb_zold_b-1.png', width: 140, height: 60), + Text( + t("Save"), + style: TextStyle(fontSize: 16, color: Colors.white), + ), + ], + )), + ], + ), + ]), + )))), + )); } } diff --git a/lib/view/exercise_plan_custom_page.dart b/lib/view/exercise_plan_custom_page.dart index 2af863b..9e438e8 100644 --- a/lib/view/exercise_plan_custom_page.dart +++ b/lib/view/exercise_plan_custom_page.dart @@ -14,6 +14,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; class ExercisePlanCustomPage extends StatefulWidget { @override @@ -109,7 +110,7 @@ class _ExercisePlanCustomPage extends State with Trans { Text(" "), Text( t("Custom Exercise Plan"), - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + style: GoogleFonts.archivoBlack(fontSize: 20), ), ], ), @@ -118,7 +119,7 @@ class _ExercisePlanCustomPage extends State with Trans { ), Text( t("Select manually the exercises what you would like to have in your plan. At the end don't forget to save."), - style: TextStyle(fontSize: 12, fontWeight: FontWeight.normal), + style: GoogleFonts.inter(fontSize: 12, fontWeight: FontWeight.normal), ), ], @@ -131,7 +132,7 @@ class _ExercisePlanCustomPage extends State with Trans { exerciseTypes.add(Container( margin: const EdgeInsets.only(left: 4.0), child: TreeViewChild( - startExpanded: true, + startExpanded: false, parent: TreeviewParentWidget(text: name), children: _getChildList(list, bloc), ))); @@ -157,8 +158,8 @@ class _ExercisePlanCustomPage extends State with Trans { mainAxisAlignment: MainAxisAlignment.start, children: [ IconButton( - icon: element.selected ? Icon(Icons.check, color: Colors.greenAccent.shade700,) - : Icon(Icons.add, color: Colors.blue.shade400,), + icon: element.selected ? Icon(Icons.check, color: Colors.green[600],) + : Icon(Icons.add, color: Colors.indigo,), onPressed: () => clickAddDetail(bloc, element), ), SizedBox(width: 10), @@ -171,7 +172,7 @@ class _ExercisePlanCustomPage extends State with Trans { Text( element.name, textAlign: TextAlign.start, - style: TextStyle(fontSize: 12, color: Colors.black), + style: GoogleFonts.inter(fontSize: 16, color: Colors.black), ), onTap: () => clickAddDetail(bloc, element), ), diff --git a/lib/view/exercise_type_description.dart b/lib/view/exercise_type_description.dart index 4d2e98f..02755c0 100644 --- a/lib/view/exercise_type_description.dart +++ b/lib/view/exercise_type_description.dart @@ -1,5 +1,6 @@ import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; +import 'package:aitrainer_app/widgets/app_bar_min.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -18,23 +19,7 @@ class ExerciseTypeDescription extends StatelessWidget { exerciseRepository.exerciseType.nameTranslation; return Scaffold( - appBar: AppBar( - backgroundColor: Colors.transparent, - title: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Image.asset( - 'asset/image/WT_long_logo.png', - fit: BoxFit.cover, - height: 65.0, - ), - ], - ), - leading: IconButton( - icon: Icon(Icons.arrow_back, color: Colors.white), - onPressed: () => Navigator.of(context).pop(), - ), - ), + appBar: AppBarMin(back: true,), body: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, diff --git a/lib/view/gdpr.dart b/lib/view/gdpr.dart index c63ce40..3e005d9 100644 --- a/lib/view/gdpr.dart +++ b/lib/view/gdpr.dart @@ -6,34 +6,18 @@ class Gdpr extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - body: Container( - padding: const EdgeInsets.only (left:15, right: 15), - child: ListView( - children: [ - new InkWell( - child: new Text( - AppLocalizations.of(context).translate('gdpr_text'), - - ), - - customBorder: Border.all(color:Colors.teal, width:1), - ), - Spacer(flex:2), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - FlatButton( - textColor: Colors.black, - - onPressed: () { }, - - ) + body: Container( + padding: const EdgeInsets.only(left: 15, right: 15), + child: ListView( + children: [ + new InkWell( + child: new Text( + AppLocalizations.of(context).translate('gdpr_text'), + ), + customBorder: Border.all(color: Colors.teal, width: 1), + ), + Spacer(flex: 2), ], - ) - ], - ) - ) - ); + ))); } - -} \ No newline at end of file +} diff --git a/lib/view/login.dart b/lib/view/login.dart index 74d95d7..542be44 100644 --- a/lib/view/login.dart +++ b/lib/view/login.dart @@ -29,7 +29,6 @@ class LoginWidget extends StatefulWidget { class _LoginWidget extends State with Common, Trans { final GlobalKey _scaffoldKey = new GlobalKey(); - final _formKey = GlobalKey(); @override Widget build(BuildContext context) { @@ -57,29 +56,36 @@ class _LoginWidget extends State with Common, Trans { LoadingDialog.hide(context); showInSnackBar(t(state.failureResponse)); }, - child: SafeArea( - top: false, - bottom: false, - child: Container( - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_login.png'), - fit: BoxFit.cover, - alignment: Alignment.center, - ), - ), - child: buildLoginForm(loginBloc, accountBloc), - ), - ) + onLoaded: (context, state ) { + + }, + child: loadForm(loginBloc, accountBloc) ), ); })); } + Widget loadForm(LoginFormBloc loginBloc, AccountBloc accountBloc) { + return SafeArea( + top: false, + bottom: false, + child: Container( + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_login.png'), + fit: BoxFit.cover, + alignment: Alignment.center, + ), + ), + child: buildLoginForm(loginBloc, accountBloc), + ), + ); + } + Widget buildLoginForm(LoginFormBloc formBloc, AccountBloc accountBloc) { return Form( - key: _formKey, + key: _scaffoldKey, child: Container( padding: const EdgeInsets.only(left: 15, right: 50), child: diff --git a/lib/widgets/app_bar_min.dart b/lib/widgets/app_bar_min.dart index 4a5cbbd..e751cff 100644 --- a/lib/widgets/app_bar_min.dart +++ b/lib/widgets/app_bar_min.dart @@ -12,8 +12,10 @@ import 'package:percent_indicator/linear_percent_indicator.dart'; import 'package:rainbow_color/rainbow_color.dart'; +// ignore: must_be_immutable class AppBarMin extends StatefulWidget implements PreferredSizeWidget { - const AppBarMin(); + bool back = false; + AppBarMin({this.back = false }); @override _AppBarNav createState() => _AppBarNav(); @@ -44,10 +46,12 @@ class _AppBarNav extends State with Common { ], ), leading: IconButton( - icon: Icon(Icons.arrow_back, color: Colors.black), + icon: Icon(Icons.arrow_back, color: widget.back ? Colors.white : Colors.black), onPressed: () => { - + if ( widget.back ) { + Navigator.of(context).pop() + } }, ) ); diff --git a/lib/widgets/bmi_widget.dart b/lib/widgets/bmi_widget.dart index e69de29..003355f 100644 --- a/lib/widgets/bmi_widget.dart +++ b/lib/widgets/bmi_widget.dart @@ -0,0 +1,246 @@ +import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; +import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/util/trans.dart'; +import 'package:animated_widgets/widgets/rotation_animated.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'app_bar.dart'; +import 'package:keyboard_actions/keyboard_actions.dart'; + +// ignore: must_be_immutable +class BMI extends StatefulWidget { + final ExerciseNewBloc exerciseBloc; + BMI({this.exerciseBloc}); + + @override + _BMIState createState() => _BMIState(); +} + +class _BMIState extends State with Trans { + final FocusNode _nodeText1 = FocusNode(); + final FocusNode _nodeText2 = FocusNode(); + + KeyboardActionsConfig _buildConfig(BuildContext context) { + return KeyboardActionsConfig( + keyboardActionsPlatform: KeyboardActionsPlatform.ALL, + keyboardBarColor: Colors.grey[200], + keyboardSeparatorColor: Colors.black26, + nextFocus: true, + actions: [ + KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [ + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + padding: EdgeInsets.all(8.0), + color: Colors.orange[500], + child: Text( + AppLocalizations.of(context).translate("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ]), + KeyboardActionsItem( + focusNode: _nodeText1, + toolbarButtons: [ + //button 2 + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + color: Colors.orange, + padding: EdgeInsets.all(8.0), + child: Text( + AppLocalizations.of(context).translate("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ], + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + setContext(context); + widget.exerciseBloc.getBMI(); + return Form( + child: Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBarNav(depth: 1), + body: Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_background.png'), + fit: BoxFit.fill, + alignment: Alignment.center, + ), + ), + child: KeyboardActions( + config: _buildConfig(context), + child: SingleChildScrollView( + child: + Column(crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ + getWeightInput(), + Text(AppLocalizations.of(context).translate("Body Mass Index"), + style: GoogleFonts.archivoBlack( + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 3.0, + color: Colors.black54, + ), + ], + fontSize: 30, + color: Colors.orange[500], + )), + Text(widget.exerciseBloc.bmi.toStringAsFixed(1) + "%", + style: GoogleFonts.archivoBlack( + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 3.0, + color: Colors.black54, + ), + ], + fontSize: 60, + color: Colors.orange[500], + )), + Divider(color: Colors.transparent), + Stack(alignment: Alignment.center, children: [ + Container( + padding: EdgeInsets.only(left: 30, right: 30), + child: Image.asset( + "asset/image/BMI_graph_c.png", + ), + ), + Positioned( + top: widget.exerciseBloc.bmiTop, + left: widget.exerciseBloc.bmiLeft, + child: RotationAnimatedWidget.tween( + enabled: true, + duration: const Duration(milliseconds: 1000), + rotationDisabled: Rotation.deg(), + rotationEnabled: Rotation.deg(z: widget.exerciseBloc.bmiAngle), + child: Image.asset( + "asset/image/BMI_mutato.png", + width: 65, + ))) + ]), + Divider(color: Colors.transparent), + Container( + padding: EdgeInsets.only(left: 65, right: 65), + alignment: Alignment.center, + child: Text(t("Based on your weight and height your goal for BMI and weight:"), + textAlign: TextAlign.center, + style: GoogleFonts.inter( + fontSize: 16, + color: Colors.yellow[200], + )), + ), + Text("BMI" + ": " + widget.exerciseBloc.goalBMI.toStringAsFixed(0), + style: GoogleFonts.archivoBlack( + fontSize: 40, + color: Colors.orange[500], + )), + Text(t("Weight") + ": " + widget.exerciseBloc.goalWeight.toStringAsFixed(0) + " kg", + style: GoogleFonts.archivoBlack( + fontSize: 30, + color: Colors.orange[200], + )), + ])))))); + } + + Widget buildAnimatedPointer() { + return TweenAnimationBuilder( + tween: IntTween(begin: 0, end: 30), + duration: Duration(milliseconds: 2000), + curve: Curves.linear, + builder: (context, val, child) { + return Image.asset( + "asset/image/BMI_mutato.png", + width: 65, + ); + }, + ); + } + + Widget getHeightInput() { + if (widget.exerciseBloc.customerRepository.customer.birthYear < 2003) { + return Flexible( + child: TextFormField( + focusNode: _nodeText2, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5), + labelText: AppLocalizations.of(context).translate("Actual Height"), + labelStyle: GoogleFonts.inter(fontSize: 16, color: Colors.yellow[50]), + fillColor: Colors.black38, + filled: true, + border: OutlineInputBorder( + gapPadding: 4.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.white12, width: 0.4), + ), + ), + initialValue: widget.exerciseBloc.height.toStringAsFixed(0), + keyboardType: TextInputType.numberWithOptions(decimal: true), + textInputAction: TextInputAction.done, + style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.yellow[300]), + onChanged: (value) => {widget.exerciseBloc.add(ExerciseNewHeightChange(value: double.parse(value)))}), + ); + } else { + return Container(); + } + } + + Widget getWeightInput() { + return Container( + padding: EdgeInsets.only(top: 15, left: 65, right: 65, bottom: 10), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + getHeightInput(), + SizedBox( + width: 10, + ), + Flexible( + child: TextFormField( + focusNode: _nodeText1, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5), + labelText: AppLocalizations.of(context).translate("Actual Weight"), + labelStyle: GoogleFonts.inter(fontSize: 16, color: Colors.yellow[50]), + fillColor: Colors.black38, + filled: true, + border: OutlineInputBorder( + gapPadding: 2.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.white12, width: 0.4), + ), + ), + initialValue: widget.exerciseBloc.weight.toStringAsFixed(0), + keyboardType: TextInputType.numberWithOptions(decimal: true), + textInputAction: TextInputAction.done, + style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.yellow[300]), + onChanged: (value) => {widget.exerciseBloc.add(ExerciseNewWeightChange(value: double.parse(value)))}, + ), + ), + IconButton( + icon: Icon(Icons.save), + hoverColor: Colors.blueAccent, + color: widget.exerciseBloc.changedWeight ? Colors.blue[200] : Colors.black54, + onPressed: () => {print("Save"), widget.exerciseBloc.add(ExerciseNewSaveWeight())}) + ], + )); + } +} diff --git a/lib/widgets/bottom_nav.dart b/lib/widgets/bottom_nav.dart index 8092b7c..dec6b2b 100644 --- a/lib/widgets/bottom_nav.dart +++ b/lib/widgets/bottom_nav.dart @@ -14,8 +14,6 @@ class BottomNavigator extends StatefulWidget { } class _NawDrawerWidget extends State { - - @override void initState() { super.initState(); @@ -34,7 +32,8 @@ class _NawDrawerWidget extends State { // return GradientBottomNavigationBar( - currentIndex: widget.bottomNavIndex, // this will be set when a new tab is tapped + currentIndex: + widget.bottomNavIndex, // this will be set when a new tab is tapped backgroundColorStart: bgrColorEnd, backgroundColorEnd: bgrColor, fixedColor: active, @@ -46,77 +45,91 @@ class _NawDrawerWidget extends State { BottomNavigationBarItem( backgroundColor: bgrColor, icon: new Icon(Icons.home, color: inactive), - activeIcon: new Icon(Icons.home, color: active,), + activeIcon: new Icon( + Icons.home, + color: active, + ), title: new Text(AppLocalizations.of(context).translate("Home"), - style: TextStyle(fontSize: 9)), + style: TextStyle(fontSize: 9)), ), BottomNavigationBarItem( backgroundColor: bgrColor, icon: new Icon(Icons.trending_up, color: inactive), - activeIcon: new Icon(Icons.trending_up, color: active,), - title: new Text(AppLocalizations.of(context).translate("My Development"), - style: TextStyle(fontSize: 9),), + activeIcon: new Icon( + Icons.trending_up, + color: active, + ), + title: new Text( + AppLocalizations.of(context).translate("My Development"), + style: TextStyle(fontSize: 9), + ), ), - BottomNavigationBarItem( backgroundColor: bgrColor, icon: new Icon(Icons.featured_play_list, color: inactive), - activeIcon: new Icon(Icons.featured_play_list, color: active,), - title: new Text(AppLocalizations.of(context).translate("My Training Plan"), - style: TextStyle(fontSize: 9),), + activeIcon: new Icon( + Icons.featured_play_list, + color: active, + ), + title: new Text( + AppLocalizations.of(context).translate("My Training Plan"), + style: TextStyle(fontSize: 9), + ), ), - BottomNavigationBarItem( backgroundColor: bgrColor, - icon: Icon(Icons.person, color: inactive,), - activeIcon: new Icon(Icons.person, color: active,), - title: Text(AppLocalizations.of(context).translate("Account"), - style: TextStyle(fontSize: 9),) - ), + icon: Icon( + Icons.person, + color: inactive, + ), + activeIcon: new Icon( + Icons.person, + color: active, + ), + title: Text( + AppLocalizations.of(context).translate("Account"), + style: TextStyle(fontSize: 9), + )), BottomNavigationBarItem( backgroundColor: bgrColor, icon: Icon(Icons.settings, color: inactive), - activeIcon: new Icon(Icons.settings, color: active,), + activeIcon: new Icon( + Icons.settings, + color: active, + ), title: Text(AppLocalizations.of(context).translate("Settings"), - style: TextStyle(fontSize: 9)) - ) + style: TextStyle(fontSize: 9))) ], - onTap:(index) { - setState(() { - widget.bottomNavIndex = index; - switch (index) { - case 0: - Navigator.of(context).pop(); - Navigator.of(context).pushNamed('home'); + onTap: (index) { + setState(() { + widget.bottomNavIndex = index; + switch (index) { + case 0: + Navigator.of(context).pop(); + Navigator.of(context).pushNamed('home'); - break; - case 1: - Navigator.of(context).pop(); - Navigator.of(context).pushNamed('myDevelopment'); - break; - case 2: + break; + case 1: + Navigator.of(context).pop(); + Navigator.of(context).pushNamed('myDevelopment'); + break; + case 2: + Navigator.of(context).pop(); + Navigator.of(context).pushNamed('myExercisePlan'); - Navigator.of(context).pop(); - Navigator.of(context).pushNamed('myExercisePlan'); + break; + case 3: + Navigator.of(context).pop(); + Navigator.of(context).pushNamed('account'); - break; - case 3: - Navigator.of(context).pop(); - Navigator.of(context).pushNamed('account'); + break; + case 4: + Navigator.of(context).pop(); + Navigator.of(context).pushNamed('settings'); - break; - case 4: - Navigator.of(context).pop(); - Navigator.of(context).pushNamed('settings'); - - break; - } - - }); - } - - ); + break; + } + }); + }); } - - -} \ No newline at end of file +} diff --git a/lib/widgets/image_button.dart b/lib/widgets/image_button.dart index fd2aa96..179d6d4 100644 --- a/lib/widgets/image_button.dart +++ b/lib/widgets/image_button.dart @@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:bloc/bloc.dart'; +// ignore: must_be_immutable class ImageButton extends StatelessWidget { final String text; TextStyle style = TextStyle(fontSize: 14); @@ -17,62 +18,64 @@ class ImageButton extends StatelessWidget { final VoidCallback onTap; bool isLocked; - ImageButton({ - this.text, - this.style, - this.image, - this.top, - this.left, - this.height, - this.width, - this.bloc, - this.isShape, - this.textAlignment, - this.onTap, - @required this.isLocked - }) { + ImageButton( + {this.text, + this.style, + this.image, + this.top, + this.left, + this.height, + this.width, + this.bloc, + this.isShape, + this.textAlignment, + this.onTap, + @required this.isLocked}) { width = width ?? 180; style = style ?? TextStyle(fontSize: 14, fontFamily: "Roboto Mono"); } @override Widget build(BuildContext context) { - double top = width - (style.fontSize - 5) * text.length - 2 * left < 0 ? width - 2 * style.fontSize - 10 : width - style.fontSize - 10; - print ("Top: " + top.toStringAsFixed(0) + " length: " + ((style.fontSize - 5) * text.length).toString()); + double top = width - (style.fontSize - 5) * text.length - 2 * left < 0 + ? width - 2 * style.fontSize - 10 + : width - style.fontSize - 10; + print("Top: " + + top.toStringAsFixed(0) + + " length: " + + ((style.fontSize - 5) * text.length).toString()); return Stack( //alignment: textAlignment, fit: StackFit.passthrough, overflow: Overflow.clip, children: [ FlatButton( - child: image == null ? - _getButtonImage("asset/image/WT_menu_dark.png") : - _getButtonImage(image), + child: image == null + ? _getButtonImage("asset/image/WT_menu_dark.png") + : _getButtonImage(image), padding: EdgeInsets.only(left: 0.0, bottom: 0), shape: getShape(isShape), onPressed: onTap ?? onTap, ), - Stack( - alignment: Alignment.topLeft, - children: [ + Stack(alignment: Alignment.topLeft, children: [ Positioned( top: 50, left: 50, - child: this.isLocked? - Image.asset( - 'asset/image/lock.png', - height: 60, - width: 60, - ) - : Container(), - )] - ), + child: this.isLocked + ? Image.asset( + 'asset/image/lock.png', + height: 60, + width: 60, + ) + : Container(), + ) + ]), Positioned( top: top, left: left, child: Container( height: width - 2 * left, - width: width - 2 * left, + width: width - 2 * left, child: InkWell( onTap: onTap ?? onTap, child: Text( diff --git a/lib/widgets/input_dialog_widget.dart b/lib/widgets/input_dialog_widget.dart index dd6e179..064fc27 100644 --- a/lib/widgets/input_dialog_widget.dart +++ b/lib/widgets/input_dialog_widget.dart @@ -1,6 +1,61 @@ +import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:keyboard_actions/keyboard_actions.dart'; + +/// Dialog for input any data and call of an [Event] of a [Bloc] +class InputDialog extends StatefulWidget { + final ValueChanged onChanged; + + final double initialValue; + + /// Dialog title + final String title; + + final String subtitle; + + const InputDialog({this.onChanged, this.initialValue, this.title, this.subtitle}); + + @override + _InputDialogState createState() => _InputDialogState(); +} + +class _InputDialogState extends State> with Trans { + final FocusNode _nodeText1 = FocusNode(); + double inputValue = 0; + + KeyboardActionsConfig _buildConfig(BuildContext context) { + setContext(context); + return KeyboardActionsConfig( + keyboardActionsPlatform: KeyboardActionsPlatform.ALL, + keyboardBarColor: Colors.grey[200], + keyboardSeparatorColor: Colors.black26, + nextFocus: true, + actions: [ + KeyboardActionsItem( + focusNode: _nodeText1, + toolbarButtons: [ + //button 2 + (node) { + return GestureDetector( + onTap: () => node.unfocus(), + child: Container( + color: Colors.orange, + padding: EdgeInsets.all(8.0), + child: Text( + t("Done"), + style: TextStyle(color: Colors.white), + ), + ), + ); + } + ], + ), + ], + ); + } -class InputDialog extends StatelessWidget { @override Widget build(BuildContext context) { return Dialog( @@ -12,54 +67,105 @@ class InputDialog extends StatelessWidget { } _buildChild(BuildContext context) => Container( - height: 350, - decoration: BoxDecoration(color: Colors.redAccent, shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(12))), + height: 350, + decoration: BoxDecoration(color: Colors.white60, shape: BoxShape.rectangle, borderRadius: BorderRadius.all(Radius.circular(12))), + child: KeyboardActions( + config: _buildConfig(context), child: Column( children: [ Container( - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Image.asset( - 'assets/image/lock.png', - height: 120, - width: 120, + padding: const EdgeInsets.all(12.0), + child: Column(children: [ + Text( + widget.title, + style: GoogleFonts.archivoBlack( + shadows: [ + Shadow( + offset: Offset(3.0, 3.0), + blurRadius: 3.0, + color: Colors.black54, + ), + ], + fontSize: 25, + color: Colors.orange[500], + ), ), - ), + Text( + widget.subtitle, + style: GoogleFonts.archivoBlack( + shadows: [ + Shadow( + offset: Offset(3.0, 3.0), + blurRadius: 3.0, + color: Colors.black54, + ), + ], + fontSize: 30, + color: Colors.orange[500], + ), + ), + ]), width: double.infinity, decoration: BoxDecoration( - color: Colors.white, + color: Colors.white70, shape: BoxShape.rectangle, borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12))), ), - SizedBox( - height: 24, - ), - Text( - 'Do you want to exit?', - style: TextStyle(fontSize: 20, color: Colors.white, fontWeight: FontWeight.bold), - ), SizedBox( height: 8, ), Padding( - padding: const EdgeInsets.only(right: 16, left: 16), + padding: const EdgeInsets.only(top: 20, right: 16, left: 16), child: Text( - 'If back button is pressed by mistake then click on no to continue.', - style: TextStyle(color: Colors.white), + t("Please type the following data:"), + style: GoogleFonts.inter(fontSize: 16, color: Colors.yellow[200], shadows: [ + Shadow( + offset: Offset(2.0, 2.0), + blurRadius: 3.0, + color: Colors.black54, + ) + ]), textAlign: TextAlign.center, ), ), SizedBox( height: 24, ), + Padding( + padding: const EdgeInsets.only(left: 90, right: 90), + child: TextFormField( + focusNode: _nodeText1, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5), + labelText: widget.subtitle, + labelStyle: GoogleFonts.inter(fontSize: 16, color: Colors.yellow[50]), + fillColor: Colors.black38, + filled: true, + border: OutlineInputBorder( + gapPadding: 2.0, + borderRadius: BorderRadius.circular(12.0), + borderSide: BorderSide(color: Colors.white12, width: 0.4), + ), + ), + initialValue: widget.initialValue.toStringAsFixed(0), + keyboardType: TextInputType.numberWithOptions(decimal: true), + textInputAction: TextInputAction.done, + style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.yellow[300]), + onChanged: (value) => this.inputValue = double.parse(value), + ), + ), + SizedBox( + height: 24, + ), Row( mainAxisSize: MainAxisSize.min, children: [ - FlatButton( + RaisedButton( onPressed: () { Navigator.of(context).pop(); }, - child: Text('No'), + child: Text(t('Cancel')), + color: Colors.black26, textColor: Colors.white, ), SizedBox( @@ -67,15 +173,16 @@ class InputDialog extends StatelessWidget { ), RaisedButton( onPressed: () { + widget.onChanged(this.inputValue); return Navigator.of(context).pop(true); }, - child: Text('Yes'), - color: Colors.white, - textColor: Colors.redAccent, + child: Text(t('Save')), + color: Colors.orange[600], + textColor: Colors.white, ) ], ) ], ), - ); + )); } diff --git a/lib/widgets/menu_info_widget.dart b/lib/widgets/menu_info_widget.dart index 3c5467f..4abe6c2 100644 --- a/lib/widgets/menu_info_widget.dart +++ b/lib/widgets/menu_info_widget.dart @@ -42,75 +42,72 @@ class MenuInfoWidget extends StatelessWidget with Common { @override Widget build(BuildContext context) { - int length = title.length + text2.length + text3.length + link.length; - return /* Container( - height: length > 100? 350 : 250, - width: 180, - padding: EdgeInsets.all(25.0), - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - "asset/menu/3.bcs1.png", - ), - fit: BoxFit.contain), - ), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 9, sigmaY: 9), - child:*/ Container( - padding: EdgeInsets.only(top: 10.0, left: 15, right: 10, bottom: 5), + return Container( + padding: EdgeInsets.only(top: 10.0, left: 15, right: 10, bottom: 5), - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.5), - border: Border.all(color: Colors.white60), - borderRadius: BorderRadius.all(Radius.circular(10.0)), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - title, - maxLines: 4, - textAlign: TextAlign.center, - style: - TextStyle(color: titleColor, fontSize: titleSize, fontWeight: titleWeight), - ), - Divider(), - Text( - text, - maxLines: 6, - style: TextStyle(color: textColor, fontSize: textSize, fontWeight: textWeight), - ), - Divider(), - Text( - text2, - maxLines: 6, - style: TextStyle(color: textColor, fontSize: textSize, fontWeight: textWeight), - ), - Divider(), - Text( - text3, - maxLines: 6, - style: TextStyle(color: textColor, fontSize: textSize, fontWeight: textWeight), - ), - getLink(), - ], - ), - //), - // ) + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.5), + border: Border.all(color: Colors.white60), + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + title, + maxLines: 4, + textAlign: TextAlign.center, + style: TextStyle( + color: titleColor, + fontSize: titleSize, + fontWeight: titleWeight), + ), + Divider(), + Text( + text, + maxLines: 6, + style: TextStyle( + color: textColor, fontSize: textSize, fontWeight: textWeight), + ), + Divider(), + Text( + text2, + maxLines: 6, + style: TextStyle( + color: textColor, fontSize: textSize, fontWeight: textWeight), + ), + Divider(), + Text( + text3, + maxLines: 6, + style: TextStyle( + color: textColor, fontSize: textSize, fontWeight: textWeight), + ), + getLink(), + ], + ), + //), + // ) ); } Widget getLink() { int missingId; return InkWell( - child: new Text(link, style: TextStyle(color: Colors.lightBlueAccent, fontSize: textSize, fontFamily: 'Arial', fontWeight: textWeight),), - onTap: () => - { - missingId = bloc.menuTreeRepository.getMissingTreeIdByName(bloc.missingTreeName), - print("menu " + missingId.toString()), - bloc.add(MenuTreeJump(parent: missingId)) - } - ); + child: new Text( + link, + style: TextStyle( + color: Colors.lightBlueAccent, + fontSize: textSize, + fontFamily: 'Arial', + fontWeight: textWeight), + ), + onTap: () => { + missingId = bloc.menuTreeRepository + .getMissingTreeIdByName(bloc.missingTreeName), + print("menu " + missingId.toString()), + bloc.add(MenuTreeJump(parent: missingId)) + }); } } diff --git a/lib/widgets/menu_page_widget.dart b/lib/widgets/menu_page_widget.dart index 60157af..ed00aa0 100644 --- a/lib/widgets/menu_page_widget.dart +++ b/lib/widgets/menu_page_widget.dart @@ -9,6 +9,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'menu_info_widget.dart'; @@ -70,7 +71,7 @@ class MenuPageWidget extends StatelessWidget with Trans { onPressed: () => menuClick(workoutTree, menuBloc, context), ), Positioned( - top: workoutTree.name.length > 15 ? 140 : 150, + top: workoutTree.name.length > 20 ? 130 : 145, left: 5, child: Container( height: 300, @@ -80,11 +81,10 @@ class MenuPageWidget extends StatelessWidget with Trans { child: Text( " " + workoutTree.name, maxLines: 2, - style: TextStyle( + style: GoogleFonts.archivoBlack( color: workoutTree.color, fontSize: workoutTree.fontSize, - fontFamily: 'Arial', - fontWeight: FontWeight.w900), + ), ), highlightColor: workoutTree.color, diff --git a/lib/widgets/size_widget.dart b/lib/widgets/size_widget.dart index e110d73..3226646 100644 --- a/lib/widgets/size_widget.dart +++ b/lib/widgets/size_widget.dart @@ -1,12 +1,13 @@ import 'package:aitrainer_app/bloc/exercise_new/exercise_new_bloc.dart'; -import 'package:aitrainer_app/localization/app_localization.dart'; +import 'package:aitrainer_app/library/custom_icon_icons.dart'; +import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:google_fonts/google_fonts.dart'; import 'app_bar.dart'; -import 'package:keyboard_actions/keyboard_actions.dart'; +import 'input_dialog_widget.dart'; // ignore: must_be_immutable class SizeWidget extends StatefulWidget { @@ -19,122 +20,126 @@ class SizeWidget extends StatefulWidget { } class _SizeState extends State with Trans { - double bmr = 0; - - final FocusNode _nodeText1 = FocusNode(); - - KeyboardActionsConfig _buildConfig(BuildContext context) { - return KeyboardActionsConfig( - keyboardActionsPlatform: KeyboardActionsPlatform.ALL, - keyboardBarColor: Colors.grey[200], - keyboardSeparatorColor: Colors.black26, - nextFocus: true, - actions: [ - KeyboardActionsItem( - focusNode: _nodeText1, - toolbarButtons: [ - //button 2 - (node) { - return GestureDetector( - onTap: () => node.unfocus(), - child: Container( - color: Colors.orange, - padding: EdgeInsets.all(8.0), - child: Text( - AppLocalizations.of(context).translate("Done"), - style: TextStyle(color: Colors.white), - ), - ), - ); - } - ], - ), - ], - ); - } - @override Widget build(BuildContext context) { setContext(context); - print("sex " + widget.exerciseBloc.customerRepository.sex); return Form( child: Scaffold( resizeToAvoidBottomInset: true, appBar: AppBarNav(depth: 1), body: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage('asset/image/WT_black_background.png'), - fit: BoxFit.fill, - alignment: Alignment.center, - ), + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('asset/image/WT_black_background.png'), + fit: BoxFit.fill, + alignment: Alignment.center, ), - child: KeyboardActions( - config: _buildConfig(context), - child: Container( - padding: EdgeInsets.only(top: 10), - child: - Column(crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Stack( - children: [ - widget.exerciseBloc.customerRepository.sex == "Man" - ? Image.asset( - "asset/image/man_sizes.png", - height: MediaQuery.of(context).size.height * .85, - ) - : Image.asset( - "asset/image/woman_sizes.png", - height: MediaQuery.of(context).size.height * .85, - ), - Positioned( - top: 30, - left: 175, - child: Image.asset( - "asset/image/sizes_empty.png", - ), - ) - ], - ) - ])))))); + ), + child: SafeArea( + child: Container( + padding: EdgeInsets.only(top: 10), + child: Column(crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ + Stack( + children: getSizeFigure(), + ) + ]))), + ))); } - Widget getWeightInput() { - return Container( - padding: EdgeInsets.only(top: 15, left: 65, right: 65, bottom: 10), - alignment: Alignment.center, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Flexible( - child: TextFormField( - focusNode: _nodeText1, - decoration: InputDecoration( - contentPadding: EdgeInsets.only(left: 15, top: 5, bottom: 5), - labelText: AppLocalizations.of(context).translate("Actual Weight"), - labelStyle: GoogleFonts.inter(fontSize: 16, color: Colors.yellow[50]), - fillColor: Colors.black38, - filled: true, - border: OutlineInputBorder( - gapPadding: 2.0, - borderRadius: BorderRadius.circular(12.0), - borderSide: BorderSide(color: Colors.white12, width: 0.4), - ), - ), - initialValue: widget.exerciseBloc.weight.toStringAsFixed(0), - keyboardType: TextInputType.numberWithOptions(decimal: true), - textInputAction: TextInputAction.done, - style: GoogleFonts.archivoBlack(fontSize: 20, color: Colors.yellow[300]), - onChanged: (value) => {widget.exerciseBloc.add(ExerciseNewWeightChange(value: double.parse(value)))}, - ), - ), - IconButton( - icon: Icon(Icons.save), - hoverColor: Colors.blueAccent, - color: widget.exerciseBloc.changedWeight ? Colors.blue[200] : Colors.black54, - onPressed: () => {print("Save"), widget.exerciseBloc.add(ExerciseNewSaveWeight())}) - ], - )); + List getSizeFigure() { + //print("w " + MediaQuery.of(context).size.width.toString() + "h " + MediaQuery.of(context).size.height.toString()); + List list = List(); + list.add(SizedBox( + width: MediaQuery.of(context).size.width * .80, + height: MediaQuery.of(context).size.height * .80, + )); + list.add( + Positioned( + top: 20, + left: 160, + child: Stack( + alignment: Alignment.topLeft, + children: [ + SizedBox(height: 80, width: 100), + Text(t("Your Sizes"), + style: GoogleFonts.archivoBlack( + shadows: [ + Shadow( + offset: Offset(5.0, 5.0), + blurRadius: 3.0, + color: Colors.black54, + ), + ], + fontSize: 22, + color: Colors.orange[500], + )), + Positioned( + top: 30, + left: 60, + child: IconButton( + padding: EdgeInsets.zero, + icon: Icon(Icons.save), + iconSize: 40, + hoverColor: Colors.blueAccent, + color: widget.exerciseBloc.changedSizes ? Colors.orange[300] : Colors.black54, + onPressed: () => {print("Save"), widget.exerciseBloc.add(ExerciseNewSaveWeight())})) + ], + )), + ); + list.add(widget.exerciseBloc.customerRepository.sex == "Man" + ? Image.asset( + "asset/image/man_sizes.png", + height: MediaQuery.of(context).size.height * .80, + ) + : Image.asset( + "asset/image/woman_sizes.png", + height: MediaQuery.of(context).size.height * .80, + )); + + list.addAll(getSizeElements()); + return list; + } + + List getSizeElements() { + List list = List(); + + widget.exerciseBloc.manSizes.forEach((element) { + list.add( + Positioned( + top: element.top.toDouble(), + left: element.left.toDouble(), + child: element.value != 0 + ? IconButton( + icon: Icon(CustomIcon.ok_circled), + padding: EdgeInsets.zero, + color: Colors.green[200], + onPressed: () => onPressed(element), + ) + : IconButton( + icon: Icon(CustomIcon.question), + padding: EdgeInsets.zero, + color: Colors.red[800], + onPressed: () => onPressed(element), + )), + ); + }); + + return list; + } + + void onPressed(Property element) { + print(element.propertyName); + showDialog( + context: context, + builder: (context) => InputDialog( + title: t("Size Of Your"), + subtitle: element.propertyNameTranslation, + initialValue: element.value, + onChanged: (value) { + widget.exerciseBloc.add(ExerciseNewSizeChange(propertyName: element.propertyName, value: value)); + }, + )); } } diff --git a/lib/widgets/treeview_parent_widget.dart b/lib/widgets/treeview_parent_widget.dart index 15730f4..a31561a 100644 --- a/lib/widgets/treeview_parent_widget.dart +++ b/lib/widgets/treeview_parent_widget.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; class TreeviewParentWidget extends StatelessWidget { final String text; @@ -11,7 +12,7 @@ class TreeviewParentWidget extends StatelessWidget { Widget build(BuildContext context) { Widget parentWidget = Text( this.text, - style: TextStyle(fontWeight: FontWeight.w800, color: Colors.blueAccent, backgroundColor: Colors.transparent), + style: GoogleFonts.archivoBlack(fontSize: 24, color: Colors.blue[800], backgroundColor: Colors.transparent), ); Icon icon = Icon(Icons.person); @@ -27,4 +28,4 @@ class TreeviewParentWidget extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/pubspec.lock b/pubspec.lock index 536e4bb..7ac4f7b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -14,7 +14,14 @@ packages: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.40.5" + version: "0.40.6" + animated_widgets: + dependency: "direct main" + description: + name: animated_widgets + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.6" archive: dependency: transitive description: @@ -84,7 +91,7 @@ packages: name: build_resolvers url: "https://pub.dartlang.org" source: hosted - version: "1.4.2" + version: "1.4.3" build_runner: dependency: "direct dev" description: @@ -175,7 +182,7 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.14.1" + version: "0.14.2" crypto: dependency: transitive description: @@ -196,7 +203,7 @@ packages: name: dart_style url: "https://pub.dartlang.org" source: hosted - version: "1.3.8" + version: "1.3.9" devicelocale: dependency: "direct main" description: @@ -204,6 +211,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.3.3" + dropdown_search: + dependency: "direct main" + description: + name: dropdown_search + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.6" equatable: dependency: "direct main" description: @@ -280,7 +294,7 @@ packages: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.2.1" fixnum: dependency: transitive description: @@ -306,7 +320,7 @@ packages: name: flutter_bloc url: "https://pub.dartlang.org" source: hosted - version: "6.0.6" + version: "6.1.1" flutter_driver: dependency: "direct dev" description: flutter @@ -332,7 +346,7 @@ packages: name: flutter_keyboard_visibility url: "https://pub.dartlang.org" source: hosted - version: "3.2.2" + version: "3.3.0" flutter_launcher_icons: dependency: "direct dev" description: @@ -436,7 +450,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "2.1.18" + version: "2.1.19" infinite_listview: dependency: "direct main" description: @@ -479,6 +493,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.2" + keyboard_actions: + dependency: "direct main" + description: + name: keyboard_actions + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.1+1" logging: dependency: transitive description: @@ -527,7 +548,7 @@ packages: name: node_interop url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.2.0" node_io: dependency: transitive description: @@ -576,7 +597,7 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "1.6.22" + version: "1.6.24" path_provider_linux: dependency: transitive description: @@ -590,21 +611,21 @@ packages: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+4" + version: "0.0.4+6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+1" + version: "0.0.4+3" pedantic: dependency: transitive description: @@ -681,7 +702,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.1.4+1" + version: "2.1.5" rainbow_color: dependency: "direct main" description: @@ -716,21 +737,21 @@ packages: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "0.5.12+2" + version: "0.5.12+4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.2+2" + version: "0.0.2+4" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+10" + version: "0.0.1+11" shared_preferences_platform_interface: dependency: transitive description: @@ -751,7 +772,7 @@ packages: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+1" + version: "0.0.1+3" shelf: dependency: transitive description: @@ -931,7 +952,7 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "5.3.1" + version: "5.5.0" vm_service_client: dependency: transitive description: @@ -966,7 +987,7 @@ packages: name: webkit_inspection_protocol url: "https://pub.dartlang.org" source: hosted - version: "0.7.3" + version: "0.7.4" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4858449..a7e3df3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,11 +39,14 @@ dependencies: fl_chart: ^0.12.0 infinite_listview: ^1.0.1+1 toggle_switch: ^0.1.8 + keyboard_actions: ^3.3.1+1 + dropdown_search: ^0.4.6 firebase_core: 0.5.0+1 #firebase_analytics: ^6.0.2 firebase_auth: ^0.18.1+2 flutter_facebook_auth: ^0.3.3 + animated_widgets: ^1.0.6 mockito: ^4.1.1 @@ -74,7 +77,10 @@ flutter_icons: # The following section is specific to Flutter. flutter: - + fonts: + - family: CustomIcon + fonts: + - asset: asset/font/CustomIcon.ttf # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. @@ -82,9 +88,16 @@ flutter: # To add assets to your application, add an assets section, like this: assets: + - asset/icon/gomb_kek_a-2.png + - asset/icon/gomb_orange_a.png + - asset/icon/gomb_pink_a.png + - asset/icon/gomb_pink_b.png + - asset/icon/gomb_zold_b-1.png + - asset/icon/gomb_sarga_a.png - asset/image/WT_menu_welcome.png - asset/image/WT01_loading_layers.png - asset/image/WT_menu_backround.png + - asset/image/WT_black_background.png - asset/image/WT_menu.png - asset/image/WT_login.png - asset/image/WT_OK.png @@ -107,6 +120,11 @@ flutter: - asset/image/exercise_plan_custom.jpg - asset/image/exercise_plan_suggested.jpg - asset/image/predictions.jpg + - asset/image/man_sizes.png + - asset/image/woman_sizes.png + - asset/image/BMI_diagram_b.png + - asset/image/BMI_graph_c.png + - asset/image/BMI_mutato.png - asset/menu/1.cardio.png - asset/menu/1.1.aerob.png - asset/menu/1.2.anaerob.png