wt1.1a flutter_bloc
This commit is contained in:
parent
8363d7772f
commit
ac1c6be8f3
@ -8,7 +8,7 @@ if (localPropertiesFile.exists()) {
|
|||||||
|
|
||||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
if (flutterRoot == null) {
|
if (flutterRoot == null) {
|
||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
throw new Exception("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
@ -26,6 +26,12 @@ apply plugin: 'kotlin-android'
|
|||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
|
||||||
|
def keystoreProperties = new Properties()
|
||||||
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
|
|
||||||
@ -46,11 +52,20 @@ android {
|
|||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
release {
|
||||||
|
keyAlias keystoreProperties['keyAlias']
|
||||||
|
keyPassword keystoreProperties['keyPassword']
|
||||||
|
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||||
|
storePassword keystoreProperties['storePassword']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
// TODO: Add your own signing config for the release build.
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.release
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,4 +77,5 @@ flutter {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation 'com.google.firebase:firebase-analytics:17.2.2'
|
implementation 'com.google.firebase:firebase-analytics:17.2.2'
|
||||||
|
implementation 'com.facebook.android:facebook-login:[5,6)'
|
||||||
}
|
}
|
||||||
|
@ -48,5 +48,23 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
||||||
|
<meta-data android:name="com.facebook.sdk.ApplicationId"
|
||||||
|
android:value="@string/app_name"/>
|
||||||
|
|
||||||
|
<activity android:name="com.facebook.FacebookActivity"
|
||||||
|
android:configChanges=
|
||||||
|
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
|
||||||
|
android:label="WorkoutTest" />
|
||||||
|
<activity
|
||||||
|
android:name="com.facebook.CustomTabActivity"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="@string/fb_login_protocol_scheme" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
13
android/app/src/main/res/values/strings.xml
Normal file
13
android/app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">WorkoutTest</string>
|
||||||
|
|
||||||
|
<!-- Replace "000000000000" with your Facebook App ID here. -->
|
||||||
|
<string name="facebook_app_id">584181112271127</string>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Replace "000000000000" with your Facebook App ID here.
|
||||||
|
**NOTE**: The scheme needs to start with `fb` and then your ID.
|
||||||
|
-->
|
||||||
|
<string name="fb_login_protocol_scheme">fb584181112271127</string>
|
||||||
|
</resources>
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
|
||||||
|
4
android/key.properties
Normal file
4
android/key.properties
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
storePassword=tbi6012Andi
|
||||||
|
keyPassword=tbi6012Andi
|
||||||
|
keyAlias=key
|
||||||
|
storeFile=c:/Users/bossa/.ssh/key.jks
|
1
android/settings_aar.gradle
Normal file
1
android/settings_aar.gradle
Normal file
@ -0,0 +1 @@
|
|||||||
|
include ':app'
|
BIN
asset/icon/WT_long_logo_1024x500.png
Normal file
BIN
asset/icon/WT_long_logo_1024x500.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
asset/icon/icon_512.png
Normal file
BIN
asset/icon/icon_512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
BIN
asset/image/login_fb.png
Normal file
BIN
asset/image/login_fb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
14
i18n/en.json
14
i18n/en.json
File diff suppressed because one or more lines are too long
16
i18n/hu.json
16
i18n/hu.json
@ -23,8 +23,9 @@
|
|||||||
"gdpr_text": "",
|
"gdpr_text": "",
|
||||||
|
|
||||||
"Please log in": "Kérlek jelentkezz be",
|
"Please log in": "Kérlek jelentkezz be",
|
||||||
"Customer does not exist or the password is wrong": "A felhasználónév nem létezik vagy a jelszó rossz.",
|
"Exception: Customer does not exist or the password is wrong": "A felhasználónév nem létezik vagy a jelszó rossz.",
|
||||||
"Please select an exercise": "Válassz ki egy gyakorlatot",
|
"Please select an exercise": "Válassz ki egy gyakorlatot",
|
||||||
|
"There is an error: during registration:": "Hiba lépett fel a regisztráció során:",
|
||||||
"Customer exists": "Ez az email cím már regisztrálva van",
|
"Customer exists": "Ez az email cím már regisztrálva van",
|
||||||
"Cardio": "Kardió",
|
"Cardio": "Kardió",
|
||||||
"400m": "400m",
|
"400m": "400m",
|
||||||
@ -50,7 +51,10 @@
|
|||||||
"BMR": "Alapanyagcsere",
|
"BMR": "Alapanyagcsere",
|
||||||
"Sizes": "Méretek",
|
"Sizes": "Méretek",
|
||||||
"Save Exercise": "gyakorlat mentése",
|
"Save Exercise": "gyakorlat mentése",
|
||||||
"Save": "Save",
|
"Save": "Mentés",
|
||||||
|
"The number of the exercise": "Írd be a gyakorlat számát",
|
||||||
|
"The number of the exercise done with": "Írd be, mennyivel csináltad a gyakorlatot",
|
||||||
|
|
||||||
|
|
||||||
"Name": "Név",
|
"Name": "Név",
|
||||||
"Exercise": "Gyakorlat",
|
"Exercise": "Gyakorlat",
|
||||||
@ -58,17 +62,23 @@
|
|||||||
"Unit": "Egység",
|
"Unit": "Egység",
|
||||||
"Exercise date and time": "A gyakorlat időpontja",
|
"Exercise date and time": "A gyakorlat időpontja",
|
||||||
"Please type the right quantity 0-1000": "Kérlek írj be egy helyes számot 0-10000 között",
|
"Please type the right quantity 0-1000": "Kérlek írj be egy helyes számot 0-10000 között",
|
||||||
|
"Yes": "Igen",
|
||||||
|
"No": "Nem",
|
||||||
|
"with": "",
|
||||||
|
"Do you save this exercise with these parameters?":"Elmented a gyakorlatot ezekkel az adatokkal?",
|
||||||
|
|
||||||
"repeat": "ismétlés",
|
"repeat": "ismétlés",
|
||||||
"meter": "meter",
|
"meter": "meter",
|
||||||
"percent": "százalék",
|
"percent": "százalék",
|
||||||
"kg": "kg",
|
"kg": "kg",
|
||||||
|
"kilogram": "kilogramm",
|
||||||
"lbs": "lbs",
|
"lbs": "lbs",
|
||||||
"second": "másodperc",
|
"second": "másodperc",
|
||||||
|
|
||||||
"Email": "Email",
|
"Email": "Email",
|
||||||
"Password": "Jelszó",
|
"Password": "Jelszó",
|
||||||
"Password (Leave empty if you don't want to change)":"Jelszó (hagyd üresen, ha nem akarod megváltoztatni)",
|
"OR": "VAGY",
|
||||||
|
"Password (Leave empty if no change)":"Jelszó (üres, ha nincs változás)",
|
||||||
"First Name": "Keresztnév",
|
"First Name": "Keresztnév",
|
||||||
"Birth Year": "Születési év",
|
"Birth Year": "Születési év",
|
||||||
"Weight": "Tömeg",
|
"Weight": "Tömeg",
|
||||||
|
46
lib/bloc/account/account_bloc.dart
Normal file
46
lib/bloc/account/account_bloc.dart
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
part 'account_event.dart';
|
||||||
|
part 'account_state.dart';
|
||||||
|
|
||||||
|
class AccountBloc extends Bloc<AccountEvent, AccountState> {
|
||||||
|
final CustomerRepository customerRepository;
|
||||||
|
bool loggedIn = false;
|
||||||
|
AccountBloc({this.customerRepository}) : super(AccountInitial()) {
|
||||||
|
if ( Auth().userLoggedIn != null ) {
|
||||||
|
customerRepository.customer = Auth().userLoggedIn;
|
||||||
|
loggedIn = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<AccountState> mapEventToState(
|
||||||
|
AccountEvent event,
|
||||||
|
) async* {
|
||||||
|
try {
|
||||||
|
if (event is AccountChangeCustomer) {
|
||||||
|
// route to Customer Change page
|
||||||
|
yield AccountReady();
|
||||||
|
} else if (event is AccountLogin) {
|
||||||
|
//route to Login Page
|
||||||
|
} else if (event is AccountLogInFinished) {
|
||||||
|
customerRepository.customer = event.customer;
|
||||||
|
yield AccountLoggedIn();
|
||||||
|
} else if (event is AccountLogout) {
|
||||||
|
await Auth().logout();
|
||||||
|
customerRepository.customer = null;
|
||||||
|
loggedIn = false;
|
||||||
|
yield AccountLoggedOut();
|
||||||
|
}
|
||||||
|
} on Exception catch(e) {
|
||||||
|
yield AccountError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
lib/bloc/account/account_event.dart
Normal file
46
lib/bloc/account/account_event.dart
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
part of 'account_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class AccountEvent extends Equatable {
|
||||||
|
const AccountEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountChangeCustomer extends AccountEvent {
|
||||||
|
final Customer customer;
|
||||||
|
|
||||||
|
const AccountChangeCustomer({this.customer});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [customer];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountLogout extends AccountEvent {
|
||||||
|
final Customer customer;
|
||||||
|
|
||||||
|
const AccountLogout({this.customer});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [customer];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountLogin extends AccountEvent {
|
||||||
|
final Customer customer;
|
||||||
|
|
||||||
|
const AccountLogin({this.customer});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [customer];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountLogInFinished extends AccountEvent {
|
||||||
|
final Customer customer;
|
||||||
|
|
||||||
|
const AccountLogInFinished({this.customer});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [customer];
|
||||||
|
}
|
36
lib/bloc/account/account_state.dart
Normal file
36
lib/bloc/account/account_state.dart
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
part of 'account_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class AccountState extends Equatable {
|
||||||
|
const AccountState();
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountInitial extends AccountState {
|
||||||
|
const AccountInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountLoading extends AccountState {
|
||||||
|
const AccountLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountReady extends AccountState {
|
||||||
|
const AccountReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountLoggedOut extends AccountState {
|
||||||
|
const AccountLoggedOut();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountLoggedIn extends AccountState {
|
||||||
|
const AccountLoggedIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountError extends AccountState {
|
||||||
|
final String message;
|
||||||
|
const AccountError({this.message});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
127
lib/bloc/custom_exercise_form_bloc.dart
Normal file
127
lib/bloc/custom_exercise_form_bloc.dart
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class CustomExerciseFormBloc extends FormBloc<String, String> {
|
||||||
|
final ExerciseRepository exerciseRepository;
|
||||||
|
final quantityField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final unitQuantityField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
//1RM calculated Fields
|
||||||
|
final rmWendlerField = TextFieldBloc( initialValue: "0",);
|
||||||
|
final rmMcGothlinField = TextFieldBloc( initialValue: "0");
|
||||||
|
final rmLombardiField = TextFieldBloc( initialValue: "0");
|
||||||
|
final rmMayhewField = TextFieldBloc( initialValue: "0");
|
||||||
|
final rmOconnerField = TextFieldBloc( initialValue: "0");
|
||||||
|
final rmWathenField = TextFieldBloc( initialValue: "0");
|
||||||
|
final rmAverageField = TextFieldBloc( initialValue: "0");
|
||||||
|
final rm90Field = TextFieldBloc( initialValue: "0");
|
||||||
|
final rm80Field = TextFieldBloc( initialValue: "0");
|
||||||
|
final rm70Field = TextFieldBloc( initialValue: "0");
|
||||||
|
final rm60Field = TextFieldBloc( initialValue: "0");
|
||||||
|
final rm50Field = TextFieldBloc( initialValue: "0");
|
||||||
|
|
||||||
|
CustomExerciseFormBloc({this.exerciseRepository}) {
|
||||||
|
addFieldBlocs(fieldBlocs: [
|
||||||
|
quantityField,
|
||||||
|
unitQuantityField,
|
||||||
|
rmWendlerField,
|
||||||
|
rmMcGothlinField,
|
||||||
|
rmLombardiField,
|
||||||
|
rmMayhewField,
|
||||||
|
rmOconnerField,
|
||||||
|
rmWathenField,
|
||||||
|
rmAverageField,
|
||||||
|
rm90Field,
|
||||||
|
rm80Field,
|
||||||
|
rm70Field,
|
||||||
|
rm60Field,
|
||||||
|
rm50Field
|
||||||
|
]);
|
||||||
|
|
||||||
|
quantityField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exerciseRepository.setQuantity(current.valueToDouble);
|
||||||
|
calculate1RM();
|
||||||
|
});
|
||||||
|
|
||||||
|
unitQuantityField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exerciseRepository.setUnitQuantity(current.valueToDouble);
|
||||||
|
calculate1RM();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSubmitting() async {
|
||||||
|
print("on Submitting Custom form");
|
||||||
|
try {
|
||||||
|
emitLoading(progress: 30);
|
||||||
|
// Emit either Loaded or Error
|
||||||
|
|
||||||
|
emitSuccess(canSubmitAgain: false);
|
||||||
|
} on Exception catch (ex) {
|
||||||
|
emitFailure(failureResponse: ex.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculate1RM() {
|
||||||
|
double weight = exerciseRepository.exercise.unitQuantity;
|
||||||
|
double repeat = exerciseRepository.exercise.quantity;
|
||||||
|
if ( weight == 0 || repeat == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print("Calculating 1RM");
|
||||||
|
exerciseRepository.rmWendler = weight * repeat * 0.0333 + weight;
|
||||||
|
rmWendlerField.updateValue(exerciseRepository.rmWendler.toString());
|
||||||
|
exerciseRepository.rmMcglothlin = 100 * weight / (101.3 - 2.67123 * repeat);
|
||||||
|
rmMcGothlinField.updateValue(exerciseRepository.rmMcglothlin.toString());
|
||||||
|
exerciseRepository.rmLombardi = pow(weight * repeat, 0.1);
|
||||||
|
rmLombardiField.updateValue(exerciseRepository.rmLombardi.toString());
|
||||||
|
exerciseRepository.rmOconner = weight * (1 + repeat / 40);
|
||||||
|
rmOconnerField.updateValue(exerciseRepository.rmOconner.toString());
|
||||||
|
exerciseRepository.rmMayhew =
|
||||||
|
100 * weight / (52.2 + 41.9 * pow(e, -0.055 * repeat));
|
||||||
|
rmMayhewField.updateValue(exerciseRepository.rmMayhew.toString());
|
||||||
|
exerciseRepository.rmWathen =
|
||||||
|
100 * weight / (48.8 + 53.8 * pow(e, -0.075 * repeat));
|
||||||
|
rmWathenField.updateValue(exerciseRepository.rmWathen.toString());
|
||||||
|
double average = (exerciseRepository.rmWendler + exerciseRepository.rmWathen +
|
||||||
|
exerciseRepository.rmMayhew + exerciseRepository.rmOconner +
|
||||||
|
exerciseRepository.rmMcglothlin)/5;
|
||||||
|
rmAverageField.updateValue(average.toString());
|
||||||
|
rm90Field.updateValue((average*0.9).toString());
|
||||||
|
rm80Field.updateValue((average*0.8).toString());
|
||||||
|
rm70Field.updateValue((average*0.7).toString());
|
||||||
|
rm60Field.updateValue((average*0.6).toString());
|
||||||
|
rm50Field.updateValue((average*0.5).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
//@override
|
||||||
|
Future<void> close() {
|
||||||
|
quantityField.close();
|
||||||
|
unitQuantityField.close();
|
||||||
|
|
||||||
|
rmWendlerField.close();
|
||||||
|
rmMcGothlinField.close();
|
||||||
|
rmLombardiField.close();
|
||||||
|
rmMayhewField.close();
|
||||||
|
rmOconnerField.close();
|
||||||
|
rmWathenField.close();
|
||||||
|
rmAverageField.close();
|
||||||
|
rm90Field.close();
|
||||||
|
rm80Field.close();
|
||||||
|
rm70Field.close();
|
||||||
|
rm60Field.close();
|
||||||
|
rm50Field.close();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
}
|
38
lib/bloc/customer_change/customer_change_bloc.dart
Normal file
38
lib/bloc/customer_change/customer_change_bloc.dart
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
part 'customer_change_event.dart';
|
||||||
|
part 'customer_change_state.dart';
|
||||||
|
|
||||||
|
class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState> {
|
||||||
|
final CustomerRepository customerRepository;
|
||||||
|
CustomerChangeBloc({this.customerRepository}) : super(CustomerChangeInitial());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<CustomerChangeState> mapEventToState(
|
||||||
|
CustomerChangeEvent event,
|
||||||
|
) async* {
|
||||||
|
try {
|
||||||
|
if (event is CustomerGoalChange) {
|
||||||
|
customerRepository.setGoal(event.goal);
|
||||||
|
yield CustomerDataChanged();
|
||||||
|
} else if (event is CustomerFitnessChange) {
|
||||||
|
customerRepository.setFitnessLevel(event.fitness);
|
||||||
|
yield CustomerDataChanged();
|
||||||
|
} else if (event is CustomerBodyTypeChange) {
|
||||||
|
customerRepository.setBodyType(event.bodyType);
|
||||||
|
yield CustomerDataChanged();
|
||||||
|
} else if (event is CustomerSave) {
|
||||||
|
yield CustomerSaving();
|
||||||
|
await customerRepository.saveCustomer();
|
||||||
|
yield CustomerSaveSuccess();
|
||||||
|
}
|
||||||
|
} on Exception catch(e) {
|
||||||
|
yield CustomerSaveError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
lib/bloc/customer_change/customer_change_event.dart
Normal file
36
lib/bloc/customer_change/customer_change_event.dart
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
part of 'customer_change_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class CustomerChangeEvent extends Equatable {
|
||||||
|
const CustomerChangeEvent();
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerGoalChange extends CustomerChangeEvent {
|
||||||
|
final String goal;
|
||||||
|
const CustomerGoalChange({this.goal});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [goal];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerFitnessChange extends CustomerChangeEvent {
|
||||||
|
final String fitness;
|
||||||
|
const CustomerFitnessChange({this.fitness});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [fitness];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerBodyTypeChange extends CustomerChangeEvent {
|
||||||
|
final String bodyType;
|
||||||
|
const CustomerBodyTypeChange({this.bodyType});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [bodyType];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerSave extends CustomerChangeEvent {
|
||||||
|
const CustomerSave();
|
||||||
|
}
|
32
lib/bloc/customer_change/customer_change_state.dart
Normal file
32
lib/bloc/customer_change/customer_change_state.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
part of 'customer_change_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class CustomerChangeState extends Equatable {
|
||||||
|
const CustomerChangeState();
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerChangeInitial extends CustomerChangeState {
|
||||||
|
const CustomerChangeInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerSaving extends CustomerChangeState {
|
||||||
|
const CustomerSaving();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerDataChanged extends CustomerChangeState {
|
||||||
|
const CustomerDataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerSaveSuccess extends CustomerChangeState {
|
||||||
|
const CustomerSaveSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerSaveError extends CustomerChangeState {
|
||||||
|
final String message;
|
||||||
|
const CustomerSaveError({this.message});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
101
lib/bloc/customer_change_form_bloc.dart
Normal file
101
lib/bloc/customer_change_form_bloc.dart
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class CustomerChangeFormBloc extends FormBloc<String, String> {
|
||||||
|
final CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
final emailField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final firstNameField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final nameField = TextFieldBloc();
|
||||||
|
final passwordField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
//FieldBlocValidators.confirmPassword(passwordField),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final birthYearField = TextFieldBloc();
|
||||||
|
final weightField = TextFieldBloc();
|
||||||
|
final genderField = SelectFieldBloc();
|
||||||
|
|
||||||
|
final goalField = TextFieldBloc();
|
||||||
|
|
||||||
|
CustomerChangeFormBloc({this.customerRepository}) {
|
||||||
|
addFieldBlocs(fieldBlocs: [
|
||||||
|
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));
|
||||||
|
|
||||||
|
firstNameField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
customerRepository.setFirstName(current.value);
|
||||||
|
});
|
||||||
|
nameField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
customerRepository.setName(current.value);
|
||||||
|
});
|
||||||
|
birthYearField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
customerRepository.setBirthYear(current.valueToInt);
|
||||||
|
});
|
||||||
|
weightField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
customerRepository.setWeight(current.valueToInt);
|
||||||
|
});
|
||||||
|
|
||||||
|
customerRepository.genders.forEach((element) {
|
||||||
|
genderField.addItem(element.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
genderField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
String dbValue = customerRepository.getGenderByName(current.value);
|
||||||
|
customerRepository.setSex(dbValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSubmitting() async {
|
||||||
|
print("on Submitting Custom form");
|
||||||
|
try {
|
||||||
|
emitLoading(progress: 30);
|
||||||
|
// Emit either Loaded or Error
|
||||||
|
await customerRepository.saveCustomer();
|
||||||
|
emitSuccess(canSubmitAgain: false);
|
||||||
|
} on Exception catch (ex) {
|
||||||
|
emitFailure(failureResponse: ex.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() {
|
||||||
|
emailField.close();
|
||||||
|
firstNameField.close();
|
||||||
|
nameField.close();
|
||||||
|
passwordField.close();
|
||||||
|
birthYearField.close();
|
||||||
|
weightField.close();
|
||||||
|
genderField.close();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
64
lib/bloc/exercise_form_bloc.dart
Normal file
64
lib/bloc/exercise_form_bloc.dart
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class ExerciseFormBloc extends FormBloc<String, String> {
|
||||||
|
final ExerciseRepository exerciseRepository;
|
||||||
|
|
||||||
|
final quantityField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final unitField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final unitQuantityField = TextFieldBloc();
|
||||||
|
final unitQuantityUnitField = TextFieldBloc();
|
||||||
|
|
||||||
|
ExerciseFormBloc({this.exerciseRepository}) {
|
||||||
|
addFieldBlocs(fieldBlocs: [
|
||||||
|
quantityField,
|
||||||
|
unitField,
|
||||||
|
unitQuantityField,
|
||||||
|
unitQuantityUnitField
|
||||||
|
]);
|
||||||
|
|
||||||
|
quantityField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exerciseRepository.setQuantity(current.valueToDouble);
|
||||||
|
});
|
||||||
|
|
||||||
|
unitField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exerciseRepository.setUnit(current.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
unitQuantityField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exerciseRepository.setUnitQuantity(current.valueToDouble);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSubmitting() async {
|
||||||
|
try {
|
||||||
|
emitLoading(progress: 30);
|
||||||
|
// Emit either Loaded or Error
|
||||||
|
await exerciseRepository.addExercise();
|
||||||
|
emitSuccess(canSubmitAgain: false);
|
||||||
|
|
||||||
|
} on Exception catch (ex) {
|
||||||
|
emitFailure(failureResponse: ex.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() {
|
||||||
|
unitQuantityField.close();
|
||||||
|
unitQuantityUnitField.close();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
61
lib/bloc/login_form_bloc.dart
Normal file
61
lib/bloc/login_form_bloc.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class LoginFormBloc extends FormBloc<String, String> {
|
||||||
|
final AccountBloc accountBloc;
|
||||||
|
final UserRepository userRepository;
|
||||||
|
|
||||||
|
final emailField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final passwordField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
LoginFormBloc({this.userRepository, this.accountBloc}) {
|
||||||
|
addFieldBlocs(fieldBlocs: [
|
||||||
|
emailField,
|
||||||
|
passwordField
|
||||||
|
]);
|
||||||
|
|
||||||
|
emailField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
userRepository.setEmail(current.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
passwordField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
userRepository.setPassword(current.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSubmitting() async {
|
||||||
|
try {
|
||||||
|
emitLoading(progress: 30);
|
||||||
|
if ( ! Common.validateEmail(userRepository)) {
|
||||||
|
emailField.addFieldError(Common.EMAIL_ERROR, isPermanent: true);
|
||||||
|
|
||||||
|
emitFailure(failureResponse: Common.EMAIL_ERROR);
|
||||||
|
} else if ( ! Common.validatePassword(userRepository)) {
|
||||||
|
passwordField.addFieldError(Common.PASSWORD_ERROR, isPermanent: true);
|
||||||
|
emitFailure(failureResponse: Common.PASSWORD_ERROR);
|
||||||
|
} else {
|
||||||
|
// Emit either Loaded or Error
|
||||||
|
await userRepository.getUser();
|
||||||
|
emitSuccess(canSubmitAgain: false);
|
||||||
|
accountBloc.add(AccountLogInFinished(customer: Auth().userLoggedIn));
|
||||||
|
}
|
||||||
|
} on Exception catch (ex) {
|
||||||
|
emitFailure(failureResponse: ex.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
lib/bloc/menu/menu_bloc.dart
Normal file
51
lib/bloc/menu/menu_bloc.dart
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/repository/menu_tree_repository.dart';
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
part 'menu_event.dart';
|
||||||
|
part 'menu_state.dart';
|
||||||
|
|
||||||
|
class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||||
|
final MenuTreeRepository menuTreeRepository;
|
||||||
|
int parent;
|
||||||
|
|
||||||
|
MenuBloc({this.menuTreeRepository}) : super(MenuInitial()) {
|
||||||
|
parent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<MenuState> mapEventToState(
|
||||||
|
MenuEvent event,
|
||||||
|
) async* {
|
||||||
|
try {
|
||||||
|
if ( event is MenuCreate ) {
|
||||||
|
yield MenuLoading();
|
||||||
|
await menuTreeRepository.createTree();
|
||||||
|
yield MenuReady();
|
||||||
|
} else if (event is MenuTreeDown) {
|
||||||
|
// get child menus or exercises
|
||||||
|
yield MenuLoading();
|
||||||
|
parent = event.parent;
|
||||||
|
menuTreeRepository.getBranch(event.parent);
|
||||||
|
yield MenuReady();
|
||||||
|
} else if (event is MenuTreeUp) {
|
||||||
|
yield MenuLoading();
|
||||||
|
// get parent menus or exercises
|
||||||
|
parent = event.parent;
|
||||||
|
menuTreeRepository.getBranch(parent);
|
||||||
|
|
||||||
|
yield MenuReady();
|
||||||
|
} else if (event is MenuClickExercise) {
|
||||||
|
yield MenuLoading();
|
||||||
|
// get exercise page
|
||||||
|
yield MenuReady();
|
||||||
|
}
|
||||||
|
} on Exception catch(ex) {
|
||||||
|
yield MenuError(message: ex.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
lib/bloc/menu/menu_event.dart
Normal file
41
lib/bloc/menu/menu_event.dart
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
part of 'menu_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class MenuEvent extends Equatable {
|
||||||
|
const MenuEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuCreate extends MenuEvent {
|
||||||
|
const MenuCreate();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuTreeDown extends MenuEvent {
|
||||||
|
final int parent;
|
||||||
|
const MenuTreeDown({this.parent});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [parent];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuTreeUp extends MenuEvent {
|
||||||
|
final int parent;
|
||||||
|
const MenuTreeUp({this.parent});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [parent];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuClickExercise extends MenuEvent {
|
||||||
|
final int exerciseTypeId;
|
||||||
|
const MenuClickExercise({this.exerciseTypeId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [exerciseTypeId];
|
||||||
|
}
|
||||||
|
|
34
lib/bloc/menu/menu_state.dart
Normal file
34
lib/bloc/menu/menu_state.dart
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
part of 'menu_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class MenuState extends Equatable {
|
||||||
|
const MenuState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuInitial extends MenuState {
|
||||||
|
const MenuInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuLoading extends MenuState {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuReady extends MenuState {
|
||||||
|
final WorkoutTree workoutTree;
|
||||||
|
|
||||||
|
const MenuReady({this.workoutTree});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [workoutTree];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuError extends MenuState {
|
||||||
|
final String message;
|
||||||
|
const MenuError({this.message});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
61
lib/bloc/registration_form_bloc.dart
Normal file
61
lib/bloc/registration_form_bloc.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
import 'account/account_bloc.dart';
|
||||||
|
|
||||||
|
class RegistrationFormBloc extends FormBloc<String, String> {
|
||||||
|
final AccountBloc accountBloc;
|
||||||
|
final emailField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
final passwordField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
final UserRepository userRepository;
|
||||||
|
|
||||||
|
RegistrationFormBloc({this.userRepository, this.accountBloc}) {
|
||||||
|
addFieldBlocs(fieldBlocs: [
|
||||||
|
emailField,
|
||||||
|
passwordField
|
||||||
|
]);
|
||||||
|
|
||||||
|
emailField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
userRepository.setEmail(current.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
passwordField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
userRepository.setPassword(current.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSubmitting() async {
|
||||||
|
try {
|
||||||
|
emitLoading(progress: 30);
|
||||||
|
if ( ! Common.validateEmail(userRepository)) {
|
||||||
|
emailField.addFieldError(Common.EMAIL_ERROR, isPermanent: true);
|
||||||
|
|
||||||
|
emitFailure(failureResponse: Common.EMAIL_ERROR);
|
||||||
|
} else if ( ! Common.validatePassword(userRepository)) {
|
||||||
|
passwordField.addFieldError(Common.PASSWORD_ERROR, isPermanent: true);
|
||||||
|
emitFailure(failureResponse: Common.PASSWORD_ERROR);
|
||||||
|
} else {
|
||||||
|
// Emit either Loaded or Error
|
||||||
|
await userRepository.addUser();
|
||||||
|
emitSuccess(canSubmitAgain: false);
|
||||||
|
accountBloc.add(AccountLogInFinished(customer: Auth().userLoggedIn));
|
||||||
|
}
|
||||||
|
} on Exception catch (ex) {
|
||||||
|
emitFailure(failureResponse: ex.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
35
lib/bloc/session/session_bloc.dart
Normal file
35
lib/bloc/session/session_bloc.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/util/session.dart';
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
part 'session_event.dart';
|
||||||
|
part 'session_state.dart';
|
||||||
|
|
||||||
|
class SessionBloc extends Bloc<SessionEvent, SessionState> {
|
||||||
|
final Session session;
|
||||||
|
SessionBloc({this.session}) : super(SessionInitial());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<SessionState> mapEventToState(
|
||||||
|
SessionEvent event,
|
||||||
|
) async* {
|
||||||
|
try {
|
||||||
|
if (event is SessionStart) {
|
||||||
|
yield SessionLoading();
|
||||||
|
await session.fetchSessionAndNavigate();
|
||||||
|
yield SessionReady();
|
||||||
|
}
|
||||||
|
} on Exception catch(ex) {
|
||||||
|
yield SessionFailure(message: ex.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() async {
|
||||||
|
await this.close(); super.close();
|
||||||
|
}
|
||||||
|
}
|
16
lib/bloc/session/session_event.dart
Normal file
16
lib/bloc/session/session_event.dart
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
part of 'session_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class SessionEvent extends Equatable {
|
||||||
|
const SessionEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionStart extends SessionEvent {
|
||||||
|
const SessionStart();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
32
lib/bloc/session/session_state.dart
Normal file
32
lib/bloc/session/session_state.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
part of 'session_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class SessionState extends Equatable {
|
||||||
|
const SessionState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionInitial extends SessionState {
|
||||||
|
const SessionInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionLoading extends SessionState {
|
||||||
|
const SessionLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionReady extends SessionState {
|
||||||
|
const SessionReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
class SessionFailure extends SessionState {
|
||||||
|
final String message;
|
||||||
|
const SessionFailure({this.message});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
55
lib/bloc/settings/settings_bloc.dart
Normal file
55
lib/bloc/settings/settings_bloc.dart
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
part 'settings_event.dart';
|
||||||
|
part 'settings_state.dart';
|
||||||
|
|
||||||
|
class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
||||||
|
String language;
|
||||||
|
Locale _locale;
|
||||||
|
BuildContext context;
|
||||||
|
|
||||||
|
SettingsBloc({this.context}) : super(SettingsInitial());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<SettingsState> mapEventToState(
|
||||||
|
SettingsEvent event,
|
||||||
|
) async* {
|
||||||
|
if (event is SettingsChangeLanguage) {
|
||||||
|
yield SettingsLoading();
|
||||||
|
await _changeLang( event.language);
|
||||||
|
yield SettingsReady(_locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _changeLang( String lang ) async{
|
||||||
|
|
||||||
|
switch ( lang ) {
|
||||||
|
case "English":
|
||||||
|
case "Angol":
|
||||||
|
_locale = Locale('en');
|
||||||
|
break;
|
||||||
|
case "Hungarian":
|
||||||
|
case "Magyar":
|
||||||
|
_locale = Locale('hu');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.language = lang;
|
||||||
|
await loadLang();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadLang() async{
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
appLanguage.changeLanguage(_locale);
|
||||||
|
if ( context != null ) {
|
||||||
|
AppLocalizations.of(context).setLocale(_locale);
|
||||||
|
await AppLocalizations.of(context).load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
lib/bloc/settings/settings_event.dart
Normal file
13
lib/bloc/settings/settings_event.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
part of 'settings_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class SettingsEvent extends Equatable {
|
||||||
|
const SettingsEvent();
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsChangeLanguage extends SettingsEvent {
|
||||||
|
final String language;
|
||||||
|
const SettingsChangeLanguage({this.language});
|
||||||
|
}
|
46
lib/bloc/settings/settings_state.dart
Normal file
46
lib/bloc/settings/settings_state.dart
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
part of 'settings_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class SettingsState extends Equatable {
|
||||||
|
const SettingsState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class SettingsInitial extends SettingsState {
|
||||||
|
Locale locale;
|
||||||
|
SettingsInitial();
|
||||||
|
|
||||||
|
setLocale(locale) {
|
||||||
|
this.locale = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [locale];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsLoading extends SettingsState {
|
||||||
|
final Locale locale;
|
||||||
|
const SettingsLoading({this.locale});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [locale];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsReady extends SettingsState {
|
||||||
|
final Locale locale;
|
||||||
|
const SettingsReady(this.locale);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [locale];
|
||||||
|
}
|
||||||
|
|
||||||
|
class SettingsError extends SettingsState {
|
||||||
|
final String message;
|
||||||
|
const SettingsError(this.message);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
9
lib/library_keys.dart
Normal file
9
lib/library_keys.dart
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class LibraryKeys {
|
||||||
|
|
||||||
|
// Login
|
||||||
|
static final loginEmailField = const Key('__loginEmailField__');
|
||||||
|
static final loginPasswordField = const Key('__loginPasswordField__');
|
||||||
|
static final loginOKButton = const Key('__loginOKButton__');
|
||||||
|
}
|
@ -6,8 +6,9 @@ import 'package:flutter/services.dart';
|
|||||||
|
|
||||||
class AppLocalizations {
|
class AppLocalizations {
|
||||||
Locale locale;
|
Locale locale;
|
||||||
|
bool isTest;
|
||||||
|
|
||||||
AppLocalizations(this.locale);
|
AppLocalizations(this.locale, {this.isTest = false});
|
||||||
|
|
||||||
// Helper method to keep the code in the widgets concise
|
// Helper method to keep the code in the widgets concise
|
||||||
// Localizations are accessed using an InheritedWidget "of" syntax
|
// Localizations are accessed using an InheritedWidget "of" syntax
|
||||||
@ -17,7 +18,7 @@ class AppLocalizations {
|
|||||||
|
|
||||||
// Static member to have a simple access to the delegate from the MaterialApp
|
// Static member to have a simple access to the delegate from the MaterialApp
|
||||||
static const LocalizationsDelegate<AppLocalizations> delegate =
|
static const LocalizationsDelegate<AppLocalizations> delegate =
|
||||||
_AppLocalizationsDelegate();
|
AppLocalizationsDelegate();
|
||||||
|
|
||||||
Map<String, String> _localizedStrings;
|
Map<String, String> _localizedStrings;
|
||||||
|
|
||||||
@ -38,18 +39,24 @@ class AppLocalizations {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<AppLocalizations> loadTest(Locale locale) async {
|
||||||
|
return AppLocalizations(locale);
|
||||||
|
}
|
||||||
|
|
||||||
// This method will be called from every widget which needs a localized text
|
// This method will be called from every widget which needs a localized text
|
||||||
String translate(String key) {
|
String translate(String key) {
|
||||||
|
if (isTest) return key;
|
||||||
return _localizedStrings[key];
|
return _localizedStrings[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate
|
class AppLocalizationsDelegate
|
||||||
extends LocalizationsDelegate<AppLocalizations> {
|
extends LocalizationsDelegate<AppLocalizations> {
|
||||||
|
final bool isTest;
|
||||||
// This delegate instance will never change (it doesn't even have fields!)
|
// This delegate instance will never change (it doesn't even have fields!)
|
||||||
// It can provide a constant constructor.
|
// It can provide a constant constructor.
|
||||||
const _AppLocalizationsDelegate();
|
const AppLocalizationsDelegate({this.isTest = false});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isSupported(Locale locale) {
|
bool isSupported(Locale locale) {
|
||||||
@ -60,11 +67,16 @@ class _AppLocalizationsDelegate
|
|||||||
@override
|
@override
|
||||||
Future<AppLocalizations> load(Locale locale) async {
|
Future<AppLocalizations> load(Locale locale) async {
|
||||||
// AppLocalizations class is where the JSON loading actually runs
|
// AppLocalizations class is where the JSON loading actually runs
|
||||||
AppLocalizations localizations = new AppLocalizations(locale);
|
AppLocalizations localizations = new AppLocalizations(locale, isTest: this.isTest);
|
||||||
await localizations.load();
|
if (isTest) {
|
||||||
|
await localizations.loadTest(locale);
|
||||||
|
} else {
|
||||||
|
await localizations.load();
|
||||||
|
}
|
||||||
return localizations;
|
return localizations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
bool shouldReload(AppLocalizationsDelegate old) => false;
|
||||||
}
|
}
|
@ -1,33 +1,33 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/menu_tree_repository.dart';
|
||||||
|
import 'package:aitrainer_app/util/session.dart';
|
||||||
import 'package:aitrainer_app/view/account.dart';
|
import 'package:aitrainer_app/view/account.dart';
|
||||||
|
import 'package:aitrainer_app/view/custom_exercise_page.dart';
|
||||||
import 'package:aitrainer_app/view/customer_bodytype_page.dart';
|
import 'package:aitrainer_app/view/customer_bodytype_page.dart';
|
||||||
import 'package:aitrainer_app/view/customer_fitness_page.dart';
|
import 'package:aitrainer_app/view/customer_fitness_page.dart';
|
||||||
import 'package:aitrainer_app/view/customer_goal_page.dart';
|
import 'package:aitrainer_app/view/customer_goal_page.dart';
|
||||||
import 'package:aitrainer_app/view/customer_modify_page.dart';
|
import 'package:aitrainer_app/view/customer_modify_page.dart';
|
||||||
import 'package:aitrainer_app/view/customer_new_page.dart';
|
|
||||||
import 'package:aitrainer_app/view/customer_welcome_page.dart';
|
import 'package:aitrainer_app/view/customer_welcome_page.dart';
|
||||||
import 'package:aitrainer_app/view/gdpr.dart';
|
import 'package:aitrainer_app/view/gdpr.dart';
|
||||||
import 'package:aitrainer_app/view/login.dart';
|
import 'package:aitrainer_app/view/login.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_new_page.dart';
|
import 'package:aitrainer_app/view/exercise_new_page.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_type_modify_page.dart';
|
|
||||||
import 'package:aitrainer_app/view/exercise_type_new_page.dart';
|
|
||||||
import 'package:aitrainer_app/view/menu_page.dart';
|
import 'package:aitrainer_app/view/menu_page.dart';
|
||||||
import 'package:aitrainer_app/view/registration.dart';
|
import 'package:aitrainer_app/view/registration.dart';
|
||||||
import 'package:aitrainer_app/view/settings.dart';
|
import 'package:aitrainer_app/view/settings.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/home.dart';
|
import 'package:aitrainer_app/widgets/home.dart';
|
||||||
import 'package:aitrainer_app/widgets/loading.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:aitrainer_app/view/customer_list_page.dart';
|
|
||||||
import 'package:aitrainer_app/view/exercise_type_list_page.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:sentry/sentry.dart';
|
import 'package:sentry/sentry.dart';
|
||||||
|
import 'bloc/account/account_bloc.dart';
|
||||||
|
import 'bloc/menu/menu_bloc.dart';
|
||||||
|
import 'bloc/session/session_bloc.dart';
|
||||||
|
import 'bloc/settings/settings_bloc.dart';
|
||||||
|
|
||||||
final SentryClient _sentry = new SentryClient(dsn: 'https://5fac40cbfcfb4c15aa80c7a8638d7310@o418565.ingest.sentry.io/5322520');
|
final SentryClient _sentry = new SentryClient(dsn: 'https://5fac40cbfcfb4c15aa80c7a8638d7310@o418565.ingest.sentry.io/5322520');
|
||||||
|
|
||||||
@ -95,17 +95,25 @@ Future<Null> main() async {
|
|||||||
// - https://www.dartlang.org/articles/libraries/zones
|
// - https://www.dartlang.org/articles/libraries/zones
|
||||||
runZonedGuarded<Future<Null>>(() async {
|
runZonedGuarded<Future<Null>>(() async {
|
||||||
runApp(
|
runApp(
|
||||||
MultiProvider(
|
MultiBlocProvider(
|
||||||
// Initialize the model in the builder. That way, Provider
|
|
||||||
// can own Models's lifecycle, making sure to call `dispose`
|
|
||||||
// when not needed anymore.
|
|
||||||
providers: [
|
providers: [
|
||||||
ChangeNotifierProvider(create: (context) => ExerciseChangingViewModel(null)),
|
BlocProvider<SessionBloc>(
|
||||||
ChangeNotifierProvider(create: (context) => CustomerChangingViewModel(null)),
|
create: (BuildContext context) => SessionBloc(session: Session()),
|
||||||
|
),
|
||||||
|
BlocProvider<MenuBloc>(
|
||||||
|
create: (BuildContext context) => MenuBloc( menuTreeRepository: MenuTreeRepository()),
|
||||||
|
),
|
||||||
|
BlocProvider<SettingsBloc>(
|
||||||
|
create: (BuildContext context) => SettingsBloc(),
|
||||||
|
),
|
||||||
|
BlocProvider<AccountBloc>(
|
||||||
|
create: (BuildContext context) => AccountBloc(customerRepository: CustomerRepository()),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
|
|
||||||
child: AitrainerApp(),
|
child: AitrainerApp(),
|
||||||
));
|
)
|
||||||
|
);
|
||||||
}, (error, stackTrace) async {
|
}, (error, stackTrace) async {
|
||||||
await _reportError(error, stackTrace);
|
await _reportError(error, stackTrace);
|
||||||
});
|
});
|
||||||
@ -147,18 +155,13 @@ class AitrainerApp extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
routes: {
|
routes: {
|
||||||
'home': (context) => AitrainerHome(),
|
'home': (context) => AitrainerHome(),
|
||||||
'loading': (context) => LoadingScreenMain(),
|
|
||||||
'customersPage': (context) => CustomerListPage(),
|
|
||||||
'customerNewPage': (context) => CustomerNewPage(),
|
|
||||||
'customerModifyPage': (context) => CustomerModifyPage(),
|
'customerModifyPage': (context) => CustomerModifyPage(),
|
||||||
'customerGoalPage': (context) => CustomerGoalPage(),
|
'customerGoalPage': (context) => CustomerGoalPage(),
|
||||||
'customerFitnessPage': (context) => CustomerFitnessPage(),
|
'customerFitnessPage': (context) => CustomerFitnessPage(),
|
||||||
'customerBodyTypePage': (context) => CustomerBodyTypePage(),
|
'customerBodyTypePage': (context) => CustomerBodyTypePage(),
|
||||||
'customerWelcomePage': (context) => CustomerWelcomePage(),
|
'customerWelcomePage': (context) => CustomerWelcomePage(),
|
||||||
'exerciseTypeListPage': (context) => ExerciseTypeListPage(),
|
|
||||||
'exerciseTypeNewPage': (context) => ExerciseTypeNewPage(),
|
|
||||||
'exerciseTypeModifyPage': (context) => ExerciseTypeModifyPage(),
|
|
||||||
'exerciseNewPage': (context) => ExerciseNewPage(),
|
'exerciseNewPage': (context) => ExerciseNewPage(),
|
||||||
|
'exerciseCustomPage': (context) => CustomExercisePage(),
|
||||||
'login': (context) => LoginPage(),
|
'login': (context) => LoginPage(),
|
||||||
'registration': (context) => RegistrationPage(),
|
'registration': (context) => RegistrationPage(),
|
||||||
'gdpr': (context) => Gdpr(),
|
'gdpr': (context) => Gdpr(),
|
||||||
@ -166,7 +169,7 @@ class AitrainerApp extends StatelessWidget {
|
|||||||
'account': (context) => AccountPage(),
|
'account': (context) => AccountPage(),
|
||||||
'settings': (context) => SettingsPage(),
|
'settings': (context) => SettingsPage(),
|
||||||
},
|
},
|
||||||
initialRoute: 'loading',
|
initialRoute: 'home',
|
||||||
title: 'Aitrainer',
|
title: 'Aitrainer',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
@ -176,7 +179,7 @@ class AitrainerApp extends StatelessWidget {
|
|||||||
bodyText1: TextStyle(fontSize: 14.0),
|
bodyText1: TextStyle(fontSize: 14.0),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
home: LoadingScreenMain(),
|
home: AitrainerHome(),
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import 'package:aitrainer_app/model/customer.dart';
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_tree.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercise_tree_service.dart';
|
||||||
import 'package:aitrainer_app/service/exercisetype_service.dart';
|
import 'package:aitrainer_app/service/exercisetype_service.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
@ -35,7 +37,8 @@ class Auth {
|
|||||||
static final String isRegisteredKey = 'is_registered';
|
static final String isRegisteredKey = 'is_registered';
|
||||||
static final String isLoggedInKey = 'is_logged_in';
|
static final String isLoggedInKey = 'is_logged_in';
|
||||||
|
|
||||||
static final String _baseUrl = 'http://andio.eu:8888/api/';
|
static final String baseUrl = 'http://aitrainer.info:8888/api/';
|
||||||
|
static final String mediaUrl = 'https://aitrainer.info:4343/media/';
|
||||||
static final String username = 'bosi';
|
static final String username = 'bosi';
|
||||||
static final String password = 'andio2009';
|
static final String password = 'andio2009';
|
||||||
|
|
||||||
@ -43,7 +46,9 @@ class Auth {
|
|||||||
Customer userLoggedIn;
|
Customer userLoggedIn;
|
||||||
bool firstLoad = true;
|
bool firstLoad = true;
|
||||||
List<ExerciseType> _exerciseTypes;
|
List<ExerciseType> _exerciseTypes;
|
||||||
|
List<ExerciseTree> _exerciseTree;
|
||||||
List deviceLanguages;
|
List deviceLanguages;
|
||||||
|
String startPage;
|
||||||
|
|
||||||
factory Auth() {
|
factory Auth() {
|
||||||
return _singleton;
|
return _singleton;
|
||||||
@ -60,7 +65,11 @@ class Auth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String getBaseUrl() {
|
static String getBaseUrl() {
|
||||||
return _baseUrl;
|
return baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getMediaUrl() {
|
||||||
|
return mediaUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
afterRegistration(Customer customer) {
|
afterRegistration(Customer customer) {
|
||||||
@ -70,20 +79,19 @@ class Auth {
|
|||||||
setPreferences(prefs, SharePrefsChange.registration, customer.customerId);
|
setPreferences(prefs, SharePrefsChange.registration, customer.customerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
afterLogin(Customer customer) {
|
afterLogin(Customer customer) async {
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
|
|
||||||
userLoggedIn = customer;
|
userLoggedIn = customer;
|
||||||
setPreferences(prefs, SharePrefsChange.login, customer.customerId);
|
await setPreferences(prefs, SharePrefsChange.login, customer.customerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(){
|
logout() async {
|
||||||
userLoggedIn = null;
|
userLoggedIn = null;
|
||||||
authToken = "";
|
authToken = "";
|
||||||
//firstLoad = true;
|
//firstLoad = true;
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
setPreferences(prefs, SharePrefsChange.logout, 0);
|
await setPreferences(prefs, SharePrefsChange.logout, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setPreferences(Future<SharedPreferences> prefs,
|
setPreferences(Future<SharedPreferences> prefs,
|
||||||
@ -95,18 +103,21 @@ class Auth {
|
|||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
sharedPreferences.setString(Auth.lastStoreDateKey, now.toString());
|
sharedPreferences.setString(Auth.lastStoreDateKey, now.toString());
|
||||||
if ( type == SharePrefsChange.registration ) {
|
if ( type == SharePrefsChange.registration ) {
|
||||||
|
Auth().startPage = "home";
|
||||||
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
||||||
sharedPreferences.setBool(Auth.isRegisteredKey, true);
|
sharedPreferences.setBool(Auth.isRegisteredKey, true);
|
||||||
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
||||||
await ExerciseTypeApi().getExerciseTypes("");
|
await ExerciseTypeApi().getExerciseTypes();
|
||||||
|
await ExerciseTreeApi().getExerciseTree();
|
||||||
} else if ( type == SharePrefsChange.login ) {
|
} else if ( type == SharePrefsChange.login ) {
|
||||||
|
Auth().startPage = "home";
|
||||||
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
sharedPreferences.setInt(Auth.customerIdKey, customerId);
|
||||||
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
sharedPreferences.setBool(Auth.isLoggedInKey, true);
|
||||||
await ExerciseTypeApi().getExerciseTypes("");
|
await ExerciseTypeApi().getExerciseTypes();
|
||||||
|
await ExerciseTreeApi().getExerciseTree();
|
||||||
} else if ( type == SharePrefsChange.logout ) {
|
} else if ( type == SharePrefsChange.logout ) {
|
||||||
sharedPreferences.setBool(Auth.isLoggedInKey, false);
|
sharedPreferences.setBool(Auth.isLoggedInKey, false);
|
||||||
//sharedPreferences.setInt(Auth.customerIdKey, 0);
|
sharedPreferences.setInt(Auth.customerIdKey, 0);
|
||||||
sharedPreferences.setString(authTokenKey, "");
|
sharedPreferences.setString(authTokenKey, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +126,15 @@ class Auth {
|
|||||||
this._exerciseTypes = exerciseTypes;
|
this._exerciseTypes = exerciseTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setExerciseTree( List<ExerciseTree> exerciseTree) {
|
||||||
|
this._exerciseTree = exerciseTree;
|
||||||
|
}
|
||||||
|
|
||||||
List<ExerciseType> getExerciseTypes() {
|
List<ExerciseType> getExerciseTypes() {
|
||||||
return this._exerciseTypes;
|
return this._exerciseTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<ExerciseTree> getExerciseTree() {
|
||||||
|
return this._exerciseTree;
|
||||||
|
}
|
||||||
}
|
}
|
20
lib/model/exercise_tree.dart
Normal file
20
lib/model/exercise_tree.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
class ExerciseTree {
|
||||||
|
int treeId;
|
||||||
|
int parentId;
|
||||||
|
String name;
|
||||||
|
String imageUrl;
|
||||||
|
bool active;
|
||||||
|
String nameTranslation;
|
||||||
|
|
||||||
|
ExerciseTree.fromJson(Map json) {
|
||||||
|
this.treeId = json['treeId'];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -2,22 +2,32 @@ import 'package:flutter/services.dart';
|
|||||||
|
|
||||||
class ExerciseType {
|
class ExerciseType {
|
||||||
int exerciseTypeId;
|
int exerciseTypeId;
|
||||||
|
int treeId;
|
||||||
String name;
|
String name;
|
||||||
String description;
|
String description;
|
||||||
BinaryCodec video;
|
BinaryCodec video;
|
||||||
String unit;
|
String unit;
|
||||||
String unitQuantity;
|
String unitQuantity;
|
||||||
String unitQuantityUnit;
|
String unitQuantityUnit;
|
||||||
|
bool active;
|
||||||
|
String imageUrl;
|
||||||
|
String nameTranslation;
|
||||||
|
String descriptionTranslation;
|
||||||
|
|
||||||
ExerciseType({this.name, this.description});
|
ExerciseType({this.name, this.description});
|
||||||
|
|
||||||
ExerciseType.fromJson(Map json) {
|
ExerciseType.fromJson(Map json) {
|
||||||
this.exerciseTypeId = json['exerciseTypeId'];
|
this.exerciseTypeId = json['exerciseTypeId'];
|
||||||
|
this.treeId = json['treeId'];
|
||||||
this.name = json['name'];
|
this.name = json['name'];
|
||||||
this.description = json['description'];
|
this.description = json['description'];
|
||||||
this.unit = json['unit'];
|
this.unit = json['unit'];
|
||||||
this.unitQuantity = json['unitQuantity'];
|
this.unitQuantity = json['unitQuantity'];
|
||||||
this.unitQuantityUnit = json['unitQuantityUnit'];
|
this.unitQuantityUnit = json['unitQuantityUnit'];
|
||||||
|
this.active = json['active'];
|
||||||
|
this.imageUrl = json['images'][0]['url'];
|
||||||
|
this.nameTranslation = json['translations'][0]['name'];
|
||||||
|
this.descriptionTranslation = json['translations'][0]['description'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() =>
|
Map<String, dynamic> toJson() =>
|
||||||
@ -26,6 +36,7 @@ class ExerciseType {
|
|||||||
"description": description,
|
"description": description,
|
||||||
"unit": unit,
|
"unit": unit,
|
||||||
"unitQuantity": unitQuantity,
|
"unitQuantity": unitQuantity,
|
||||||
"unitQuantityUnit": unitQuantityUnit
|
"unitQuantityUnit": unitQuantityUnit,
|
||||||
|
"active": active
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'exercise_type.dart';
|
||||||
|
|
||||||
class WorkoutTree {
|
class WorkoutTree {
|
||||||
int id;
|
int id;
|
||||||
int parent;
|
int parent;
|
||||||
@ -9,7 +11,8 @@ class WorkoutTree {
|
|||||||
double fontSize;
|
double fontSize;
|
||||||
bool child;
|
bool child;
|
||||||
int exerciseTypeId;
|
int exerciseTypeId;
|
||||||
|
ExerciseType exerciseType;
|
||||||
|
|
||||||
WorkoutTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exerciseTypeId);
|
WorkoutTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exerciseTypeId, this.exerciseType);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
143
lib/repository/customer_repository.dart
Normal file
143
lib/repository/customer_repository.dart
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/service/customer_service.dart';
|
||||||
|
|
||||||
|
class GenderItem {
|
||||||
|
GenderItem(this.dbValue,this.name);
|
||||||
|
final String dbValue;
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomerRepository {
|
||||||
|
Customer customer;
|
||||||
|
//List<CustomerRepository> customerList = List<CustomerRepository>();
|
||||||
|
bool visibleDetails = false;
|
||||||
|
List<GenderItem> genders;
|
||||||
|
|
||||||
|
CustomerRepository({this.customer}) {
|
||||||
|
customer = Customer();
|
||||||
|
genders = [
|
||||||
|
GenderItem("m", "Man"),
|
||||||
|
GenderItem("w", "Woman"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String getGenderByName(String name) {
|
||||||
|
String dbValue;
|
||||||
|
genders.forEach((element) {
|
||||||
|
if (element.name == name) {
|
||||||
|
dbValue = element.dbValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return dbValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getGenderByDBValue(String dbValue) {
|
||||||
|
String name;
|
||||||
|
genders.forEach((element) {
|
||||||
|
if (element.dbValue == dbValue) {
|
||||||
|
name = element.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get name {
|
||||||
|
return this.customer.name != null ? this.customer.name : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String get firstName {
|
||||||
|
return this.customer.firstname != null ? this.customer.firstname : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String get sex {
|
||||||
|
return this.customer.sex == "m" ? "Man" : "Woman";
|
||||||
|
}
|
||||||
|
|
||||||
|
int get birthYear {
|
||||||
|
return this.customer.birthYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get goal {
|
||||||
|
return this.customer.goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get fitnessLevel {
|
||||||
|
return this.customer.fitnessLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
String get bodyType {
|
||||||
|
return this.customer.bodyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
setName(String name) {
|
||||||
|
this.customer.name = name;
|
||||||
|
}
|
||||||
|
setFirstName(String firstName) {
|
||||||
|
this.customer.firstname = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPassword( String password ) {
|
||||||
|
this.customer.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
setEmail(String email) {
|
||||||
|
this.customer.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setSex(String sex) {
|
||||||
|
this.customer.sex = sex;
|
||||||
|
}
|
||||||
|
|
||||||
|
setWeight( int weight) {
|
||||||
|
this.customer.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBirthYear( int birthYear ) {
|
||||||
|
this.customer.birthYear = birthYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFitnessLevel( String level ) {
|
||||||
|
this.customer.fitnessLevel = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
setGoal( String goal ) {
|
||||||
|
this.customer.goal = goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBodyType(String bodyType) {
|
||||||
|
this.customer.bodyType = bodyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
createNew() {
|
||||||
|
this.customer = Customer();
|
||||||
|
}
|
||||||
|
|
||||||
|
Customer getCustomer() {
|
||||||
|
return this.customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCustomer ( Customer customer ) {
|
||||||
|
this.customer = customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> addCustomer() async {
|
||||||
|
final Customer modelCustomer = customer;
|
||||||
|
await CustomerApi().addCustomer(modelCustomer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveCustomer() async {
|
||||||
|
final Customer modelCustomer = customer;
|
||||||
|
await CustomerApi().saveCustomer(modelCustomer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Future<List<CustomerRepository>> getCustomers() async {
|
||||||
|
final results = await CustomerApi().getRealCustomers("");
|
||||||
|
this.customerList = results.map((item) => CustomerRepository(customer: item)).toList();
|
||||||
|
return this.customerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
addNewCustomerToList(CustomerRepository customerViewModel) {
|
||||||
|
customerList.add(customerViewModel);
|
||||||
|
}*/
|
||||||
|
}
|
88
lib/repository/exercise_repository.dart
Normal file
88
lib/repository/exercise_repository.dart
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercise_service.dart';
|
||||||
|
|
||||||
|
class ExerciseRepository {
|
||||||
|
Exercise exercise;
|
||||||
|
Customer customer;
|
||||||
|
ExerciseType exerciseType;
|
||||||
|
|
||||||
|
double rmWendler = 0;
|
||||||
|
double rmMcglothlin = 0;
|
||||||
|
double rmLombardi = 0;
|
||||||
|
double rmMayhew = 0;
|
||||||
|
double rmOconner = 0;
|
||||||
|
double rmWathen = 0;
|
||||||
|
|
||||||
|
createNew() {
|
||||||
|
this.exercise = Exercise();
|
||||||
|
exercise.dateAdd = DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
setQuantity(double quantity) {
|
||||||
|
if ( this.exercise == null ) {
|
||||||
|
this.createNew();
|
||||||
|
}
|
||||||
|
this.exercise.quantity = quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUnitQuantity(double unitQuantity) {
|
||||||
|
if ( this.exercise == null ) {
|
||||||
|
this.createNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exercise.unitQuantity = unitQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
setUnit( String unit) {
|
||||||
|
if ( this.exercise == null ) {
|
||||||
|
this.createNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exercise.unit = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDatetimeExercise(DateTime datetimeExercise) {
|
||||||
|
if ( this.exercise == null ) {
|
||||||
|
this.createNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exercise.dateAdd = datetimeExercise;
|
||||||
|
}
|
||||||
|
|
||||||
|
double get unitQuantity {
|
||||||
|
return this.exercise.unitQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
double get quantity {
|
||||||
|
return this.exercise.quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Exercise getExercise() {
|
||||||
|
return this.exercise;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> addExercise() async {
|
||||||
|
final Exercise modelExercise = this.exercise;
|
||||||
|
modelExercise.customerId = this.customer.customerId;
|
||||||
|
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
|
||||||
|
await ExerciseApi().addExercise(modelExercise);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setCustomer(Customer customer) {
|
||||||
|
this.customer = customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
setExerciseType( ExerciseType exerciseType) {
|
||||||
|
this.exerciseType = exerciseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Future<List<ExerciseRepository>> getExercisesByCustomer( int customerId ) async {
|
||||||
|
final results = await ExerciseApi().getExercisesByCustomer(customerId);
|
||||||
|
this.exerciseList = results.map((item) => ExerciseRepository(exercise: item)).toList();
|
||||||
|
return this.exerciseList;
|
||||||
|
} */
|
||||||
|
}
|
73
lib/repository/menu_tree_repository.dart
Normal file
73
lib/repository/menu_tree_repository.dart
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_tree.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercise_tree_service.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercisetype_service.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class MenuTreeRepository {
|
||||||
|
final LinkedHashMap tree = LinkedHashMap<String, WorkoutTree>();
|
||||||
|
|
||||||
|
Future<void> createTree() async {
|
||||||
|
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
bool isEnglish = appLanguage.appLocal == Locale('en');
|
||||||
|
|
||||||
|
List<ExerciseTree> exerciseTree = Auth().getExerciseTree();
|
||||||
|
if ( exerciseTree == null || exerciseTree.length == 0) {
|
||||||
|
await ExerciseTreeApi().getExerciseTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
exerciseTree.forEach( (treeItem) async {
|
||||||
|
String treeName = isEnglish ? treeItem.name : treeItem.nameTranslation;
|
||||||
|
String assetImage = 'asset/menu/' + treeItem.imageUrl.substring(7);
|
||||||
|
this.tree[treeItem.name] = WorkoutTree(
|
||||||
|
treeItem.treeId,
|
||||||
|
treeItem.parentId,
|
||||||
|
treeName,
|
||||||
|
assetImage, Colors.white,
|
||||||
|
32,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
List<ExerciseType> exerciseTypes = Auth().getExerciseTypes();
|
||||||
|
if ( exerciseTypes == null || exerciseTypes.length == 0) {
|
||||||
|
await ExerciseTypeApi().getExerciseTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
exerciseTypes.forEach( (exerciseType) {
|
||||||
|
String exerciseTypeName = isEnglish ?
|
||||||
|
exerciseType.name : exerciseType.nameTranslation;
|
||||||
|
String assetImage = 'asset/menu/' + exerciseType.imageUrl.substring(7);
|
||||||
|
this.tree[exerciseType.name] = WorkoutTree(
|
||||||
|
exerciseType.exerciseTypeId,
|
||||||
|
exerciseType.treeId,
|
||||||
|
exerciseTypeName,
|
||||||
|
assetImage,
|
||||||
|
Colors.white,
|
||||||
|
16,
|
||||||
|
true,
|
||||||
|
exerciseType.exerciseTypeId,
|
||||||
|
exerciseType
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LinkedHashMap getBranch(int parent) {
|
||||||
|
LinkedHashMap branch = LinkedHashMap<String, WorkoutTree>();
|
||||||
|
tree.forEach((key, value) {
|
||||||
|
WorkoutTree workoutTree = value as WorkoutTree;
|
||||||
|
if ( parent == workoutTree.parent) {
|
||||||
|
branch[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return branch;
|
||||||
|
}
|
||||||
|
}
|
32
lib/repository/user_repository.dart
Normal file
32
lib/repository/user_repository.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import 'package:aitrainer_app/model/user.dart';
|
||||||
|
import 'package:aitrainer_app/service/customer_service.dart';
|
||||||
|
|
||||||
|
class UserRepository {
|
||||||
|
User user;
|
||||||
|
|
||||||
|
UserRepository() {
|
||||||
|
this.createNewUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
setEmail(String email) {
|
||||||
|
this.user.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPassword(String password) {
|
||||||
|
this.user.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
createNewUser() {
|
||||||
|
this.user = User();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> addUser() async {
|
||||||
|
final User modelUser = this.user;
|
||||||
|
await CustomerApi().addUser(modelUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getUser() async {
|
||||||
|
final User modelUser = this.user;
|
||||||
|
await CustomerApi().getUser(modelUser);
|
||||||
|
}
|
||||||
|
}
|
@ -39,8 +39,13 @@ class CustomerApi {
|
|||||||
body);
|
body);
|
||||||
Customer customer;
|
Customer customer;
|
||||||
try {
|
try {
|
||||||
customer = Customer.fromJson(jsonDecode(responseBody));
|
int status = jsonDecode(responseBody)['status'];
|
||||||
Auth().afterRegistration(customer);
|
if ( status != null ) {
|
||||||
|
throw new Exception(jsonDecode(responseBody)['error']);
|
||||||
|
} else {
|
||||||
|
customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
|
Auth().afterRegistration(customer);
|
||||||
|
}
|
||||||
} on FormatException catch(exception) {
|
} on FormatException catch(exception) {
|
||||||
throw new Exception(responseBody);
|
throw new Exception(responseBody);
|
||||||
}
|
}
|
||||||
@ -56,7 +61,7 @@ class CustomerApi {
|
|||||||
Customer customer;
|
Customer customer;
|
||||||
try {
|
try {
|
||||||
customer = Customer.fromJson(jsonDecode(responseBody));
|
customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
Auth().afterRegistration(customer);
|
await Auth().afterLogin(customer);
|
||||||
} on FormatException catch(exception) {
|
} on FormatException catch(exception) {
|
||||||
throw new Exception(responseBody);
|
throw new Exception(responseBody);
|
||||||
}
|
}
|
||||||
@ -66,10 +71,17 @@ class CustomerApi {
|
|||||||
Future<void> getCustomer(int customerId) async {
|
Future<void> getCustomer(int customerId) async {
|
||||||
String body = "";
|
String body = "";
|
||||||
print(" ===== get the customer by id: " + customerId.toString() );
|
print(" ===== get the customer by id: " + customerId.toString() );
|
||||||
final String responseBody = await _client.get(
|
try {
|
||||||
"customers/"+customerId.toString(),
|
final String responseBody = await _client.get(
|
||||||
body);
|
"customers/"+customerId.toString(),
|
||||||
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
body);
|
||||||
Auth().afterRegistration(customer);
|
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
|
Auth().afterRegistration(customer);
|
||||||
|
} catch (exception) {
|
||||||
|
print ("Exception: " + exception.toString());
|
||||||
|
print (" === go to registration ");
|
||||||
|
Auth().logout();
|
||||||
|
Auth().startPage = "registration";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
19
lib/service/exercise_tree_service.dart
Normal file
19
lib/service/exercise_tree_service.dart
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_tree.dart';
|
||||||
|
import 'api.dart';
|
||||||
|
|
||||||
|
class ExerciseTreeApi {
|
||||||
|
final APIClient _client = new APIClient();
|
||||||
|
|
||||||
|
Future<List<ExerciseTree>> getExerciseTree() async {
|
||||||
|
final body = await _client.get("exercise_tree", "");
|
||||||
|
final Iterable json = jsonDecode(body);
|
||||||
|
final List<ExerciseTree> exerciseTree = json.map((exerciseTree) =>
|
||||||
|
ExerciseTree.fromJson(exerciseTree)).toList();
|
||||||
|
Auth().setExerciseTree(exerciseTree);
|
||||||
|
return exerciseTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,8 +7,8 @@ import 'package:aitrainer_app/service/api.dart';
|
|||||||
class ExerciseTypeApi {
|
class ExerciseTypeApi {
|
||||||
final APIClient _client=new APIClient();
|
final APIClient _client=new APIClient();
|
||||||
|
|
||||||
Future<List<ExerciseType>> getExerciseTypes(String param) async {
|
Future<List<ExerciseType>> getExerciseTypes() async {
|
||||||
final body = await _client.get("exercise_type", param);
|
final body = await _client.get("exercise_type/active", "");
|
||||||
final Iterable json = jsonDecode(body);
|
final Iterable json = jsonDecode(body);
|
||||||
final List<ExerciseType> exerciseTypes = json.map( (exerciseType) => ExerciseType.fromJson(exerciseType) ).toList();
|
final List<ExerciseType> exerciseTypes = json.map( (exerciseType) => ExerciseType.fromJson(exerciseType) ).toList();
|
||||||
Auth().setExerciseTypes(exerciseTypes);
|
Auth().setExerciseTypes(exerciseTypes);
|
||||||
|
@ -3,10 +3,16 @@ import 'dart:convert';
|
|||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
import 'package:aitrainer_app/model/auth.dart';
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class Common {
|
class Common {
|
||||||
|
|
||||||
|
static const EMAIL_ERROR = "Please type a right email address here.";
|
||||||
|
static const PASSWORD_ERROR = "The password must have at least 8 characters.";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static String toJson( Map<String, String> map ) {
|
static String toJson( Map<String, String> map ) {
|
||||||
String rc = "{";
|
String rc = "{";
|
||||||
@ -47,4 +53,26 @@ class Common {
|
|||||||
List<int> bytes = text.toString().codeUnits;
|
List<int> bytes = text.toString().codeUnits;
|
||||||
return utf8.decode(bytes);
|
return utf8.decode(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double mediaSizeWidth( BuildContext context ) {
|
||||||
|
return MediaQuery.of(context).size.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool validateEmail(UserRepository userRepository) {
|
||||||
|
final String email = userRepository.user.email;
|
||||||
|
final RegExp _emailRegExp = RegExp(
|
||||||
|
r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$',
|
||||||
|
);
|
||||||
|
return _emailRegExp.hasMatch(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool validatePassword(UserRepository userRepository) {
|
||||||
|
final password = userRepository.user.password;
|
||||||
|
final RegExp _passwordRegExp =
|
||||||
|
RegExp(r'^(?=.*[A-Za-z0-9])(?=.*\d)[A-Za-z\d]{7,}$');
|
||||||
|
|
||||||
|
return _passwordRegExp.hasMatch(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,61 +0,0 @@
|
|||||||
import 'package:aitrainer_app/util/loading_screen_state.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
|
|
||||||
/// Loading Screen Widget that updates the screen once all inistializer methods
|
|
||||||
/// are called
|
|
||||||
// ignore: must_be_immutable
|
|
||||||
class LoadingScreen extends StatefulWidget {
|
|
||||||
/// List of methods that are called once the Loading Screen is rendered
|
|
||||||
/// for the first time. These are the methods that can update the messages
|
|
||||||
/// that are shown under the loading symbol
|
|
||||||
final List<dynamic> initializers;
|
|
||||||
|
|
||||||
/// The name of the application that is shown at the top of the loading screen
|
|
||||||
RichText title = RichText(text: TextSpan(text: 'AI Trainer'));
|
|
||||||
//final Text title;
|
|
||||||
|
|
||||||
/// The background colour which is used as a filler when the image doesn't
|
|
||||||
/// occupy the full screen
|
|
||||||
final Color backgroundColor;
|
|
||||||
|
|
||||||
/// The styling that is used with the text (messages) that are displayed under
|
|
||||||
/// the loader symbol
|
|
||||||
final TextStyle styleTextUnderTheLoader;
|
|
||||||
|
|
||||||
/// The Layout/Scaffold Widget that is loaded once all the initializer methods
|
|
||||||
/// have been executed
|
|
||||||
final dynamic navigateToWidget;
|
|
||||||
|
|
||||||
/// The colour that is used for the loader symbol
|
|
||||||
final Color loaderColor;
|
|
||||||
|
|
||||||
/// The image widget that is used as a background cover to the loading screen
|
|
||||||
final Image image;
|
|
||||||
|
|
||||||
/// The message that is displayed on the first load of the widget
|
|
||||||
final String initialMessage;
|
|
||||||
|
|
||||||
/// Constructor for the LoadingScreen widget with all the required
|
|
||||||
/// initializers
|
|
||||||
LoadingScreen(
|
|
||||||
{this.initializers,
|
|
||||||
this.navigateToWidget,
|
|
||||||
this.loaderColor,
|
|
||||||
this.image,
|
|
||||||
//this.title = Text("Welcome"),
|
|
||||||
this.backgroundColor = Colors.white,
|
|
||||||
this.styleTextUnderTheLoader = const TextStyle(
|
|
||||||
fontSize: 18.0, fontWeight: FontWeight.bold, color: Colors.black),
|
|
||||||
this.initialMessage})
|
|
||||||
// The Widget depends on the initializers and navigateToWidget to have a
|
|
||||||
// valid value. Thus we assert that the values passed are valid and
|
|
||||||
// not null
|
|
||||||
: assert(initializers != null && initializers.length > 0),
|
|
||||||
assert(navigateToWidget != null);
|
|
||||||
|
|
||||||
/// Bind the Widget to the custom State object
|
|
||||||
@override
|
|
||||||
LoadingScreenState createState() => LoadingScreenState();
|
|
||||||
}
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
|||||||
import 'dart:core';
|
|
||||||
import 'dart:async';
|
|
||||||
import 'package:aitrainer_app/util/loading_screen.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/home.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/scheduler.dart';
|
|
||||||
import 'package:aitrainer_app/util/message_state.dart';
|
|
||||||
|
|
||||||
/// The custom state that is used by the Loading Screen widget to handle the
|
|
||||||
/// messages that are provided by the initializer methods.
|
|
||||||
///
|
|
||||||
/// Note: Although the class is not exported from the package as not required by
|
|
||||||
/// the implementers using the package, the protected metatag is added to make
|
|
||||||
/// the code clearer.
|
|
||||||
@protected
|
|
||||||
class LoadingScreenState extends MessageState<LoadingScreen> {
|
|
||||||
|
|
||||||
/// Initialise the state
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
/// If the LoadingScreen widget has an initial message set, then the default
|
|
||||||
/// message in the MessageState class needs to be updated
|
|
||||||
if (widget.initialMessage != null) {
|
|
||||||
initialMessage = widget.initialMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// We require the initializers to run after the loading screen is rendered
|
|
||||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
|
||||||
runInitTasks();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This method calls the initializers and once they complete redirects to
|
|
||||||
/// the widget provided in navigateAfterInit
|
|
||||||
@protected
|
|
||||||
Future runInitTasks() async {
|
|
||||||
print(" ----- runInitTasks");
|
|
||||||
/// Run each initializer method sequentially
|
|
||||||
Future.forEach(widget.initializers, (init) => init(this, callbackFunction)).whenComplete(() {
|
|
||||||
// When all the initializers has been called and terminated their
|
|
||||||
// execution. The screen is navigated to the next scaffolding widget
|
|
||||||
if (widget.navigateToWidget is String) {
|
|
||||||
// It's fairly safe to assume this is using the in-built material
|
|
||||||
// named route component
|
|
||||||
print(" ----- navigate to " + widget.navigateToWidget);
|
|
||||||
Navigator.of(context).pushReplacementNamed(widget.navigateToWidget);
|
|
||||||
} else if (widget.navigateToWidget is Widget) {
|
|
||||||
Navigator.of(context).pushReplacement(new MaterialPageRoute(
|
|
||||||
builder: (BuildContext context) => widget.navigateToWidget));
|
|
||||||
print(" ----- navigate to main ");
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new ArgumentError(
|
|
||||||
'widget.navigateAfterSeconds must either be a String or Widget');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void callbackFunction() {
|
|
||||||
print("Call Home callback if widget");
|
|
||||||
if (widget.navigateToWidget is Widget) {
|
|
||||||
AitrainerHome home = widget.navigateToWidget as AitrainerHome;
|
|
||||||
home.callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render the LoadingScreen widget
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: widget.backgroundColor,
|
|
||||||
body: new InkWell(
|
|
||||||
child: new Stack(
|
|
||||||
fit: StackFit.expand,
|
|
||||||
children: <Widget>[
|
|
||||||
/// Paint the area where the inner widgets are loaded with the
|
|
||||||
/// background to keep consistency with the screen background
|
|
||||||
new Container(
|
|
||||||
decoration: BoxDecoration(color: widget.backgroundColor),
|
|
||||||
),
|
|
||||||
/// Render the background image
|
|
||||||
new Container(
|
|
||||||
child: widget.image,
|
|
||||||
),
|
|
||||||
/// Render the Title widget, loader and messages below each other
|
|
||||||
new Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
new Expanded(
|
|
||||||
flex: 3,
|
|
||||||
child: new Container(
|
|
||||||
child: new Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: <Widget>[
|
|
||||||
new Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 30.0),
|
|
||||||
),
|
|
||||||
widget.title,
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 1,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
/// Loader Animation Widget
|
|
||||||
CircularProgressIndicator(
|
|
||||||
valueColor: new AlwaysStoppedAnimation<Color>(
|
|
||||||
widget.loaderColor),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 20.0),
|
|
||||||
),
|
|
||||||
Text(getMessage, style: widget.styleTextUnderTheLoader),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
import 'dart:collection';
|
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
|
||||||
import 'package:aitrainer_app/model/workout_tree.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class MenuTests {
|
|
||||||
LinkedHashMap tree = LinkedHashMap();
|
|
||||||
|
|
||||||
MenuTests(BuildContext context) {
|
|
||||||
this.tree['Cardio']= WorkoutTree(1, 0, AppLocalizations.of(context).translate("Cardio"),
|
|
||||||
'asset/menu/1.cardio.png',
|
|
||||||
Colors.white, 32, false,0);
|
|
||||||
this.tree['Aerobic']= WorkoutTree(2, 1, AppLocalizations.of(context).translate("Aerobic"),
|
|
||||||
'asset/menu/1.1.aerob.png',
|
|
||||||
Colors.white, 32, false,0);
|
|
||||||
this.tree['Cooper']= WorkoutTree(21, 2, AppLocalizations.of(context).translate("Cooper"),
|
|
||||||
'asset/menu/1.1.1.cooper.png',
|
|
||||||
Colors.white, 32, true,30);
|
|
||||||
this.tree['Anaerobic']= WorkoutTree(3, 1, AppLocalizations.of(context).translate("Anaerobic"),
|
|
||||||
'asset/menu/1.2.anaerob.png',
|
|
||||||
Colors.white, 32, false,0);
|
|
||||||
this.tree['300m']= WorkoutTree(22, 3, "300m",
|
|
||||||
'asset/menu/1.2.1.300m.png',
|
|
||||||
Colors.white, 32, true,31);
|
|
||||||
this.tree['400m']= WorkoutTree(24, 3, "400m",
|
|
||||||
'asset/menu/1.2.2.400m.png',
|
|
||||||
Colors.white, 32, true,32);
|
|
||||||
|
|
||||||
this.tree['Strength']= WorkoutTree(4, 0, AppLocalizations.of(context).translate("Strength"),
|
|
||||||
'asset/menu/2.strength.png',
|
|
||||||
Colors.white, 32, false,0);
|
|
||||||
this.tree['Endurance']= WorkoutTree(5, 4, AppLocalizations.of(context).translate("Endurance"),
|
|
||||||
'asset/menu/2.1.endurance.png',
|
|
||||||
Colors.white, 36, false,0);
|
|
||||||
this.tree['Pullups']= WorkoutTree(6, 5, AppLocalizations.of(context).translate("Pull Ups"),
|
|
||||||
'asset/menu/2.1.1.pull-ups.png',
|
|
||||||
Colors.white, 32, true,38);
|
|
||||||
this.tree['Pushups']= WorkoutTree(7, 5, AppLocalizations.of(context).translate("Pushups"),
|
|
||||||
'asset/menu/2.1.2.pushup.png',
|
|
||||||
Colors.white, 32, true,33);
|
|
||||||
this.tree['Situps']= WorkoutTree(10, 5, AppLocalizations.of(context).translate("Sit-ups"),
|
|
||||||
'asset/menu/2.1.3.sit-ups.png',
|
|
||||||
Colors.white, 32, true,36);
|
|
||||||
this.tree['Squats']= WorkoutTree(11, 5, AppLocalizations.of(context).translate("Squats"),
|
|
||||||
'asset/menu/2.1.4.squats.png',
|
|
||||||
Colors.white, 32, true,35);
|
|
||||||
this.tree['TimedPushups']= WorkoutTree(12, 5, AppLocalizations.of(context).translate("Timed Pushups"),
|
|
||||||
'asset/menu/2.1.5.timedpushup.png',
|
|
||||||
Colors.white, 32, true,34);
|
|
||||||
this.tree['Core']= WorkoutTree(43, 5, AppLocalizations.of(context).translate("Core"),
|
|
||||||
'asset/menu/2.1.6.core.png',
|
|
||||||
Colors.white, 32, true,45);
|
|
||||||
|
|
||||||
this.tree['1RM']= WorkoutTree(8, 4, AppLocalizations.of(context).translate("1RM"),
|
|
||||||
'asset/menu/2.2.1.1RM.png',
|
|
||||||
Colors.white, 32, false,0);
|
|
||||||
this.tree['Chestpress']= WorkoutTree(13, 8, AppLocalizations.of(context).translate("Chest Press"),
|
|
||||||
'asset/menu/2.2.1.1.chestpress.png',
|
|
||||||
Colors.white, 32, true,37);
|
|
||||||
this.tree['PullUps1rm']= WorkoutTree(14, 8, AppLocalizations.of(context).translate("Pull Ups"),
|
|
||||||
'asset/menu/2.2.1.2.pullups.png',
|
|
||||||
Colors.white, 32, true, 38);
|
|
||||||
this.tree['Biceps']= WorkoutTree(15, 8, AppLocalizations.of(context).translate("Biceps"),
|
|
||||||
'asset/menu/2.2.1.3.biceps.png',
|
|
||||||
Colors.white, 32, true, 39);
|
|
||||||
this.tree['Triceps']= WorkoutTree(16, 8, AppLocalizations.of(context).translate("Triceps"),
|
|
||||||
'asset/menu/2.2.1.4.triceps.png',
|
|
||||||
Colors.white, 32, true, 40);
|
|
||||||
this.tree['Shoulders']= WorkoutTree(17, 8, AppLocalizations.of(context).translate("Shoulders"),
|
|
||||||
'asset/menu/2.2.1.5.shoulders.png',
|
|
||||||
Colors.white, 32, true, 41);
|
|
||||||
|
|
||||||
this.tree['BodyCompositions']= WorkoutTree(9, 0, AppLocalizations.of(context).translate("Body Compositions"),
|
|
||||||
'asset/menu/3.bcs1.png',
|
|
||||||
Colors.white, 32, false,0);
|
|
||||||
this.tree['BMI']= WorkoutTree(18, 9, AppLocalizations.of(context).translate("BMI"),
|
|
||||||
'asset/menu/3.1.BMI.png',
|
|
||||||
Colors.white, 32, true,42);
|
|
||||||
this.tree['BMR']= WorkoutTree(19, 9, AppLocalizations.of(context).translate("BMR"),
|
|
||||||
'asset/menu/3.2.BMR.png',
|
|
||||||
Colors.white, 32, true, 43);
|
|
||||||
this.tree['Sizes']= WorkoutTree(20, 9, AppLocalizations.of(context).translate("Sizes"),
|
|
||||||
'asset/menu/3.3.sizes.png',
|
|
||||||
Colors.white, 32, true, 44);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkedHashMap getMenuItems() {
|
|
||||||
return this.tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
import 'package:flutter/widgets.dart';
|
|
||||||
|
|
||||||
/// An extension class to the Flutter standard State. The class provides getter
|
|
||||||
/// and setters for updating the message section of the loading screen
|
|
||||||
///
|
|
||||||
/// Note: The class is marked as abstract to avoid IDE issues that expects
|
|
||||||
/// protected methods to be overloaded
|
|
||||||
abstract class MessageState<T extends StatefulWidget> extends State<T> {
|
|
||||||
/// The state variable that will hold the latest message that needs to be
|
|
||||||
/// displayed.
|
|
||||||
///
|
|
||||||
/// Note: Although Flutter standard allow member variables to be used from
|
|
||||||
/// instance object reference, this is not a best practice with OOP. OOP
|
|
||||||
/// design proposes that member variables should be accessed through getter
|
|
||||||
/// and setter methods.
|
|
||||||
@protected
|
|
||||||
String _message = 'Loading . . .';
|
|
||||||
|
|
||||||
/// The member variable is set as protected this it is not exposed to the
|
|
||||||
/// widget state class. As a workaround a protected setter is set so it is
|
|
||||||
/// not used outside the package
|
|
||||||
@protected
|
|
||||||
set initialMessage(String message) => _message = message;
|
|
||||||
|
|
||||||
/// Setter for the message variable
|
|
||||||
set setMessage(String message) => setState(() {
|
|
||||||
_message = message;
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Getter for the message variable
|
|
||||||
String get getMessage => _message;
|
|
||||||
}
|
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/service/api.dart';
|
import 'package:aitrainer_app/service/api.dart';
|
||||||
import 'package:aitrainer_app/service/customer_service.dart';
|
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/exercisetype_service.dart';
|
||||||
import 'package:devicelocale/devicelocale.dart';
|
import 'package:devicelocale/devicelocale.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -12,18 +14,24 @@ import '../push_notifications.dart';
|
|||||||
class Session {
|
class Session {
|
||||||
|
|
||||||
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
||||||
Auth _auth = Auth();
|
|
||||||
SharedPreferences _sharedPreferences;
|
SharedPreferences _sharedPreferences;
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
|
||||||
fetchSessionAndNavigate(Function callback ) async {
|
fetchSessionAndNavigate( ) async {
|
||||||
|
print (" -- Session: await prefs..");
|
||||||
_sharedPreferences = await _prefs;
|
_sharedPreferences = await _prefs;
|
||||||
|
|
||||||
|
|
||||||
if ( _auth.firstLoad ) {
|
if ( Auth().firstLoad ) {
|
||||||
_fetchToken(_sharedPreferences, callback);
|
|
||||||
|
print (" -- Session: fetch locale..");
|
||||||
|
await appLanguage.fetchLocale();
|
||||||
|
await AppLocalizations.delegate.load(appLanguage.appLocal);
|
||||||
|
print (" -- Session: fetch token..");
|
||||||
|
await _fetchToken(_sharedPreferences);
|
||||||
initDeviceLocale();
|
initDeviceLocale();
|
||||||
appLanguage.fetchLocale();
|
|
||||||
PushNotificationsManager().init();
|
PushNotificationsManager().init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +61,7 @@ class Session {
|
|||||||
/*
|
/*
|
||||||
Auth flow of the user, see auth.dart
|
Auth flow of the user, see auth.dart
|
||||||
*/
|
*/
|
||||||
_fetchToken(SharedPreferences prefs, Function callback) async {
|
_fetchToken(SharedPreferences prefs) async {
|
||||||
|
|
||||||
var responseJson = await APIClient.authenticateUser(
|
var responseJson = await APIClient.authenticateUser(
|
||||||
Auth.username,
|
Auth.username,
|
||||||
@ -71,6 +79,7 @@ class Session {
|
|||||||
// registration
|
// registration
|
||||||
//Navigator.of(context).pushNamed('registration');
|
//Navigator.of(context).pushNamed('registration');
|
||||||
prefs.setBool(Auth.isRegisteredKey, true);
|
prefs.setBool(Auth.isRegisteredKey, true);
|
||||||
|
Auth().startPage = "registration";
|
||||||
} else {
|
} else {
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
DateTime lastStoreDate = DateTime.parse(
|
DateTime lastStoreDate = DateTime.parse(
|
||||||
@ -83,16 +92,17 @@ class Session {
|
|||||||
prefs.get(Auth.isLoggedInKey) == false) {
|
prefs.get(Auth.isLoggedInKey) == false) {
|
||||||
print("************* Login");
|
print("************* Login");
|
||||||
//Navigator.of(context).pushNamed('login');
|
//Navigator.of(context).pushNamed('login');
|
||||||
|
Auth().startPage = "login";
|
||||||
} else {
|
} else {
|
||||||
print("************** Store SharedPreferences");
|
print("************** Store SharedPreferences");
|
||||||
// get API customer
|
// get API customer
|
||||||
await CustomerApi().getCustomer(prefs.getInt(Auth.customerIdKey));
|
await CustomerApi().getCustomer(prefs.getInt(Auth.customerIdKey));
|
||||||
|
Auth().startPage = "home";
|
||||||
}
|
}
|
||||||
|
|
||||||
await ExerciseTypeApi().getExerciseTypes("");
|
await ExerciseTypeApi().getExerciseTypes();
|
||||||
print("--- Session finished, call callback ");
|
await ExerciseTreeApi().getExerciseTree();
|
||||||
callback();
|
print("--- Session finished");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,142 +1,110 @@
|
|||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/model/auth.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/customer_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_view_model.dart';
|
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
class AccountPage extends StatefulWidget{
|
class AccountPage extends StatelessWidget {
|
||||||
_AccountPagePageState _state;
|
// ignore: close_sinks
|
||||||
|
AccountBloc accountBloc;
|
||||||
_AccountPagePageState createState() {
|
|
||||||
_state = new _AccountPagePageState();
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
|
|
||||||
State getState() {
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AccountPagePageState extends State<AccountPage> {
|
|
||||||
final UserViewModel user = UserViewModel();
|
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
|
||||||
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
|
||||||
final BottomNavigator bottomNav = BottomNavigator();
|
|
||||||
Future<List<ExerciseViewModel>> _exercises;
|
|
||||||
ExerciseChangingViewModel exerciseChangingViewModel;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
exerciseChangingViewModel = Provider.of<ExerciseChangingViewModel>(context, listen: false);
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<CustomerChangingViewModel>(
|
accountBloc = BlocProvider.of<AccountBloc>(context);
|
||||||
builder: (context, model, child ) {
|
return Scaffold(
|
||||||
if ( model.customer == null ) {
|
appBar: AppBar(
|
||||||
CustomerViewModel customerViewModel = CustomerViewModel();
|
title: Text(AppLocalizations.of(context).translate('Account')),
|
||||||
model.customer = customerViewModel;
|
backgroundColor: Colors.transparent,
|
||||||
if ( model.customer.getCustomer() == null ) {
|
),
|
||||||
model.customer.setCustomer(Auth().userLoggedIn);
|
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'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: BlocConsumer<AccountBloc, AccountState>(
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( Auth().userLoggedIn != null ) {
|
|
||||||
_exercises =
|
|
||||||
exerciseChangingViewModel.getExercisesByCustomer(
|
|
||||||
Auth().userLoggedIn.customerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(AppLocalizations.of(context).translate('Account')),
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
),
|
),
|
||||||
body: Container(
|
),
|
||||||
foregroundDecoration: BoxDecoration(
|
bottomNavigationBar: BottomNavigator(bottomNavIndex: 2));
|
||||||
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'),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child:
|
|
||||||
ListView(
|
|
||||||
padding: EdgeInsets.only(top: 135),
|
|
||||||
children: <Widget>[
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.perm_identity),
|
|
||||||
subtitle: Text(
|
|
||||||
AppLocalizations.of(context).translate("Profile")),
|
|
||||||
title: FlatButton(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(Auth().userLoggedIn != null ?
|
|
||||||
Auth().userLoggedIn.name + " " +
|
|
||||||
Auth().userLoggedIn.firstname : "",
|
|
||||||
style: TextStyle(color: Colors.blue)),
|
|
||||||
Icon(Icons.arrow_forward_ios),
|
|
||||||
]),
|
|
||||||
textColor: Colors.grey,
|
|
||||||
color: Colors.white,
|
|
||||||
onPressed: () => {
|
|
||||||
if (model.customer.getCustomer() != null) {
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
'customerModifyPage'),
|
|
||||||
print("Profile"),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.language),
|
|
||||||
title: Text(appLanguage.appLocal == Locale('en') ?
|
|
||||||
AppLocalizations.of(context).translate("English") :
|
|
||||||
AppLocalizations.of(context).translate("Hungarian")),
|
|
||||||
subtitle: Text(AppLocalizations.of(context).translate(
|
|
||||||
"Selected Language")),
|
|
||||||
),
|
|
||||||
loginOut( model ),
|
|
||||||
exercises(exerciseChangingViewModel),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
bottomNavigationBar: bottomNav.buildBottomNavigator(
|
|
||||||
context, widget._state)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListTile loginOut( CustomerChangingViewModel model ) {
|
ListView accountWidget(BuildContext context, String customerName, AccountBloc accountBloc) {
|
||||||
|
return ListView(padding: EdgeInsets.only(top: 135), children: <Widget>[
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.perm_identity),
|
||||||
|
subtitle:
|
||||||
|
Text(AppLocalizations.of(context).translate("Profile")),
|
||||||
|
title: FlatButton(
|
||||||
|
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"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
loginOut( context, accountBloc ),
|
||||||
|
//exercises(exerciseChangingViewModel),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListTile loginOut( BuildContext context, AccountBloc accountBloc ) {
|
||||||
ListTile element = ListTile();
|
ListTile element = ListTile();
|
||||||
|
|
||||||
String text = "Logout";
|
String text = "Logout";
|
||||||
Color buttonColor = Colors.orange;
|
Color buttonColor = Colors.orange;
|
||||||
|
|
||||||
if ( model.customer.getCustomer() == null ) {
|
if ( accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer.email == null) {
|
||||||
text = "Login";
|
text = "Login";
|
||||||
buttonColor = Colors.blue;
|
buttonColor = Colors.blue;
|
||||||
}
|
}
|
||||||
@ -149,25 +117,20 @@ class _AccountPagePageState extends State<AccountPage> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(AppLocalizations.of(context).translate(text),
|
Text(AppLocalizations.of(context).translate(text),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: buttonColor
|
color: buttonColor
|
||||||
)),
|
)),
|
||||||
Icon(Icons.arrow_forward_ios),
|
Icon(Icons.arrow_forward_ios),
|
||||||
]),
|
]),
|
||||||
textColor: buttonColor,
|
textColor: buttonColor,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
onPressed: () => {
|
onPressed: () => {
|
||||||
setState(() {
|
if ( accountBloc.loggedIn ) {
|
||||||
if ( model.customer.getCustomer() == null ) {
|
accountBloc.add(AccountLogout())
|
||||||
print("Login");
|
} else {
|
||||||
Navigator.of(context).pushNamed("login", arguments: widget._state);
|
accountBloc.add(AccountLogin()),
|
||||||
} else {
|
Navigator.of(context).pushNamed('login'),
|
||||||
print("Logout");
|
}
|
||||||
Auth().logout();
|
|
||||||
model.customer.setCustomer(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -175,7 +138,7 @@ class _AccountPagePageState extends State<AccountPage> {
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListTile exercises( ExerciseChangingViewModel model ) {
|
/* ListTile exercises( ExerciseChangingViewModel model ) {
|
||||||
ListTile element = ListTile();
|
ListTile element = ListTile();
|
||||||
if ( Auth().userLoggedIn == null ) {
|
if ( Auth().userLoggedIn == null ) {
|
||||||
return element;
|
return element;
|
||||||
@ -202,7 +165,8 @@ class _AccountPagePageState extends State<AccountPage> {
|
|||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
Widget getExercises( ExerciseChangingViewModel model ) {
|
Widget getExercises( ExerciseChangingViewModel model ) {
|
||||||
List<ExerciseViewModel> exercises = model.exerciseList;
|
List<ExerciseViewModel> exercises = model.exerciseList;
|
||||||
|
|
||||||
@ -262,5 +226,5 @@ class _AccountPagePageState extends State<AccountPage> {
|
|||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
|
||||||
}
|
} */
|
||||||
}
|
}
|
346
lib/view/custom_exercise_page.dart
Normal file
346
lib/view/custom_exercise_page.dart
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/custom_exercise_form_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/splash.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class CustomExercisePage extends StatefulWidget {
|
||||||
|
_CustomExerciseNewPageState createState() => _CustomExerciseNewPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomExerciseNewPageState extends State<CustomExercisePage> {
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final ExerciseType exerciseType = ModalRoute.of(context).settings.arguments;
|
||||||
|
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
CustomExerciseFormBloc(exerciseRepository: ExerciseRepository()),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final exerciseBloc = BlocProvider.of<CustomExerciseFormBloc>(context);
|
||||||
|
exerciseBloc.exerciseRepository.setExerciseType(exerciseType);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
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(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: FormBlocListener<CustomExerciseFormBloc, String, String>(
|
||||||
|
onSubmitting: (context, state) {
|
||||||
|
LoadingDialog.show(context);
|
||||||
|
},
|
||||||
|
onSuccess: (context, state) {
|
||||||
|
LoadingDialog.hide(context);
|
||||||
|
},
|
||||||
|
onFailure: (context, state) {
|
||||||
|
LoadingDialog.hide(context);
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
content: Text(state.failureResponse,
|
||||||
|
style: TextStyle(color: Colors.white))));
|
||||||
|
},
|
||||||
|
child: 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: CustomScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
slivers: [
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildListDelegate(
|
||||||
|
[
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top:20,left:25, right:25),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text("Custom Exercise",
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.deepOrange)),
|
||||||
|
columnQuantityUnit(exerciseBloc),
|
||||||
|
columnQuantity(exerciseBloc),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
|
gridCalculation(exerciseBloc)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Column columnQuantityUnit(CustomExerciseFormBloc bloc) {
|
||||||
|
Column column = Column();
|
||||||
|
if (bloc.exerciseRepository.exerciseType != null &&
|
||||||
|
bloc.exerciseRepository.exerciseType.unitQuantity == "1") {
|
||||||
|
column = Column(children: [
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
textFieldBloc: bloc.unitQuantityField,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.lightBlue,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter(RegExp(r"[\d.]"), allow: true)
|
||||||
|
],
|
||||||
|
onChanged: (input) => {
|
||||||
|
print("UnitQuantity value $input"),
|
||||||
|
bloc.exerciseRepository.setUnitQuantity(double.parse(input))
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black54,
|
||||||
|
fontWeight: FontWeight.w100),
|
||||||
|
hintText: AppLocalizations.of(context)
|
||||||
|
.translate("The number of the exercise done with"),
|
||||||
|
labelStyle: TextStyle(fontSize: 12, color: Colors.lightBlue),
|
||||||
|
labelText: AppLocalizations.of(context).translate(
|
||||||
|
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate(
|
||||||
|
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||||
|
style: TextStyle(fontSize: 12)),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
Column columnQuantity(CustomExerciseFormBloc bloc) {
|
||||||
|
Column column = Column(children: [
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
textFieldBloc: bloc.quantityField,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
color: Colors.deepOrange,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter(RegExp(r"[\d.]"), allow: true)
|
||||||
|
],
|
||||||
|
onChanged: (input) => {
|
||||||
|
print("Quantity value $input"),
|
||||||
|
bloc.exerciseRepository.setQuantity(double.parse(input)),
|
||||||
|
bloc.exerciseRepository
|
||||||
|
.setUnit(bloc.exerciseRepository.exerciseType.unit)
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 12, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||||
|
hintText: AppLocalizations.of(context)
|
||||||
|
.translate("The number of the exercise"),
|
||||||
|
labelStyle: TextStyle(fontSize: 12, color: Colors.deepOrange),
|
||||||
|
labelText: AppLocalizations.of(context)
|
||||||
|
.translate(bloc.exerciseRepository.exerciseType.unit),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
SliverGrid gridCalculation(CustomExerciseFormBloc bloc) {
|
||||||
|
return SliverGrid(
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 2,
|
||||||
|
mainAxisSpacing: 10.0,
|
||||||
|
crossAxisSpacing: 10.0,
|
||||||
|
childAspectRatio: 4.0,
|
||||||
|
),
|
||||||
|
delegate: SliverChildListDelegate(
|
||||||
|
[
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
textFieldBloc: bloc.rmWendlerField,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM by Wendler: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
textFieldBloc: bloc.rmMcGothlinField,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM by McGlothin: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rmLombardiField,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM by Lambordini: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rmWathenField,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM by Wahten: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rmOconnerField,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM by O'Conner: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rmMayhewField,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM by Mayhew: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rmAverageField,
|
||||||
|
style: TextStyle(color: Colors.blueAccent, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM Average: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rm90Field,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM 90%: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rm80Field,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM 80%: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rm70Field,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM 70%: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rm60Field,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM 60%: ",
|
||||||
|
)),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
isEnabled: false,
|
||||||
|
padding: EdgeInsets.only(left:30),
|
||||||
|
maxLines: 1,
|
||||||
|
textFieldBloc: bloc.rm50Field,
|
||||||
|
style: TextStyle(color: Colors.deepOrange, fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
border: InputBorder.none,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
labelText: "1RM 50%: ",
|
||||||
|
))
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class CustomerBodyTypePage extends StatefulWidget{
|
class CustomerBodyTypePage extends StatefulWidget {
|
||||||
_CustomerBodyTypePageState _state;
|
_CustomerBodyTypePageState _state;
|
||||||
|
|
||||||
_CustomerBodyTypePageState createState() {
|
_CustomerBodyTypePageState createState() {
|
||||||
@ -13,7 +15,6 @@ class CustomerBodyTypePage extends StatefulWidget{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BodyTypeItem {
|
class BodyTypeItem {
|
||||||
|
|
||||||
static String endomorph = "endomorph";
|
static String endomorph = "endomorph";
|
||||||
static String ectomorph = "ectomorph";
|
static String ectomorph = "ectomorph";
|
||||||
static String mesomorph = "mesomorph";
|
static String mesomorph = "mesomorph";
|
||||||
@ -23,15 +24,15 @@ class _CustomerBodyTypePageState extends State<CustomerBodyTypePage> {
|
|||||||
String selected;
|
String selected;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final CustomerChangingViewModel changingViewModel = ModalRoute.of(context).settings.arguments;
|
final CustomerRepository customerRepository =
|
||||||
final double cWidth = MediaQuery.of(context).size.width*0.75;
|
ModalRoute.of(context).settings.arguments;
|
||||||
|
final double cWidth = MediaQuery.of(context).size.width * 0.75;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'asset/image/WT_long_logo.png',
|
'asset/image/WT_long_logo.png',
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
@ -40,150 +41,159 @@ class _CustomerBodyTypePageState extends State<CustomerBodyTypePage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
),
|
),
|
||||||
body: Container(
|
body: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage('asset/image/WT_light_background.png'),
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Column(
|
),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: BlocProvider(
|
||||||
children: [
|
create: (context) =>
|
||||||
Divider(),
|
CustomerChangeBloc(customerRepository: customerRepository),
|
||||||
Wrap(
|
child: Builder(builder: (context) {
|
||||||
//runAlignment: WrapAlignment.center,
|
// ignore: close_sinks
|
||||||
alignment: WrapAlignment.center,
|
CustomerChangeBloc changeBloc =
|
||||||
|
BlocProvider.of<CustomerChangeBloc>(context);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Divider(),
|
||||||
AppLocalizations.of(context).translate("Your Body Type"),
|
Wrap(
|
||||||
textAlign: TextAlign.center,
|
//runAlignment: WrapAlignment.center,
|
||||||
style: TextStyle(color: Colors.orange,
|
alignment: WrapAlignment.center,
|
||||||
fontSize: 42, fontFamily: 'Arial',
|
|
||||||
fontWeight: FontWeight.w900 ),)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
|
|
||||||
|
|
||||||
Divider(),
|
|
||||||
FlatButton(
|
|
||||||
child: Container(
|
|
||||||
width: cWidth,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
children: [
|
||||||
Text(AppLocalizations.of(context).translate("Endomorph"),
|
Text(
|
||||||
textWidthBasis: TextWidthBasis.longestLine,
|
AppLocalizations.of(context)
|
||||||
style: TextStyle(color: Colors.blue,
|
.translate("Your Body Type"),
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
textAlign: TextAlign.center,
|
||||||
fontWeight: FontWeight.w900 )),
|
style: TextStyle(
|
||||||
|
color: Colors.orange,
|
||||||
],
|
fontSize: 42,
|
||||||
)
|
fontFamily: 'Arial',
|
||||||
),
|
fontWeight: FontWeight.w900),
|
||||||
padding: EdgeInsets.all(10.0),
|
)
|
||||||
shape: getShape(changingViewModel, BodyTypeItem.endomorph ),
|
]),
|
||||||
onPressed:() =>
|
Divider(),
|
||||||
{
|
FlatButton(
|
||||||
setState((){
|
child: Container(
|
||||||
selected = BodyTypeItem.endomorph;
|
width: cWidth,
|
||||||
changingViewModel.customer.setBodyType(selected);
|
child: Column(
|
||||||
print(selected);
|
children: [
|
||||||
}),
|
Text(
|
||||||
|
AppLocalizations.of(context)
|
||||||
}
|
.translate("Endomorph"),
|
||||||
|
textWidthBasis: TextWidthBasis.longestLine,
|
||||||
),
|
style: TextStyle(
|
||||||
Divider(),
|
color: Colors.blue,
|
||||||
FlatButton(
|
fontSize: 32,
|
||||||
child: Container(
|
fontFamily: 'Arial',
|
||||||
width: cWidth,
|
fontWeight: FontWeight.w900)),
|
||||||
child: Column(
|
],
|
||||||
children: [
|
)),
|
||||||
InkWell(
|
padding: EdgeInsets.all(10.0),
|
||||||
child: Text(AppLocalizations.of(context).translate("Ectomorph"),
|
shape: getShape(
|
||||||
style: TextStyle(color: Colors.blue,
|
customerRepository, BodyTypeItem.endomorph),
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
onPressed: () => {
|
||||||
fontWeight: FontWeight.w900 ),),
|
setState(() {
|
||||||
highlightColor: Colors.white,
|
selected = BodyTypeItem.endomorph;
|
||||||
|
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
|
||||||
|
print(selected);
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
Divider(),
|
||||||
|
FlatButton(
|
||||||
|
child: Container(
|
||||||
|
width: cWidth,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)
|
||||||
|
.translate("Ectomorph"),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.blue,
|
||||||
|
fontSize: 32,
|
||||||
|
fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900),
|
||||||
|
),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
padding: EdgeInsets.all(10.0),
|
||||||
|
shape: getShape(customerRepository, BodyTypeItem.ectomorph ),
|
||||||
|
|
||||||
],
|
onPressed: () => {
|
||||||
),
|
setState(() {
|
||||||
),
|
selected = BodyTypeItem.ectomorph;
|
||||||
padding: EdgeInsets.all(10.0),
|
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
|
||||||
shape: getShape(changingViewModel, BodyTypeItem.ectomorph ),
|
print(selected);
|
||||||
|
}),
|
||||||
onPressed:() =>
|
}),
|
||||||
{
|
Divider(),
|
||||||
setState((){
|
FlatButton(
|
||||||
selected = BodyTypeItem.ectomorph;
|
child: Container(
|
||||||
changingViewModel.customer.setBodyType(selected);
|
width: cWidth,
|
||||||
print(selected);
|
child: Column(
|
||||||
}),
|
children: [
|
||||||
|
InkWell(
|
||||||
}
|
child: Text(
|
||||||
),
|
AppLocalizations.of(context)
|
||||||
Divider(),
|
.translate("Mesomorph"),
|
||||||
FlatButton(
|
style: TextStyle(
|
||||||
child: Container(
|
color: Colors.blue,
|
||||||
width: cWidth,
|
fontSize: 32,
|
||||||
child: Column(
|
fontFamily: 'Arial',
|
||||||
children: [
|
fontWeight: FontWeight.w900),
|
||||||
InkWell(
|
),
|
||||||
child: Text(AppLocalizations.of(context).translate("Mesomorph"),
|
highlightColor: Colors.white,
|
||||||
style: TextStyle(color: Colors.blue,
|
),
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
],
|
||||||
fontWeight: FontWeight.w900 ),),
|
),
|
||||||
highlightColor: Colors.white,
|
|
||||||
),
|
),
|
||||||
|
padding: EdgeInsets.all(10.0),
|
||||||
|
shape: getShape(customerRepository, BodyTypeItem.mesomorph ),
|
||||||
|
onPressed: () => {
|
||||||
|
setState(() {
|
||||||
|
selected = BodyTypeItem.mesomorph;
|
||||||
|
changeBloc.add(CustomerBodyTypeChange(bodyType: selected));
|
||||||
|
|
||||||
],
|
print(selected);
|
||||||
),
|
}),
|
||||||
),
|
}),
|
||||||
padding: EdgeInsets.all(10.0),
|
Divider(),
|
||||||
shape: getShape(changingViewModel, BodyTypeItem.mesomorph ),
|
RaisedButton(
|
||||||
onPressed:() =>
|
color: Colors.orange,
|
||||||
{
|
textColor: Colors.white,
|
||||||
setState((){
|
child: InkWell(
|
||||||
selected = BodyTypeItem.mesomorph;
|
child: Text(
|
||||||
changingViewModel.customer.setBodyType(selected);
|
AppLocalizations.of(context).translate("Next"))),
|
||||||
print(selected);
|
onPressed: () => {
|
||||||
}),
|
changeBloc.add(CustomerSave()),
|
||||||
|
Navigator.of(context).pop(),
|
||||||
}
|
Navigator.of(context).pushNamed("customerWelcomePage", arguments: customerRepository)
|
||||||
),
|
},
|
||||||
|
)
|
||||||
Divider(),
|
],
|
||||||
RaisedButton(
|
);
|
||||||
|
})),
|
||||||
color: Colors.orange,
|
));
|
||||||
textColor: Colors.white,
|
|
||||||
child: InkWell(
|
|
||||||
child: Text(AppLocalizations.of(context).translate("Next"))),
|
|
||||||
onPressed: () => {
|
|
||||||
changingViewModel.saveCustomer(),
|
|
||||||
Navigator.of(context).pop(),
|
|
||||||
Navigator.of(context).pushNamed("customerWelcomePage", arguments: changingViewModel)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic getShape( CustomerChangingViewModel changingViewModel, String fitnessLevel ) {
|
dynamic getShape(CustomerRepository customerRepository, String fitnessLevel) {
|
||||||
String selected = changingViewModel.customer.bodyType;
|
String selected = customerRepository.bodyType;
|
||||||
dynamic returnCode = ( selected == fitnessLevel ) ?
|
dynamic returnCode = (selected == fitnessLevel)
|
||||||
RoundedRectangleBorder(
|
? RoundedRectangleBorder(
|
||||||
side: BorderSide(width: 4, color: Colors.orange),
|
side: BorderSide(width: 4, color: Colors.orange),
|
||||||
)
|
)
|
||||||
:
|
: RoundedRectangleBorder(
|
||||||
RoundedRectangleBorder(
|
side: BorderSide(width: 1, color: Colors.blue),
|
||||||
side: BorderSide(width: 1, color: Colors.blue),
|
);
|
||||||
);
|
|
||||||
//return
|
//return
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class CustomerFitnessPage extends StatefulWidget{
|
class CustomerFitnessPage extends StatefulWidget {
|
||||||
_CustomerFitnessPageState _state;
|
_CustomerFitnessPageState _state;
|
||||||
|
|
||||||
_CustomerFitnessPageState createState() {
|
_CustomerFitnessPageState createState() {
|
||||||
@ -29,15 +31,15 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final double cWidth = MediaQuery.of(context).size.width*0.75;
|
final double cWidth = MediaQuery.of(context).size.width * 0.75;
|
||||||
final CustomerChangingViewModel changingViewModel = ModalRoute.of(context).settings.arguments;
|
final CustomerRepository customerRepository =
|
||||||
selected = changingViewModel.customer.fitnessLevel;
|
ModalRoute.of(context).settings.arguments;
|
||||||
|
selected = customerRepository.customer.fitnessLevel;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'asset/image/WT_long_logo.png',
|
'asset/image/WT_long_logo.png',
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
@ -46,206 +48,243 @@ class _CustomerFitnessPageState extends State<CustomerFitnessPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: BlocProvider(
|
||||||
scrollDirection: Axis.vertical,
|
create: (context) =>
|
||||||
child: Container(
|
CustomerChangeBloc(customerRepository: customerRepository),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
CustomerChangeBloc changeBloc =
|
||||||
|
BlocProvider.of<CustomerChangeBloc>(context);
|
||||||
|
|
||||||
padding: EdgeInsets.only(bottom: 200),
|
return SingleChildScrollView(
|
||||||
decoration: BoxDecoration(
|
scrollDirection: Axis.vertical,
|
||||||
image: DecorationImage(
|
child: Container(
|
||||||
image: AssetImage('asset/image/WT_light_background.png'),
|
padding: EdgeInsets.only(bottom: 200),
|
||||||
fit: BoxFit.cover,
|
decoration: BoxDecoration(
|
||||||
alignment: Alignment.center,
|
image: DecorationImage(
|
||||||
),
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
),
|
fit: BoxFit.cover,
|
||||||
child: Column(
|
alignment: Alignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
),
|
||||||
children: [
|
|
||||||
Divider(),
|
|
||||||
Wrap(
|
|
||||||
//runAlignment: WrapAlignment.center,
|
|
||||||
alignment: WrapAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
AppLocalizations.of(context).translate("Your Fitness State"),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(color: Colors.orange,
|
|
||||||
fontSize: 42, fontFamily: 'Arial',
|
|
||||||
fontWeight: FontWeight.w900 ),)
|
|
||||||
]
|
|
||||||
),
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Divider(),
|
children: [
|
||||||
FlatButton(
|
Divider(),
|
||||||
child: Container(
|
Wrap(
|
||||||
width: cWidth,
|
//runAlignment: WrapAlignment.center,
|
||||||
child: Column(
|
alignment: WrapAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(AppLocalizations.of(context).translate("Beginner"),
|
Text(
|
||||||
textWidthBasis: TextWidthBasis.longestLine,
|
AppLocalizations.of(context)
|
||||||
style: TextStyle(color: Colors.blue,
|
.translate("Your Fitness State"),
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
textAlign: TextAlign.center,
|
||||||
fontWeight: FontWeight.w900 )),
|
style: TextStyle(
|
||||||
Text(AppLocalizations.of(context).translate("I am beginner"),
|
color: Colors.orange,
|
||||||
style: TextStyle(color: Colors.black,
|
fontSize: 42,
|
||||||
fontSize: 20, fontFamily: 'Arial',
|
fontFamily: 'Arial',
|
||||||
fontWeight: FontWeight.w100 ),),
|
fontWeight: FontWeight.w900),
|
||||||
],
|
)
|
||||||
)
|
]),
|
||||||
),
|
Divider(),
|
||||||
padding: EdgeInsets.all(10.0),
|
FlatButton(
|
||||||
shape: getShape(changingViewModel, FitnessItem.beginner ),
|
child: Container(
|
||||||
onPressed:() =>
|
width: cWidth,
|
||||||
{
|
child: Column(
|
||||||
setState((){
|
children: [
|
||||||
selected = FitnessItem.beginner;
|
Text(
|
||||||
changingViewModel.customer.setFitnessLevel(selected);
|
AppLocalizations.of(context)
|
||||||
print(selected);
|
.translate("Beginner"),
|
||||||
}),
|
textWidthBasis:
|
||||||
|
TextWidthBasis.longestLine,
|
||||||
}
|
style: TextStyle(
|
||||||
|
color: Colors.blue,
|
||||||
),
|
fontSize: 32,
|
||||||
Divider(),
|
fontFamily: 'Arial',
|
||||||
FlatButton(
|
fontWeight: FontWeight.w900)),
|
||||||
child: Container(
|
Text(
|
||||||
width: cWidth,
|
AppLocalizations.of(context)
|
||||||
child: Column(
|
.translate("I am beginner"),
|
||||||
children: [
|
style: TextStyle(
|
||||||
InkWell(
|
color: Colors.black,
|
||||||
child: Text(AppLocalizations.of(context).translate("Intermediate"),
|
fontSize: 20,
|
||||||
style: TextStyle(color: Colors.blue,
|
fontFamily: 'Arial',
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
fontWeight: FontWeight.w100),
|
||||||
fontWeight: FontWeight.w900 ),),
|
),
|
||||||
highlightColor: Colors.white,
|
],
|
||||||
|
)),
|
||||||
|
padding: EdgeInsets.all(10.0),
|
||||||
|
shape: getShape(
|
||||||
|
customerRepository, FitnessItem.beginner),
|
||||||
|
onPressed: () => {
|
||||||
|
setState(() {
|
||||||
|
selected = FitnessItem.beginner;
|
||||||
|
changeBloc.add(CustomerFitnessChange(fitness: selected));
|
||||||
|
print(selected);
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
Divider(),
|
||||||
|
FlatButton(
|
||||||
|
child: Container(
|
||||||
|
width: cWidth,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
child: Text(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
InkWell(
|
),
|
||||||
child: Text(AppLocalizations.of(context).translate("I am intermediate"),
|
padding: EdgeInsets.all(10.0),
|
||||||
style: TextStyle(color: Colors.black,
|
shape: getShape(
|
||||||
fontSize: 20, fontFamily: 'Arial',
|
customerRepository, FitnessItem.intermediate),
|
||||||
fontWeight: FontWeight.w100 ),),
|
onPressed: () => {
|
||||||
highlightColor: Colors.white,
|
setState(() {
|
||||||
|
selected = FitnessItem.intermediate;
|
||||||
|
changeBloc.add(CustomerFitnessChange(fitness: selected));
|
||||||
|
print(selected);
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
Divider(),
|
||||||
|
FlatButton(
|
||||||
|
child: Container(
|
||||||
|
width: cWidth,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
child: Text(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
padding: EdgeInsets.all(10.0),
|
||||||
),
|
shape: getShape(
|
||||||
padding: EdgeInsets.all(10.0),
|
customerRepository, FitnessItem.advanced),
|
||||||
shape: getShape(changingViewModel, FitnessItem.intermediate ),
|
onPressed: () => {
|
||||||
|
setState(() {
|
||||||
onPressed:() =>
|
selected = FitnessItem.advanced;
|
||||||
{
|
changeBloc.add(CustomerFitnessChange(fitness: selected));
|
||||||
setState((){
|
print(selected);
|
||||||
selected = FitnessItem.intermediate;
|
}),
|
||||||
changingViewModel.customer.setFitnessLevel(selected);
|
}),
|
||||||
print(selected);
|
Divider(),
|
||||||
}),
|
FlatButton(
|
||||||
|
child: Container(
|
||||||
}
|
width: cWidth,
|
||||||
),
|
child: Column(
|
||||||
Divider(),
|
children: [
|
||||||
FlatButton(
|
InkWell(
|
||||||
child: Container(
|
child: Text(
|
||||||
width: cWidth,
|
AppLocalizations.of(context)
|
||||||
child: Column(
|
.translate("Professional"),
|
||||||
children: [
|
style: TextStyle(
|
||||||
InkWell(
|
color: Colors.blue,
|
||||||
child: Text(AppLocalizations.of(context).translate("Advanced"),
|
fontSize: 32,
|
||||||
style: TextStyle(color: Colors.blue,
|
fontFamily: 'Arial',
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
fontWeight: FontWeight.w900),
|
||||||
fontWeight: FontWeight.w900 ),),
|
),
|
||||||
highlightColor: Colors.white,
|
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),
|
||||||
|
),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
InkWell(
|
),
|
||||||
child: Text(AppLocalizations.of(context).translate("I am advanced"),
|
padding: EdgeInsets.all(10.0),
|
||||||
style: TextStyle(color: Colors.black,
|
shape: getShape(
|
||||||
fontSize: 20, fontFamily: 'Arial',
|
customerRepository, FitnessItem.professional),
|
||||||
fontWeight: FontWeight.w100 ),),
|
onPressed: () => {
|
||||||
highlightColor: Colors.white,
|
setState(() {
|
||||||
),
|
selected = FitnessItem.professional;
|
||||||
],
|
changeBloc.add(CustomerFitnessChange(fitness: selected));
|
||||||
),
|
print(selected);
|
||||||
),
|
}),
|
||||||
padding: EdgeInsets.all(10.0),
|
}),
|
||||||
shape: getShape(changingViewModel, FitnessItem.advanced ),
|
Divider(),
|
||||||
onPressed:() =>
|
RaisedButton(
|
||||||
{
|
color: Colors.orange,
|
||||||
setState((){
|
textColor: Colors.white,
|
||||||
selected = FitnessItem.advanced;
|
child: InkWell(
|
||||||
changingViewModel.customer.setFitnessLevel(selected);
|
child: Text(AppLocalizations.of(context)
|
||||||
print(selected);
|
.translate("Next"))),
|
||||||
}),
|
onPressed: () => {
|
||||||
|
changeBloc.add(CustomerSave()),
|
||||||
}
|
Navigator.of(context).pop(),
|
||||||
),
|
Navigator.of(context).pushNamed(
|
||||||
Divider(),
|
"customerBodyTypePage",
|
||||||
FlatButton(
|
arguments: customerRepository)
|
||||||
child: Container(
|
},
|
||||||
width: cWidth,
|
)
|
||||||
child: Column(
|
],
|
||||||
children: [
|
),
|
||||||
InkWell(
|
),
|
||||||
child: Text(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 ),),
|
|
||||||
highlightColor: Colors.white,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
padding: EdgeInsets.all(10.0),
|
|
||||||
shape: getShape(changingViewModel, FitnessItem.professional ),
|
|
||||||
onPressed:() =>
|
|
||||||
{
|
|
||||||
setState((){
|
|
||||||
selected = FitnessItem.professional;
|
|
||||||
changingViewModel.customer.setFitnessLevel(selected);
|
|
||||||
print(selected);
|
|
||||||
}),
|
|
||||||
|
|
||||||
}
|
|
||||||
),
|
|
||||||
Divider(),
|
|
||||||
RaisedButton(
|
|
||||||
|
|
||||||
color: Colors.orange,
|
|
||||||
textColor: Colors.white,
|
|
||||||
child: InkWell(
|
|
||||||
child: Text(AppLocalizations.of(context).translate("Next"))),
|
|
||||||
onPressed: () => {
|
|
||||||
changingViewModel.saveCustomer(),
|
|
||||||
Navigator.of(context).pop(),
|
|
||||||
Navigator.of(context).pushNamed("customerBodyTypePage", arguments: changingViewModel)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic getShape( CustomerChangingViewModel changingViewModel, String fitnessLevel ) {
|
dynamic getShape(CustomerRepository customerRepository, String fitnessLevel) {
|
||||||
String selected = changingViewModel.customer.fitnessLevel;
|
String selected = customerRepository.fitnessLevel;
|
||||||
dynamic returnCode = ( selected == fitnessLevel ) ?
|
dynamic returnCode = (selected == fitnessLevel)
|
||||||
RoundedRectangleBorder(
|
? RoundedRectangleBorder(
|
||||||
side: BorderSide(width: 4, color: Colors.orange),
|
side: BorderSide(width: 4, color: Colors.orange),
|
||||||
)
|
)
|
||||||
:
|
: RoundedRectangleBorder(
|
||||||
RoundedRectangleBorder(
|
side: BorderSide(width: 1, color: Colors.blue),
|
||||||
side: BorderSide(width: 1, color: Colors.blue),
|
);
|
||||||
);
|
|
||||||
//return
|
//return
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,41 +1,37 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/customer_change/customer_change_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
class GoalsItem {
|
||||||
class CustomerGoalPage extends StatefulWidget{
|
|
||||||
_CustomerGoalPageState _state;
|
|
||||||
|
|
||||||
_CustomerGoalPageState createState() {
|
|
||||||
_state = _CustomerGoalPageState();
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GoalsItem{
|
|
||||||
static String muscle = "gain_muscle";
|
static String muscle = "gain_muscle";
|
||||||
static String weight = "weight_loss";
|
static String weight = "weight_loss";
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CustomerGoalPageState extends State<CustomerGoalPage> {
|
// ignore: must_be_immutable
|
||||||
String selected;
|
class CustomerGoalPage extends StatefulWidget {
|
||||||
|
|
||||||
initState() {
|
@override
|
||||||
super.initState();
|
State<StatefulWidget> createState() => _CustomerGoalPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class _CustomerGoalPage extends State<CustomerGoalPage> {
|
||||||
|
String selected;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final double cWidth = MediaQuery.of(context).size.width*0.75;
|
final double cWidth = MediaQuery.of(context).size.width * 0.75;
|
||||||
final CustomerChangingViewModel changingViewModel = ModalRoute.of(context).settings.arguments;
|
final CustomerRepository customerRepository =
|
||||||
selected = changingViewModel.customer.goal;
|
ModalRoute.of(context).settings.arguments;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'asset/image/WT_long_logo.png',
|
'asset/image/WT_long_logo.png',
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
@ -44,116 +40,138 @@ class _CustomerGoalPageState extends State<CustomerGoalPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
),
|
),
|
||||||
body: Container(
|
body: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage('asset/image/WT_light_background.png'),
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
height: double.infinity,
|
|
||||||
width: double.infinity,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Divider(),
|
|
||||||
InkWell(
|
|
||||||
child: Text(AppLocalizations.of(context).translate("Set Your Goals"),
|
|
||||||
style: TextStyle(color: Colors.orange,
|
|
||||||
fontSize: 50, fontFamily: 'Arial',
|
|
||||||
fontWeight: FontWeight.w900 ),),
|
|
||||||
highlightColor: Colors.white,
|
|
||||||
),
|
|
||||||
|
|
||||||
Stack(
|
|
||||||
alignment: Alignment.bottomLeft,
|
|
||||||
overflow: Overflow.visible,
|
|
||||||
children: [
|
|
||||||
FlatButton(
|
|
||||||
child: Image.asset("asset/image/WT_gain_muscle.png", height: 180,),
|
|
||||||
padding: EdgeInsets.all(0.0),
|
|
||||||
shape: getShape(changingViewModel, GoalsItem.muscle ),
|
|
||||||
onPressed:() =>
|
|
||||||
{
|
|
||||||
print("gain muscle"),
|
|
||||||
setState((){
|
|
||||||
selected = GoalsItem.muscle;
|
|
||||||
changingViewModel.customer.setGoal(GoalsItem.muscle);
|
|
||||||
}),
|
|
||||||
|
|
||||||
}
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
child: Text(AppLocalizations.of(context).translate("Gain Muscle"),
|
|
||||||
style: TextStyle(color: Colors.white,
|
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
|
||||||
fontWeight: FontWeight.w900 ),),
|
|
||||||
highlightColor: Colors.white,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
Divider(),
|
|
||||||
Stack(
|
|
||||||
alignment: Alignment.bottomLeft,
|
|
||||||
overflow: Overflow.visible,
|
|
||||||
children: [
|
|
||||||
FlatButton(
|
|
||||||
child: Image.asset("asset/image/WT_weight_loss.png", height: 180,),
|
|
||||||
padding: EdgeInsets.all(0.0),
|
|
||||||
shape: getShape(changingViewModel, GoalsItem.weight ),
|
|
||||||
onPressed:() =>
|
|
||||||
{
|
|
||||||
print("weight_loss"),
|
|
||||||
setState((){
|
|
||||||
selected = GoalsItem.weight;
|
|
||||||
changingViewModel.customer.setGoal(GoalsItem.weight);
|
|
||||||
}),
|
|
||||||
|
|
||||||
}
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
child: Text(AppLocalizations.of(context).translate("Loose Weight"),
|
|
||||||
style: TextStyle(color: Colors.white,
|
|
||||||
fontSize: 32, fontFamily: 'Arial',
|
|
||||||
fontWeight: FontWeight.w900 ),),
|
|
||||||
highlightColor: Colors.white,
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
Divider(),
|
|
||||||
RaisedButton(
|
|
||||||
|
|
||||||
color: Colors.orange,
|
|
||||||
textColor: Colors.white,
|
|
||||||
child: InkWell(
|
|
||||||
child: Text(AppLocalizations.of(context).translate("Next"))),
|
|
||||||
onPressed: () => {
|
|
||||||
changingViewModel.saveCustomer(),
|
|
||||||
Navigator.of(context).pop(),
|
|
||||||
Navigator.of(context).pushNamed("customerFitnessPage", arguments: changingViewModel)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
);
|
height: double.infinity,
|
||||||
|
width: double.infinity,
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
CustomerChangeBloc(customerRepository: customerRepository),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
CustomerChangeBloc changeBloc =
|
||||||
|
BlocProvider.of<CustomerChangeBloc>(context);
|
||||||
|
|
||||||
|
|
||||||
|
return SingleChildScrollView(
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Divider(),
|
||||||
|
InkWell(
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)
|
||||||
|
.translate("Set Your Goals"),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.orange,
|
||||||
|
fontSize: 50,
|
||||||
|
fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900),
|
||||||
|
),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
),
|
||||||
|
Stack(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
overflow: Overflow.visible,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
child: Image.asset(
|
||||||
|
"asset/image/WT_gain_muscle.png",
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
shape: getShape(changeBloc, GoalsItem.muscle),
|
||||||
|
onPressed: () => {
|
||||||
|
print("gain muscle"),
|
||||||
|
setState((){
|
||||||
|
selected = GoalsItem.muscle;
|
||||||
|
changeBloc.add(CustomerGoalChange(goal: GoalsItem.muscle));
|
||||||
|
}),
|
||||||
|
|
||||||
|
}),
|
||||||
|
InkWell(
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)
|
||||||
|
.translate("Gain Muscle"),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 32,
|
||||||
|
fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900),
|
||||||
|
),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
Divider(),
|
||||||
|
Stack(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
overflow: Overflow.visible,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
child: Image.asset(
|
||||||
|
"asset/image/WT_weight_loss.png",
|
||||||
|
height: 180,
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
shape: getShape(changeBloc, GoalsItem.weight),
|
||||||
|
onPressed: () => {
|
||||||
|
print("weight_loss"),
|
||||||
|
setState((){
|
||||||
|
selected = GoalsItem.muscle;
|
||||||
|
changeBloc.add(CustomerGoalChange(goal: GoalsItem.weight));
|
||||||
|
}),
|
||||||
|
|
||||||
|
}),
|
||||||
|
InkWell(
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)
|
||||||
|
.translate("Loose Weight"),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 32,
|
||||||
|
fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900),
|
||||||
|
),
|
||||||
|
highlightColor: Colors.white,
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
Divider(),
|
||||||
|
RaisedButton(
|
||||||
|
color: Colors.orange,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: InkWell(
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).translate("Next"))),
|
||||||
|
onPressed: () => {
|
||||||
|
//changingViewModel.saveCustomer(),
|
||||||
|
changeBloc.add(CustomerSave()),
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
Navigator.of(context).pushNamed("customerFitnessPage",
|
||||||
|
arguments: changeBloc.customerRepository)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic getShape( CustomerChangingViewModel changingViewModel, String goal ) {
|
dynamic getShape(CustomerChangeBloc customerBloc, String goal) {
|
||||||
String selectedGoal = changingViewModel.customer.goal;
|
String selectedGoal = customerBloc.customerRepository.goal;
|
||||||
dynamic returnCode = ( selectedGoal == goal ) ?
|
dynamic returnCode = (selectedGoal == goal)
|
||||||
RoundedRectangleBorder(
|
? RoundedRectangleBorder(
|
||||||
side: BorderSide(width: 4, color: Colors.red),
|
side: BorderSide(width: 4, color: Colors.red),
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
//return
|
//return
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,93 +0,0 @@
|
|||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/customer_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/customer_list_widget.dart';
|
|
||||||
|
|
||||||
class CustomerListPage extends StatefulWidget{
|
|
||||||
_CustomerListPageState createState() => _CustomerListPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CustomerListPageState extends State<CustomerListPage> {
|
|
||||||
//final TextEditingController _controller = TextEditingController();
|
|
||||||
Future<List<CustomerViewModel>> _customers;
|
|
||||||
final _customerViewModel = CustomerChangingViewModel(null);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_customers = _customerViewModel.getCustomers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
|
|
||||||
//final customerViewModel = CustomerChangingViewModel(null);
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text("Real customers")
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: FutureBuilder<List<CustomerViewModel>>(
|
|
||||||
future: _customers,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
return CustomerListWidget(customers: _customerViewModel.customerList);
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Text("${snapshot.error}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// By default, show a loading spinner.
|
|
||||||
return CircularProgressIndicator();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
/* body: Container(
|
|
||||||
padding: EdgeInsets.all(10),
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
height: MediaQuery.of(context).size.height,
|
|
||||||
child: Column(children: <Widget>[
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.only(left: 10),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.grey,
|
|
||||||
borderRadius: BorderRadius.circular(10)
|
|
||||||
),
|
|
||||||
child: TextField(
|
|
||||||
controller: _controller,
|
|
||||||
onSubmitted: (value) {
|
|
||||||
if(value.isNotEmpty) {
|
|
||||||
customerViewModel.getCustomers();
|
|
||||||
_controller.clear();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: "Search",
|
|
||||||
hintStyle: TextStyle(color: Colors.white),
|
|
||||||
border: InputBorder.none
|
|
||||||
),
|
|
||||||
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: CustomerListWidget(customers: customerViewModel.customers)),
|
|
||||||
]),
|
|
||||||
|
|
||||||
), */
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () => Navigator.pushNamed(
|
|
||||||
context,
|
|
||||||
'customerNewPage',
|
|
||||||
),
|
|
||||||
child: Icon(Icons.add,),
|
|
||||||
mini: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,278 +1,302 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/bloc/customer_change_form_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
import '../library_keys.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class CustomerModifyPage extends StatefulWidget{
|
class CustomerModifyPage extends StatelessWidget{
|
||||||
_CustomerModifyPageState _state;
|
|
||||||
|
|
||||||
_CustomerModifyPageState createState() {
|
|
||||||
_state = _CustomerModifyPageState();
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GenderItem {
|
|
||||||
GenderItem(this.dbValue,this.name);
|
|
||||||
final String dbValue;
|
|
||||||
String name;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CustomerModifyPageState extends State<CustomerModifyPage> {
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
GenderItem selectedGender;
|
|
||||||
List<GenderItem> genders;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
genders = [
|
|
||||||
GenderItem("m", "Man"),
|
|
||||||
GenderItem("w", "Woman"),
|
|
||||||
];
|
|
||||||
selectedGender = genders[0];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
//final CustomerViewModel model = CustomerViewModel();
|
// ignore: close_sinks
|
||||||
//model.customer = Auth().userLoggedIn;
|
final accountBloc = BlocProvider.of<AccountBloc>(context);
|
||||||
//final CustomerChangingViewModel customerChangeModel =
|
|
||||||
// CustomerChangingViewModel(model);
|
|
||||||
CustomerChangingViewModel customerChangingViewModel = Provider.of<CustomerChangingViewModel>(context, listen: false);
|
|
||||||
customerChangingViewModel.customer.customer.sex = selectedGender.dbValue;
|
|
||||||
|
|
||||||
// we cannot initialize the translations in the initState
|
// we cannot initialize the translations in the initState
|
||||||
genders.forEach((GenderItem element) {
|
/* genders.forEach((GenderItem element) {
|
||||||
if ( element.dbValue == "m") {
|
if (element.dbValue == "m") {
|
||||||
element.name = AppLocalizations.of(context).translate("Man");
|
element.name = AppLocalizations.of(context).translate("Man");
|
||||||
}
|
}
|
||||||
if ( element.dbValue == "w") {
|
if (element.dbValue == "w") {
|
||||||
element.name = AppLocalizations.of(context).translate("Woman");
|
element.name = AppLocalizations.of(context).translate("Woman");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
CustomerChangeFormBloc(customerRepository: accountBloc.customerRepository),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final customerBloc = BlocProvider.of<CustomerChangeFormBloc>(context);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: true,
|
resizeToAvoidBottomInset: true,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text("Profil"),
|
Text("Profil"),
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'asset/image/WT_long_logo.png',
|
'asset/image/WT_long_logo.png',
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
height: 65.0,
|
height: 65.0,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
//title: Text(AppLocalizations.of(context).translate('Settings')),
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
),
|
|
||||||
body: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
image: DecorationImage(
|
|
||||||
image: AssetImage('asset/image/WT_light_background.png'),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
),
|
||||||
|
//title: Text(AppLocalizations.of(context).translate('Settings')),
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
),
|
),
|
||||||
child: Form(
|
body: Container(
|
||||||
key: _formKey,
|
decoration: BoxDecoration(
|
||||||
child: SingleChildScrollView(
|
image: DecorationImage(
|
||||||
scrollDirection: Axis.vertical,
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
padding: EdgeInsets.only(top: 40, left: 25, right: 45, bottom:100),
|
fit: BoxFit.cover,
|
||||||
|
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(
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TextFormField(
|
child:
|
||||||
style: TextStyle(fontSize: 12),
|
TextFieldBlocBuilder(
|
||||||
decoration: InputDecoration(
|
key: LibraryKeys.loginEmailField,
|
||||||
fillColor: Colors.white24,
|
style: TextStyle(fontSize: 12),
|
||||||
filled: true,
|
textFieldBloc: customerBloc.emailField,
|
||||||
labelText: AppLocalizations.of(context).translate('Email'),
|
decoration: InputDecoration(
|
||||||
),
|
fillColor: Colors.white24,
|
||||||
initialValue: customerChangingViewModel.customer.customer.email,
|
filled: true,
|
||||||
onFieldSubmitted: (input) => customerChangingViewModel.customer.setEmail(input)
|
labelText: AppLocalizations.of(context)
|
||||||
)
|
.translate('Email'),
|
||||||
)
|
),
|
||||||
],
|
),
|
||||||
),
|
|
||||||
Divider(),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Expanded(
|
/* TextFormField(
|
||||||
child: TextFormField(
|
style: TextStyle(fontSize: 12),
|
||||||
style: TextStyle(fontSize: 12),
|
decoration: InputDecoration(
|
||||||
obscureText: true,
|
fillColor: Colors.white24,
|
||||||
decoration: InputDecoration(
|
filled: true,
|
||||||
fillColor: Colors.white24,
|
labelText: AppLocalizations.of(context)
|
||||||
filled: true,
|
.translate('Email'),
|
||||||
labelText: AppLocalizations.of(context).translate('Password (Leave empty if you don\'t want to change)' ),
|
), */
|
||||||
|
// initialValue: customerChangingViewModel.customer
|
||||||
|
// .customer.email,
|
||||||
|
// onFieldSubmitted: (input) =>
|
||||||
|
// customerChangingViewModel.customer.setEmail(
|
||||||
|
// input)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
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: AppLocalizations.of(context)
|
||||||
|
.translate('Password (Leave empty if no change)'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
initialValue: customerChangingViewModel.customer.customer.password,
|
/*TextFormField(
|
||||||
onFieldSubmitted: (input) => customerChangingViewModel.customer.setPassword(input)
|
style: TextStyle(fontSize: 12),
|
||||||
|
obscureText: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context)
|
||||||
|
.translate(
|
||||||
|
'Password (Leave empty if you don\'t want to change)'),
|
||||||
|
),
|
||||||
|
//initialValue: customerChangingViewModel.customer.customer.password,
|
||||||
|
// onFieldSubmitted: (input) => customerChangingViewModel.customer.setPassword(input)
|
||||||
|
)*/
|
||||||
)
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
|
||||||
Divider(),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Expanded(
|
Row(
|
||||||
child: TextFormField(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: TextStyle(fontSize: 12),
|
children: [
|
||||||
decoration: InputDecoration(
|
|
||||||
fillColor: Colors.white24,
|
Expanded(
|
||||||
filled: true,
|
child: TextFieldBlocBuilder(
|
||||||
labelText: AppLocalizations.of(context).translate('Name'),
|
style: TextStyle(fontSize: 12),
|
||||||
|
textFieldBloc: customerBloc.nameField,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context)
|
||||||
|
.translate('Name'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
initialValue: customerChangingViewModel.customer.customer.name,
|
|
||||||
onFieldSubmitted: (input) => customerChangingViewModel.customer.setName(input)
|
|
||||||
)
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
|
||||||
Divider(),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Expanded(
|
Row(
|
||||||
child: TextFormField(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: TextStyle(fontSize: 12),
|
children: [
|
||||||
decoration: InputDecoration(
|
|
||||||
fillColor: Colors.white24,
|
|
||||||
filled: true,
|
|
||||||
|
|
||||||
labelText: AppLocalizations.of(context).translate('First Name'),
|
Expanded(
|
||||||
|
child: TextFieldBlocBuilder(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
textFieldBloc: customerBloc.firstNameField,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context)
|
||||||
|
.translate('First Name'),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
keyboardType: TextInputType.emailAddress,
|
|
||||||
initialValue: customerChangingViewModel.customer.customer.firstname,
|
|
||||||
onFieldSubmitted: (input) => customerChangingViewModel.customer.setFirstName(input)
|
|
||||||
)
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
|
||||||
Divider(),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Expanded(
|
Row(
|
||||||
child: TextFormField(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
style: TextStyle(fontSize: 12),
|
children: [
|
||||||
decoration: InputDecoration(
|
|
||||||
fillColor: Colors.white24,
|
Expanded(
|
||||||
filled: true,
|
child: TextFieldBlocBuilder(
|
||||||
labelText: AppLocalizations.of(context).translate('Birth Year'),
|
style: TextStyle(fontSize: 12),
|
||||||
),
|
textFieldBloc: customerBloc.birthYearField,
|
||||||
keyboardType: TextInputType.number,
|
inputFormatters: [
|
||||||
inputFormatters: <TextInputFormatter>[
|
FilteringTextInputFormatter(RegExp(r"[\d]"), allow: true)
|
||||||
WhitelistingTextInputFormatter.digitsOnly
|
|
||||||
],
|
],
|
||||||
initialValue: customerChangingViewModel.customer.customer.birthYear.toString(),
|
decoration: InputDecoration(
|
||||||
onFieldSubmitted: (input) => customerChangingViewModel.customer.setBirthYear(int.parse(input))
|
fillColor: Colors.white24,
|
||||||
)
|
filled: true,
|
||||||
)
|
labelText: AppLocalizations.of(context)
|
||||||
],
|
.translate('Birth Year'),
|
||||||
),
|
),
|
||||||
Divider(),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Expanded(
|
|
||||||
child: TextFormField(
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
fillColor: Colors.white24,
|
|
||||||
filled: true,
|
|
||||||
labelText: AppLocalizations.of(context).translate('Weight'),
|
|
||||||
),
|
),
|
||||||
inputFormatters: <TextInputFormatter>[
|
|
||||||
WhitelistingTextInputFormatter.digitsOnly
|
|
||||||
],
|
|
||||||
initialValue: customerChangingViewModel.customer.customer.weight.toString(),
|
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
onFieldSubmitted: (input) => customerChangingViewModel.customer.setWeight(int.parse(input)),
|
|
||||||
)
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
Row(
|
||||||
Divider(),
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: DropdownButtonHideUnderline(
|
child: TextFieldBlocBuilder(
|
||||||
|
style: TextStyle(fontSize: 12),
|
||||||
|
textFieldBloc: customerBloc.weightField,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter(RegExp(r"[\d]"), allow: true)
|
||||||
|
],
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white24,
|
||||||
|
filled: true,
|
||||||
|
labelText: AppLocalizations.of(context)
|
||||||
|
.translate('Weight'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: DropdownFieldBlocBuilder(
|
||||||
|
selectFieldBloc: customerBloc.genderField,
|
||||||
|
itemBuilder: (context, item) => item,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: AppLocalizations.of(context).translate(
|
||||||
|
'Select a gender'),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
/* child: DropdownButtonHideUnderline(
|
||||||
child: DropdownButton<GenderItem>(
|
child: DropdownButton<GenderItem>(
|
||||||
hint: Text(AppLocalizations.of(context).translate('Select a gender')),
|
hint: Text(
|
||||||
style: TextStyle(fontSize: 12, color: Colors.black),
|
AppLocalizations.of(context).translate(
|
||||||
|
'Select a gender')),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12, color: Colors.black),
|
||||||
focusColor: Colors.white24,
|
focusColor: Colors.white24,
|
||||||
value: selectedGender,
|
// value: selectedGender,
|
||||||
items: genders.map((GenderItem gender){
|
items: genders.map((GenderItem gender) {
|
||||||
return DropdownMenuItem<GenderItem>(
|
return DropdownMenuItem<GenderItem>(
|
||||||
value: gender,
|
value: gender,
|
||||||
child: Text(gender.name)
|
child: Text(gender.name)
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged:(GenderItem gender) => {
|
onChanged: (GenderItem gender) => {
|
||||||
setState(() {
|
// setState(() {
|
||||||
selectedGender = gender;
|
// selectedGender = gender;
|
||||||
customerChangingViewModel.customer.setSex(gender.dbValue);
|
// customerChangingViewModel.customer.setSex(gender.dbValue);
|
||||||
|
|
||||||
print ("Gender " + gender.name);
|
print ("Gender " + gender.name);
|
||||||
})
|
//})
|
||||||
//model.customer.sex =
|
//model.customer.sex =
|
||||||
},
|
},
|
||||||
|
)
|
||||||
|
) */
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: RaisedButton(
|
||||||
|
|
||||||
|
color: Colors.orange,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: InkWell(
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).translate(
|
||||||
|
"Next"))),
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
customerBloc.add(SubmitFormBloc()),
|
||||||
|
Navigator.of(context).pushNamed("customerGoalPage", arguments: customerBloc.customerRepository)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
),
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Expanded(
|
|
||||||
child: RaisedButton(
|
|
||||||
|
|
||||||
color: Colors.orange,
|
|
||||||
textColor: Colors.white,
|
|
||||||
child: InkWell(
|
|
||||||
child: Text(AppLocalizations.of(context).translate("Next"))),
|
|
||||||
onPressed: () => {
|
|
||||||
customerChangingViewModel.saveCustomer(),
|
|
||||||
Navigator.of(context).pushNamed("customerGoalPage", arguments: customerChangingViewModel)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
),
|
)
|
||||||
)
|
);
|
||||||
)
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,153 +1,156 @@
|
|||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/bloc/exercise_form_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
//import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
|
|
||||||
|
|
||||||
class ExerciseNewPage extends StatefulWidget{
|
class ExerciseNewPage extends StatefulWidget{
|
||||||
_ExerciseNewPageState createState() => _ExerciseNewPageState();
|
_ExerciseNewPageState createState() => _ExerciseNewPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ExerciseNewPageState extends State {
|
class _ExerciseNewPageState extends State<ExerciseNewPage> {
|
||||||
final List excluded = [43,44];
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final ExerciseType exerciseType = ModalRoute.of(context).settings.arguments;
|
||||||
|
|
||||||
return Consumer<ExerciseChangingViewModel>(
|
return BlocProvider(
|
||||||
builder: (context, model, child ) {
|
create: (context) => ExerciseFormBloc(exerciseRepository: ExerciseRepository()),
|
||||||
String exerciseName = "";
|
child: Builder(builder: (context) {
|
||||||
String customerName = "";
|
// ignore: close_sinks
|
||||||
if ( model != null ) {
|
final exerciseBloc = BlocProvider.of<ExerciseFormBloc>(context);
|
||||||
if ( model.exerciseViewModel == null ) {
|
|
||||||
model.createNewModel();
|
|
||||||
}
|
|
||||||
model.exerciseViewModel.createNew();
|
|
||||||
customerName = model != null && model.customer != null
|
|
||||||
? model.customer.name + " " +
|
|
||||||
model.customer.firstname
|
|
||||||
: "Please select a customer";
|
|
||||||
|
|
||||||
exerciseName = model != null &&
|
exerciseBloc.exerciseRepository.setExerciseType(exerciseType);
|
||||||
model.exerciseType != null
|
String exerciseName = exerciseBloc.exerciseRepository.exerciseType.name;
|
||||||
? model.exerciseType.name
|
|
||||||
: "Please select an exercise";
|
|
||||||
}
|
|
||||||
|
|
||||||
AppLanguage appLanguage = AppLanguage();
|
return Form(
|
||||||
var date = DateTime.now();
|
|
||||||
String dateName = DateFormat(DateFormat.YEAR_MONTH_DAY, appLanguage.appLocal.toString()).format(date.toUtc()) +
|
|
||||||
" " +DateFormat(DateFormat.HOUR_MINUTE, appLanguage.appLocal.toString()).format(date.toUtc());
|
|
||||||
|
|
||||||
return Form(
|
|
||||||
key: _formKey,
|
|
||||||
autovalidate: true,
|
autovalidate: true,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: true,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: IconButton(
|
backgroundColor: Colors.transparent,
|
||||||
icon: Icon(Icons.arrow_back, color: Colors.deepOrange),
|
title: Row(
|
||||||
onPressed: () => {
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
Navigator.of(context).pop()
|
children: <Widget>[
|
||||||
},
|
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(),
|
||||||
),
|
),
|
||||||
title: Text(AppLocalizations.of(context).translate(exerciseName) + " " +
|
|
||||||
AppLocalizations.of(context).translate('Save Exercise'),
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange)),
|
|
||||||
backgroundColor: Colors.white70,
|
|
||||||
),
|
),
|
||||||
body: Container(
|
body: Container(
|
||||||
decoration: BoxDecoration(
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
image: AssetImage('asset/image/WT_login.png'),
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.fill,
|
||||||
//height: double.infinity,
|
alignment: Alignment.center,
|
||||||
//width: double.infinity,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.only (top: 65, left:25, right: 100),
|
padding: const EdgeInsets.only (top: 25, left:25, right: 25),
|
||||||
child: Column(
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
columnQuantityUnit(model),
|
Divider(color: Colors.transparent,),
|
||||||
columnQuantity(model),
|
Divider(color: Colors.transparent,),
|
||||||
|
Divider(color: Colors.transparent,),
|
||||||
|
|
||||||
Column(
|
Text(AppLocalizations.of(context).translate(exerciseName) + " " +
|
||||||
children: [
|
AppLocalizations.of(context).translate('Save Exercise'),
|
||||||
Row(
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange)),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
Divider(color: Colors.transparent,),
|
||||||
children: [
|
Divider(color: Colors.transparent,),
|
||||||
new InkWell(
|
Divider(color: Colors.transparent,),
|
||||||
child: new Text(dateName,
|
columnQuantityUnit(exerciseBloc),
|
||||||
style: TextStyle( fontSize: 16,color: Colors.blue)),
|
Divider(color: Colors.transparent,),
|
||||||
),
|
Divider(color: Colors.transparent,),
|
||||||
ButtonTheme(
|
Divider(color: Colors.transparent,),
|
||||||
minWidth: 30.0,
|
|
||||||
height: 30.0,
|
|
||||||
child: FlatButton(
|
|
||||||
|
|
||||||
padding: EdgeInsets.only(bottom: 0),
|
columnQuantity(exerciseBloc),
|
||||||
color: Colors.transparent,
|
Divider(),
|
||||||
splashColor: Colors.black26,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
|
|
||||||
Icon(Icons.arrow_forward_ios, color: Colors.orange,)
|
|
||||||
]),
|
|
||||||
onPressed:() { print("date change");},
|
|
||||||
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
new InkWell(
|
|
||||||
child: new Text(AppLocalizations.of(context).translate('Exercise date and time'),
|
|
||||||
style: TextStyle( fontSize: 16)),
|
|
||||||
),
|
|
||||||
|
|
||||||
]),
|
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
color: Colors.deepOrange,
|
color: Colors.deepOrange,
|
||||||
focusColor: Colors.white,
|
focusColor: Colors.white,
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
{
|
{
|
||||||
if (_formKey.currentState.validate()) {
|
confirmationDialog( exerciseBloc ),
|
||||||
//model = ExerciseChangingViewModel(model.exerciseViewModel),
|
|
||||||
|
|
||||||
if ( ! excluded.contains(model.exerciseType.exerciseTypeId) ) {
|
|
||||||
model.addExercise(),
|
|
||||||
},
|
|
||||||
Navigator.pop(context),
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
child: Text("Save", style: TextStyle(fontSize: 16),)
|
child: Text(AppLocalizations.of(context).translate("Save"), style: TextStyle(fontSize: 16),)
|
||||||
),
|
),
|
||||||
|
Divider(color: Colors.transparent,),
|
||||||
|
Divider(color: Colors.transparent,),
|
||||||
|
Divider(color: Colors.transparent,),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Column columnQuantityUnit( ExerciseChangingViewModel model) {
|
Column columnQuantityUnit( ExerciseFormBloc bloc ) {
|
||||||
Column column = Column();
|
Column column = Column();
|
||||||
if ( model.exerciseType != null && model.exerciseType.unitQuantity == "1") {
|
if ( bloc.exerciseRepository.exerciseType != null &&
|
||||||
|
bloc.exerciseRepository.exerciseType.unitQuantity == "1") {
|
||||||
column = Column(
|
column = Column(
|
||||||
children: [
|
children: [
|
||||||
TextFormField(
|
TextFieldBlocBuilder(
|
||||||
|
textFieldBloc: bloc.unitQuantityField,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 30,
|
||||||
|
color: Colors.lightBlue,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter(RegExp(r"[\d.]"), allow: true)
|
||||||
|
],
|
||||||
|
onChanged: (input) => {
|
||||||
|
print ("UnitQuantity value $input"),
|
||||||
|
bloc.exerciseRepository.setUnitQuantity(
|
||||||
|
double.parse(input))
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintStyle: TextStyle(fontSize: 16, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||||
|
hintText: AppLocalizations.of(context).translate("The number of the exercise done with"),
|
||||||
|
labelStyle: TextStyle(fontSize: 16, color: Colors.lightBlue),
|
||||||
|
labelText: AppLocalizations.of(context).translate(
|
||||||
|
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/*TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintStyle: TextStyle(fontSize: 16, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||||
|
hintText: AppLocalizations.of(context).translate("The number of the exercise done with"),
|
||||||
|
labelStyle: TextStyle(fontSize: 16, color: Colors.lightBlue),
|
||||||
|
labelText: AppLocalizations.of(context).translate(
|
||||||
|
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||||
|
),
|
||||||
autovalidate: true,
|
autovalidate: true,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
initialValue: "0",
|
initialValue: "",
|
||||||
style: TextStyle(fontSize: 30,
|
style: TextStyle(fontSize: 30,
|
||||||
color: Colors.lightBlue,
|
color: Colors.lightBlue,
|
||||||
fontWeight: FontWeight.bold),
|
fontWeight: FontWeight.bold),
|
||||||
@ -155,18 +158,19 @@ class _ExerciseNewPageState extends State {
|
|||||||
return validateNumberInput(input);
|
return validateNumberInput(input);
|
||||||
},
|
},
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
WhitelistingTextInputFormatter(RegExp(r"[\d.]"))
|
FilteringTextInputFormatter(RegExp(r"[\d.]"))
|
||||||
|
//WhitelistingTextInputFormatter(RegExp(r"[\d.]"))
|
||||||
],
|
],
|
||||||
onChanged: (input) => {
|
onChanged: (input) => {
|
||||||
print ("UnitQuantity value $input"),
|
print ("UnitQuantity value $input"),
|
||||||
model.exerciseViewModel.setUnitQuantity(
|
bloc.exerciseRepository.setUnitQuantity(
|
||||||
double.parse(input))
|
double.parse(input))
|
||||||
},
|
},
|
||||||
|
|
||||||
),
|
), */
|
||||||
new InkWell(
|
new InkWell(
|
||||||
child: new Text(AppLocalizations.of(context).translate(
|
child: new Text(AppLocalizations.of(context).translate(
|
||||||
model.exerciseType.unitQuantityUnit),
|
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||||
style: TextStyle(fontSize: 16)),
|
style: TextStyle(fontSize: 16)),
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -175,16 +179,48 @@ class _ExerciseNewPageState extends State {
|
|||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
|
|
||||||
Column columnQuantity( ExerciseChangingViewModel model) {
|
Column columnQuantity( ExerciseFormBloc bloc ) {
|
||||||
Column column = Column();
|
Column column = Column(
|
||||||
|
|
||||||
column = Column(
|
|
||||||
children: [
|
children: [
|
||||||
TextFormField(
|
TextFieldBlocBuilder(
|
||||||
|
textFieldBloc: bloc.quantityField,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 50,
|
||||||
|
color: Colors.deepOrange,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter(RegExp(r"[\d.]"), allow: true)
|
||||||
|
],
|
||||||
|
onChanged: (input) =>
|
||||||
|
{
|
||||||
|
print ("Quantity value $input"),
|
||||||
|
bloc.exerciseRepository.setQuantity(double.parse(input)),
|
||||||
|
bloc.exerciseRepository.setUnit(bloc.exerciseRepository.exerciseType.unit)
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintStyle: TextStyle(fontSize: 16, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||||
|
hintText: AppLocalizations.of(context).translate("The number of the exercise"),
|
||||||
|
labelStyle: TextStyle(fontSize: 16, color: Colors.deepOrange),
|
||||||
|
labelText: AppLocalizations.of(context).translate(
|
||||||
|
bloc.exerciseRepository.exerciseType.unit),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/* TextFormField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintText: AppLocalizations.of(context).translate("The number of the exercise"),
|
||||||
|
hintStyle: TextStyle(fontSize: 16, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||||
|
labelStyle: TextStyle(fontSize: 16, color: Colors.deepOrange),
|
||||||
|
labelText: AppLocalizations.of(context).translate(
|
||||||
|
bloc.exerciseRepository.exerciseType.unit),
|
||||||
|
),
|
||||||
autovalidate: true,
|
autovalidate: true,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
initialValue: "0",
|
initialValue: "",
|
||||||
style: TextStyle(fontSize: 60,
|
style: TextStyle(fontSize: 50,
|
||||||
color: Colors.deepOrange,
|
color: Colors.deepOrange,
|
||||||
fontWeight: FontWeight.bold),
|
fontWeight: FontWeight.bold),
|
||||||
validator: (input) {
|
validator: (input) {
|
||||||
@ -195,17 +231,12 @@ class _ExerciseNewPageState extends State {
|
|||||||
],
|
],
|
||||||
onChanged: (input) =>
|
onChanged: (input) =>
|
||||||
{
|
{
|
||||||
print ("Quantity value $input"),
|
print ("Quantity value $input"),
|
||||||
model.exerciseViewModel.setQuantity(
|
bloc.exerciseRepository.setQuantity(double.parse(input)),
|
||||||
double.parse(input)),
|
bloc.exerciseRepository.setUnit(bloc.exerciseRepository.exerciseType.unit)
|
||||||
model.exerciseViewModel.setUnit(model.exerciseType.unit)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
),
|
),*/
|
||||||
new InkWell(
|
|
||||||
child: new Text(AppLocalizations.of(context).translate(model.exerciseType.unit),
|
|
||||||
style: TextStyle(fontSize: 16)),
|
|
||||||
),
|
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -238,4 +269,65 @@ class _ExerciseNewPageState extends State {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void confirmationDialog( ExerciseFormBloc bloc ) {
|
||||||
|
|
||||||
|
print("exercise validated " + bloc.exerciseRepository.exercise.quantity.toString());
|
||||||
|
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 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(AppLocalizations.of(context).translate("Do you save this exercise with these parameters?")),
|
||||||
|
content: Column(
|
||||||
|
|
||||||
|
children: [
|
||||||
|
Divider(),
|
||||||
|
Text(AppLocalizations.of(context).translate("Exercise") + ": " +
|
||||||
|
AppLocalizations.of(context).translate(bloc.exerciseRepository.exerciseType.name),
|
||||||
|
style: (TextStyle(color: Colors.blue)),),
|
||||||
|
Text(quantity + " " +
|
||||||
|
AppLocalizations.of(context).translate(bloc.exerciseRepository.exerciseType.unit),
|
||||||
|
style: (TextStyle(color: Colors.deepOrange)),),
|
||||||
|
Text(bloc.exerciseRepository.exerciseType.unitQuantity == "1" ?
|
||||||
|
AppLocalizations.of(context).translate("with") + " "
|
||||||
|
+ unitQuantity + " "
|
||||||
|
+ AppLocalizations.of(context).translate(bloc.exerciseRepository.exerciseType.unitQuantityUnit) :
|
||||||
|
"",
|
||||||
|
style: (TextStyle(color: Colors.deepOrange)),
|
||||||
|
),
|
||||||
|
|
||||||
|
]),
|
||||||
|
actions: [
|
||||||
|
FlatButton(
|
||||||
|
child: Text(AppLocalizations.of(context).translate("No")),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
FlatButton(
|
||||||
|
child: Text(AppLocalizations.of(context).translate("Yes")),
|
||||||
|
onPressed: () => {
|
||||||
|
bloc.exerciseRepository.setCustomer(Auth().userLoggedIn),
|
||||||
|
bloc.exerciseRepository.addExercise(),
|
||||||
|
|
||||||
|
Navigator.pop(context),
|
||||||
|
Navigator.pop(context),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
import 'package:aitrainer_app/viewmodel/exercise_type_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/exercise_type_list_widget.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
|
||||||
|
|
||||||
class ExerciseTypeListPage extends StatefulWidget{
|
|
||||||
_ExerciseTypeListPageState createState() => _ExerciseTypeListPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ExerciseTypeListPageState extends State {
|
|
||||||
Future<List<ExerciseTypeViewModel>> _exerciseTypes;
|
|
||||||
final _exerciseTypeViewModel = ExerciseTypeChangingViewModel(null);
|
|
||||||
|
|
||||||
// Push the page and remove everything else
|
|
||||||
navigateToPage(BuildContext context, String page) {
|
|
||||||
Navigator.of(context).pushNamedAndRemoveUntil(page, (Route<dynamic> route) => false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_exerciseTypes = _exerciseTypeViewModel.getExerciseTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Exercises'),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: FutureBuilder<List<ExerciseTypeViewModel>>(
|
|
||||||
future: _exerciseTypes,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
return ExerciseTypeListWidget(exerciseTypes: _exerciseTypeViewModel.exerciseTypeList);
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Text("${snapshot.error}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// By default, show a loading spinner.
|
|
||||||
return CircularProgressIndicator();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () => Navigator.pushNamed(
|
|
||||||
context,
|
|
||||||
'exerciseTypeNewPage',
|
|
||||||
),
|
|
||||||
child: Icon(Icons.add,),
|
|
||||||
mini: true,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
import 'package:aitrainer_app/viewmodel/exercise_type_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
|
||||||
class ExerciseTypeModifyPage extends StatefulWidget{
|
|
||||||
ExerciseTypeViewModel exerciseTypeViewModel;
|
|
||||||
ExerciseTypeModifyPage({this.exerciseTypeViewModel});
|
|
||||||
_ExerciseTypeModifyPageState createState() => _ExerciseTypeModifyPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ExerciseTypeModifyPageState extends State<ExerciseTypeModifyPage> {
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final ExerciseTypeViewModel exerciseType = ModalRoute.of(context).settings.arguments;
|
|
||||||
ExerciseTypeChangingViewModel changeModel;
|
|
||||||
return Scaffold(
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('Modify "' + exerciseType.name + '"' ),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: Form(
|
|
||||||
key:_formKey,
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
TextFormField(
|
|
||||||
initialValue: exerciseType.name,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Exercise',
|
|
||||||
),
|
|
||||||
validator: (input) => input.length == 0 ? "Please type the name of the exercise" : null,
|
|
||||||
onChanged: (input) => exerciseType.setName(input),
|
|
||||||
) ,
|
|
||||||
TextFormField(
|
|
||||||
initialValue: exerciseType.description,
|
|
||||||
minLines: 4,
|
|
||||||
maxLines: 10,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Description',
|
|
||||||
),
|
|
||||||
onChanged: (input) => exerciseType.setDescription(input),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () => {
|
|
||||||
if (_formKey.currentState.validate()) {
|
|
||||||
changeModel = ExerciseTypeChangingViewModel(exerciseType),
|
|
||||||
changeModel.saveExerciseType(),
|
|
||||||
Navigator.pop(context),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Icon(Icons.save,),
|
|
||||||
mini: true,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
import 'package:aitrainer_app/viewmodel/exercise_type_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/nav_drawer.dart';
|
|
||||||
|
|
||||||
class ExerciseTypeNewPage extends StatefulWidget{
|
|
||||||
_ExerciseTypeNewPageState createState() => _ExerciseTypeNewPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ExerciseTypeNewPageState extends State {
|
|
||||||
final ExerciseTypeViewModel exerciseType = ExerciseTypeViewModel();
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
ExerciseTypeChangingViewModel model;
|
|
||||||
exerciseType.createNew();
|
|
||||||
return Scaffold(
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text('New exercise'),
|
|
||||||
),
|
|
||||||
body: Center(
|
|
||||||
child: Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
TextFormField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Exercise',
|
|
||||||
),
|
|
||||||
validator: (input) => input.length == 0 ? "Please type the name of the exercise" : null,
|
|
||||||
onChanged: (input) => exerciseType.setName(input),
|
|
||||||
) ,
|
|
||||||
TextFormField(
|
|
||||||
minLines: 4,
|
|
||||||
maxLines: 10,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
labelText: 'Description',
|
|
||||||
),
|
|
||||||
onChanged: (input) => exerciseType.setDescription(input),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () => {
|
|
||||||
if (_formKey.currentState.validate()) {
|
|
||||||
model = ExerciseTypeChangingViewModel(exerciseType),
|
|
||||||
model.addExerciseType(),
|
|
||||||
model.addNewExercise(exerciseType),
|
|
||||||
Navigator.pop(context),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Icon(Icons.save,),
|
|
||||||
mini: true,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,162 +1,201 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/login_form_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/model/auth.dart';
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/view/account.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
import 'package:aitrainer_app/widgets/splash.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/user_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_facebook_login/flutter_facebook_login.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
import '../library_keys.dart';
|
||||||
|
|
||||||
class LoginPage extends StatefulWidget{
|
class LoginPage extends StatelessWidget {
|
||||||
_LoginPageState createState() => _LoginPageState();
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return LoginWidget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LoginPageState extends State<LoginPage> {
|
class LoginWidget extends StatefulWidget {
|
||||||
|
LoginWidget();
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _LoginWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginWidget extends State<LoginWidget> {
|
||||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
final UserViewModel user = UserViewModel();
|
|
||||||
final bool _obscureText = true;
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
UserChangingViewModel model = UserChangingViewModel(user);
|
final accountBloc = BlocProvider.of<AccountBloc>(context);
|
||||||
CustomerChangingViewModel customerChangingViewModel = Provider.of<CustomerChangingViewModel>(context, listen: false);
|
return BlocProvider(
|
||||||
user.createNew();
|
create: (context) => LoginFormBloc(
|
||||||
Future<dynamic> customer;
|
userRepository: UserRepository(),
|
||||||
final State<AccountPage> stateAccount = ModalRoute.of(context).settings.arguments;
|
accountBloc: accountBloc
|
||||||
|
),
|
||||||
return Scaffold(
|
child: Builder(builder: (context) {
|
||||||
key: _scaffoldKey,
|
final loginBloc = BlocProvider.of<LoginFormBloc>(context);
|
||||||
body: Container(
|
return Scaffold(
|
||||||
decoration: BoxDecoration(
|
key: _scaffoldKey,
|
||||||
image: DecorationImage(
|
body: FormBlocListener<LoginFormBloc, String, String>(
|
||||||
image: AssetImage('asset/image/WT_login.png'),
|
onSubmitting: (context, state) {
|
||||||
fit: BoxFit.cover,
|
LoadingDialog.show(context);
|
||||||
//height: double.infinity,
|
},
|
||||||
//width: double.infinity,
|
onSuccess: (context, state) {
|
||||||
alignment: Alignment.center,
|
LoadingDialog.hide(context);
|
||||||
),
|
Navigator.of(context).pushNamed('home');
|
||||||
),
|
},
|
||||||
child: Form(
|
onFailure: (context, state) {
|
||||||
key: _formKey,
|
LoadingDialog.hide(context);
|
||||||
|
showInSnackBar(state.failureResponse);
|
||||||
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.only (left: 25, right: 100),
|
decoration: BoxDecoration(
|
||||||
child: Column(
|
image: DecorationImage(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
image: AssetImage('asset/image/WT_login.png'),
|
||||||
children: <Widget>[
|
fit: BoxFit.cover,
|
||||||
Spacer(flex: 4),
|
//height: double.infinity,
|
||||||
Row(
|
//width: double.infinity,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
alignment: Alignment.center,
|
||||||
children: [
|
),
|
||||||
new InkWell(
|
),
|
||||||
child: new Text(
|
child: buildLoginForm(loginBloc, accountBloc),
|
||||||
AppLocalizations.of(context).translate(
|
|
||||||
'Login'),
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 24)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
TextFormField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
fillColor: Colors.white,
|
|
||||||
filled: true,
|
|
||||||
labelText: 'Email',
|
|
||||||
),
|
|
||||||
validator: (String input) {
|
|
||||||
RegExp exp = new RegExp(r"[\w._]+\@[\w._]+.[a-z]+",
|
|
||||||
caseSensitive: false,
|
|
||||||
multiLine: false,);
|
|
||||||
String ret = exp.hasMatch(input) == true ?
|
|
||||||
null :
|
|
||||||
AppLocalizations.of(context).translate(
|
|
||||||
'Please type an email address');
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
onChanged: (input) => user.setEmail(input),
|
|
||||||
),
|
|
||||||
Spacer(flex: 1),
|
|
||||||
new TextFormField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
filled: true,
|
|
||||||
labelText: "Password",
|
|
||||||
fillColor: Colors.white,
|
|
||||||
focusColor: Colors.white,
|
|
||||||
),
|
|
||||||
validator: (val) => val.length < 6
|
|
||||||
? AppLocalizations.of(context).translate(
|
|
||||||
'Password too short')
|
|
||||||
: null,
|
|
||||||
obscureText: _obscureText,
|
|
||||||
onChanged: (input) => user.setPassword(input),
|
|
||||||
),
|
|
||||||
Spacer(flex: 1),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: <Widget>[ new FlatButton(
|
|
||||||
child: Image.asset('asset/image/WT_OK.png',
|
|
||||||
width: 100,
|
|
||||||
height: 100
|
|
||||||
),
|
|
||||||
onPressed: () =>
|
|
||||||
{
|
|
||||||
if (_formKey.currentState.validate()) {
|
|
||||||
model = UserChangingViewModel(user),
|
|
||||||
model.getUser().then((_) =>
|
|
||||||
{
|
|
||||||
if ( stateAccount != null ) {
|
|
||||||
stateAccount.setState(() {
|
|
||||||
print("update account");
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
customerChangingViewModel.customer.setCustomer(Auth().userLoggedIn),
|
|
||||||
Navigator.pop(context),
|
|
||||||
}).catchError(( error, stackTrace )=> showInSnackBar(error)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
Spacer(flex: 2),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: <Widget>[
|
|
||||||
new InkWell(
|
|
||||||
child: new Text(
|
|
||||||
AppLocalizations.of(context).translate(
|
|
||||||
'SignUp')),
|
|
||||||
onTap: () =>
|
|
||||||
Navigator.of(context).pushNamed(
|
|
||||||
'registration'),
|
|
||||||
),
|
|
||||||
Spacer(flex: 1),
|
|
||||||
new InkWell(
|
|
||||||
child: new Text(
|
|
||||||
AppLocalizations.of(context).translate(
|
|
||||||
'Privacy')),
|
|
||||||
onTap: () =>
|
|
||||||
Navigator.of(context).pushNamed('gdpr'),
|
|
||||||
),
|
|
||||||
Spacer(flex: 2),
|
|
||||||
]),
|
|
||||||
Spacer(flex: 2),
|
|
||||||
])
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildLoginForm(LoginFormBloc formBloc, AccountBloc accountBloc) {
|
||||||
|
final cWidth = Common.mediaSizeWidth(context);
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(left: 25, right: 100),
|
||||||
|
child:
|
||||||
|
ListView(shrinkWrap: false, padding: EdgeInsets.only(top: 120.0),
|
||||||
|
children: <Widget>[
|
||||||
|
FlatButton(
|
||||||
|
child: new Image.asset(
|
||||||
|
'asset/image/login_fb.png',
|
||||||
|
width: cWidth * .85,
|
||||||
|
),
|
||||||
|
onPressed: () => {
|
||||||
|
_fbLogin(),
|
||||||
|
print("Login with FB"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text(AppLocalizations.of(context).translate("OR")),
|
||||||
|
Divider(),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate('Login'),
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, fontSize: 24)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
key: LibraryKeys.loginEmailField,
|
||||||
|
textFieldBloc: formBloc.emailField,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
labelText: 'Email',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Divider(
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
key: LibraryKeys.loginPasswordField,
|
||||||
|
textFieldBloc: formBloc.passwordField,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
labelText: 'Password',
|
||||||
|
),
|
||||||
|
suffixButton: SuffixButton.obscureText,
|
||||||
|
),
|
||||||
|
Divider(
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
new FlatButton(
|
||||||
|
key: LibraryKeys.loginOKButton,
|
||||||
|
child: Image.asset('asset/image/WT_OK.png',
|
||||||
|
width: 100, height: 100),
|
||||||
|
onPressed: () => {
|
||||||
|
formBloc.add(SubmitFormBloc())
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Divider(
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate('SignUp')),
|
||||||
|
onTap: () =>
|
||||||
|
Navigator.of(context).pushNamed('registration'),
|
||||||
|
),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(
|
||||||
|
AppLocalizations.of(context).translate('Privacy')),
|
||||||
|
onTap: () => Navigator.of(context).pushNamed('gdpr'),
|
||||||
|
),
|
||||||
|
Spacer(flex: 2),
|
||||||
|
]),
|
||||||
|
])),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void showInSnackBar(String error) {
|
void showInSnackBar(String error) {
|
||||||
_scaffoldKey.currentState.showSnackBar(
|
_scaffoldKey.currentState.showSnackBar(SnackBar(
|
||||||
SnackBar(
|
backgroundColor: Colors.orange,
|
||||||
backgroundColor: Colors.orange,
|
content: Text(error, style: TextStyle(color: Colors.white))));
|
||||||
content: Text(
|
}
|
||||||
AppLocalizations.of(context).translate("Customer does not exist or the password is wrong") + " " + error,
|
|
||||||
style: TextStyle(color: Colors.white))
|
Future<Null> _fbLogin() async {
|
||||||
)
|
final FacebookLogin facebookSignIn = new FacebookLogin();
|
||||||
);
|
final FacebookLoginResult result = await facebookSignIn.logIn(['email']);
|
||||||
|
|
||||||
|
switch (result.status) {
|
||||||
|
case FacebookLoginStatus.loggedIn:
|
||||||
|
final FacebookAccessToken accessToken = result.accessToken;
|
||||||
|
showInSnackBar('''
|
||||||
|
Logged in!
|
||||||
|
|
||||||
|
Token: ${accessToken.token}
|
||||||
|
User id: ${accessToken.userId}
|
||||||
|
Expires: ${accessToken.expires}
|
||||||
|
Permissions: ${accessToken.permissions}
|
||||||
|
Declined permissions: ${accessToken.declinedPermissions}
|
||||||
|
''');
|
||||||
|
break;
|
||||||
|
case FacebookLoginStatus.cancelledByUser:
|
||||||
|
showInSnackBar('Login cancelled by the user.');
|
||||||
|
break;
|
||||||
|
case FacebookLoginStatus.error:
|
||||||
|
showInSnackBar('Something went wrong with the login process.\n'
|
||||||
|
'Here\'s the error Facebook gave us: ${result.errorMessage}');
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,161 +1,115 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/model/auth.dart';
|
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
|
||||||
import 'package:aitrainer_app/model/workout_tree.dart';
|
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
|
||||||
import 'package:aitrainer_app/util/menu_tests.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/menu_page_widget.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'dart:collection';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class MenuPage extends StatefulWidget {
|
class MenuPage extends StatelessWidget {
|
||||||
_MenuPageState _state;
|
|
||||||
static const routeName = '/menu_page';
|
static const routeName = '/menu_page';
|
||||||
int parent;
|
int parent;
|
||||||
|
MenuBloc menuBloc;
|
||||||
|
|
||||||
MenuPage({this.parent});
|
MenuPage({this.parent});
|
||||||
|
|
||||||
@override
|
|
||||||
_MenuPageState createState() {
|
|
||||||
_state = new _MenuPageState();
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MenuPageState extends State<MenuPage> {
|
|
||||||
final BottomNavigator bottomNav = BottomNavigator();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final MenuTests menu = MenuTests(context);
|
menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(AppLocalizations.of(context).translate("Tests")),
|
Text(AppLocalizations.of(context).translate("Tests")),
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'asset/image/WT_long_logo.png',
|
'asset/image/WT_long_logo.png',
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
height: 65.0,
|
height: 65.0,
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
leading: IconButton(
|
|
||||||
icon: Icon(Icons.arrow_back, color: Colors.white),
|
|
||||||
onPressed: () => {
|
|
||||||
this.setState(() {
|
|
||||||
widget.parent = 0;
|
|
||||||
},
|
|
||||||
)},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
body: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
image: DecorationImage(
|
|
||||||
image: AssetImage('asset/image/WT_menu_dark.png'),
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: CustomScrollView(
|
],
|
||||||
scrollDirection: Axis.vertical,
|
|
||||||
slivers: <Widget>[
|
|
||||||
buildMenuColumn(widget.parent, context, menu)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
|
leading: IconButton(
|
||||||
|
icon: Icon(Icons.arrow_back, color: Colors.white),
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
menuBloc.add(MenuTreeUp(parent: 0))
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
body: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_menu_dark.png'),
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: BlocConsumer<MenuBloc, MenuState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (state is MenuError) {
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
content: Text("error", style: TextStyle(color: Colors.white))));
|
||||||
|
} else if ( state is MenuLoading ) {
|
||||||
|
return MenuPageWidget();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ignore: missing_return
|
||||||
|
builder: (context, state) {
|
||||||
|
if ( state is MenuInitial ) {
|
||||||
|
return LoadingMenuDialog();
|
||||||
|
} else if (state is MenuReady ) {
|
||||||
|
return MenuPageWidget();
|
||||||
|
} else if ( state is MenuLoading ) {
|
||||||
|
return LoadingMenuDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
bottomNavigationBar: BottomNavigator(bottomNavIndex: 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoadingMenuDialog extends StatefulWidget {
|
||||||
|
|
||||||
|
LoadingMenuDialog({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _LoadingMenuDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoadingMenuDialog extends State<LoadingMenuDialog> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
/// We require the initializers to run after the loading screen is rendered
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
BlocProvider.of<MenuBloc>(context).add(MenuCreate());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return WillPopScope(
|
||||||
|
onWillPop: () async => false,
|
||||||
|
child: Center(
|
||||||
|
child: Card(
|
||||||
|
child: Container(
|
||||||
|
width: 80,
|
||||||
|
height: 80,
|
||||||
|
padding: EdgeInsets.all(12.0),
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
SliverList buildMenuColumn(int parent, BuildContext context, MenuTests menu) {
|
|
||||||
LinkedHashMap tree = menu.getMenuItems();
|
|
||||||
List<Widget> _columnChildren = List();
|
|
||||||
ExerciseType exerciseType;
|
|
||||||
ExerciseChangingViewModel model = Provider.of<ExerciseChangingViewModel>(context, listen: false);
|
|
||||||
|
|
||||||
tree.forEach((treeName, value) {
|
|
||||||
WorkoutTree workoutTree = value as WorkoutTree;
|
|
||||||
|
|
||||||
if ( workoutTree.parent == parent ) {
|
|
||||||
_columnChildren.add(
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.only(top: 16.0),
|
|
||||||
child: Center(
|
|
||||||
child: Stack(
|
|
||||||
alignment: Alignment.bottomLeft,
|
|
||||||
overflow: Overflow.visible,
|
|
||||||
children: [
|
|
||||||
FlatButton(
|
|
||||||
child: _getButtonImage(workoutTree),
|
|
||||||
padding: EdgeInsets.all(0.0),
|
|
||||||
onPressed:() =>
|
|
||||||
{
|
|
||||||
print("Hi!, Menu clicked " + workoutTree.id.toString()),
|
|
||||||
if ( workoutTree.child == false ) {
|
|
||||||
this.setState(() {
|
|
||||||
widget.parent = workoutTree.id;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
} else {
|
|
||||||
exerciseType = Common.getExerciseType(workoutTree.exerciseTypeId),
|
|
||||||
model.setExerciseType(exerciseType),
|
|
||||||
model.setCustomer(Auth().userLoggedIn),
|
|
||||||
if ( Auth().userLoggedIn == null ) {
|
|
||||||
Scaffold.of(context)
|
|
||||||
. showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
backgroundColor: Colors.orange,
|
|
||||||
content: Text(
|
|
||||||
AppLocalizations.of(context).translate('Please log in'),
|
|
||||||
style: TextStyle(color: Colors.white))
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Navigator.of(context).pushNamed('exerciseNewPage'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
),
|
|
||||||
InkWell(
|
|
||||||
child: Text(workoutTree.name, style: TextStyle(color: workoutTree.color, fontSize: workoutTree.fontSize, fontFamily: 'Arial', fontWeight: FontWeight.w900 ),),
|
|
||||||
highlightColor: workoutTree.color,
|
|
||||||
)]))));
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//_columnChildren.add(Spacer(flex: 3));
|
|
||||||
SliverList sliverList =
|
|
||||||
SliverList(
|
|
||||||
delegate: SliverChildListDelegate(
|
|
||||||
_columnChildren
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return sliverList;
|
|
||||||
}
|
|
||||||
|
|
||||||
dynamic _getButtonImage(WorkoutTree workoutTree) {
|
|
||||||
dynamic image;
|
|
||||||
if ( workoutTree.imageName.startsWith("http") ) {
|
|
||||||
image = FadeInImage.assetNetwork(
|
|
||||||
image: workoutTree.imageName,
|
|
||||||
placeholder: 'asset/image/dots.gif',
|
|
||||||
//imageScale: 0.1,
|
|
||||||
height: 180,
|
|
||||||
placeholderScale: 0.1,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
image = Image.asset(workoutTree.imageName, height: 180,);
|
|
||||||
}
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,142 +1,216 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/bloc/registration_form_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/model/auth.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/customer_changing_view_model.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/user_changing_view_model.dart';
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
import 'package:aitrainer_app/widgets/splash.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_facebook_login/flutter_facebook_login.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
class RegistrationPage extends StatefulWidget{
|
import '../library_keys.dart';
|
||||||
_RegistrationPageState createState() => _RegistrationPageState();
|
|
||||||
|
class RegistrationPage extends StatelessWidget {
|
||||||
|
final UserRepository userRepository = UserRepository();
|
||||||
|
final CustomerRepository customerRepository = CustomerRepository();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RegistrationWidget(
|
||||||
|
userRepository: userRepository, customerRepository: customerRepository);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RegistrationPageState extends State<RegistrationPage> {
|
class RegistrationWidget extends StatefulWidget {
|
||||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
final UserRepository userRepository;
|
||||||
final UserViewModel user = UserViewModel();
|
final CustomerRepository customerRepository;
|
||||||
bool _obscureText = true;
|
|
||||||
|
|
||||||
|
RegistrationWidget({this.userRepository, this.customerRepository});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _RegistrationWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RegistrationWidget extends State<RegistrationWidget> {
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
UserChangingViewModel model = UserChangingViewModel(user);
|
final cWidth = Common.mediaSizeWidth(context);
|
||||||
CustomerChangingViewModel customerChangingViewModel = Provider.of<CustomerChangingViewModel>(context, listen: false);
|
// ignore: close_sinks
|
||||||
user.createNew();
|
final accountBloc = BlocProvider.of<AccountBloc>(context);
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => RegistrationFormBloc(
|
||||||
|
userRepository: UserRepository(),
|
||||||
|
accountBloc: accountBloc),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final registrationBloc = BlocProvider.of<RegistrationFormBloc>(context);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: _scaffoldKey,
|
key: _scaffoldKey,
|
||||||
body: Container(
|
body: FormBlocListener<RegistrationFormBloc, String, String>(
|
||||||
decoration: BoxDecoration(
|
onSubmitting: (context, state) {
|
||||||
image: DecorationImage(
|
LoadingDialog.show(context);
|
||||||
image: AssetImage('asset/image/WT_login.png'),
|
},
|
||||||
fit: BoxFit.cover,
|
onSuccess: (context, state) {
|
||||||
//height: double.infinity,
|
LoadingDialog.hide(context);
|
||||||
//width: double.infinity,
|
Navigator.of(context).pushNamed('customerModifyPage');
|
||||||
alignment: Alignment.center,
|
},
|
||||||
),
|
onFailure: (context, state) {
|
||||||
),
|
LoadingDialog.hide(context);
|
||||||
child: Form(
|
showInSnackBar(state.failureResponse);
|
||||||
key: _formKey,
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.only (left:25, right: 100),
|
decoration: BoxDecoration(
|
||||||
child: Column(
|
image: DecorationImage(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
image: AssetImage('asset/image/WT_login.png'),
|
||||||
children: <Widget>[
|
fit: BoxFit.cover,
|
||||||
Spacer(flex:4),
|
//height: double.infinity,
|
||||||
Row(
|
//width: double.infinity,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
alignment: Alignment.center,
|
||||||
children: [
|
),
|
||||||
new InkWell(
|
),
|
||||||
child: new Text(AppLocalizations.of(context).translate('SignUp'),
|
child: Form(
|
||||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)),
|
key: _formKey,
|
||||||
),
|
child: Container(
|
||||||
],
|
padding: const EdgeInsets.only(left: 25, right: 100),
|
||||||
),
|
child: ListView(
|
||||||
|
shrinkWrap: false,
|
||||||
|
padding: EdgeInsets.only(top: 120.0),
|
||||||
|
//mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
//Spacer(flex:4),
|
||||||
|
|
||||||
TextFormField(
|
FlatButton(
|
||||||
decoration: InputDecoration(
|
child: new Image.asset(
|
||||||
fillColor: Colors.white,
|
'asset/image/login_fb.png',
|
||||||
filled:true,
|
width: cWidth * .85,
|
||||||
labelText: 'Email',
|
),
|
||||||
),
|
onPressed: () => {
|
||||||
validator: (String input) {
|
_fbLogin(),
|
||||||
RegExp exp = new RegExp(r"[\w._]+\@[\w._]+.[a-z]+",
|
print("Login with FB"),
|
||||||
caseSensitive: false,
|
},
|
||||||
multiLine: false,);
|
|
||||||
String ret = exp.hasMatch(input) == true ?
|
|
||||||
null:
|
|
||||||
AppLocalizations.of(context).translate('Please type an email address');
|
|
||||||
return ret;
|
|
||||||
},
|
|
||||||
onChanged: (input) => user.setEmail(input),
|
|
||||||
),
|
|
||||||
Spacer(flex:1),
|
|
||||||
new TextFormField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
filled:true,
|
|
||||||
labelText: "Password",
|
|
||||||
fillColor: Colors.white,
|
|
||||||
focusColor: Colors.white,
|
|
||||||
),
|
|
||||||
validator: (val) => val.length < 6 ? AppLocalizations.of(context).translate('Password too short') : null,
|
|
||||||
obscureText: _obscureText,
|
|
||||||
onChanged: (input) => user.setPassword(input),
|
|
||||||
),
|
|
||||||
Spacer(flex:1),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: <Widget>[ new FlatButton(
|
|
||||||
child: Image.asset('asset/image/WT_OK.png',
|
|
||||||
width: 100,
|
|
||||||
height:100
|
|
||||||
),
|
),
|
||||||
onPressed:() => {
|
Text(AppLocalizations.of(context).translate("OR")),
|
||||||
if (_formKey.currentState.validate()) {
|
Divider(),
|
||||||
model = UserChangingViewModel(user),
|
Row(
|
||||||
model.addUser().then((_) =>
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
{
|
children: [
|
||||||
Navigator.of(context).pushNamed("customerModifyPage",),
|
new InkWell(
|
||||||
customerChangingViewModel.customer.setCustomer(Auth().userLoggedIn),
|
child: new Text(
|
||||||
}).catchError(( error, stackTrace )=> showInSnackBar()
|
AppLocalizations.of(context)
|
||||||
|
.translate('SignUp'),
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 24)),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
}
|
),
|
||||||
}),
|
Divider(),
|
||||||
]),
|
TextFieldBlocBuilder(
|
||||||
Spacer(flex:2),
|
key: LibraryKeys.loginEmailField,
|
||||||
Row(
|
textFieldBloc: registrationBloc.emailField,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
decoration: InputDecoration(
|
||||||
children: <Widget>[
|
fillColor: Colors.white,
|
||||||
new InkWell(
|
filled: true,
|
||||||
child: new Text(AppLocalizations.of(context).translate('Login')),
|
labelText: 'Email',
|
||||||
onTap: () => Navigator.of(context).pushNamed('login'),
|
),
|
||||||
),
|
),
|
||||||
Spacer(flex:1),
|
Divider(
|
||||||
new InkWell(
|
color: Colors.transparent,
|
||||||
child: new Text(AppLocalizations.of(context).translate('Privacy')),
|
),
|
||||||
onTap: () => Navigator.of(context).pushNamed('gdpr'),
|
TextFieldBlocBuilder(
|
||||||
),
|
key: LibraryKeys.loginPasswordField,
|
||||||
Spacer(flex:2),
|
textFieldBloc: registrationBloc.passwordField,
|
||||||
]),
|
decoration: InputDecoration(
|
||||||
Spacer(flex:2),
|
fillColor: Colors.white,
|
||||||
])
|
filled: true,
|
||||||
),
|
labelText: 'Password',
|
||||||
),
|
),
|
||||||
),
|
suffixButton: SuffixButton.obscureText,
|
||||||
|
),
|
||||||
);
|
Divider(
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
new FlatButton(
|
||||||
|
child: Image.asset(
|
||||||
|
'asset/image/WT_OK.png',
|
||||||
|
width: 100,
|
||||||
|
height: 100),
|
||||||
|
onPressed: () => {
|
||||||
|
registrationBloc.add(SubmitFormBloc())
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context)
|
||||||
|
.translate('Login')),
|
||||||
|
onTap: () => Navigator.of(context)
|
||||||
|
.pushNamed('login'),
|
||||||
|
),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
new InkWell(
|
||||||
|
child: new Text(AppLocalizations.of(context)
|
||||||
|
.translate('Privacy')),
|
||||||
|
onTap: () =>
|
||||||
|
Navigator.of(context).pushNamed('gdpr'),
|
||||||
|
),
|
||||||
|
Spacer(flex: 2),
|
||||||
|
]),
|
||||||
|
//Spacer(flex:2),
|
||||||
|
])),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void showInSnackBar() {
|
void showInSnackBar(String error) {
|
||||||
_scaffoldKey.currentState.showSnackBar(
|
_scaffoldKey.currentState.showSnackBar(SnackBar(
|
||||||
SnackBar(
|
backgroundColor: Colors.orange,
|
||||||
backgroundColor: Colors.orange,
|
content: Text(
|
||||||
content: Text(
|
AppLocalizations.of(context)
|
||||||
AppLocalizations.of(context).translate("Customer exists"),
|
.translate("There is an error: during registration:") +
|
||||||
style: TextStyle(color: Colors.white))
|
" " +
|
||||||
)
|
error,
|
||||||
);
|
style: TextStyle(color: Colors.white))));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Null> _fbLogin() async {
|
||||||
|
final FacebookLogin facebookSignIn = new FacebookLogin();
|
||||||
|
final FacebookLoginResult result = await facebookSignIn.logIn(['email']);
|
||||||
|
|
||||||
|
switch (result.status) {
|
||||||
|
case FacebookLoginStatus.loggedIn:
|
||||||
|
final FacebookAccessToken accessToken = result.accessToken;
|
||||||
|
showInSnackBar('''
|
||||||
|
Logged in!
|
||||||
|
Token: ${accessToken.token}
|
||||||
|
User id: ${accessToken.userId}
|
||||||
|
Expires: ${accessToken.expires}
|
||||||
|
Permissions: ${accessToken.permissions}
|
||||||
|
Declined permissions: ${accessToken.declinedPermissions}
|
||||||
|
''');
|
||||||
|
break;
|
||||||
|
case FacebookLoginStatus.cancelledByUser:
|
||||||
|
showInSnackBar('Login cancelled by the user.');
|
||||||
|
break;
|
||||||
|
case FacebookLoginStatus.error:
|
||||||
|
showInSnackBar('Something went wrong with the login process.\n'
|
||||||
|
'Here\'s the error Facebook gave us: ${result.errorMessage}');
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,30 +1,21 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/splash.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SettingsPage extends StatefulWidget{
|
class SettingsPage extends StatelessWidget{
|
||||||
_SettingsPageState _state;
|
|
||||||
|
|
||||||
_SettingsPageState createState() {
|
|
||||||
_state = new _SettingsPageState();
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SettingsPageState extends State<SettingsPage> {
|
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
|
||||||
Locale _locale;
|
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
BottomNavigator bottomNav = BottomNavigator();
|
// ignore: close_sinks
|
||||||
_locale = appLanguage.appLocal;
|
SettingsBloc settingsBloc = BlocProvider.of<SettingsBloc>(context);
|
||||||
|
settingsBloc.context = context;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Row(
|
title: Row(
|
||||||
@ -50,54 +41,60 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
child: BlocConsumer<SettingsBloc, SettingsState>(
|
||||||
child:
|
listener: (context, state) {
|
||||||
ListView(
|
if ( state is SettingsError ) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ignore: missing_return
|
||||||
|
builder: (context, state) {
|
||||||
|
if ( state is SettingsLoading ) {
|
||||||
|
return LoadingDialog();
|
||||||
|
} else if ( state is SettingsReady || state is SettingsInitial) {
|
||||||
|
return ListView(
|
||||||
padding: EdgeInsets.only(top: 150),
|
padding: EdgeInsets.only(top: 150),
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.language),
|
leading: Icon(Icons.language),
|
||||||
subtitle: Text(AppLocalizations.of(context).translate("Change App Language")),
|
subtitle: Text(
|
||||||
|
AppLocalizations.of(context).translate(
|
||||||
|
"Change App Language")),
|
||||||
title: DropdownButton(
|
title: DropdownButton(
|
||||||
value: _locale == Locale('en') ? AppLocalizations.of(context).translate("English") : AppLocalizations.of(context).translate("Hungarian"),
|
|
||||||
items: [AppLocalizations.of(context).translate("English"), AppLocalizations.of(context).translate("Hungarian")]
|
value: state.props[0] == Locale('en')
|
||||||
.map<DropdownMenuItem<String>>((String value) {
|
? AppLocalizations.of(context).translate(
|
||||||
|
"English")
|
||||||
|
: AppLocalizations.of(context).translate(
|
||||||
|
"Hungarian"),
|
||||||
|
items: [AppLocalizations.of(context).translate(
|
||||||
|
"English"), AppLocalizations.of(context)
|
||||||
|
.translate("Hungarian")
|
||||||
|
]
|
||||||
|
.map<DropdownMenuItem<String>>((String value) {
|
||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<String>(
|
||||||
value: value,
|
value: value,
|
||||||
child: Text(value),
|
child: Text(value),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged:(String lang) => _changeLanguage(lang),
|
onChanged: (String lang) =>
|
||||||
|
settingsBloc.add(
|
||||||
|
SettingsChangeLanguage(language: lang)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
}
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
bottomNavigationBar: bottomNav.buildBottomNavigator(context, widget._state)
|
bottomNavigationBar: BottomNavigator(bottomNavIndex: 3)
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_changeLanguage( String lang ) {
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
switch ( lang ) {
|
|
||||||
case "English":
|
|
||||||
case "Angol":
|
|
||||||
_locale = Locale('en');
|
|
||||||
break;
|
|
||||||
case "Hungarian":
|
|
||||||
case "Magyar":
|
|
||||||
_locale = Locale('hu');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
appLanguage.changeLanguage(_locale);
|
|
||||||
AppLocalizations.of(context).setLocale(_locale);
|
|
||||||
AppLocalizations.of(context).load();
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,37 +0,0 @@
|
|||||||
import 'package:aitrainer_app/service/customer_service.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:aitrainer_app/model/customer.dart';
|
|
||||||
|
|
||||||
import 'customer_view_model.dart';
|
|
||||||
|
|
||||||
class CustomerChangingViewModel extends ChangeNotifier {
|
|
||||||
CustomerViewModel customer = CustomerViewModel();
|
|
||||||
List<CustomerViewModel> customerList = List<CustomerViewModel>();
|
|
||||||
|
|
||||||
CustomerChangingViewModel(customer) {
|
|
||||||
this.customer = customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> addCustomer() async {
|
|
||||||
this.customer = customer;
|
|
||||||
final Customer modelCustomer = customer.getCustomer();
|
|
||||||
await CustomerApi().addCustomer(modelCustomer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> saveCustomer() async {
|
|
||||||
//this.customer = customer;
|
|
||||||
final Customer modelCustomer = customer.getCustomer();
|
|
||||||
await CustomerApi().saveCustomer(modelCustomer);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<CustomerViewModel>> getCustomers() async {
|
|
||||||
final results = await CustomerApi().getRealCustomers("");
|
|
||||||
this.customerList = results.map((item) => CustomerViewModel(customer: item)).toList();
|
|
||||||
notifyListeners();
|
|
||||||
return this.customerList;
|
|
||||||
}
|
|
||||||
|
|
||||||
addNewCustomerToList(CustomerViewModel customerViewModel) {
|
|
||||||
customerList.add(customerViewModel);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
import 'package:aitrainer_app/model/customer.dart';
|
|
||||||
|
|
||||||
class CustomerViewModel {
|
|
||||||
Customer customer;
|
|
||||||
bool visibleDetails = false;
|
|
||||||
|
|
||||||
CustomerViewModel({this.customer});
|
|
||||||
|
|
||||||
String get name {
|
|
||||||
return this.customer.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
String get firstName {
|
|
||||||
return this.customer.firstname;
|
|
||||||
}
|
|
||||||
|
|
||||||
String get sex {
|
|
||||||
return this.customer.sex == "m" ? "Man" : "Woman";
|
|
||||||
}
|
|
||||||
|
|
||||||
int get birthYear {
|
|
||||||
return this.customer.birthYear;
|
|
||||||
}
|
|
||||||
|
|
||||||
String get goal {
|
|
||||||
return this.customer.goal;
|
|
||||||
}
|
|
||||||
|
|
||||||
String get fitnessLevel {
|
|
||||||
return this.customer.fitnessLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
String get bodyType {
|
|
||||||
return this.customer.bodyType;
|
|
||||||
}
|
|
||||||
|
|
||||||
setName(String name) {
|
|
||||||
this.customer.name = name;
|
|
||||||
}
|
|
||||||
setFirstName(String firstName) {
|
|
||||||
this.customer.firstname = firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPassword( String password ) {
|
|
||||||
this.customer.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
setEmail(String email) {
|
|
||||||
this.customer.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setSex(String sex) {
|
|
||||||
this.customer.sex = sex;
|
|
||||||
}
|
|
||||||
|
|
||||||
setWeight( int weight) {
|
|
||||||
this.customer.weight = weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
setBirthYear( int birthYear ) {
|
|
||||||
this.customer.birthYear = birthYear;
|
|
||||||
}
|
|
||||||
|
|
||||||
setFitnessLevel( String level ) {
|
|
||||||
this.customer.fitnessLevel = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
setGoal( String goal ) {
|
|
||||||
this.customer.goal = goal;
|
|
||||||
}
|
|
||||||
|
|
||||||
setBodyType(String bodyType) {
|
|
||||||
this.customer.bodyType = bodyType;
|
|
||||||
}
|
|
||||||
|
|
||||||
createNew() {
|
|
||||||
this.customer = Customer();
|
|
||||||
}
|
|
||||||
|
|
||||||
Customer getCustomer() {
|
|
||||||
return this.customer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCustomer ( Customer customer ) {
|
|
||||||
this.customer = customer;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
import 'package:aitrainer_app/model/customer.dart';
|
|
||||||
import 'package:aitrainer_app/model/exercise.dart';
|
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
|
||||||
import 'package:aitrainer_app/service/exercise_service.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
|
|
||||||
import 'exercise_view_model.dart';
|
|
||||||
|
|
||||||
class ExerciseChangingViewModel with ChangeNotifier {
|
|
||||||
Customer customer;
|
|
||||||
ExerciseType exerciseType;
|
|
||||||
List<ExerciseViewModel> exerciseList = List<ExerciseViewModel>();
|
|
||||||
|
|
||||||
ExerciseViewModel exerciseViewModel = ExerciseViewModel();
|
|
||||||
|
|
||||||
ExerciseChangingViewModel(exerciseViewModel) {
|
|
||||||
this.exerciseViewModel = exerciseViewModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
int quantity;
|
|
||||||
|
|
||||||
setCustomer(Customer customer) {
|
|
||||||
this.customer = customer;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
setExerciseType( ExerciseType exerciseType) {
|
|
||||||
this.exerciseType = exerciseType;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
setQuantity(int quantity) {
|
|
||||||
this.quantity = quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
addExercise() async {
|
|
||||||
// this.exerciseViewModel = exerciseViewModel;
|
|
||||||
final Exercise modelExercise = exerciseViewModel.getExercise();
|
|
||||||
modelExercise.customerId = this.customer.customerId;
|
|
||||||
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
|
|
||||||
await ExerciseApi().addExercise(modelExercise);
|
|
||||||
}
|
|
||||||
|
|
||||||
createNewModel() {
|
|
||||||
exerciseViewModel = ExerciseViewModel();
|
|
||||||
exerciseViewModel.createNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<ExerciseViewModel>> getExercisesByCustomer( int customerId ) async {
|
|
||||||
final results = await ExerciseApi().getExercisesByCustomer(customerId);
|
|
||||||
this.exerciseList = results.map((item) => ExerciseViewModel(exercise: item)).toList();
|
|
||||||
notifyListeners();
|
|
||||||
return this.exerciseList;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:aitrainer_app/service/exercisetype_service.dart';
|
|
||||||
|
|
||||||
class ExerciseTypeChangingViewModel extends ChangeNotifier {
|
|
||||||
ExerciseTypeViewModel exerciseType = ExerciseTypeViewModel();
|
|
||||||
List<ExerciseTypeViewModel> exerciseTypeList = List<ExerciseTypeViewModel>();
|
|
||||||
|
|
||||||
ExerciseTypeChangingViewModel(exerciseType) {
|
|
||||||
this.exerciseType = exerciseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> addExerciseType() async {
|
|
||||||
this.exerciseType = exerciseType;
|
|
||||||
final ExerciseType modelExerciseType = exerciseType.getExerciseType();
|
|
||||||
await ExerciseTypeApi().addExerciseType(modelExerciseType);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> saveExerciseType() async {
|
|
||||||
this.exerciseType = exerciseType;
|
|
||||||
final ExerciseType modelExerciseType = exerciseType.getExerciseType();
|
|
||||||
await ExerciseTypeApi().saveExerciseType(modelExerciseType);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<ExerciseTypeViewModel>> getExerciseTypes() async {
|
|
||||||
final results = await ExerciseTypeApi().getExerciseTypes("");
|
|
||||||
this.exerciseTypeList = results.map((item) => ExerciseTypeViewModel( exerciseType: item) ).toList();
|
|
||||||
notifyListeners();
|
|
||||||
return this.exerciseTypeList;
|
|
||||||
}
|
|
||||||
|
|
||||||
addNewExercise(ExerciseTypeViewModel exerciseTypeViewModel) {
|
|
||||||
exerciseTypeList.add(exerciseTypeViewModel);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
|
||||||
|
|
||||||
class ExerciseTypeViewModel {
|
|
||||||
ExerciseType exerciseType;
|
|
||||||
bool visible = false;
|
|
||||||
|
|
||||||
ExerciseTypeViewModel( {this.exerciseType} );
|
|
||||||
|
|
||||||
String get name {
|
|
||||||
return this.exerciseType.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
setName(String name) {
|
|
||||||
this.exerciseType.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
String get description {
|
|
||||||
return this.exerciseType.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
setDescription(String description) {
|
|
||||||
this.exerciseType.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get exerciseTypeId {
|
|
||||||
return this.exerciseType.exerciseTypeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExerciseType getExerciseType() {
|
|
||||||
return this.exerciseType;
|
|
||||||
}
|
|
||||||
|
|
||||||
createNew() {
|
|
||||||
this.exerciseType = ExerciseType();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
import 'package:aitrainer_app/model/exercise.dart';
|
|
||||||
|
|
||||||
class ExerciseViewModel {
|
|
||||||
Exercise exercise;
|
|
||||||
ExerciseViewModel({this.exercise});
|
|
||||||
|
|
||||||
createNew() {
|
|
||||||
this.exercise = Exercise();
|
|
||||||
exercise.dateAdd = DateTime.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
setQuantity(double quantity) {
|
|
||||||
this.exercise.quantity = quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
setUnitQuantity(double unitQuantity) {
|
|
||||||
this.exercise.unitQuantity = unitQuantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
setUnit( String unit) {
|
|
||||||
this.exercise.unit = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
setDatetimeExercise(DateTime datetimeExercise) {
|
|
||||||
this.exercise.dateAdd = datetimeExercise;
|
|
||||||
}
|
|
||||||
|
|
||||||
Exercise getExercise() {
|
|
||||||
return this.exercise;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
import 'package:aitrainer_app/model/user.dart';
|
|
||||||
import 'package:aitrainer_app/service/customer_service.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/user_view_model.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
|
|
||||||
class UserChangingViewModel extends ChangeNotifier {
|
|
||||||
UserViewModel userViewModel = UserViewModel();
|
|
||||||
|
|
||||||
UserChangingViewModel(userViewModel) {
|
|
||||||
this.userViewModel = userViewModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> addUser() async {
|
|
||||||
final User modelUser = userViewModel.getUser();
|
|
||||||
await CustomerApi().addUser(modelUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> getUser() async {
|
|
||||||
final User modelUser = userViewModel.getUser();
|
|
||||||
await CustomerApi().getUser(modelUser);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
import 'package:aitrainer_app/model/user.dart';
|
|
||||||
|
|
||||||
class UserViewModel {
|
|
||||||
User user;
|
|
||||||
|
|
||||||
UserViewModel({this.user});
|
|
||||||
|
|
||||||
setEmail(String email) {
|
|
||||||
this.user.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPassword(String password) {
|
|
||||||
this.user.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
User getUser() {
|
|
||||||
return this.user;
|
|
||||||
}
|
|
||||||
|
|
||||||
createNew() {
|
|
||||||
this.user = User();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +1,35 @@
|
|||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BottomNavigator {
|
class BottomNavigator extends StatefulWidget {
|
||||||
BottomNavigationBar buildBottomNavigator(BuildContext context, State state) {
|
int bottomNavIndex = 0;
|
||||||
|
BottomNavigator({this.bottomNavIndex}) {
|
||||||
|
this.bottomNavIndex = bottomNavIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
_NawDrawerWidget createState() => _NawDrawerWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NawDrawerWidget extends State<BottomNavigator> {
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return BottomNavigationBar(
|
return BottomNavigationBar(
|
||||||
currentIndex: 0, // this will be set when a new tab is tapped
|
currentIndex: widget.bottomNavIndex, // this will be set when a new tab is tapped
|
||||||
backgroundColor: Colors.black12,
|
backgroundColor: Colors.transparent,
|
||||||
selectedItemColor: Colors.yellow,
|
selectedItemColor: Colors.yellow,
|
||||||
unselectedItemColor: Colors.lightGreen,
|
unselectedItemColor: Colors.lightGreen,
|
||||||
type: BottomNavigationBarType.shifting,
|
//type: BottomNavigationBarType.shifting,
|
||||||
showSelectedLabels: true,
|
showSelectedLabels: true,
|
||||||
|
showUnselectedLabels: true,
|
||||||
items: [
|
items: [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
backgroundColor: Colors.black12,
|
backgroundColor: Colors.black12,
|
||||||
@ -18,23 +38,29 @@ class BottomNavigator {
|
|||||||
title: new Text(AppLocalizations.of(context).translate("Home")),
|
title: new Text(AppLocalizations.of(context).translate("Home")),
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: new Icon(Icons.event, color: Colors.lightGreen),
|
backgroundColor: Colors.black12,
|
||||||
|
icon: new Icon(Icons.confirmation_number, color: Colors.lightGreen),
|
||||||
activeIcon: new Icon(Icons.event, color: Colors.yellow,),
|
activeIcon: new Icon(Icons.event, color: Colors.yellow,),
|
||||||
title: new Text(AppLocalizations.of(context).translate("Events")),
|
title: new Text(AppLocalizations.of(context).translate("Events")),
|
||||||
),
|
),
|
||||||
|
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
|
backgroundColor: Colors.black12,
|
||||||
icon: Icon(Icons.person, color: Colors.lightGreen,),
|
icon: Icon(Icons.person, color: Colors.lightGreen,),
|
||||||
activeIcon: new Icon(Icons.person, color: Colors.yellow,),
|
activeIcon: new Icon(Icons.person, color: Colors.yellow,),
|
||||||
title: Text(AppLocalizations.of(context).translate("Account"))
|
title: Text(AppLocalizations.of(context).translate("Account"))
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
|
backgroundColor: Colors.black12,
|
||||||
icon: Icon(Icons.settings, color: Colors.lightGreen),
|
icon: Icon(Icons.settings, color: Colors.lightGreen),
|
||||||
activeIcon: new Icon(Icons.settings, color: Colors.yellow,),
|
activeIcon: new Icon(Icons.settings, color: Colors.yellow,),
|
||||||
title: Text(AppLocalizations.of(context).translate("Settings"))
|
title: Text(AppLocalizations.of(context).translate("Settings"))
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
onTap:(index) {
|
onTap:(index) {
|
||||||
// ignore: invalid_use_of_protected_member
|
setState(() {
|
||||||
|
widget.bottomNavIndex = index;
|
||||||
|
});
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@ -59,4 +85,6 @@ class BottomNavigator {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,67 +0,0 @@
|
|||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/customer_view_model.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class CustomerListWidget extends StatefulWidget {
|
|
||||||
static const routeName = '/customer_list';
|
|
||||||
final List<CustomerViewModel> customers;
|
|
||||||
|
|
||||||
CustomerListWidget({this.customers});
|
|
||||||
|
|
||||||
@override
|
|
||||||
_CustomerListWidget createState() => _CustomerListWidget();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CustomerListWidget extends State<CustomerListWidget> {
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: widget.customers.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
|
|
||||||
final customer = widget.customers[index];
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
contentPadding: EdgeInsets.all(10),
|
|
||||||
leading:Icon(Icons.accessibility),
|
|
||||||
title: Text(customer.name + " " + customer.firstName),
|
|
||||||
subtitle:
|
|
||||||
Container(
|
|
||||||
child: Visibility(
|
|
||||||
visible: customer.visibleDetails,
|
|
||||||
child: Row(
|
|
||||||
children: <Widget>[
|
|
||||||
Text(customer.birthYear.toString() + " years, " + customer.sex),
|
|
||||||
new RaisedButton(
|
|
||||||
child: new Text('Modify'),
|
|
||||||
color: Color.fromRGBO(244, 122, 22, 0.9),
|
|
||||||
onPressed: () => {
|
|
||||||
|
|
||||||
},
|
|
||||||
),
|
|
||||||
new RaisedButton(
|
|
||||||
child: new Text('Select'),
|
|
||||||
color: Colors.blueGrey,
|
|
||||||
onPressed: () => {
|
|
||||||
Provider.of<ExerciseChangingViewModel>(context, listen: false).setCustomer(customer.customer),
|
|
||||||
Navigator.pop(context)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () { setState( () {
|
|
||||||
customer.visibleDetails = customer.visibleDetails ? false : true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
|
|
||||||
|
|
||||||
class CustomPicker extends CommonPickerModel {
|
|
||||||
String digits(int value, int length) {
|
|
||||||
return '$value'.padLeft(length, "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomPicker({DateTime currentTime, LocaleType locale}) : super(locale: locale) {
|
|
||||||
this.currentTime = currentTime ?? DateTime.now();
|
|
||||||
this.setLeftIndex(this.currentTime.hour);
|
|
||||||
this.setMiddleIndex(this.currentTime.minute);
|
|
||||||
this.setRightIndex(this.currentTime.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String leftStringAtIndex(int index) {
|
|
||||||
if (index >= 0 && index < 24) {
|
|
||||||
return this.digits(index, 2);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String middleStringAtIndex(int index) {
|
|
||||||
if (index >= 0 && index < 60) {
|
|
||||||
return this.digits(index, 2);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String rightStringAtIndex(int index) {
|
|
||||||
if (index >= 0 && index < 60) {
|
|
||||||
return this.digits(index, 2);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String leftDivider() {
|
|
||||||
return "|";
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String rightDivider() {
|
|
||||||
return "|";
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<int> layoutProportions() {
|
|
||||||
return [1, 2, 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
DateTime finalTime() {
|
|
||||||
return currentTime.isUtc
|
|
||||||
? DateTime.utc(currentTime.year, currentTime.month, currentTime.day,
|
|
||||||
this.currentLeftIndex(), this.currentMiddleIndex(), this.currentRightIndex())
|
|
||||||
: DateTime(currentTime.year, currentTime.month, currentTime.day, this.currentLeftIndex(),
|
|
||||||
this.currentMiddleIndex(), this.currentRightIndex());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
import 'package:aitrainer_app/viewmodel/exercise_changing_view_model.dart';
|
|
||||||
import 'package:aitrainer_app/viewmodel/exercise_type_view_model.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class ExerciseTypeListWidget extends StatefulWidget {
|
|
||||||
final List<ExerciseTypeViewModel> exerciseTypes;
|
|
||||||
ExerciseTypeListWidget({this.exerciseTypes});
|
|
||||||
|
|
||||||
@override
|
|
||||||
_ExerciseTypeListWidgetState createState() => _ExerciseTypeListWidgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ExerciseTypeListWidgetState extends State<ExerciseTypeListWidget> {
|
|
||||||
//static const routeName = '/exercise_type_list';
|
|
||||||
bool visible = false;
|
|
||||||
|
|
||||||
// Push the page and remove everything else
|
|
||||||
navigateToPage(BuildContext context, String page) {
|
|
||||||
Navigator.of(context).pushNamedAndRemoveUntil(page, (Route<dynamic> route) => false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
|
|
||||||
return ListView.builder(
|
|
||||||
itemCount: widget.exerciseTypes.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
|
|
||||||
final exerciseType = widget.exerciseTypes[index];
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
contentPadding: EdgeInsets.all(10),
|
|
||||||
leading: Icon(Icons.directions_run),
|
|
||||||
title: Text(exerciseType.name),
|
|
||||||
subtitle:
|
|
||||||
Container(
|
|
||||||
child: Visibility(
|
|
||||||
visible: exerciseType.visible,
|
|
||||||
child: Column(
|
|
||||||
children: <Widget>[
|
|
||||||
Text(exerciseType.description),
|
|
||||||
new RaisedButton(
|
|
||||||
child: new Text('Modify'),
|
|
||||||
color: Color.fromRGBO(244, 122, 22, 0.9),
|
|
||||||
onPressed: () => {
|
|
||||||
Navigator.pushNamed(
|
|
||||||
context,
|
|
||||||
'exerciseTypeModifyPage',
|
|
||||||
arguments: exerciseType
|
|
||||||
)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
new RaisedButton(
|
|
||||||
child: new Text('Select'),
|
|
||||||
color: Colors.blueGrey,
|
|
||||||
onPressed: () => {
|
|
||||||
Navigator.pop(context),
|
|
||||||
Provider.of<ExerciseChangingViewModel>(context, listen: false).setExerciseType(exerciseType.exerciseType),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () { setState( () {
|
|
||||||
exerciseType.visible = true;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,17 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/session/session_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/view/login.dart';
|
||||||
import 'package:aitrainer_app/view/menu_page.dart';
|
import 'package:aitrainer_app/view/menu_page.dart';
|
||||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
import 'package:aitrainer_app/view/registration.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'bottom_nav.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'nav_drawer.dart';
|
import 'loading.dart';
|
||||||
|
|
||||||
|
|
||||||
class AitrainerHome extends StatefulWidget {
|
class AitrainerHome extends StatefulWidget {
|
||||||
_HomePageState _state;
|
_HomePageState _state;
|
||||||
@ -15,10 +20,6 @@ class AitrainerHome extends StatefulWidget {
|
|||||||
_state = new _HomePageState();
|
_state = new _HomePageState();
|
||||||
return _state;
|
return _state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void callback() {
|
|
||||||
_state.setLangNoContext();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HomePageState extends State<AitrainerHome> {
|
class _HomePageState extends State<AitrainerHome> {
|
||||||
@ -28,30 +29,61 @@ class _HomePageState extends State<AitrainerHome> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
/// We require the initializers to run after the loading screen is rendered
|
||||||
Widget build(BuildContext context) {
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
MenuPage menu = MenuPage();
|
runDelayedEvent();
|
||||||
BottomNavigator bottomNav = BottomNavigator();
|
|
||||||
return Scaffold(
|
|
||||||
key: _scaffoldKey,
|
|
||||||
drawer: NavDrawer(),
|
|
||||||
body:Container(
|
|
||||||
child: MenuPage(parent: 0),
|
|
||||||
),
|
|
||||||
bottomNavigationBar: bottomNav.buildBottomNavigator(context, widget._state)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLangNoContext() {
|
|
||||||
print("--- Callback ");
|
|
||||||
setState(() {
|
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
|
||||||
AppLocalizations.of(context).setLocale(appLanguage.appLocal);
|
|
||||||
AppLocalizations.of(context).load();
|
|
||||||
print("--- Lang for context reloaded");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future runDelayedEvent() async {
|
||||||
|
await Future.delayed(Duration(seconds: 3), () async {
|
||||||
|
if ( context != null) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
SessionBloc sessionBloc = BlocProvider.of<SessionBloc>(context);
|
||||||
|
if (sessionBloc.state != SessionReady()) {
|
||||||
|
sessionBloc.add(SessionStart());
|
||||||
|
// ignore: close_sinks
|
||||||
|
SettingsBloc settingsBloc = BlocProvider.of<SettingsBloc>(context);
|
||||||
|
settingsBloc.loadLang();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
body: Container(
|
||||||
|
child: BlocConsumer<SessionBloc, SessionState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if ( state is SessionFailure) {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is SessionInitial) {
|
||||||
|
return LoadingScreenMain();
|
||||||
|
} else if (state is SessionLoading) {
|
||||||
|
print("loading");
|
||||||
|
return LoadingScreenMain();
|
||||||
|
} else if (state is SessionReady) {
|
||||||
|
print("ready");
|
||||||
|
if (Auth().startPage == 'login') {
|
||||||
|
return LoginPage();
|
||||||
|
} else if (Auth().startPage == 'registration') {
|
||||||
|
return RegistrationPage();
|
||||||
|
} else {
|
||||||
|
return MenuPage(parent: 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("else");
|
||||||
|
return MenuPage(parent: 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
),
|
||||||
|
//bottomNavigationBar: BottomNavigator(bottomNavIndex: 0),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,7 @@
|
|||||||
import 'package:aitrainer_app/util/message_state.dart';
|
|
||||||
import 'package:aitrainer_app/util/session.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/home.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:aitrainer_app/util/loading_screen.dart';
|
|
||||||
|
|
||||||
class LoadingScreenMain extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
LoadingScreenMainState createState() => LoadingScreenMainState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class LoadingScreenMainState extends State<LoadingScreenMain> {
|
|
||||||
|
|
||||||
|
class LoadingScreenMain extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Image _backgroundImage = Image.asset('asset/image/WT01_loading_layers.png',
|
Image _backgroundImage = Image.asset('asset/image/WT01_loading_layers.png',
|
||||||
@ -20,34 +10,60 @@ class LoadingScreenMainState extends State<LoadingScreenMain> {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
);
|
);
|
||||||
dynamic _timer = <dynamic>[TimeMessages.timer];
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: LoadingScreen(
|
backgroundColor: Colors.white,
|
||||||
initializers: _timer,
|
body: new InkWell(
|
||||||
navigateToWidget: AitrainerHome(),
|
child: new Stack(
|
||||||
loaderColor: Colors.yellow,
|
fit: StackFit.expand,
|
||||||
image: _backgroundImage,
|
children: <Widget>[
|
||||||
backgroundColor: Colors.black,
|
/// Paint the area where the inner widgets are loaded with the
|
||||||
styleTextUnderTheLoader: TextStyle(
|
/// background to keep consistency with the screen background
|
||||||
fontSize: 14.0,
|
new Container(
|
||||||
fontWeight: FontWeight.bold,
|
decoration: BoxDecoration(color: Colors.white),
|
||||||
color: Colors.lightGreenAccent),
|
),
|
||||||
)
|
/// Render the background image
|
||||||
|
new Container(
|
||||||
|
child: _backgroundImage,
|
||||||
|
),
|
||||||
|
/// Render the Title widget, loader and messages below each other
|
||||||
|
new Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
new Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: new Container(
|
||||||
|
child: new Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
new Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 30.0),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 1,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
/// Loader Animation Widget
|
||||||
|
CircularProgressIndicator(
|
||||||
|
valueColor: new AlwaysStoppedAnimation<Color>(
|
||||||
|
Colors.lightGreenAccent),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 20.0),
|
||||||
|
),
|
||||||
|
//Text(getMessage, style: widget.styleTextUnderTheLoader),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class TimeMessages {
|
|
||||||
static Future timer(MessageState state, Function callback) async {
|
|
||||||
//while (true) {
|
|
||||||
await Future.delayed(Duration(seconds: 2), () {
|
|
||||||
state.setMessage = DateTime.now().toIso8601String();
|
|
||||||
print("---- TimeMessages initializer");
|
|
||||||
Session session = Session();
|
|
||||||
session.fetchSessionAndNavigate(callback);
|
|
||||||
});
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
136
lib/widgets/menu_page_widget.dart
Normal file
136
lib/widgets/menu_page_widget.dart
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/auth.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class MenuPageWidget extends StatelessWidget {
|
||||||
|
int parent;
|
||||||
|
|
||||||
|
MenuPageWidget({this.parent});
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||||
|
|
||||||
|
return CustomScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
slivers: <Widget>[
|
||||||
|
buildMenuColumn(parent, context, menuBloc)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
SliverList buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc) {
|
||||||
|
final List<Widget> _columnChildren = List();
|
||||||
|
|
||||||
|
menuBloc.menuTreeRepository.getBranch(menuBloc.parent).forEach((treeName, value) {
|
||||||
|
WorkoutTree workoutTree = value as WorkoutTree;
|
||||||
|
_columnChildren.add(
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(top: 16.0),
|
||||||
|
child: Center(
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
|
overflow: Overflow.visible,
|
||||||
|
children: [
|
||||||
|
FlatButton(
|
||||||
|
child: _getButtonImage(workoutTree),
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
onPressed:() =>
|
||||||
|
{
|
||||||
|
print("Hi!, Menu clicked " + workoutTree.id.toString()),
|
||||||
|
if ( workoutTree.child == false ) {
|
||||||
|
menuBloc.add(MenuTreeDown(parent: workoutTree.id)),
|
||||||
|
|
||||||
|
} else {
|
||||||
|
menuBloc.add(MenuClickExercise(exerciseTypeId: workoutTree.id)),
|
||||||
|
if ( Auth().userLoggedIn == null ) {
|
||||||
|
Scaffold.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
content: Text(
|
||||||
|
AppLocalizations.of(context).translate('Please log in'),
|
||||||
|
style: TextStyle(color: Colors.white))
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
if ( workoutTree.exerciseType.name == "Custom") {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
'exerciseCustomPage',
|
||||||
|
arguments: workoutTree.exerciseType),
|
||||||
|
} else {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
'exerciseNewPage',
|
||||||
|
arguments: workoutTree.exerciseType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
child: Text(workoutTree.name, style: TextStyle(color: workoutTree.color, fontSize: workoutTree.fontSize, fontFamily: 'Arial', fontWeight: FontWeight.w900 ),),
|
||||||
|
highlightColor: workoutTree.color,
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
//_columnChildren.add(Spacer(flex: 3));
|
||||||
|
SliverList sliverList =
|
||||||
|
SliverList(
|
||||||
|
delegate: SliverChildListDelegate(
|
||||||
|
_columnChildren
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return sliverList;
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamic _getButtonImage(WorkoutTree workoutTree) {
|
||||||
|
dynamic image;
|
||||||
|
/*String url = workoutTree.imageName;
|
||||||
|
if ( workoutTree.imageName.startsWith("https") ) {
|
||||||
|
image = FadeInImage.assetNetwork(
|
||||||
|
placeholder: 'asset/image/dots.gif',
|
||||||
|
image: url,
|
||||||
|
height: 180,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
image = Image.asset(workoutTree.imageName, height: 180,);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
image = Image.asset(
|
||||||
|
workoutTree.imageName,
|
||||||
|
height: 180,
|
||||||
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
String url = Auth.mediaUrl + 'images/' + workoutTree.imageName.substring(11);
|
||||||
|
Widget image = FadeInImage.assetNetwork(
|
||||||
|
placeholder: 'asset/image/dots.gif',
|
||||||
|
image: url,
|
||||||
|
height: 180,
|
||||||
|
);
|
||||||
|
return image;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} on Exception catch(_) {
|
||||||
|
String url = Auth.mediaUrl + '/images/' + workoutTree.imageName;
|
||||||
|
image = FadeInImage.assetNetwork(
|
||||||
|
placeholder: 'asset/image/dots.gif',
|
||||||
|
image: url,
|
||||||
|
height: 180,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
}
|
@ -1,91 +0,0 @@
|
|||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
|
||||||
import 'package:aitrainer_app/model/auth.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class NavDrawer extends StatefulWidget {
|
|
||||||
|
|
||||||
@override
|
|
||||||
_NawDrawerWidget createState() => _NawDrawerWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _NawDrawerWidget extends State<NavDrawer> {
|
|
||||||
final Auth auth = Auth();
|
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
|
||||||
Locale _locale;
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Drawer(
|
|
||||||
child: ListView(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
children: <Widget>[
|
|
||||||
DrawerHeader(
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context).translate('Customers And Exercises'),
|
|
||||||
style: TextStyle(color: Colors.blue, fontSize: 25),
|
|
||||||
),
|
|
||||||
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.home),
|
|
||||||
title: Text( AppLocalizations.of(context).translate('Home')),
|
|
||||||
onTap: () => Navigator.of(context).pushNamed('home'),
|
|
||||||
),
|
|
||||||
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.people),
|
|
||||||
title: Text( AppLocalizations.of(context).translate('Customers')),
|
|
||||||
onTap: () => Navigator.of(context).pushNamed('customersPage'),
|
|
||||||
),
|
|
||||||
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.directions_run),
|
|
||||||
title: Text(AppLocalizations.of(context).translate('Exercises')),
|
|
||||||
onTap: () =>
|
|
||||||
Navigator.of(context).pushNamed('exerciseTypeListPage'),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.arrow_upward),
|
|
||||||
title: Text(AppLocalizations.of(context).translate("TRAINING!")),
|
|
||||||
onTap: () => Navigator.of(context).pushNamed('exerciseNewPage'),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.perm_identity),
|
|
||||||
title: Text(AppLocalizations.of(context).translate('Login')),
|
|
||||||
onTap: () => Navigator.of(context).pushNamed('login'),
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.cancel),
|
|
||||||
title: Text(AppLocalizations.of(context).translate('Logout')),
|
|
||||||
onTap: () =>
|
|
||||||
{
|
|
||||||
auth.logout(),
|
|
||||||
Navigator.of(context).pushNamed('home'),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
ListTile(
|
|
||||||
leading: Icon(Icons.hearing),
|
|
||||||
title: Text(AppLocalizations.of(context).translate('Change Language')),
|
|
||||||
onTap: () => _tapped(),
|
|
||||||
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _tapped() => {
|
|
||||||
/* _locale = Locale("hu"),
|
|
||||||
appLanguage.changeLanguage(_locale),
|
|
||||||
AppLocalizations.of(context).setLocale(_locale),
|
|
||||||
AppLocalizations.of(context).load() */
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
32
lib/widgets/splash.dart
Normal file
32
lib/widgets/splash.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class LoadingDialog extends StatelessWidget {
|
||||||
|
static void show(BuildContext context, {Key key}) => showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
useRootNavigator: false,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (_) => LoadingDialog(key: key),
|
||||||
|
).then((_) => FocusScope.of(context).requestFocus(FocusNode()));
|
||||||
|
|
||||||
|
static void hide(BuildContext context) => Navigator.pop(context);
|
||||||
|
|
||||||
|
LoadingDialog({Key key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return WillPopScope(
|
||||||
|
onWillPop: () async => false,
|
||||||
|
child: Center(
|
||||||
|
child: Card(
|
||||||
|
child: Container(
|
||||||
|
width: 80,
|
||||||
|
height: 80,
|
||||||
|
padding: EdgeInsets.all(12.0),
|
||||||
|
child: CircularProgressIndicator(backgroundColor: Colors.transparent,),
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
227
pubspec.lock
227
pubspec.lock
@ -7,14 +7,14 @@ packages:
|
|||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "7.0.0"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.39.12"
|
version: "0.39.17"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -35,7 +35,21 @@ packages:
|
|||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.2"
|
||||||
|
bloc:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: bloc
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "6.0.1"
|
||||||
|
bloc_test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: bloc_test
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.1"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -43,6 +57,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
characters:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: characters
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -50,13 +71,27 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.3"
|
version: "1.1.3"
|
||||||
|
cli_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_util
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
|
clock:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: clock
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.14.12"
|
version: "1.14.13"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -70,21 +105,21 @@ packages:
|
|||||||
name: coverage
|
name: coverage
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.11"
|
version: "0.14.0"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: crypto
|
name: crypto
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.5"
|
||||||
csslib:
|
csslib:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: csslib
|
name: csslib
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.16.1"
|
version: "0.16.2"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -92,13 +127,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.3"
|
||||||
datetime_picker_formfield:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: datetime_picker_formfield
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0"
|
|
||||||
devicelocale:
|
devicelocale:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -106,13 +134,27 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.1"
|
version: "0.3.1"
|
||||||
|
equatable:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: equatable
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.3"
|
||||||
|
fake_async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: fake_async
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.0"
|
||||||
file:
|
file:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: file
|
name: file
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.1.0"
|
version: "5.2.1"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -125,18 +167,39 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
flutter_datetime_picker:
|
flutter_bloc:
|
||||||
dependency: "direct dev"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_datetime_picker
|
name: flutter_bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.8"
|
version: "6.0.1"
|
||||||
flutter_driver:
|
flutter_driver:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_facebook_login:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_facebook_login
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.0"
|
||||||
|
flutter_form_bloc:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_form_bloc
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.19.0"
|
||||||
|
flutter_keyboard_visibility:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_keyboard_visibility
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.1"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -168,6 +231,18 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_web_plugins:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
form_bloc:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: form_bloc
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.19.1"
|
||||||
fuchsia_remote_debug_protocol:
|
fuchsia_remote_debug_protocol:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -214,7 +289,7 @@ packages:
|
|||||||
name: image
|
name: image
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.12"
|
version: "2.1.14"
|
||||||
intl:
|
intl:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -242,7 +317,7 @@ packages:
|
|||||||
name: json_rpc_2
|
name: json_rpc_2
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.2.1"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -256,7 +331,7 @@ packages:
|
|||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.6"
|
version: "0.12.8"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -270,7 +345,7 @@ packages:
|
|||||||
name: mime
|
name: mime
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.6+3"
|
version: "0.9.7"
|
||||||
mockito:
|
mockito:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -278,13 +353,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.1"
|
version: "4.1.1"
|
||||||
multi_server_socket:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: multi_server_socket
|
name: nested
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "0.0.4"
|
||||||
node_interop:
|
node_interop:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -319,7 +394,21 @@ packages:
|
|||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.6.4"
|
version: "1.7.0"
|
||||||
|
path_provider_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_linux
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.1+2"
|
||||||
|
path_provider_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.2"
|
||||||
pedantic:
|
pedantic:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -333,7 +422,7 @@ packages:
|
|||||||
name: petitparser
|
name: petitparser
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.0"
|
version: "3.0.4"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -361,14 +450,14 @@ packages:
|
|||||||
name: process
|
name: process
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.12"
|
version: "3.0.13"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: provider
|
name: provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.0"
|
version: "4.3.2"
|
||||||
pub_semver:
|
pub_semver:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -383,6 +472,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.3"
|
version: "2.1.3"
|
||||||
|
rxdart:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: rxdart
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.24.1"
|
||||||
sentry:
|
sentry:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -396,14 +492,42 @@ packages:
|
|||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.5.8"
|
||||||
|
shared_preferences_linux:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_linux
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.2+1"
|
||||||
|
shared_preferences_macos:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_macos
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.1+10"
|
||||||
|
shared_preferences_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_platform_interface
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
shared_preferences_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_web
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2+7"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shelf
|
name: shelf
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.7"
|
version: "0.7.8"
|
||||||
shelf_packages_handler:
|
shelf_packages_handler:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -451,13 +575,20 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.7.0"
|
version: "1.7.0"
|
||||||
|
spider_chart:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: spider_chart
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.5"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.3"
|
version: "1.9.5"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -492,28 +623,28 @@ packages:
|
|||||||
name: test
|
name: test
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.14.4"
|
version: "1.15.2"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.15"
|
version: "0.2.17"
|
||||||
test_core:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_core
|
name: test_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.4"
|
version: "0.3.10"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.6"
|
version: "1.2.0"
|
||||||
usage:
|
usage:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -521,6 +652,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.2"
|
version: "3.4.2"
|
||||||
|
uuid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.2.0"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -534,7 +672,7 @@ packages:
|
|||||||
name: vm_service
|
name: vm_service
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.0"
|
version: "4.2.0"
|
||||||
vm_service_client:
|
vm_service_client:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -570,13 +708,20 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.3"
|
version: "0.7.3"
|
||||||
|
xdg_directories:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xdg_directories
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.0"
|
||||||
xml:
|
xml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xml
|
name: xml
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.6.1"
|
version: "4.2.0"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -585,5 +730,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1"
|
version: "2.2.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.7.0 <3.0.0"
|
dart: ">=2.9.0-14.0.dev <3.0.0"
|
||||||
flutter: ">=1.12.13+hotfix.6 <2.0.0"
|
flutter: ">=1.16.0 <2.0.0"
|
||||||
|
17
pubspec.yaml
17
pubspec.yaml
@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 1.1.0+1
|
version: 1.1.0+12
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: ">=2.7.0 <3.0.0"
|
||||||
@ -31,6 +31,11 @@ dependencies:
|
|||||||
sentry: ^3.0.1
|
sentry: ^3.0.1
|
||||||
firebase_messaging: ^6.0.16
|
firebase_messaging: ^6.0.16
|
||||||
flutter_local_notifications: 1.1.1
|
flutter_local_notifications: 1.1.1
|
||||||
|
flutter_facebook_login: ^3.0.0
|
||||||
|
flutter_bloc: ^6.0.1
|
||||||
|
equatable: ^1.2.3
|
||||||
|
flutter_form_bloc: ^0.19.0
|
||||||
|
spider_chart: ^0.1.5
|
||||||
|
|
||||||
mockito: ^4.1.1
|
mockito: ^4.1.1
|
||||||
|
|
||||||
@ -41,15 +46,14 @@ dev_dependencies:
|
|||||||
flutter_driver:
|
flutter_driver:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
test: any
|
test: any
|
||||||
|
bloc_test: ^7.0.1
|
||||||
|
|
||||||
http: 0.12.1
|
http: 0.12.1
|
||||||
provider: ^3.2.0
|
provider: ^4.3.2
|
||||||
intl: 0.16.1
|
intl: 0.16.1
|
||||||
flutter_datetime_picker: ^1.3.8
|
shared_preferences: ^0.5.8
|
||||||
datetime_picker_formfield: ^1.0.0
|
|
||||||
shared_preferences: ^0.4.1
|
|
||||||
|
|
||||||
flutter_launcher_icons: "^0.7.3"
|
flutter_launcher_icons: ^0.7.5
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
android: "launcher_icon"
|
android: "launcher_icon"
|
||||||
@ -81,6 +85,7 @@ flutter:
|
|||||||
- asset/image/WT_gain_muscle.png
|
- asset/image/WT_gain_muscle.png
|
||||||
- asset/image/WT_weight_loss.png
|
- asset/image/WT_weight_loss.png
|
||||||
- asset/image/WT_welcome.png
|
- asset/image/WT_welcome.png
|
||||||
|
- asset/image/login_fb.png
|
||||||
- asset/menu/1.cardio.png
|
- asset/menu/1.cardio.png
|
||||||
- asset/menu/1.1.aerob.png
|
- asset/menu/1.1.aerob.png
|
||||||
- asset/menu/1.2.anaerob.png
|
- asset/menu/1.2.anaerob.png
|
||||||
|
79
test/account_bloc_test.dart
Normal file
79
test/account_bloc_test.dart
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
import 'package:test/test.dart' as test;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
class MockCustomerRepository extends Mock implements CustomerRepository {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
MockCustomerRepository customerRepository;
|
||||||
|
AccountBloc accountBloc;
|
||||||
|
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
test.setUp(() {
|
||||||
|
customerRepository = MockCustomerRepository();
|
||||||
|
accountBloc = AccountBloc(customerRepository: customerRepository);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.tearDown(() {
|
||||||
|
accountBloc?.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test.test('initial state is correct', () {
|
||||||
|
expect(accountBloc.state, AccountInitial());
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Account', () {
|
||||||
|
test.test(
|
||||||
|
'emits [loading, logged in] when the customer clicked login',
|
||||||
|
() {
|
||||||
|
final expectedResponse = [
|
||||||
|
AccountLoading(),
|
||||||
|
AccountLoggedIn(),
|
||||||
|
];
|
||||||
|
|
||||||
|
//verify(accountBloc.customerRepository.customer == null);
|
||||||
|
|
||||||
|
expectLater(
|
||||||
|
accountBloc, emitsInOrder(expectedResponse),
|
||||||
|
);
|
||||||
|
|
||||||
|
accountBloc.add(AccountLogin());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.test(
|
||||||
|
'emits [loading, logged out] when the customer clicked logout',
|
||||||
|
() {
|
||||||
|
final expectedResponse = [
|
||||||
|
AccountLoading(),
|
||||||
|
AccountLoggedOut(),
|
||||||
|
];
|
||||||
|
|
||||||
|
expectLater(
|
||||||
|
accountBloc, emitsInOrder(expectedResponse),
|
||||||
|
);
|
||||||
|
|
||||||
|
accountBloc.add(AccountLogout());
|
||||||
|
});
|
||||||
|
|
||||||
|
test.test(
|
||||||
|
'emits [loading, logged out] when the customer data changed',
|
||||||
|
() {
|
||||||
|
final expectedResponse = [
|
||||||
|
AccountLoading(),
|
||||||
|
AccountReady(),
|
||||||
|
];
|
||||||
|
|
||||||
|
expectLater(
|
||||||
|
accountBloc, emitsInOrder(expectedResponse),
|
||||||
|
);
|
||||||
|
|
||||||
|
accountBloc.add(AccountChangeCustomer());
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
// This is a basic Flutter widget test.
|
|
||||||
//
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
|
||||||
// utility that Flutter provides. For example, you can send tap and scroll
|
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
|
|
||||||
import 'package:aitrainer_app/main.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
|
||||||
// Build our app and trigger a frame.
|
|
||||||
await tester.pumpWidget(AitrainerApp());
|
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
|
||||||
expect(find.text('0'), findsOneWidget);
|
|
||||||
expect(find.text('1'), findsNothing);
|
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
|
||||||
expect(find.text('0'), findsNothing);
|
|
||||||
expect(find.text('1'), findsOneWidget);
|
|
||||||
});
|
|
||||||
}
|
|
107
test/widget_test.login.dart
Normal file
107
test/widget_test.login.dart
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// This is a basic Flutter widget test.
|
||||||
|
//
|
||||||
|
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||||
|
// utility that Flutter provides. For example, you can send tap and scroll
|
||||||
|
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||||
|
// tree, read text, and verify that the values of widget properties are correct.
|
||||||
|
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/bloc/login_form_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/library_keys.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/user.dart';
|
||||||
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
import 'package:aitrainer_app/view/login.dart';
|
||||||
|
import 'package:bloc_test/bloc_test.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class MockUserRepository extends Mock implements UserRepository {
|
||||||
|
final User user = User();
|
||||||
|
|
||||||
|
setEmail(String email) {
|
||||||
|
this.user.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPassword(String password) {
|
||||||
|
this.user.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getUser() async {
|
||||||
|
if ( this.user.email == "sw@andio.biz" && this.user.password == "PalKataPeter1") {
|
||||||
|
//OK
|
||||||
|
} else {
|
||||||
|
throw new Exception("Customer does not exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class MockLoginBloc extends MockBloc<FormBlocEvent>
|
||||||
|
implements LoginFormBloc {}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('LoginScreen', () {
|
||||||
|
MockLoginBloc loginBloc;
|
||||||
|
MockUserRepository userRepository;
|
||||||
|
Widget loginWidget;
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
loginBloc = MockLoginBloc();
|
||||||
|
userRepository = MockUserRepository();
|
||||||
|
|
||||||
|
loginWidget =
|
||||||
|
MaterialApp(
|
||||||
|
home: LoginPage(),
|
||||||
|
localizationsDelegates: [
|
||||||
|
AppLocalizationsDelegate(isTest: true),
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
|
routes: {
|
||||||
|
'home': (context) => LoginPage(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() {
|
||||||
|
loginBloc.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Display login page', (WidgetTester tester) async {
|
||||||
|
// Build our app and trigger a frame.
|
||||||
|
await tester.pumpWidget(loginWidget);
|
||||||
|
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.byKey(LibraryKeys.loginEmailField), findsOneWidget);
|
||||||
|
expect(find.byKey(LibraryKeys.loginPasswordField), findsOneWidget);
|
||||||
|
expect(find.byKey(LibraryKeys.loginOKButton), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Add zero length email', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(loginWidget);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
var emailField = find.byKey(LibraryKeys.loginEmailField);
|
||||||
|
var pwdField = find.byKey(LibraryKeys.loginPasswordField);
|
||||||
|
var okButton = find.byKey(LibraryKeys.loginOKButton);
|
||||||
|
expect(emailField, findsOneWidget);
|
||||||
|
expect(pwdField, findsOneWidget);
|
||||||
|
expect(okButton, findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(emailField);
|
||||||
|
await tester.enterText(emailField, "sw");
|
||||||
|
await tester.enterText(pwdField, "123");
|
||||||
|
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(okButton);
|
||||||
|
await tester.pump(const Duration(milliseconds: 500)); // add delay
|
||||||
|
final emailErrorFinder = find.text(Common.EMAIL_ERROR);
|
||||||
|
expect(emailErrorFinder, findsOneWidget);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
11
test_driver/app.dart
Normal file
11
test_driver/app.dart
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import 'package:flutter_driver/driver_extension.dart';
|
||||||
|
import 'package:aitrainer_app/main.dart' as app;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// This line enables the extension.
|
||||||
|
enableFlutterDriverExtension();
|
||||||
|
|
||||||
|
// Call the `main()` function of the app, or call `runApp` with
|
||||||
|
// any widget you are interested in testing.
|
||||||
|
app.main();
|
||||||
|
}
|
9
test_driver/app_test.dart
Normal file
9
test_driver/app_test.dart
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Imports the Flutter Driver API.
|
||||||
|
import 'package:flutter_driver/flutter_driver.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('Login App', () {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user