Merge ssh://git.aitrainer.app:6622/bossanyit/aitrainer_app
This commit is contained in:
commit
4ee16c9fa6
BIN
asset/image/lock.png
Normal file
BIN
asset/image/lock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
19
i18n/en.json
19
i18n/en.json
@ -52,6 +52,7 @@
|
|||||||
"Sizes": "Sizes",
|
"Sizes": "Sizes",
|
||||||
"Save Exercise": "Save Exercise of:",
|
"Save Exercise": "Save Exercise of:",
|
||||||
"Save": "Save",
|
"Save": "Save",
|
||||||
|
"Delete": "Delete",
|
||||||
|
|
||||||
"Name": "Name",
|
"Name": "Name",
|
||||||
"Exercise": "Exercise",
|
"Exercise": "Exercise",
|
||||||
@ -117,5 +118,21 @@
|
|||||||
"3rd Control Exercise:": "3rd Control Exercise:",
|
"3rd Control Exercise:": "3rd Control Exercise:",
|
||||||
|
|
||||||
"My Development":"My Development",
|
"My Development":"My Development",
|
||||||
"My Training Plan":"My Training Plan"
|
"My Training Plan":"My Training Plan",
|
||||||
|
|
||||||
|
"Please add an exercise plan": "Please add an exercise plan",
|
||||||
|
"Serie": "Serie",
|
||||||
|
"Repeats": "Repeats",
|
||||||
|
"Save The Exercise To The Exercise Plan": "Save The Exercise To The Exercise Plan",
|
||||||
|
"The number of the serie done with":"The number of the serie done with",
|
||||||
|
"The number of the repeats of one serie":"The number of the repeats of one serie",
|
||||||
|
|
||||||
|
"1. Chest": "1. Chest",
|
||||||
|
"2. Biceps": "2. Biceps",
|
||||||
|
"3. Triceps": "3. Triceps",
|
||||||
|
"4. Back": "4. Back",
|
||||||
|
"5. Shoulders": "5. Shoulders",
|
||||||
|
"6. Core": "6. Core",
|
||||||
|
"7. Thigh": "7. Thigh",
|
||||||
|
"8. Calf": "8. Calf"
|
||||||
}
|
}
|
20
i18n/hu.json
20
i18n/hu.json
@ -52,6 +52,7 @@
|
|||||||
"Sizes": "Méretek",
|
"Sizes": "Méretek",
|
||||||
"Save Exercise": "Gyakorlat mentése:",
|
"Save Exercise": "Gyakorlat mentése:",
|
||||||
"Save": "Mentés",
|
"Save": "Mentés",
|
||||||
|
"Delete": "Törlés",
|
||||||
"The number of the exercise": "Írd be a gyakorlat számát",
|
"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",
|
"The number of the exercise done with": "Írd be, mennyivel csináltad a gyakorlatot",
|
||||||
|
|
||||||
@ -116,5 +117,22 @@
|
|||||||
"3rd Control Exercise:": "3. kontrollgyakorlat:",
|
"3rd Control Exercise:": "3. kontrollgyakorlat:",
|
||||||
|
|
||||||
"My Development":"Fejlődésem",
|
"My Development":"Fejlődésem",
|
||||||
"My Training Plan":"Edzéstervem"
|
"My Training Plan":"Edzéstervem",
|
||||||
|
|
||||||
|
"Please add an exercise plan": "Kérlek add meg az edzéstervet a gyakorlathoz",
|
||||||
|
|
||||||
|
"Serie": "Széria",
|
||||||
|
"Repeats": "Ismétlés",
|
||||||
|
"Save The Exercise To The Exercise Plan": "Gyakorlat mentése az edzéstervhez",
|
||||||
|
"The number of the serie done with":"Mennyi szériát csinálsz",
|
||||||
|
"The number of the repeats of one serie":"Hány ismétlést csinálsz egy gyakorlaton belül",
|
||||||
|
|
||||||
|
"1. Chest": "1. Mell",
|
||||||
|
"2. Biceps": "2. Bicepsz",
|
||||||
|
"3. Triceps": "3. Tricepsz",
|
||||||
|
"4. Back": "4. Hát",
|
||||||
|
"5. Shoulders": "5. Váll",
|
||||||
|
"6. Core": "6. Has",
|
||||||
|
"7. Thigh": "7. Comb",
|
||||||
|
"8. Calf": "8. Vádli"
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
@ -16,10 +16,10 @@
|
|||||||
<viewControllerLayoutGuide type="bottom" id="wCe-IQ-FAo"/>
|
<viewControllerLayoutGuide type="bottom" id="wCe-IQ-FAo"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" autoresizesSubviews="NO" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="Ze5-6b-2t3">
|
<view key="view" autoresizesSubviews="NO" contentMode="scaleAspectFit" translatesAutoresizingMaskIntoConstraints="NO" id="Ze5-6b-2t3">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="878"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="825"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleAspectFit" ambiguous="YES" image="LaunchImage" adjustsImageSizeForAccessibilityContentSizeCategory="YES" id="YRO-k0-Ey4">
|
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleAspectFit" ambiguous="YES" image="LaunchImage" adjustsImageSizeForAccessibilityContentSizeCategory="YES" id="YRO-k0-Ey4">
|
||||||
<rect key="frame" x="-1" y="0.0" width="414" height="878"/>
|
<rect key="frame" x="-26" y="-92" width="505" height="1009"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
||||||
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default"/>
|
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default"/>
|
||||||
</imageView>
|
</imageView>
|
||||||
|
@ -3,6 +3,7 @@ import 'dart:async';
|
|||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/customer.dart';
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
@ -13,6 +14,7 @@ part 'account_state.dart';
|
|||||||
class AccountBloc extends Bloc<AccountEvent, AccountState> {
|
class AccountBloc extends Bloc<AccountEvent, AccountState> {
|
||||||
final CustomerRepository customerRepository;
|
final CustomerRepository customerRepository;
|
||||||
bool loggedIn = false;
|
bool loggedIn = false;
|
||||||
|
int traineeId = 0;
|
||||||
AccountBloc({this.customerRepository}) : super(AccountInitial()) {
|
AccountBloc({this.customerRepository}) : super(AccountInitial()) {
|
||||||
if ( Cache().userLoggedIn != null ) {
|
if ( Cache().userLoggedIn != null ) {
|
||||||
customerRepository.customer = Cache().userLoggedIn;
|
customerRepository.customer = Cache().userLoggedIn;
|
||||||
@ -36,8 +38,21 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
|
|||||||
} else if (event is AccountLogout) {
|
} else if (event is AccountLogout) {
|
||||||
await Cache().logout();
|
await Cache().logout();
|
||||||
customerRepository.customer = null;
|
customerRepository.customer = null;
|
||||||
|
customerRepository.emptyTrainees();
|
||||||
loggedIn = false;
|
loggedIn = false;
|
||||||
yield AccountLoggedOut();
|
yield AccountLoggedOut();
|
||||||
|
} else if ( event is AccountGetTrainees) {
|
||||||
|
yield AccountLoading();
|
||||||
|
await customerRepository.getTrainees();
|
||||||
|
yield AccountReady();
|
||||||
|
} else if ( event is AccountSelectTrainee ) {
|
||||||
|
yield AccountLoading();
|
||||||
|
customerRepository.setTrainee(event.traineeId);
|
||||||
|
Cache().setTrainee(customerRepository.getTraineeById(event.traineeId));
|
||||||
|
ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
|
await exerciseRepository.getExercisesByCustomer(event.traineeId);
|
||||||
|
this.traineeId = event.traineeId;
|
||||||
|
yield AccountReady();
|
||||||
}
|
}
|
||||||
} on Exception catch(e) {
|
} on Exception catch(e) {
|
||||||
yield AccountError(message: e.toString());
|
yield AccountError(message: e.toString());
|
||||||
|
@ -43,4 +43,16 @@ class AccountLogInFinished extends AccountEvent {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [customer];
|
List<Object> get props => [customer];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountGetTrainees extends AccountEvent {
|
||||||
|
const AccountGetTrainees();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccountSelectTrainee extends AccountEvent {
|
||||||
|
final int traineeId;
|
||||||
|
const AccountSelectTrainee({this.traineeId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [traineeId];
|
||||||
}
|
}
|
81
lib/bloc/exercise_add_by_plan_bloc.dart
Normal file
81
lib/bloc/exercise_add_by_plan_bloc.dart
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class ExerciseAddByPlanFormBloc extends FormBloc<String, String> {
|
||||||
|
final ExerciseRepository exerciseRepository;
|
||||||
|
final ExercisePlanRepository exercisePlanRepository;
|
||||||
|
final WorkoutTree workoutTree;
|
||||||
|
final customerId;
|
||||||
|
Customer customer;
|
||||||
|
int step = 1;
|
||||||
|
int countSteps = 1;
|
||||||
|
|
||||||
|
final quantity1Field = TextFieldBloc(
|
||||||
|
);
|
||||||
|
|
||||||
|
final unitQuantity1Field = TextFieldBloc(
|
||||||
|
);
|
||||||
|
|
||||||
|
ExerciseAddByPlanFormBloc({this.exerciseRepository, this.exercisePlanRepository, this.customerId, this.workoutTree}) {
|
||||||
|
addFieldBlocs(fieldBlocs: [
|
||||||
|
quantity1Field,
|
||||||
|
unitQuantity1Field,
|
||||||
|
]);
|
||||||
|
|
||||||
|
quantity1Field.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exerciseRepository.setQuantity(current.valueToDouble);
|
||||||
|
});
|
||||||
|
|
||||||
|
unitQuantity1Field.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exerciseRepository.setUnitQuantity(unitQuantity1Field.valueToDouble);
|
||||||
|
});
|
||||||
|
|
||||||
|
exerciseRepository.exerciseType = workoutTree.exerciseType;
|
||||||
|
if ( Cache().userLoggedIn.customerId == customerId) {
|
||||||
|
customer = Cache().userLoggedIn;
|
||||||
|
} else if ( Cache().getTrainee().customerId == customerId) {
|
||||||
|
customer = Cache().getTrainee();
|
||||||
|
}
|
||||||
|
exercisePlanRepository.setActualPlanDetail(workoutTree.exerciseType);
|
||||||
|
exerciseRepository.customer = customer;
|
||||||
|
countSteps = exercisePlanRepository.actualPlanDetail.serie;
|
||||||
|
|
||||||
|
unitQuantity1Field.updateInitialValue(exercisePlanRepository.actualPlanDetail.weightEquation);
|
||||||
|
quantity1Field.updateInitialValue(exercisePlanRepository.actualPlanDetail.repeats.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSubmitting() async {
|
||||||
|
|
||||||
|
try {
|
||||||
|
emitLoading(progress: 30);
|
||||||
|
step++;
|
||||||
|
|
||||||
|
exerciseRepository.setUnitQuantity(unitQuantity1Field.valueToDouble);
|
||||||
|
exerciseRepository.setQuantity(quantity1Field.valueToDouble);
|
||||||
|
exerciseRepository.exercise.exercisePlanDetailId =
|
||||||
|
exercisePlanRepository.actualPlanDetail.exercisePlanDetailId;
|
||||||
|
exerciseRepository.exercise.unit = workoutTree.exerciseType.unit;
|
||||||
|
workoutTree.executed = true;
|
||||||
|
print("On Submitting Add Exercise By Plan " + exerciseRepository.exercise.toJson().toString());
|
||||||
|
await exerciseRepository.addExercise();
|
||||||
|
|
||||||
|
emitSuccess(canSubmitAgain: true);
|
||||||
|
} on Exception catch (ex) {
|
||||||
|
emitFailure(failureResponse: ex.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//@override
|
||||||
|
Future<void> close() {
|
||||||
|
quantity1Field.close();
|
||||||
|
unitQuantity1Field.close();
|
||||||
|
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
}
|
58
lib/bloc/exercise_by_plan/exercise_by_plan_bloc.dart
Normal file
58
lib/bloc/exercise_by_plan/exercise_by_plan_bloc.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.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 'exercise_by_plan_event.dart';
|
||||||
|
|
||||||
|
part 'exercise_by_plan_state.dart';
|
||||||
|
|
||||||
|
class ExerciseByPlanBloc extends Bloc<ExerciseByPlanEvent, ExerciseByPlanState> {
|
||||||
|
final ExerciseRepository exerciseRepository;
|
||||||
|
final MenuTreeRepository menuTreeRepository;
|
||||||
|
final ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
|
||||||
|
int customerId;
|
||||||
|
@override
|
||||||
|
ExerciseByPlanBloc({this.exerciseRepository, this.menuTreeRepository}) : super(ExerciseByPlanStateInitial());
|
||||||
|
|
||||||
|
Future<void> getData() async {
|
||||||
|
exercisePlanRepository.setCustomerId(customerId);
|
||||||
|
await exercisePlanRepository.getLastExercisePlan();
|
||||||
|
await exercisePlanRepository.getExercisePlanDetails();
|
||||||
|
menuTreeRepository.sortedTree = null;
|
||||||
|
menuTreeRepository.sortByMuscleType();
|
||||||
|
|
||||||
|
menuTreeRepository.sortedTree.forEach((key, value) {
|
||||||
|
List<WorkoutTree> listWorkoutTree = value;
|
||||||
|
listWorkoutTree.forEach((workoutTree) {
|
||||||
|
workoutTree.selected = false;
|
||||||
|
if (exercisePlanRepository.exercisePlanDetails.length > 0) {
|
||||||
|
if (exercisePlanRepository.exercisePlanDetails[workoutTree.exerciseTypeId] != null) {
|
||||||
|
workoutTree.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<ExerciseByPlanState> mapEventToState(ExerciseByPlanEvent event) async* {
|
||||||
|
try {
|
||||||
|
if (event is ExerciseByPlanLoad) {
|
||||||
|
yield ExerciseByPlanLoading();
|
||||||
|
await this.getData();
|
||||||
|
yield ExerciseByPlanReady();
|
||||||
|
} else if (event is AddExerciseByPlanEvent) {
|
||||||
|
yield ExerciseByPlanLoading();
|
||||||
|
yield ExerciseByPlanReady();
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
yield ExerciseByPlanError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
lib/bloc/exercise_by_plan/exercise_by_plan_event.dart
Normal file
21
lib/bloc/exercise_by_plan/exercise_by_plan_event.dart
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
part of 'exercise_by_plan_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class ExerciseByPlanEvent extends Equatable {
|
||||||
|
const ExerciseByPlanEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddExerciseByPlanEvent extends ExerciseByPlanEvent {
|
||||||
|
final ExerciseType exerciseType;
|
||||||
|
const AddExerciseByPlanEvent({this.exerciseType});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [exerciseType];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExerciseByPlanLoad extends ExerciseByPlanEvent {
|
||||||
|
const ExerciseByPlanLoad();
|
||||||
|
}
|
31
lib/bloc/exercise_by_plan/exercise_by_plan_state.dart
Normal file
31
lib/bloc/exercise_by_plan/exercise_by_plan_state.dart
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
part of 'exercise_by_plan_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class ExerciseByPlanState extends Equatable {
|
||||||
|
const ExerciseByPlanState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExerciseByPlanStateInitial extends ExerciseByPlanState {
|
||||||
|
const ExerciseByPlanStateInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExerciseByPlanLoading extends ExerciseByPlanState {
|
||||||
|
const ExerciseByPlanLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
// updated screen
|
||||||
|
class ExerciseByPlanReady extends ExerciseByPlanState {
|
||||||
|
const ExerciseByPlanReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
// error splash screen
|
||||||
|
class ExerciseByPlanError extends ExerciseByPlanState {
|
||||||
|
final String message;
|
||||||
|
const ExerciseByPlanError({this.message});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
89
lib/bloc/exercise_plan/exercise_plan_bloc.dart
Normal file
89
lib/bloc/exercise_plan/exercise_plan_bloc.dart
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.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 'exercise_plan_event.dart';
|
||||||
|
|
||||||
|
part 'exercise_plan_state.dart';
|
||||||
|
|
||||||
|
class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
||||||
|
final MenuTreeRepository menuTreeRepository;
|
||||||
|
final ExerciseRepository exerciseRepository;
|
||||||
|
final ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
|
||||||
|
int customerId;
|
||||||
|
|
||||||
|
ExercisePlanBloc({this.exerciseRepository, this.menuTreeRepository}) : super(ExercisePlanInitial());
|
||||||
|
|
||||||
|
Future<void> getData() async {
|
||||||
|
exercisePlanRepository.setCustomerId(customerId);
|
||||||
|
await exercisePlanRepository.getLastExercisePlan();
|
||||||
|
await exercisePlanRepository.getExercisePlanDetails();
|
||||||
|
menuTreeRepository.sortedTree = null;
|
||||||
|
menuTreeRepository.sortByMuscleType();
|
||||||
|
|
||||||
|
menuTreeRepository.sortedTree.forEach((key, value) {
|
||||||
|
List<WorkoutTree> listWorkoutTree = value;
|
||||||
|
listWorkoutTree.forEach((workoutTree) {
|
||||||
|
workoutTree.selected = false;
|
||||||
|
if (exercisePlanRepository.exercisePlanDetails.length > 0) {
|
||||||
|
if (exercisePlanRepository.exercisePlanDetails[workoutTree.exerciseTypeId] != null) {
|
||||||
|
//print("bingo");
|
||||||
|
workoutTree.selected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<ExercisePlanState> mapEventToState(ExercisePlanEvent event) async* {
|
||||||
|
try {
|
||||||
|
if (event is ExercisePlanLoad) {
|
||||||
|
yield ExercisePlanLoading();
|
||||||
|
await this.getData();
|
||||||
|
yield ExercisePlanReady();
|
||||||
|
}
|
||||||
|
if (event is ExercisePlanUpdate) {
|
||||||
|
yield ExercisePlanLoading();
|
||||||
|
WorkoutTree workoutTree = event.workoutTree;
|
||||||
|
if (workoutTree != null) {
|
||||||
|
exercisePlanRepository.addExerciseTypeToPlan(workoutTree.exerciseType);
|
||||||
|
workoutTree.selected = true;
|
||||||
|
}
|
||||||
|
yield ExercisePlanReady();
|
||||||
|
} else if (event is ExercisePlanRemoveExercise) {
|
||||||
|
yield ExercisePlanLoading();
|
||||||
|
ExercisePlanDetail planDetail = event.exercisePlanDetail;
|
||||||
|
exercisePlanRepository.removeExerciseTypeFromPlan(planDetail.exerciseType);
|
||||||
|
this.menuTreeRepository.sortedTree.forEach((key, value) {
|
||||||
|
List<WorkoutTree> listTreeItem = value;
|
||||||
|
listTreeItem.forEach((element) {
|
||||||
|
if ( element.exerciseType.exerciseTypeId == planDetail.exerciseTypeId) {
|
||||||
|
element.selected = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
yield ExercisePlanReady();
|
||||||
|
} else if (event is ExercisePlanUpdateExercise) {
|
||||||
|
yield ExercisePlanReady();
|
||||||
|
} else if (event is ExercisePlanSave) {
|
||||||
|
if (exercisePlanRepository.getExercisePlanDetailSize() == 0) {
|
||||||
|
throw Exception("Please select an exercise");
|
||||||
|
} else {
|
||||||
|
yield ExercisePlanLoading();
|
||||||
|
exercisePlanRepository.saveExercisePlan();
|
||||||
|
yield ExercisePlanReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
yield ExercisePlanError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
lib/bloc/exercise_plan/exercise_plan_event.dart
Normal file
49
lib/bloc/exercise_plan/exercise_plan_event.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
part of 'exercise_plan_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class ExercisePlanEvent extends Equatable {
|
||||||
|
const ExercisePlanEvent();
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExercisePlanLoad extends ExercisePlanEvent {
|
||||||
|
const ExercisePlanLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExercisePlanUpdate extends ExercisePlanEvent {
|
||||||
|
final WorkoutTree workoutTree;
|
||||||
|
const ExercisePlanUpdate({this.workoutTree});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [workoutTree];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExercisePlanAddExercise extends ExercisePlanEvent {
|
||||||
|
final ExerciseType exerciseType;
|
||||||
|
const ExercisePlanAddExercise({this.exerciseType});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [exerciseType];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExercisePlanRemoveExercise extends ExercisePlanEvent {
|
||||||
|
final ExercisePlanDetail exercisePlanDetail;
|
||||||
|
const ExercisePlanRemoveExercise({this.exercisePlanDetail});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [exercisePlanDetail];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExercisePlanUpdateExercise extends ExercisePlanEvent {
|
||||||
|
final ExercisePlanDetail exercisePlanDetail;
|
||||||
|
const ExercisePlanUpdateExercise({this.exercisePlanDetail});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [exercisePlanDetail];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExercisePlanSave extends ExercisePlanEvent {
|
||||||
|
const ExercisePlanSave();
|
||||||
|
}
|
||||||
|
|
37
lib/bloc/exercise_plan/exercise_plan_state.dart
Normal file
37
lib/bloc/exercise_plan/exercise_plan_state.dart
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
part of 'exercise_plan_bloc.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
abstract class ExercisePlanState extends Equatable{
|
||||||
|
const ExercisePlanState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the last saved exercise plan
|
||||||
|
class ExercisePlanInitial extends ExercisePlanState {
|
||||||
|
const ExercisePlanInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading screen
|
||||||
|
class ExercisePlanLoading extends ExercisePlanState {
|
||||||
|
const ExercisePlanLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
// updated screen
|
||||||
|
class ExercisePlanReady extends ExercisePlanState {
|
||||||
|
const ExercisePlanReady();
|
||||||
|
}
|
||||||
|
|
||||||
|
// error splash screen
|
||||||
|
class ExercisePlanError extends ExercisePlanState {
|
||||||
|
final String message;
|
||||||
|
const ExercisePlanError({this.message});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
94
lib/bloc/exercise_plan_custom_form.dart
Normal file
94
lib/bloc/exercise_plan_custom_form.dart
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class ExercisePlanCustomerFormBloc extends FormBloc<String, String> {
|
||||||
|
final ExercisePlanRepository exercisePlanRepository;
|
||||||
|
final ExercisePlanBloc planBloc;
|
||||||
|
final serieField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final quantityField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final weightField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final exerciseTypeField = TextFieldBloc(
|
||||||
|
validators: [
|
||||||
|
FieldBlocValidators.required,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
ExercisePlanCustomerFormBloc({this.exercisePlanRepository, this.planBloc}) {
|
||||||
|
addFieldBlocs(fieldBlocs: [
|
||||||
|
quantityField,
|
||||||
|
serieField,
|
||||||
|
weightField
|
||||||
|
]);
|
||||||
|
|
||||||
|
String repeatsInitial = exercisePlanRepository.actualPlanDetail != null &&
|
||||||
|
exercisePlanRepository.actualPlanDetail.repeats != null ?
|
||||||
|
exercisePlanRepository.actualPlanDetail.repeats.toString() : "12";
|
||||||
|
quantityField.updateInitialValue(repeatsInitial);
|
||||||
|
|
||||||
|
String serieInitial = exercisePlanRepository.actualPlanDetail != null &&
|
||||||
|
exercisePlanRepository.actualPlanDetail.serie != null ?
|
||||||
|
exercisePlanRepository.actualPlanDetail.serie.toString() : "3";
|
||||||
|
serieField.updateInitialValue(serieInitial);
|
||||||
|
|
||||||
|
String weightInitial = exercisePlanRepository.actualPlanDetail != null &&
|
||||||
|
exercisePlanRepository.actualPlanDetail.weightEquation != null ?
|
||||||
|
exercisePlanRepository.actualPlanDetail.weightEquation : "30";
|
||||||
|
weightField.updateInitialValue(weightInitial);
|
||||||
|
|
||||||
|
quantityField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exercisePlanRepository.actualPlanDetail.repeats = current.valueToInt;
|
||||||
|
});
|
||||||
|
serieField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exercisePlanRepository.actualPlanDetail.serie = current.valueToInt;
|
||||||
|
});
|
||||||
|
weightField.onValueChanges(onData: (previous, current) async* {
|
||||||
|
exercisePlanRepository.actualPlanDetail.weightEquation = current.value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onSubmitting() async {
|
||||||
|
print("On Submitting Custom Plan form");
|
||||||
|
try {
|
||||||
|
emitLoading(progress: 30);
|
||||||
|
// Emit either Loaded or Error
|
||||||
|
|
||||||
|
exercisePlanRepository.actualPlanDetail.repeats = quantityField.valueToInt;
|
||||||
|
exercisePlanRepository.actualPlanDetail.serie = serieField.valueToInt;
|
||||||
|
exercisePlanRepository.actualPlanDetail.weightEquation = weightField.value;
|
||||||
|
|
||||||
|
exercisePlanRepository.addToPlan();
|
||||||
|
planBloc.add(ExercisePlanUpdate());
|
||||||
|
|
||||||
|
emitSuccess(canSubmitAgain: false);
|
||||||
|
} on Exception catch (ex) {
|
||||||
|
emitFailure(failureResponse: ex.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//@override
|
||||||
|
Future<void> close() {
|
||||||
|
quantityField.close();
|
||||||
|
serieField.close();
|
||||||
|
weightField.close();
|
||||||
|
exerciseTypeField.close();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
}
|
@ -34,6 +34,10 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
|||||||
yield SettingsLoading();
|
yield SettingsLoading();
|
||||||
await _changeLang( event.language);
|
await _changeLang( event.language);
|
||||||
yield SettingsReady(_locale);
|
yield SettingsReady(_locale);
|
||||||
|
} else if ( event is SettingsGetLanguage) {
|
||||||
|
await AppLanguage().fetchLocale();
|
||||||
|
_locale = AppLanguage().appLocal;
|
||||||
|
yield SettingsReady(_locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,12 +54,13 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.language = lang;
|
this.language = lang;
|
||||||
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
|
appLanguage.changeLanguage(_locale);
|
||||||
await loadLang();
|
await loadLang();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadLang() async{
|
Future<void> loadLang() async{
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
print (" -- Loading lang $_locale");
|
||||||
appLanguage.changeLanguage(_locale);
|
|
||||||
if ( context != null ) {
|
if ( context != null ) {
|
||||||
AppLocalizations.of(context).setLocale(_locale);
|
AppLocalizations.of(context).setLocale(_locale);
|
||||||
await AppLocalizations.of(context).load();
|
await AppLocalizations.of(context).load();
|
||||||
|
@ -11,3 +11,7 @@ class SettingsChangeLanguage extends SettingsEvent {
|
|||||||
final String language;
|
final String language;
|
||||||
const SettingsChangeLanguage({this.language});
|
const SettingsChangeLanguage({this.language});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SettingsGetLanguage extends SettingsEvent {
|
||||||
|
const SettingsGetLanguage();
|
||||||
|
}
|
||||||
|
@ -20,19 +20,24 @@ class AppLanguage{
|
|||||||
|
|
||||||
Future<void> fetchLocale() async {
|
Future<void> fetchLocale() async {
|
||||||
var prefs = await SharedPreferences.getInstance();
|
var prefs = await SharedPreferences.getInstance();
|
||||||
if (prefs.getString('language_code') == null) {
|
String langCode = prefs.getString('language_code');
|
||||||
|
print(" ---- lang code $langCode");
|
||||||
|
if ( langCode == null) {
|
||||||
_appLocale = Locale('en');
|
_appLocale = Locale('en');
|
||||||
} else {
|
} else {
|
||||||
_appLocale = Locale(prefs.getString('language_code'));
|
_appLocale = Locale(langCode);
|
||||||
}
|
}
|
||||||
print(" ---- Fetched lang: " + _appLocale.toString());
|
print(" ---- Fetched lang: " + _appLocale.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
getLocale(SharedPreferences prefs) {
|
getLocale(SharedPreferences prefs) {
|
||||||
if (prefs.getString('language_code') == null) {
|
String langCode = prefs.getString('language_code');
|
||||||
|
if ( langCode == null) {
|
||||||
_appLocale = Locale('en');
|
_appLocale = Locale('en');
|
||||||
}
|
}
|
||||||
_appLocale = Locale(prefs.getString('language_code'));
|
_appLocale = Locale(langCode);
|
||||||
|
print(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ class AppLocalizations {
|
|||||||
|
|
||||||
Future<bool> load() async {
|
Future<bool> load() async {
|
||||||
// Load the language JSON file from the "lang" folder
|
// Load the language JSON file from the "lang" folder
|
||||||
|
print(" -- load language pieces " + locale.languageCode);
|
||||||
String jsonString =
|
String jsonString =
|
||||||
await rootBundle.loadString('i18n/${locale.languageCode}.json');
|
await rootBundle.loadString('i18n/${locale.languageCode}.json');
|
||||||
Map<String, dynamic> jsonMap = json.decode(jsonString);
|
Map<String, dynamic> jsonMap = json.decode(jsonString);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
import 'package:aitrainer_app/repository/menu_tree_repository.dart';
|
import 'package:aitrainer_app/repository/menu_tree_repository.dart';
|
||||||
import 'package:aitrainer_app/util/session.dart';
|
import 'package:aitrainer_app/util/session.dart';
|
||||||
import 'package:aitrainer_app/view/account.dart';
|
import 'package:aitrainer_app/view/account.dart';
|
||||||
@ -9,13 +10,19 @@ 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_welcome_page.dart';
|
import 'package:aitrainer_app/view/customer_welcome_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/exercise_add_by_plan_page.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_control_page.dart';
|
import 'package:aitrainer_app/view/exercise_control_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/exercise_execute_by_plan_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/exercise_log_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/exercise_plan_custom_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/exercise_plan_detail_add_page.dart';
|
||||||
import 'package:aitrainer_app/view/exercise_type_description.dart';
|
import 'package:aitrainer_app/view/exercise_type_description.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/menu_page.dart';
|
import 'package:aitrainer_app/view/menu_page.dart';
|
||||||
import 'package:aitrainer_app/view/mydevelopment_page.dart';
|
import 'package:aitrainer_app/view/mydevelopment_page.dart';
|
||||||
|
import 'package:aitrainer_app/view/myexcercise_plan_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/widgets/home.dart';
|
import 'package:aitrainer_app/widgets/home.dart';
|
||||||
@ -27,6 +34,8 @@ 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/account/account_bloc.dart';
|
||||||
|
import 'bloc/exercise_by_plan/exercise_by_plan_bloc.dart';
|
||||||
|
import 'bloc/exercise_plan/exercise_plan_bloc.dart';
|
||||||
import 'bloc/menu/menu_bloc.dart';
|
import 'bloc/menu/menu_bloc.dart';
|
||||||
import 'bloc/session/session_bloc.dart';
|
import 'bloc/session/session_bloc.dart';
|
||||||
import 'bloc/settings/settings_bloc.dart';
|
import 'bloc/settings/settings_bloc.dart';
|
||||||
@ -96,14 +105,15 @@ Future<Null> main() async {
|
|||||||
// - https://api.dartlang.org/stable/1.24.2/dart-async/Zone-class.html
|
// - https://api.dartlang.org/stable/1.24.2/dart-async/Zone-class.html
|
||||||
// - https://www.dartlang.org/articles/libraries/zones
|
// - https://www.dartlang.org/articles/libraries/zones
|
||||||
runZonedGuarded<Future<Null>>(() async {
|
runZonedGuarded<Future<Null>>(() async {
|
||||||
|
final MenuTreeRepository menuTreeRepository = MenuTreeRepository();
|
||||||
runApp(
|
runApp(
|
||||||
MultiBlocProvider(
|
MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider<SessionBloc>(
|
BlocProvider<SessionBloc>(
|
||||||
create: (BuildContext context) => SessionBloc(session: Session()),
|
create: (BuildContext context) => SessionBloc(session: Session()),
|
||||||
),
|
),
|
||||||
BlocProvider<MenuBloc>(
|
BlocProvider<MenuBloc>(
|
||||||
create: (BuildContext context) => MenuBloc( menuTreeRepository: MenuTreeRepository()),
|
create: (BuildContext context) => MenuBloc( menuTreeRepository: menuTreeRepository),
|
||||||
),
|
),
|
||||||
BlocProvider<SettingsBloc>(
|
BlocProvider<SettingsBloc>(
|
||||||
create: (BuildContext context) => SettingsBloc(),
|
create: (BuildContext context) => SettingsBloc(),
|
||||||
@ -111,6 +121,12 @@ Future<Null> main() async {
|
|||||||
BlocProvider<AccountBloc>(
|
BlocProvider<AccountBloc>(
|
||||||
create: (BuildContext context) => AccountBloc(customerRepository: CustomerRepository()),
|
create: (BuildContext context) => AccountBloc(customerRepository: CustomerRepository()),
|
||||||
),
|
),
|
||||||
|
BlocProvider<ExercisePlanBloc>(
|
||||||
|
create: (BuildContext context) => ExercisePlanBloc(menuTreeRepository: menuTreeRepository),
|
||||||
|
),
|
||||||
|
BlocProvider<ExerciseByPlanBloc>(
|
||||||
|
create: (BuildContext context) => ExerciseByPlanBloc(menuTreeRepository: menuTreeRepository, exerciseRepository: ExerciseRepository()),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
|
|
||||||
child: AitrainerApp(),
|
child: AitrainerApp(),
|
||||||
@ -172,10 +188,16 @@ class AitrainerApp extends StatelessWidget {
|
|||||||
'account': (context) => AccountPage(),
|
'account': (context) => AccountPage(),
|
||||||
'settings': (context) => SettingsPage(),
|
'settings': (context) => SettingsPage(),
|
||||||
'exerciseTypeDescription': (context) => ExerciseTypeDescription(),
|
'exerciseTypeDescription': (context) => ExerciseTypeDescription(),
|
||||||
'mydevelopment': (context) => MyDevelopmentPage(),
|
'myDevelopment': (context) => MyDevelopmentPage(),
|
||||||
|
'myExercisePlan': (context) => MyExercisePlanPage(),
|
||||||
|
'exerciseLogPage': (context) => ExerciseLogPage(),
|
||||||
|
'exercisePlanCustomPage': (context) => ExercisePlanCustomPage(),
|
||||||
|
'exercisePlanDetailAdd': (context) => ExercisePlanDetailAddPage(),
|
||||||
|
'exerciseByPlanPage': (context) => ExerciseByPlanPage(),
|
||||||
|
'exerciseAddByPlanPage': (context) => ExerciseAddByPlanPage(),
|
||||||
},
|
},
|
||||||
initialRoute: 'home',
|
initialRoute: 'home',
|
||||||
title: 'Aitrainer',
|
title: 'WorkoutTest',
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
//primarySwatch: Colors.transparent,
|
//primarySwatch: Colors.transparent,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aitrainer_app/model/customer.dart';
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_tree.dart';
|
import 'package:aitrainer_app/model/exercise_tree.dart';
|
||||||
import 'package:aitrainer_app/model/exercise.dart';
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
import 'package:aitrainer_app/model/workout_tree.dart';
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
@ -55,10 +56,19 @@ class Cache {
|
|||||||
|
|
||||||
List<ExerciseType> _exerciseTypes;
|
List<ExerciseType> _exerciseTypes;
|
||||||
List<ExerciseTree> _exerciseTree;
|
List<ExerciseTree> _exerciseTree;
|
||||||
|
|
||||||
List<Exercise> _exercises;
|
List<Exercise> _exercises;
|
||||||
|
ExercisePlan _myExercisePlan;
|
||||||
|
List<ExercisePlanDetail> _myExercisesPlanDetail;
|
||||||
|
|
||||||
LinkedHashMap _tree = LinkedHashMap<String, WorkoutTree>();
|
LinkedHashMap _tree = LinkedHashMap<String, WorkoutTree>();
|
||||||
double _percentExercises = -1;
|
double _percentExercises = -1;
|
||||||
|
|
||||||
|
Customer _trainee;
|
||||||
|
List<Exercise> _exercisesTrainee;
|
||||||
|
ExercisePlan _traineeExercisePlan;
|
||||||
|
List<ExercisePlanDetail> _traineeExercisesPlanDetail;
|
||||||
|
|
||||||
List deviceLanguages;
|
List deviceLanguages;
|
||||||
String startPage;
|
String startPage;
|
||||||
|
|
||||||
@ -73,6 +83,10 @@ class Cache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setTestBaseUrl() {
|
||||||
|
baseUrl = 'http://aitrainer.app:8899/api/';
|
||||||
|
}
|
||||||
|
|
||||||
String getAuthToken() {
|
String getAuthToken() {
|
||||||
return this.authToken;
|
return this.authToken;
|
||||||
}
|
}
|
||||||
@ -106,6 +120,12 @@ class Cache {
|
|||||||
logout() async {
|
logout() async {
|
||||||
userLoggedIn = null;
|
userLoggedIn = null;
|
||||||
authToken = "";
|
authToken = "";
|
||||||
|
_trainee = null;
|
||||||
|
_percentExercises = -1;
|
||||||
|
_exercisesTrainee = null;
|
||||||
|
_traineeExercisePlan = null;
|
||||||
|
_exercises = List();
|
||||||
|
print("Trainees is null? " + (_trainee == null).toString() );
|
||||||
//firstLoad = true;
|
//firstLoad = true;
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
await setPreferences(prefs, SharePrefsChange.logout, 0);
|
await setPreferences(prefs, SharePrefsChange.logout, 0);
|
||||||
@ -154,6 +174,10 @@ class Cache {
|
|||||||
this._exercises = exercises;
|
this._exercises = exercises;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setExercisesTrainee( List<Exercise> exercises ) {
|
||||||
|
this._exercisesTrainee = exercises;
|
||||||
|
}
|
||||||
|
|
||||||
void setWorkoutTree( LinkedHashMap<String, WorkoutTree> tree) {
|
void setWorkoutTree( LinkedHashMap<String, WorkoutTree> tree) {
|
||||||
this._tree = tree;
|
this._tree = tree;
|
||||||
}
|
}
|
||||||
@ -170,6 +194,10 @@ class Cache {
|
|||||||
return this._exercises;
|
return this._exercises;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Exercise> getExercisesTrainee() {
|
||||||
|
return this._exercisesTrainee;
|
||||||
|
}
|
||||||
|
|
||||||
LinkedHashMap<String, WorkoutTree> getWorkoutTree() {
|
LinkedHashMap<String, WorkoutTree> getWorkoutTree() {
|
||||||
return this._tree;
|
return this._tree;
|
||||||
}
|
}
|
||||||
@ -186,4 +214,20 @@ class Cache {
|
|||||||
_exercises.add(exercise);
|
_exercises.add(exercise);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addExerciseTrainee(Exercise exercise) {
|
||||||
|
_exercisesTrainee.add(exercise);
|
||||||
|
}
|
||||||
|
|
||||||
|
Customer getTrainee() {
|
||||||
|
return this._trainee;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTrainee(Customer trainee) {
|
||||||
|
this._trainee = trainee;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTraineeExercisePlan(ExercisePlan exercisePlan) {
|
||||||
|
this._traineeExercisePlan = exercisePlan;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ class Customer {
|
|||||||
String fitnessLevel;
|
String fitnessLevel;
|
||||||
String bodyType;
|
String bodyType;
|
||||||
int admin;
|
int admin;
|
||||||
|
int trainer;
|
||||||
int dataPolicyAllowed;
|
int dataPolicyAllowed;
|
||||||
|
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ class Customer {
|
|||||||
this.goal,
|
this.goal,
|
||||||
this.weight,
|
this.weight,
|
||||||
this.admin,
|
this.admin,
|
||||||
|
this.trainer,
|
||||||
this.dataPolicyAllowed
|
this.dataPolicyAllowed
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -47,6 +49,7 @@ class Customer {
|
|||||||
this.goal = json['goal'];
|
this.goal = json['goal'];
|
||||||
this.weight = json['weight'];
|
this.weight = json['weight'];
|
||||||
this.admin = json['admin'];
|
this.admin = json['admin'];
|
||||||
|
this.trainer = json['trainer'];
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() =>
|
Map<String, dynamic> toJson() =>
|
||||||
@ -64,6 +67,7 @@ class Customer {
|
|||||||
"goal": goal,
|
"goal": goal,
|
||||||
"weight": weight,
|
"weight": weight,
|
||||||
"admin": admin,
|
"admin": admin,
|
||||||
|
"trainer": trainer,
|
||||||
"dataPolicyAllowed": dataPolicyAllowed,
|
"dataPolicyAllowed": dataPolicyAllowed,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ class Exercise {
|
|||||||
String unit;
|
String unit;
|
||||||
double unitQuantity;
|
double unitQuantity;
|
||||||
DateTime dateAdd;
|
DateTime dateAdd;
|
||||||
|
int exercisePlanDetailId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -30,5 +31,6 @@ class Exercise {
|
|||||||
"unit": unit,
|
"unit": unit,
|
||||||
"unitQuantity": unitQuantity,
|
"unitQuantity": unitQuantity,
|
||||||
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
|
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
|
||||||
|
"exercisePlanDetailId": exercisePlanDetailId,
|
||||||
};
|
};
|
||||||
}
|
}
|
58
lib/model/exercise_plan.dart
Normal file
58
lib/model/exercise_plan.dart
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
class ExercisePlan {
|
||||||
|
int exercisePlanId;
|
||||||
|
int customerId;
|
||||||
|
String name;
|
||||||
|
String description;
|
||||||
|
bool private;
|
||||||
|
DateTime dateAdd;
|
||||||
|
DateTime dateUpd;
|
||||||
|
|
||||||
|
ExercisePlan(String name, int customerId) {
|
||||||
|
this.customerId = customerId;
|
||||||
|
this.name = name;
|
||||||
|
this.dateUpd = DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExercisePlan.fromJson(Map json) {
|
||||||
|
this.exercisePlanId = json['exercisePlanId'];
|
||||||
|
this.customerId = json['customerId'];
|
||||||
|
this.name = json['name'];
|
||||||
|
this.private = json['private'];
|
||||||
|
this.description = json['description'];
|
||||||
|
this.dateAdd = json['dateAdd'] == null ? null : DateTime.parse( json['dateAdd'] );
|
||||||
|
this.dateUpd = json['dateUpd'] == null ? null : DateTime.parse( json['dateUpd'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
String formattedDateAdd;
|
||||||
|
if ( dateAdd != null) {
|
||||||
|
formattedDateAdd = DateFormat('yyyy-MM-dd HH:mm').format(dateAdd);
|
||||||
|
}
|
||||||
|
String formattedDateUpd = DateFormat('yyyy-MM-dd HH:mm').format(dateUpd);
|
||||||
|
|
||||||
|
print("DateAdd $formattedDateAdd");
|
||||||
|
if ( exercisePlanId == null ) {
|
||||||
|
return {
|
||||||
|
"customerId": customerId,
|
||||||
|
"name": name,
|
||||||
|
"description": description,
|
||||||
|
"private": private,
|
||||||
|
"dateAdd": formattedDateAdd,
|
||||||
|
"dateUpd": formattedDateUpd,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
"exercisePlanId": exercisePlanId,
|
||||||
|
"customerId": customerId,
|
||||||
|
"name": name,
|
||||||
|
"description": description,
|
||||||
|
"private": private,
|
||||||
|
"dateAdd": formattedDateAdd,
|
||||||
|
"dateUpd": formattedDateUpd,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
lib/model/exercise_plan_detail.dart
Normal file
36
lib/model/exercise_plan_detail.dart
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import 'package:aitrainer_app/model/exercise_plan.dart';
|
||||||
|
|
||||||
|
import 'exercise_type.dart';
|
||||||
|
|
||||||
|
class ExercisePlanDetail {
|
||||||
|
int exercisePlanDetailId;
|
||||||
|
int exercisePlanId;
|
||||||
|
int exerciseTypeId;
|
||||||
|
int serie;
|
||||||
|
int repeats;
|
||||||
|
String weightEquation;
|
||||||
|
|
||||||
|
ExerciseType exerciseType;
|
||||||
|
|
||||||
|
ExercisePlanDetail(int exerciseTypeId) {
|
||||||
|
this.exerciseTypeId = exerciseTypeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExercisePlanDetail.fromJson(Map json) {
|
||||||
|
this.exercisePlanDetailId = json['exercisePlanDetailId'];
|
||||||
|
this.exercisePlanId = json['exercisePlanId'];
|
||||||
|
this.exerciseTypeId = json['exerciseTypeId'];
|
||||||
|
this.serie = json['serie'];
|
||||||
|
this.repeats = json['repeats'];
|
||||||
|
this.weightEquation = json['weightEquation'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() =>
|
||||||
|
{
|
||||||
|
"exercisePlanId": exercisePlanId,
|
||||||
|
"exerciseTypeId": exerciseTypeId,
|
||||||
|
"serie": serie,
|
||||||
|
"repeats": repeats,
|
||||||
|
"weightEquation": weightEquation
|
||||||
|
};
|
||||||
|
}
|
@ -5,7 +5,7 @@ import 'exercise_type.dart';
|
|||||||
class WorkoutTree {
|
class WorkoutTree {
|
||||||
int id;
|
int id;
|
||||||
int parent;
|
int parent;
|
||||||
String name; // is also the key
|
String name;
|
||||||
String imageName;
|
String imageName;
|
||||||
Color color;
|
Color color;
|
||||||
double fontSize;
|
double fontSize;
|
||||||
@ -15,7 +15,26 @@ class WorkoutTree {
|
|||||||
bool base;
|
bool base;
|
||||||
|
|
||||||
bool is1RM;
|
bool is1RM;
|
||||||
|
bool selected = false;
|
||||||
|
bool executed = false;
|
||||||
|
String exerciseDetail;
|
||||||
|
String nameEnglish;
|
||||||
|
|
||||||
WorkoutTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child, this.exerciseTypeId, this.exerciseType, this.base, this.is1RM);
|
WorkoutTree(this.id, this.parent, this.name, this.imageName, this.color, this.fontSize, this.child,
|
||||||
|
this.exerciseTypeId, this.exerciseType, this.base, this.is1RM, this.nameEnglish);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
"id": id,
|
||||||
|
"parent": parent,
|
||||||
|
"name": name,
|
||||||
|
"imageName": imageName,
|
||||||
|
"color": color.toString(),
|
||||||
|
"fontSize": fontSize.toString(),
|
||||||
|
"child": child.toString(),
|
||||||
|
"exerciseTypeId": exerciseTypeId.toString(),
|
||||||
|
"base": base.toString(),
|
||||||
|
"is1RM": is1RM.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/customer.dart';
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
import 'package:aitrainer_app/service/customer_service.dart';
|
import 'package:aitrainer_app/service/customer_service.dart';
|
||||||
|
|
||||||
@ -9,6 +10,9 @@ class GenderItem {
|
|||||||
|
|
||||||
class CustomerRepository {
|
class CustomerRepository {
|
||||||
Customer customer;
|
Customer customer;
|
||||||
|
Customer _trainee;
|
||||||
|
List<Customer> _trainees;
|
||||||
|
|
||||||
//List<CustomerRepository> customerList = List<CustomerRepository>();
|
//List<CustomerRepository> customerList = List<CustomerRepository>();
|
||||||
bool visibleDetails = false;
|
bool visibleDetails = false;
|
||||||
List<GenderItem> genders;
|
List<GenderItem> genders;
|
||||||
@ -131,13 +135,53 @@ class CustomerRepository {
|
|||||||
await CustomerApi().saveCustomer(modelCustomer);
|
await CustomerApi().saveCustomer(modelCustomer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Future<List<CustomerRepository>> getCustomers() async {
|
Future<Customer> getTraineeAsCustomer() async {
|
||||||
final results = await CustomerApi().getRealCustomers("");
|
this._trainee = await CustomerApi().getTrainee(
|
||||||
this.customerList = results.map((item) => CustomerRepository(customer: item)).toList();
|
Cache().userLoggedIn.customerId
|
||||||
return this.customerList;
|
);
|
||||||
|
return _trainee;
|
||||||
}
|
}
|
||||||
|
|
||||||
addNewCustomerToList(CustomerRepository customerViewModel) {
|
Future<List<Customer>> getTrainees() async {
|
||||||
customerList.add(customerViewModel);
|
int trainerId = Cache().userLoggedIn.customerId;
|
||||||
}*/
|
final results = await CustomerApi().getTrainees(trainerId);
|
||||||
|
this._trainees = results;
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Customer> getTraineesList() {
|
||||||
|
return _trainees;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTrainee(int traineeId ) {
|
||||||
|
if ( _trainees == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_trainees.forEach((element) {
|
||||||
|
if ( traineeId == element.customerId) {
|
||||||
|
this._trainee = element;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void emptyTrainees() {
|
||||||
|
_trainees = null;
|
||||||
|
_trainee = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Customer getTrainee() {
|
||||||
|
return this._trainee;
|
||||||
|
}
|
||||||
|
|
||||||
|
Customer getTraineeById(int customerId) {
|
||||||
|
if (_trainees == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
_trainees.forEach((element) {
|
||||||
|
if ( customerId == element.customerId) {
|
||||||
|
this._trainee = element;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return _trainee;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
167
lib/repository/exercise_plan_repository.dart
Normal file
167
lib/repository/exercise_plan_repository.dart
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercise_plan_service.dart';
|
||||||
|
|
||||||
|
class ExercisePlanRepository {
|
||||||
|
bool newPlan = true;
|
||||||
|
ExercisePlan _exercisePlan;
|
||||||
|
LinkedHashMap<int, ExercisePlanDetail> exercisePlanDetails =
|
||||||
|
LinkedHashMap<int, ExercisePlanDetail>();
|
||||||
|
LinkedHashMap<int, ExercisePlanDetail> _origExercisePlanDetails =
|
||||||
|
LinkedHashMap<int, ExercisePlanDetail>();
|
||||||
|
int _customerId = 0;
|
||||||
|
ExercisePlanDetail actualPlanDetail;
|
||||||
|
|
||||||
|
void setCustomerId( int customerId ) {
|
||||||
|
this._customerId = customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getCustomerId() {
|
||||||
|
return this._customerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addExerciseTypeToPlan(ExerciseType exerciseType) {
|
||||||
|
setActualPlanDetail(exerciseType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToPlan() {
|
||||||
|
exercisePlanDetails[actualPlanDetail.exerciseTypeId] = actualPlanDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setActualPlanDetail(ExerciseType exerciseType) {
|
||||||
|
ExercisePlanDetail detail = exercisePlanDetails[exerciseType.exerciseTypeId];
|
||||||
|
if ( detail != null ) {
|
||||||
|
actualPlanDetail = detail;
|
||||||
|
} else {
|
||||||
|
actualPlanDetail = ExercisePlanDetail(exerciseType.exerciseTypeId);
|
||||||
|
}
|
||||||
|
actualPlanDetail.exerciseType = exerciseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getPlanDetailId(int exerciseTypeId) {
|
||||||
|
ExercisePlanDetail detail = exercisePlanDetails[exerciseTypeId];
|
||||||
|
return detail.exercisePlanDetailId;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPlanDetail(int exerciseTypeId) {
|
||||||
|
ExercisePlanDetail detail = exercisePlanDetails[exerciseTypeId];
|
||||||
|
String detailString = "";
|
||||||
|
if ( detail != null) {
|
||||||
|
detailString =
|
||||||
|
detail.serie.toString() + "x" + detail.repeats.toString() + " " +
|
||||||
|
detail.weightEquation + "kg";
|
||||||
|
}
|
||||||
|
return detailString;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getExercisePlanDetailSize() {
|
||||||
|
return exercisePlanDetails.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateExercisePlanDetail(ExerciseType exerciseType, int serie, int repeat, String weight) {
|
||||||
|
if ( exercisePlanDetails[exerciseType.exerciseTypeId] == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ExercisePlanDetail exercisePlanDetail = exercisePlanDetails[exerciseType.exerciseTypeId];
|
||||||
|
exercisePlanDetail.serie = serie;
|
||||||
|
exercisePlanDetail.repeats = repeat;
|
||||||
|
exercisePlanDetail.weightEquation = weight;
|
||||||
|
|
||||||
|
exercisePlanDetails[exerciseType.exerciseTypeId] = exercisePlanDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeExerciseTypeFromPlan(ExerciseType exerciseType) {
|
||||||
|
exercisePlanDetails.remove(exerciseType.exerciseTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveExercisePlan() async {
|
||||||
|
|
||||||
|
if ( _exercisePlan == null ) {
|
||||||
|
if ( Cache().userLoggedIn == null ) {
|
||||||
|
throw Exception("please log in");
|
||||||
|
}
|
||||||
|
|
||||||
|
String exercisePlanName;
|
||||||
|
if ( this._customerId == Cache().userLoggedIn.customerId) {
|
||||||
|
exercisePlanName = Cache().userLoggedIn.name + " private";
|
||||||
|
} else {
|
||||||
|
exercisePlanName = Cache().getTrainee().name + " " + Cache().getTrainee().firstname + " private";
|
||||||
|
}
|
||||||
|
|
||||||
|
_exercisePlan = ExercisePlan(exercisePlanName, this._customerId);
|
||||||
|
}
|
||||||
|
if ( newPlan ) {
|
||||||
|
_exercisePlan.dateAdd = DateTime.now();
|
||||||
|
_exercisePlan.private = true;
|
||||||
|
ExercisePlan savedExercisePlan =
|
||||||
|
await ExercisePlanApi().saveExercisePlan(_exercisePlan);
|
||||||
|
|
||||||
|
exercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async {
|
||||||
|
exercisePlanDetail.exercisePlanId = savedExercisePlan.exercisePlanId;
|
||||||
|
await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
|
||||||
|
await ExercisePlanApi().updateExercisePlan(_exercisePlan, _exercisePlan.exercisePlanId);
|
||||||
|
|
||||||
|
_origExercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async {
|
||||||
|
if (exercisePlanDetails[exercisePlanDetail.exercisePlanDetailId] == null) {
|
||||||
|
await ExercisePlanApi()
|
||||||
|
.deleteExercisePlanDetail(exercisePlanDetail.exercisePlanDetailId);
|
||||||
|
} else {
|
||||||
|
await ExercisePlanApi()
|
||||||
|
.updateExercisePlanDetail(exercisePlanDetail, exercisePlanDetail.exercisePlanDetailId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
exercisePlanDetails.forEach((exerciseTypeId, exercisePlanDetail) async{
|
||||||
|
exercisePlanDetail.exercisePlanId = _exercisePlan.exercisePlanId;
|
||||||
|
if ( _origExercisePlanDetails[exercisePlanDetail.exercisePlanDetailId] == null) {
|
||||||
|
await ExercisePlanApi()
|
||||||
|
.saveExercisePlanDetail(exercisePlanDetail);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ExercisePlan> getLastExercisePlan() async {
|
||||||
|
if ( _customerId == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
_exercisePlan = await ExercisePlanApi().getLastExercisePlan(_customerId);
|
||||||
|
newPlan = (_exercisePlan == null);
|
||||||
|
print("New plan: " + newPlan.toString());
|
||||||
|
|
||||||
|
return _exercisePlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getExercisePlanDetails() async {
|
||||||
|
if (_exercisePlan == null) {
|
||||||
|
ExercisePlan exercisePlan = await this.getLastExercisePlan();
|
||||||
|
if ( exercisePlan == null ) {
|
||||||
|
exercisePlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
|
||||||
|
_origExercisePlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exercisePlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
|
||||||
|
_origExercisePlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
|
||||||
|
|
||||||
|
List<ExercisePlanDetail> list =
|
||||||
|
await ExercisePlanApi().getExercisePlanDetail(_exercisePlan.exercisePlanId);
|
||||||
|
|
||||||
|
list.forEach((element) {
|
||||||
|
newPlan = false;
|
||||||
|
ExercisePlanDetail detail = element;
|
||||||
|
_origExercisePlanDetails[detail.exerciseTypeId] = detail;
|
||||||
|
exercisePlanDetails[detail.exerciseTypeId] = detail;
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -72,8 +72,12 @@ class ExerciseRepository {
|
|||||||
final Exercise modelExercise = this.exercise;
|
final Exercise modelExercise = this.exercise;
|
||||||
modelExercise.customerId = this.customer.customerId;
|
modelExercise.customerId = this.customer.customerId;
|
||||||
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
|
modelExercise.exerciseTypeId = this.exerciseType.exerciseTypeId;
|
||||||
await ExerciseApi().addExercise(modelExercise);
|
Exercise savedExercise = await ExerciseApi().addExercise(modelExercise);
|
||||||
Cache().addExercise(exercise);
|
if ( customer.customerId == Cache().userLoggedIn.customerId) {
|
||||||
|
Cache().addExercise(savedExercise);
|
||||||
|
} else if ( Cache().getTrainee() != null && customer.customerId == Cache().getTrainee().customerId ) {
|
||||||
|
Cache().addExerciseTrainee(savedExercise);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,15 +93,26 @@ class ExerciseRepository {
|
|||||||
Future<List<Exercise>> getExercisesByCustomer( int customerId ) async {
|
Future<List<Exercise>> getExercisesByCustomer( int customerId ) async {
|
||||||
final results = await ExerciseApi().getExercisesByCustomer(customerId);
|
final results = await ExerciseApi().getExercisesByCustomer(customerId);
|
||||||
this.exerciseList = results;
|
this.exerciseList = results;
|
||||||
Cache().setExercises(exerciseList);
|
if ( customerId == Cache().userLoggedIn.customerId) {
|
||||||
|
Cache().setExercises(exerciseList);
|
||||||
|
} else if ( Cache().getTrainee() != null && customerId == Cache().getTrainee().customerId ) {
|
||||||
|
Cache().setExercisesTrainee(exerciseList);
|
||||||
|
}
|
||||||
return this.exerciseList;
|
return this.exerciseList;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Exercise> getExerciseList() {
|
List<Exercise> getExerciseList() {
|
||||||
if ( this.exerciseList == null || this.exerciseList.length == 0 ) {
|
//if ( this.exerciseList == null || this.exerciseList.length == 0 ) {
|
||||||
this.exerciseList = Cache().getExercises();
|
return this.exerciseList = Cache().getExercises();
|
||||||
}
|
//}
|
||||||
return this.exerciseList;
|
//return this.exerciseList;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Exercise> getExerciseListTrainee() {
|
||||||
|
//if ( this.exerciseList == null || this.exerciseList.length == 0 ) {
|
||||||
|
return this.exerciseList = Cache().getExercisesTrainee();
|
||||||
|
//}
|
||||||
|
//return this.exerciseList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void getBaseExerciseFinishedPercent() {
|
void getBaseExerciseFinishedPercent() {
|
||||||
|
@ -9,12 +9,44 @@ 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:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class Antagonist {
|
||||||
|
static String chest = "Chest";
|
||||||
|
static int chestNr = 1;
|
||||||
|
static String biceps = "Biceps";
|
||||||
|
static int bicepsNr = 2;
|
||||||
|
static String triceps = "Triceps";
|
||||||
|
static int tricepsNr =3;
|
||||||
|
static String back = "Back";
|
||||||
|
static int backNr = 4;
|
||||||
|
static String shoulder = "Shoulders";
|
||||||
|
static int shoulderNr = 5;
|
||||||
|
static String core = "Core";
|
||||||
|
static int coreNr = 6;
|
||||||
|
static String thigh = "Thigh";
|
||||||
|
static int thighNr = 7;
|
||||||
|
static String calf = "Calf";
|
||||||
|
static int calfNr = 8;
|
||||||
|
}
|
||||||
|
|
||||||
class MenuTreeRepository {
|
class MenuTreeRepository {
|
||||||
final LinkedHashMap tree = LinkedHashMap<String, WorkoutTree>();
|
final LinkedHashMap tree = LinkedHashMap<String, WorkoutTree>();
|
||||||
|
SplayTreeMap sortedTree = SplayTreeMap<String, List<WorkoutTree>>();
|
||||||
|
bool isEnglish;
|
||||||
|
|
||||||
|
final Map<String, int> _antagonist = {
|
||||||
|
Antagonist.chest: Antagonist.chestNr,
|
||||||
|
Antagonist.biceps: Antagonist.bicepsNr,
|
||||||
|
Antagonist.triceps: Antagonist.tricepsNr,
|
||||||
|
Antagonist.back: Antagonist.backNr,
|
||||||
|
Antagonist.shoulder: Antagonist.shoulderNr,
|
||||||
|
Antagonist.core: Antagonist.coreNr,
|
||||||
|
Antagonist.thigh: Antagonist.thighNr,
|
||||||
|
Antagonist.calf: Antagonist.calfNr
|
||||||
|
};
|
||||||
|
|
||||||
Future<void> createTree() async {
|
Future<void> createTree() async {
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
final AppLanguage appLanguage = AppLanguage();
|
||||||
bool isEnglish = appLanguage.appLocal == Locale('en');
|
isEnglish = appLanguage.appLocal == Locale('en');
|
||||||
print("** Start creating tree on lang: " + appLanguage.appLocal.toString());
|
print("** Start creating tree on lang: " + appLanguage.appLocal.toString());
|
||||||
|
|
||||||
List<ExerciseTree> exerciseTree = Cache().getExerciseTree();
|
List<ExerciseTree> exerciseTree = Cache().getExerciseTree();
|
||||||
@ -25,7 +57,7 @@ class MenuTreeRepository {
|
|||||||
exerciseTree.forEach( (treeItem) async {
|
exerciseTree.forEach( (treeItem) async {
|
||||||
String treeName = isEnglish ? treeItem.name : treeItem.nameTranslation;
|
String treeName = isEnglish ? treeItem.name : treeItem.nameTranslation;
|
||||||
String assetImage = 'asset/menu/' + treeItem.imageUrl.substring(7);
|
String assetImage = 'asset/menu/' + treeItem.imageUrl.substring(7);
|
||||||
bool is1RM = treeItem.name == '1RM' ? true : false;
|
bool is1RM = treeItem.name == 'One Rep Max' ? true : false;
|
||||||
if ( is1RM == false && treeItem.parentId != 0) {
|
if ( is1RM == false && treeItem.parentId != 0) {
|
||||||
is1RM = isParent1RM(treeItem.parentId);
|
is1RM = isParent1RM(treeItem.parentId);
|
||||||
}
|
}
|
||||||
@ -34,12 +66,13 @@ class MenuTreeRepository {
|
|||||||
treeItem.parentId,
|
treeItem.parentId,
|
||||||
treeName,
|
treeName,
|
||||||
assetImage, Colors.white,
|
assetImage, Colors.white,
|
||||||
32,
|
24,
|
||||||
false,
|
false,
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
is1RM
|
is1RM,
|
||||||
|
treeItem.name,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -65,7 +98,8 @@ class MenuTreeRepository {
|
|||||||
exerciseType.exerciseTypeId,
|
exerciseType.exerciseTypeId,
|
||||||
exerciseType,
|
exerciseType,
|
||||||
exerciseType.base,
|
exerciseType.base,
|
||||||
is1RM
|
is1RM,
|
||||||
|
exerciseType.name
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -81,7 +115,7 @@ class MenuTreeRepository {
|
|||||||
WorkoutTree treeItem = value as WorkoutTree;
|
WorkoutTree treeItem = value as WorkoutTree;
|
||||||
if ( treeItem.id == treeId ) {
|
if ( treeItem.id == treeId ) {
|
||||||
isTreeItem1RM = treeItem.is1RM;
|
isTreeItem1RM = treeItem.is1RM;
|
||||||
//print (treeItem.name + " 1RM " + treeItem.is1RM.toString() );
|
print (treeItem.name + " 1RM " + treeItem.is1RM.toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -99,4 +133,34 @@ class MenuTreeRepository {
|
|||||||
});
|
});
|
||||||
return branch;
|
return branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<WorkoutTree> getBranchList(int parent) {
|
||||||
|
List branch = List<WorkoutTree>();
|
||||||
|
tree.forEach((key, value) {
|
||||||
|
WorkoutTree workoutTree = value as WorkoutTree;
|
||||||
|
if ( parent == workoutTree.parent) {
|
||||||
|
branch.add(workoutTree);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return branch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sortByMuscleType() {
|
||||||
|
sortedTree = SplayTreeMap<String, List<WorkoutTree>>();
|
||||||
|
tree.forEach((key, value) {
|
||||||
|
WorkoutTree workoutTree = value as WorkoutTree;
|
||||||
|
//print("treeitem: " + workoutTree.toJson().toString());
|
||||||
|
/*if ( workoutTree.exerciseType != null) {
|
||||||
|
print("treeItem exerciseTye " + workoutTree.exerciseType.toJson().toString());
|
||||||
|
} else {
|
||||||
|
print("treeItem exerciseType null " + workoutTree.toJson().toString());
|
||||||
|
}*/
|
||||||
|
if ( workoutTree.nameEnglish != 'One Rep Max' && workoutTree.is1RM && workoutTree.exerciseTypeId == 0) {
|
||||||
|
String treeName = _antagonist[workoutTree.nameEnglish].toString() + ". " + workoutTree.name;
|
||||||
|
sortedTree[treeName] = this.getBranchList(workoutTree.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
import 'package:aitrainer_app/util/not_found_exception.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
|
||||||
@ -22,6 +23,8 @@ class APIClient with Common {
|
|||||||
);
|
);
|
||||||
if(response.statusCode == 200) {
|
if(response.statusCode == 200) {
|
||||||
return utf8.decode(response.bodyBytes);
|
return utf8.decode(response.bodyBytes);
|
||||||
|
} else if(response.statusCode == 404 ) {
|
||||||
|
throw NotFoundException(message: "Not Found");
|
||||||
} else {
|
} else {
|
||||||
throw Exception("Unable to perform HTTP request!");
|
throw Exception("Unable to perform HTTP request!");
|
||||||
}
|
}
|
||||||
|
@ -5,64 +5,65 @@ import 'package:aitrainer_app/service/api.dart';
|
|||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
|
||||||
class CustomerApi {
|
class CustomerApi {
|
||||||
final APIClient _client=new APIClient();
|
final APIClient _client = new APIClient();
|
||||||
|
|
||||||
Future<List<Customer>> getRealCustomers(String param) async {
|
Future<List<Customer>> getRealCustomers(String param) async {
|
||||||
final body = await _client.get("customers/", param);
|
final body = await _client.get("customers/", param);
|
||||||
final Iterable json = jsonDecode(body);
|
final Iterable json = jsonDecode(body);
|
||||||
final List<Customer> customers = json.map( (customer) => Customer.fromJson(customer) ).toList();
|
final List<Customer> customers = json.map((customer) =>
|
||||||
|
Customer.fromJson(customer)).toList();
|
||||||
|
|
||||||
return customers;
|
return customers;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveCustomer(Customer customer) async {
|
Future<void> saveCustomer(Customer customer) async {
|
||||||
String body = JsonEncoder().convert(customer.toJson());
|
String body = JsonEncoder().convert(customer.toJson());
|
||||||
print(" ===== saving customer id: " + customer.customerId.toString() + ":" + body );
|
print(" ===== saving customer id: " + customer.customerId.toString() + ":" +
|
||||||
|
body);
|
||||||
await _client.post(
|
await _client.post(
|
||||||
"customers/"+customer.customerId.toString(),
|
"customers/" + customer.customerId.toString(),
|
||||||
body);
|
body);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addCustomer(Customer customer) async {
|
Future<void> addCustomer(Customer customer) async {
|
||||||
String body = JsonEncoder().convert(customer.toJson());
|
String body = JsonEncoder().convert(customer.toJson());
|
||||||
print(" ===== add new customer: " + body );
|
print(" ===== add new customer: " + body);
|
||||||
await _client.post(
|
await _client.post(
|
||||||
"customers",
|
"customers",
|
||||||
body);
|
body);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addUser(User user) async {
|
Future<void> addUser(User user) async {
|
||||||
String body = JsonEncoder().convert(user.toJson());
|
String body = JsonEncoder().convert(user.toJson());
|
||||||
print(" ===== register new user: " + body );
|
print(" ===== register new user: " + body);
|
||||||
final String responseBody = await _client.post(
|
final String responseBody = await _client.post(
|
||||||
"registration",
|
"registration",
|
||||||
body);
|
body);
|
||||||
Customer customer;
|
Customer customer;
|
||||||
try {
|
try {
|
||||||
int status = jsonDecode(responseBody)['status'];
|
int status = jsonDecode(responseBody)['status'];
|
||||||
if ( status != null ) {
|
if (status != null) {
|
||||||
throw new Exception(jsonDecode(responseBody)['error']);
|
throw new Exception(jsonDecode(responseBody)['error']);
|
||||||
} else {
|
} else {
|
||||||
customer = Customer.fromJson(jsonDecode(responseBody));
|
customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
Cache().afterRegistration(customer);
|
Cache().afterRegistration(customer);
|
||||||
}
|
}
|
||||||
} on FormatException catch(exception) {
|
} on FormatException catch (exception) {
|
||||||
throw new Exception(responseBody);
|
throw new Exception(responseBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getUser(User user) async {
|
Future<void> getUser(User user) async {
|
||||||
String body = JsonEncoder().convert(user.toJson());
|
String body = JsonEncoder().convert(user.toJson());
|
||||||
print(" ===== login the user: " + body );
|
print(" ===== login the user: " + body);
|
||||||
final String responseBody = await _client.post(
|
final String responseBody = await _client.post(
|
||||||
"login",
|
"login",
|
||||||
body);
|
body);
|
||||||
Customer customer;
|
Customer customer;
|
||||||
try {
|
try {
|
||||||
customer = Customer.fromJson(jsonDecode(responseBody));
|
customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
await Cache().afterLogin(customer);
|
await Cache().afterLogin(customer);
|
||||||
} on FormatException catch(exception) {
|
} on FormatException catch (exception) {
|
||||||
throw new Exception(responseBody);
|
throw new Exception(responseBody);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,18 +71,54 @@ 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());
|
||||||
try {
|
try {
|
||||||
final String responseBody = await _client.get(
|
final String responseBody = await _client.get(
|
||||||
"customers/"+customerId.toString(),
|
"customers/" + customerId.toString(),
|
||||||
body);
|
body);
|
||||||
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
Customer customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
|
print(" --- Customer: " + customer.toJson().toString());
|
||||||
Cache().afterRegistration(customer);
|
Cache().afterRegistration(customer);
|
||||||
} catch (exception) {
|
} catch (exception) {
|
||||||
print ("Exception: " + exception.toString());
|
print("Exception: " + exception.toString());
|
||||||
print (" === go to registration ");
|
print(" === go to registration ");
|
||||||
Cache().logout();
|
Cache().logout();
|
||||||
Cache().startPage = "registration";
|
Cache().startPage = "registration";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Customer> getTrainee(int customerId) async {
|
||||||
|
String body = "";
|
||||||
|
Customer customer;
|
||||||
|
print(" ===== get Trainee customer by id: " + customerId.toString());
|
||||||
|
try {
|
||||||
|
final String responseBody = await _client.get(
|
||||||
|
"customers/" + customerId.toString(),
|
||||||
|
body);
|
||||||
|
customer = Customer.fromJson(jsonDecode(responseBody));
|
||||||
|
print(" --- Trainee: " + customer.toJson().toString());
|
||||||
|
} catch (exception) {
|
||||||
|
print("Exception: " + exception.toString());
|
||||||
|
throw Exception(exception);
|
||||||
|
}
|
||||||
|
return customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Customer>> getTrainees(int trainerId) async {
|
||||||
|
List<Customer> trainees = List<Customer>();
|
||||||
|
print("Get trainees list");
|
||||||
|
try {
|
||||||
|
String body = "";
|
||||||
|
final String responseBody = await _client.get(
|
||||||
|
"customers/trainees/" + trainerId.toString(),
|
||||||
|
body
|
||||||
|
);
|
||||||
|
final Iterable json = jsonDecode(responseBody);
|
||||||
|
trainees = json.map((customer) => Customer.fromJson(customer)).toList();
|
||||||
|
} catch (exception) {
|
||||||
|
print("Exception: " + exception.toString());
|
||||||
|
throw Exception(exception);
|
||||||
|
}
|
||||||
|
return trainees;
|
||||||
|
}
|
||||||
}
|
}
|
145
lib/service/exercise_plan_service.dart
Normal file
145
lib/service/exercise_plan_service.dart
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
|
import 'package:aitrainer_app/util/not_found_exception.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'api.dart';
|
||||||
|
|
||||||
|
class ExercisePlanApi {
|
||||||
|
final APIClient _client = new APIClient();
|
||||||
|
|
||||||
|
Future<ExercisePlan> saveExercisePlan(ExercisePlan exercisePlan) async {
|
||||||
|
String body = JsonEncoder().convert(exercisePlan.toJson());
|
||||||
|
print(" ===== saving exercisePlan $exercisePlan");
|
||||||
|
ExercisePlan savedExercisePlan;
|
||||||
|
try {
|
||||||
|
final String responseBody = await _client.post(
|
||||||
|
"exercise_plan",
|
||||||
|
body);
|
||||||
|
savedExercisePlan = ExercisePlan.fromJson(jsonDecode(responseBody));
|
||||||
|
Cache().setTraineeExercisePlan(savedExercisePlan);
|
||||||
|
} on Exception catch(e) {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
return savedExercisePlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ExercisePlan> updateExercisePlan(
|
||||||
|
ExercisePlan exercisePlan,
|
||||||
|
int exercisePlanId) async {
|
||||||
|
String body = JsonEncoder().convert(exercisePlan.toJson());
|
||||||
|
print(" ===== saving exercisePlan $exercisePlan");
|
||||||
|
ExercisePlan updatedExercisePlan;
|
||||||
|
try {
|
||||||
|
final String responseBody = await _client.post(
|
||||||
|
"exercise_plan/" + exercisePlanId.toString(),
|
||||||
|
body);
|
||||||
|
updatedExercisePlan = ExercisePlan.fromJson(jsonDecode(responseBody));
|
||||||
|
Cache().setTraineeExercisePlan(updatedExercisePlan);
|
||||||
|
} on Exception catch(e) {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
return updatedExercisePlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ExercisePlanDetail> saveExercisePlanDetail(ExercisePlanDetail exercisePlanDetail) async {
|
||||||
|
String body = JsonEncoder().convert(exercisePlanDetail.toJson());
|
||||||
|
print(" ===== update exercisePlanDetail $exercisePlanDetail");
|
||||||
|
ExercisePlanDetail savedExercisePlanDetail;
|
||||||
|
try {
|
||||||
|
final String responseBody = await _client.post(
|
||||||
|
"exercise_plan_detail",
|
||||||
|
body);
|
||||||
|
savedExercisePlanDetail = ExercisePlanDetail.fromJson(jsonDecode(responseBody));
|
||||||
|
} on Exception catch(e) {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
return savedExercisePlanDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ExercisePlanDetail> updateExercisePlanDetail(ExercisePlanDetail exercisePlanDetail,
|
||||||
|
int exercisePlanDetailId) async {
|
||||||
|
String body = JsonEncoder().convert(exercisePlanDetail.toJson());
|
||||||
|
print(" ===== update exercisePlanDetail $exercisePlanDetail");
|
||||||
|
ExercisePlanDetail savedExercisePlanDetail;
|
||||||
|
try {
|
||||||
|
final String responseBody = await _client.post(
|
||||||
|
"exercise_plan_detail/" + exercisePlanDetailId.toString(),
|
||||||
|
body);
|
||||||
|
savedExercisePlanDetail = ExercisePlanDetail.fromJson(jsonDecode(responseBody));
|
||||||
|
} on Exception catch(e) {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
return savedExercisePlanDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteExercisePlanDetail(int exercisePlanDetailId) async {
|
||||||
|
print(" ===== delete exercisePlanDetail $exercisePlanDetailId");
|
||||||
|
String body = "";
|
||||||
|
try {
|
||||||
|
await _client.post(
|
||||||
|
"exercise_plan_detail/delete/" + exercisePlanDetailId.toString(),
|
||||||
|
body);
|
||||||
|
|
||||||
|
} on Exception catch(e) {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteExercisePlan(int exercisePlanId) async {
|
||||||
|
String body = "";
|
||||||
|
print(" ===== delete exercisePlan $exercisePlanId");
|
||||||
|
|
||||||
|
try {
|
||||||
|
await _client.post(
|
||||||
|
"exercise_plan/delete/" + exercisePlanId.toString(),
|
||||||
|
body);
|
||||||
|
|
||||||
|
} on Exception catch(e) {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ExercisePlan> getLastExercisePlan(int customerId) async {
|
||||||
|
String body = "";
|
||||||
|
print(" ===== get last exercisePlan $customerId");
|
||||||
|
ExercisePlan exercisePlan;
|
||||||
|
try {
|
||||||
|
final String responseBody = await _client.get(
|
||||||
|
"exercise_plan/last/" + customerId.toString(),
|
||||||
|
body);
|
||||||
|
exercisePlan = ExercisePlan.fromJson(jsonDecode(responseBody));
|
||||||
|
} on Exception catch(e) {
|
||||||
|
if ( e is NotFoundException) {
|
||||||
|
print("ExercisePlan not found for " + customerId.toString());
|
||||||
|
return exercisePlan;
|
||||||
|
} else {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exercisePlan;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<ExercisePlanDetail>> getExercisePlanDetail(int exercisePlanId) async {
|
||||||
|
String body = "";
|
||||||
|
print(" ===== get exercisePlanDetail $exercisePlanId");
|
||||||
|
List<ExercisePlanDetail> listExercisePlanDetail;
|
||||||
|
try {
|
||||||
|
final String responseBody = await _client.get(
|
||||||
|
"exercise_plan_detail/" + exercisePlanId.toString(),
|
||||||
|
body);
|
||||||
|
print("response body:" + responseBody);
|
||||||
|
final Iterable json = jsonDecode(responseBody);
|
||||||
|
listExercisePlanDetail = json.map( (planDetail) => ExercisePlanDetail.fromJson(planDetail) ) .toList();
|
||||||
|
} on Exception catch(e) {
|
||||||
|
throw new Exception(e.toString());
|
||||||
|
}
|
||||||
|
return listExercisePlanDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -22,12 +22,14 @@ class ExerciseApi {
|
|||||||
body);
|
body);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addExercise(Exercise exercise) async {
|
Future<Exercise> addExercise(Exercise exercise) async {
|
||||||
String body = JsonEncoder().convert(exercise.toJson());
|
String body = JsonEncoder().convert(exercise.toJson());
|
||||||
print(" ===== add new exercise: " + body );
|
print(" ===== add new exercise: " + body );
|
||||||
await _client.post(
|
final String response = await _client.post(
|
||||||
"exercises",
|
"exercises",
|
||||||
body);
|
body);
|
||||||
|
final Exercise savedExercise = Exercise.fromJson(jsonDecode(response));
|
||||||
|
return savedExercise;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Exercise>> getExercisesByCustomer(int customerId ) async {
|
Future<List<Exercise>> getExercisesByCustomer(int customerId ) async {
|
||||||
|
4
lib/util/not_found_exception.dart
Normal file
4
lib/util/not_found_exception.dart
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
class NotFoundException implements Exception {
|
||||||
|
final String message;
|
||||||
|
const NotFoundException({this.message});
|
||||||
|
}
|
@ -27,7 +27,7 @@ class Session {
|
|||||||
if ( Cache().firstLoad ) {
|
if ( Cache().firstLoad ) {
|
||||||
|
|
||||||
print (" -- Session: fetch locale..");
|
print (" -- Session: fetch locale..");
|
||||||
await appLanguage.fetchLocale();
|
await appLanguage.getLocale(_sharedPreferences);
|
||||||
await AppLocalizations.delegate.load(appLanguage.appLocal);
|
await AppLocalizations.delegate.load(appLanguage.appLocal);
|
||||||
print (" -- Session: fetch token..");
|
print (" -- Session: fetch token..");
|
||||||
await _fetchToken(_sharedPreferences);
|
await _fetchToken(_sharedPreferences);
|
||||||
@ -95,7 +95,6 @@ class Session {
|
|||||||
//Navigator.of(context).pushNamed('login');
|
//Navigator.of(context).pushNamed('login');
|
||||||
Cache().startPage = "login";
|
Cache().startPage = "login";
|
||||||
} else {
|
} else {
|
||||||
print("************** Store SharedPreferences");
|
|
||||||
// get API customer
|
// get API customer
|
||||||
customerId = prefs.getInt(Cache.customerIdKey);
|
customerId = prefs.getInt(Cache.customerIdKey);
|
||||||
await CustomerApi().getCustomer(customerId);
|
await CustomerApi().getCustomer(customerId);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
import 'package:aitrainer_app/bloc/account/account_bloc.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/model/customer.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.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';
|
||||||
@ -7,6 +9,7 @@ import 'package:flutter/cupertino.dart';
|
|||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class AccountPage extends StatelessWidget {
|
class AccountPage extends StatelessWidget {
|
||||||
|
// ignore: close_sinks
|
||||||
AccountBloc accountBloc;
|
AccountBloc accountBloc;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -93,7 +96,7 @@ class AccountPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
loginOut( context, accountBloc ),
|
loginOut( context, accountBloc ),
|
||||||
//exercises(exerciseChangingViewModel),
|
getMyTrainees(context, accountBloc),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,93 +140,72 @@ class AccountPage extends StatelessWidget {
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ListTile exercises( ExerciseChangingViewModel model ) {
|
Widget getMyTrainees( BuildContext context, AccountBloc accountBloc ) {
|
||||||
ListTile element = ListTile();
|
if ( accountBloc.customerRepository.customer == null ) {
|
||||||
if ( Auth().userLoggedIn == null ) {
|
return Container();
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
if ( accountBloc.customerRepository.customer.trainer == 0 ) {
|
||||||
element = ListTile(
|
return ListTile(
|
||||||
title: Text(AppLocalizations.of(context).translate("Exercises")),
|
title: Container(),
|
||||||
subtitle: Column(
|
|
||||||
children: [
|
|
||||||
FutureBuilder<List<ExerciseViewModel>>(
|
|
||||||
future: _exercises,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
return getExercises( model );//CustomerListWidget(customers: _exerciseViewModel.exerciseList);
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Text("${snapshot.error}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// By default, show a loading spinner.
|
|
||||||
return CircularProgressIndicator();
|
|
||||||
}
|
|
||||||
),]
|
|
||||||
));
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
Widget getExercises( ExerciseChangingViewModel model ) {
|
|
||||||
List<ExerciseViewModel> exercises = model.exerciseList;
|
|
||||||
|
|
||||||
Column element = Column();
|
|
||||||
if (exercises.length > 0) {
|
|
||||||
List<Column> rows = List();
|
|
||||||
|
|
||||||
exercises.forEach((exercise) {
|
|
||||||
String exerciseName = AppLocalizations.of(context).translate(
|
|
||||||
Common.getExerciseType(exercise.getExercise().exerciseTypeId).name);
|
|
||||||
|
|
||||||
String quantity = exercise.getExercise().quantity.toString() + " " +
|
|
||||||
AppLocalizations.of(context).translate(exercise.getExercise().unit);
|
|
||||||
|
|
||||||
String unitQuantity = "";
|
|
||||||
String unitQuantityUnit = "";
|
|
||||||
String date = Common.getDateLocale(exercise.getExercise().dateAdd, false);
|
|
||||||
if (exercise.getExercise().unitQuantity != null) {
|
|
||||||
unitQuantity = exercise.getExercise().unitQuantity.toString();
|
|
||||||
unitQuantityUnit = AppLocalizations.of(context).translate(
|
|
||||||
Common.getExerciseType(exercise.getExercise().exerciseTypeId).unitQuantityUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
TableRow row = TableRow(
|
|
||||||
children: [
|
|
||||||
Text(date),
|
|
||||||
Text(exerciseName),
|
|
||||||
Text(quantity),
|
|
||||||
|
|
||||||
Text(unitQuantity + " " + unitQuantityUnit),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
Table table = Table(
|
|
||||||
defaultColumnWidth: FractionColumnWidth(0.28),
|
|
||||||
children: [row],
|
|
||||||
);
|
|
||||||
|
|
||||||
Column col = Column(
|
|
||||||
children: [
|
|
||||||
table,
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text(" "),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
rows.add(col);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
element = Column(
|
|
||||||
children: rows,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return element;
|
if (accountBloc.customerRepository.getTraineesList() == null ) {
|
||||||
|
return ListTile(
|
||||||
|
leading: Icon(Icons.people),
|
||||||
|
title: RaisedButton(
|
||||||
|
color: Colors.white70,
|
||||||
|
onPressed: () => accountBloc.add(AccountGetTrainees()),
|
||||||
|
child: Text("See my trainees"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> elements = List<Widget>();
|
||||||
|
accountBloc.customerRepository.getTraineesList().forEach((element) {
|
||||||
|
Customer trainee = element;
|
||||||
|
String name = trainee.name;
|
||||||
|
String firstName = trainee.firstname;
|
||||||
|
String nodeName = AppLanguage().appLocal == Locale("en") ?
|
||||||
|
firstName + " " + name : name + " " + firstName;
|
||||||
|
|
||||||
|
bool selected = accountBloc.traineeId == trainee.customerId;
|
||||||
|
|
||||||
|
Widget widget = FlatButton(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
shape:RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
side: BorderSide(width: 2, color: selected ? Colors.blue : Colors.black26 ),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
accountBloc.add(AccountSelectTrainee(traineeId: trainee.customerId));
|
||||||
|
//Navigator.of(context).pushNamed('login');
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(nodeName, style:
|
||||||
|
TextStyle(
|
||||||
|
color: selected ? Colors.blue : Colors.black54,
|
||||||
|
fontWeight: selected ? FontWeight.bold : FontWeight.normal
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(Icons.arrow_forward_ios),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
elements.add(widget);
|
||||||
|
});
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
leading: Icon(Icons.people),
|
||||||
|
subtitle: Text("My Trainees"),
|
||||||
|
title: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: elements,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
|
241
lib/view/exercise_add_by_plan_page.dart
Normal file
241
lib/view/exercise_add_by_plan_page.dart
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/bloc/exercise_add_by_plan_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/bloc/exercise_by_plan/exercise_by_plan_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/splash.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class ExerciseAddByPlanPage extends StatefulWidget{
|
||||||
|
_ExerciseAddByPlanPage createState() => _ExerciseAddByPlanPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExerciseAddByPlanPage extends State<ExerciseAddByPlanPage> {
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
|
||||||
|
// ignore: close_sinks
|
||||||
|
final ExerciseByPlanBloc bloc = arguments['blocExerciseByPlan'];
|
||||||
|
final int customerId = arguments['customerId'];
|
||||||
|
final WorkoutTree workoutTree = arguments['workoutTree'];
|
||||||
|
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
|
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
ExerciseAddByPlanFormBloc(
|
||||||
|
exerciseRepository: exerciseRepository,
|
||||||
|
exercisePlanRepository: bloc.exercisePlanRepository,
|
||||||
|
customerId: customerId,
|
||||||
|
workoutTree: workoutTree),
|
||||||
|
child: BlocBuilder<ExerciseAddByPlanFormBloc, FormBlocState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final exerciseBloc = BlocProvider.of<ExerciseAddByPlanFormBloc>(context);
|
||||||
|
if ( state is FormBlocLoading ) {
|
||||||
|
return LoadingDialog();
|
||||||
|
} else if ( state is FormBlocSuccess) {
|
||||||
|
return getControlForm(exerciseBloc);
|
||||||
|
} else {
|
||||||
|
return getControlForm(exerciseBloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Form getControlForm( ExerciseAddByPlanFormBloc exerciseBloc) {
|
||||||
|
String exerciseName = AppLanguage().appLocal == Locale("en") ?
|
||||||
|
exerciseBloc.exerciseRepository.exerciseType.name :
|
||||||
|
exerciseBloc.exerciseRepository.exerciseType.nameTranslation;
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
autovalidate: true,
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
Text("Add Exercise"),
|
||||||
|
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: Container(
|
||||||
|
width: MediaQuery
|
||||||
|
.of(context)
|
||||||
|
.size
|
||||||
|
.width,
|
||||||
|
height: MediaQuery
|
||||||
|
.of(context)
|
||||||
|
.size
|
||||||
|
.height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only (top: 25, left: 25, right: 25),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(exerciseName,
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 18,
|
||||||
|
color: Colors.deepOrange),
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: true,
|
||||||
|
),
|
||||||
|
Divider(color: Colors.transparent,),
|
||||||
|
|
||||||
|
Divider(),
|
||||||
|
Column(
|
||||||
|
children: repeatExercises(exerciseBloc),
|
||||||
|
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Column> repeatExercises(ExerciseAddByPlanFormBloc exerciseBloc) {
|
||||||
|
List<Column> listColumns = List<Column>();
|
||||||
|
for ( int i = 0; i < exerciseBloc.countSteps; i++) {
|
||||||
|
Column col = Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Divider(color: Colors.transparent,),
|
||||||
|
Text("Execute the " + (i+1).toString() + ". set!",
|
||||||
|
style: TextStyle(),),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
readOnly: exerciseBloc.step != i+1,
|
||||||
|
textFieldBloc: exerciseBloc.quantity1Field,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.deepOrange,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [
|
||||||
|
WhitelistingTextInputFormatter(RegExp(r"[\d.]"))
|
||||||
|
],
|
||||||
|
|
||||||
|
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, fontWeight: FontWeight.normal),
|
||||||
|
labelText: "Please repeat with " + exerciseBloc.unitQuantity1Field.value + " " +
|
||||||
|
exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit + " " +
|
||||||
|
exerciseBloc.exercisePlanRepository.actualPlanDetail.repeats.toString() + " times!",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
readOnly: exerciseBloc.step != i+1,
|
||||||
|
textFieldBloc: exerciseBloc.unitQuantity1Field,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.black54,
|
||||||
|
fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [
|
||||||
|
WhitelistingTextInputFormatter(RegExp(r"[\d.]"))
|
||||||
|
],
|
||||||
|
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontSize: 12, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||||
|
labelStyle: TextStyle(fontSize: 12, color: Colors.deepOrange, fontWeight: FontWeight.normal),
|
||||||
|
labelText: exerciseBloc.exerciseRepository.exerciseType.unitQuantityUnit,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
RaisedButton(
|
||||||
|
|
||||||
|
padding: EdgeInsets.all(0),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: exerciseBloc.step == i+1 ? Colors.blue : Colors.black26,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
print ("Submit step " + exerciseBloc.step.toString() + " (i) " + i.toString()),
|
||||||
|
if ( exerciseBloc.step == i+1 ) {
|
||||||
|
exerciseBloc.submit()
|
||||||
|
},
|
||||||
|
if ( i+1 == exerciseBloc.countSteps) {
|
||||||
|
Navigator.of(context).pop()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).translate("Check"),
|
||||||
|
style: TextStyle(fontSize: 12),)
|
||||||
|
),
|
||||||
|
Divider(color: Colors.transparent,),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
listColumns.add(col);
|
||||||
|
}
|
||||||
|
return listColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
String validateNumberInput(input) {
|
||||||
|
String error = AppLocalizations.of(context).translate(
|
||||||
|
"Please type the right quantity 0-10000");
|
||||||
|
dynamic rc = (input != null && input.length > 0);
|
||||||
|
if (!rc) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pattern pattern = r'^\d+(?:\.\d+)?$';
|
||||||
|
RegExp regex = new RegExp(pattern);
|
||||||
|
if (!regex.hasMatch(input)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = double.tryParse(input);
|
||||||
|
if (rc == null) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!(double.parse(input) < 10000 && double.parse(input) > 0)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
187
lib/view/exercise_execute_by_plan_page.dart
Normal file
187
lib/view/exercise_execute_by_plan_page.dart
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/bloc/exercise_by_plan/exercise_by_plan_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/splash.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_treeview/tree_view.dart';
|
||||||
|
|
||||||
|
class ExerciseByPlanPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ExerciseByPlanPage createState() => _ExerciseByPlanPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExerciseByPlanPage extends State<ExerciseByPlanPage> {
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
|
// ignore: close_sinks
|
||||||
|
ExerciseByPlanBloc bloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
/// We require the initializers to run after the loading screen is rendered
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
BlocProvider.of<ExerciseByPlanBloc>(context).add(ExerciseByPlanLoad());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
|
||||||
|
final int customerId = arguments['customerId'];
|
||||||
|
bloc = BlocProvider.of<ExerciseByPlanBloc>(context);
|
||||||
|
bloc.customerId = customerId;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: AppBarCommonNav(),
|
||||||
|
body: Container(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: customerId == Cache().userLoggedIn.customerId ? AssetImage('asset/image/WT_light_background.png'):
|
||||||
|
AssetImage('asset/image/WT_menu_dark.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: BlocConsumer<ExerciseByPlanBloc, ExerciseByPlanState>(listener: (context, state) {
|
||||||
|
if (state is ExerciseByPlanError) {
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text(
|
||||||
|
state.message,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
));
|
||||||
|
} else if (state is ExerciseByPlanLoading) {
|
||||||
|
LoadingDialog();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ignore: missing_return
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is ExerciseByPlanStateInitial || state is ExerciseByPlanLoading) {
|
||||||
|
return Container();
|
||||||
|
} else if (state is ExerciseByPlanReady) {
|
||||||
|
return exerciseWidget(bloc);
|
||||||
|
} else if (state is ExerciseByPlanError) {
|
||||||
|
return exerciseWidget(bloc);
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget exerciseWidget(ExerciseByPlanBloc bloc) {
|
||||||
|
final LinkedHashMap args = LinkedHashMap();
|
||||||
|
TreeViewController _treeViewController = TreeViewController(children: nodeExercisePlan(bloc));
|
||||||
|
|
||||||
|
TreeViewTheme _treeViewTheme = TreeViewTheme(
|
||||||
|
expanderTheme: ExpanderThemeData(
|
||||||
|
type: ExpanderType.plusMinus,
|
||||||
|
modifier: ExpanderModifier.circleOutlined,
|
||||||
|
position: ExpanderPosition.start,
|
||||||
|
color: Colors.black26,
|
||||||
|
size: 10,
|
||||||
|
),
|
||||||
|
labelStyle: TextStyle(fontSize: 14, letterSpacing: 0, color: Colors.blue.shade800),
|
||||||
|
parentLabelStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
letterSpacing: 0.3,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
color: Colors.orange.shade600,
|
||||||
|
),
|
||||||
|
iconTheme: IconThemeData(
|
||||||
|
size: 20,
|
||||||
|
color: Colors.blue.shade800,
|
||||||
|
),
|
||||||
|
colorScheme: bloc.customerId == Cache().userLoggedIn.customerId ? ColorScheme.light(background: Colors.transparent) : ColorScheme.dark(background: Colors.transparent),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
body: TreeView(
|
||||||
|
controller: _treeViewController,
|
||||||
|
allowParentSelect: false,
|
||||||
|
supportParentDoubleTap: false,
|
||||||
|
//onExpansionChanged: _expandNodeHandler,
|
||||||
|
onNodeTap: (key) {
|
||||||
|
/* Node<dynamic> node = _treeViewController.getNode(key);
|
||||||
|
WorkoutTree workoutTree = node.data as WorkoutTree;
|
||||||
|
bloc.exercisePlanRepository.setActualPlanDetail(workoutTree.exerciseType);
|
||||||
|
print("change node " + node.label + " key " + key);
|
||||||
|
bloc.add(ExercisePlanUpdate(workoutTree: workoutTree));
|
||||||
|
Navigator.of(context).pushNamed("exercisePlanDetailAdd", arguments: bloc); */
|
||||||
|
|
||||||
|
Node<dynamic> node = _treeViewController.getNode(key);
|
||||||
|
WorkoutTree workoutTree = node.data as WorkoutTree;
|
||||||
|
args['blocExerciseByPlan'] = bloc;
|
||||||
|
args['customerId'] = bloc.customerId;
|
||||||
|
args['workoutTree'] = workoutTree;
|
||||||
|
Navigator.of(context).pushNamed("exerciseAddByPlanPage", arguments: args);
|
||||||
|
},
|
||||||
|
|
||||||
|
theme: _treeViewTheme,
|
||||||
|
),
|
||||||
|
//bottomNavigationBar: BottomNavigator(bottomNavIndex: 2),
|
||||||
|
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Node> nodeExercisePlan(ExerciseByPlanBloc bloc) {
|
||||||
|
List<Node> nodes = List<Node>();
|
||||||
|
Node actualNode;
|
||||||
|
bool isEnglish = AppLanguage().appLocal == Locale("en");
|
||||||
|
|
||||||
|
bloc.menuTreeRepository.sortedTree.forEach((name, list) {
|
||||||
|
List<WorkoutTree> listWorkoutItem = list;
|
||||||
|
List<Node> listExerciseTypePerMuscle = List<Node>();
|
||||||
|
NodeIcon icon;
|
||||||
|
listWorkoutItem.forEach((element) {
|
||||||
|
|
||||||
|
WorkoutTree treeItem = element;
|
||||||
|
if ( treeItem.selected ) {
|
||||||
|
icon =
|
||||||
|
treeItem.executed == false ? NodeIcon(codePoint: Icons.bubble_chart.codePoint, color: "blueAccent") :
|
||||||
|
NodeIcon(codePoint: Icons.check_box.codePoint, color: "green");
|
||||||
|
|
||||||
|
String exerciseLabel = isEnglish
|
||||||
|
? treeItem.name
|
||||||
|
: treeItem.exerciseType == null ? treeItem.name : treeItem.exerciseType.nameTranslation;
|
||||||
|
|
||||||
|
List<Node<dynamic>> planDetailList = List<Node<dynamic>>();
|
||||||
|
String planDetail = bloc.exercisePlanRepository.getPlanDetail(treeItem.exerciseTypeId);
|
||||||
|
|
||||||
|
if (planDetail.length > 0) {
|
||||||
|
exerciseLabel += " (" + planDetail + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
actualNode = Node(
|
||||||
|
label: exerciseLabel,
|
||||||
|
key: treeItem.id.toString(),
|
||||||
|
data: treeItem,
|
||||||
|
expanded: planDetailList.length > 0 ? true : false,
|
||||||
|
children: [],
|
||||||
|
icon: icon);
|
||||||
|
listExerciseTypePerMuscle.add(actualNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (name != null) {
|
||||||
|
actualNode = Node(
|
||||||
|
label: name,
|
||||||
|
key: name,
|
||||||
|
expanded: true,
|
||||||
|
children: listExerciseTypePerMuscle,
|
||||||
|
icon: NodeIcon(codePoint: Icons.perm_identity.codePoint, color: "orange"));
|
||||||
|
nodes.add(actualNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
148
lib/view/exercise_log_page.dart
Normal file
148
lib/view/exercise_log_page.dart
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
|
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_treeview/tree_view.dart';
|
||||||
|
|
||||||
|
class ExerciseLogPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ExerciseLogPage createState() => _ExerciseLogPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExerciseLogPage extends State<ExerciseLogPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
|
||||||
|
final ExerciseRepository exerciseRepository = arguments['exerciseRepository'];
|
||||||
|
final CustomerRepository customerRepository = arguments['customerRepository'];
|
||||||
|
final int customerId = arguments['customerId'];
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBarCommonNav(),
|
||||||
|
body: Container(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: customerId == Cache().userLoggedIn.customerId ? AssetImage('asset/image/WT_light_background.png'):
|
||||||
|
AssetImage('asset/image/WT_menu_dark.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: exerciseWidget(exerciseRepository, customerId),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget exerciseWidget(ExerciseRepository exerciseRepository, int customerId) {
|
||||||
|
TreeViewController _treeViewController =
|
||||||
|
TreeViewController(children: nodeExercises(exerciseRepository, customerId));
|
||||||
|
|
||||||
|
TreeViewTheme _treeViewTheme = TreeViewTheme(
|
||||||
|
expanderTheme: ExpanderThemeData(
|
||||||
|
type: ExpanderType.caret,
|
||||||
|
modifier: ExpanderModifier.none,
|
||||||
|
position: ExpanderPosition.start,
|
||||||
|
color: Colors.red.shade800,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
labelStyle: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
letterSpacing: 0.1,
|
||||||
|
),
|
||||||
|
parentLabelStyle: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
letterSpacing: 0.1,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
color: Colors.orange.shade600,
|
||||||
|
),
|
||||||
|
iconTheme: IconThemeData(
|
||||||
|
size: 18,
|
||||||
|
color: Colors.grey.shade800,
|
||||||
|
),
|
||||||
|
colorScheme: ColorScheme.light(background: Colors.transparent),
|
||||||
|
);
|
||||||
|
|
||||||
|
return TreeView(
|
||||||
|
controller: _treeViewController,
|
||||||
|
allowParentSelect: false,
|
||||||
|
supportParentDoubleTap: false,
|
||||||
|
//onExpansionChanged: _expandNodeHandler,
|
||||||
|
onNodeTap: (key) {
|
||||||
|
setState(() {
|
||||||
|
_treeViewController = _treeViewController.copyWith(selectedKey: key);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
theme: _treeViewTheme,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Node> nodeExercises(ExerciseRepository exerciseRepository, int customerId) {
|
||||||
|
List<Node> nodes = List<Node>();
|
||||||
|
List<Exercise> exercises;
|
||||||
|
if ( customerId == Cache().userLoggedIn.customerId ) {
|
||||||
|
exercises = exerciseRepository.getExerciseList();
|
||||||
|
} else if ( Cache().getTrainee() != null && customerId == Cache().getTrainee().customerId ) {
|
||||||
|
exercises = exerciseRepository.getExerciseListTrainee();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String prevDay = "";
|
||||||
|
Node actualNode;
|
||||||
|
List<Node> listExercisesPerDay;
|
||||||
|
exercises.forEach((element) {
|
||||||
|
Exercise exercise = element;
|
||||||
|
ExerciseType exerciseType =
|
||||||
|
exerciseRepository.getExerciseTypeById(exercise.exerciseTypeId);
|
||||||
|
String actualDay = exercise.dateAdd.year.toString() +
|
||||||
|
"-" +
|
||||||
|
exercise.dateAdd.month.toString() +
|
||||||
|
"-" +
|
||||||
|
exercise.dateAdd.day.toString();
|
||||||
|
|
||||||
|
if (prevDay.compareTo(actualDay) != 0) {
|
||||||
|
listExercisesPerDay = List<Node>();
|
||||||
|
actualNode = Node(
|
||||||
|
label: actualDay,
|
||||||
|
key: exercise.dateAdd.toString(),
|
||||||
|
expanded: true,
|
||||||
|
children: listExercisesPerDay,
|
||||||
|
icon:
|
||||||
|
NodeIcon(codePoint: Icons.date_range.codePoint, color: "blue"));
|
||||||
|
nodes.add(actualNode);
|
||||||
|
prevDay = actualDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
String exerciseName = AppLanguage().appLocal == Locale("en")
|
||||||
|
? exerciseType.name
|
||||||
|
: exerciseType.nameTranslation;
|
||||||
|
String unitQuantity = exerciseType.unitQuantity == "1"
|
||||||
|
? exercise.unitQuantity.toStringAsFixed(0) +
|
||||||
|
" " +
|
||||||
|
AppLocalizations.of(context)
|
||||||
|
.translate(exerciseType.unitQuantityUnit) +
|
||||||
|
" "
|
||||||
|
: "";
|
||||||
|
|
||||||
|
String labelExercise = exerciseName +
|
||||||
|
" " +
|
||||||
|
unitQuantity +
|
||||||
|
exercise.quantity.toStringAsFixed(0) +
|
||||||
|
" " +
|
||||||
|
AppLocalizations.of(context).translate(exercise.unit);
|
||||||
|
listExercisesPerDay.add(Node(
|
||||||
|
label: labelExercise,
|
||||||
|
key: exercise.exerciseId.toString(),
|
||||||
|
expanded: false,
|
||||||
|
icon: NodeIcon(codePoint: Icons.repeat.codePoint, color: "blue")));
|
||||||
|
});
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
190
lib/view/exercise_plan_custom_page.dart
Normal file
190
lib/view/exercise_plan_custom_page.dart
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/workout_tree.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/splash.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_treeview/tree_view.dart';
|
||||||
|
|
||||||
|
class ExercisePlanCustomPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ExercisePlanCustomPage createState() => _ExercisePlanCustomPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExercisePlanCustomPage extends State<ExercisePlanCustomPage> {
|
||||||
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
|
// ignore: close_sinks
|
||||||
|
ExercisePlanBloc bloc;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
/// We require the initializers to run after the loading screen is rendered
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
BlocProvider.of<ExercisePlanBloc>(context).add(ExercisePlanLoad());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
|
||||||
|
final ExerciseRepository exerciseRepository = arguments['exerciseRepository'];
|
||||||
|
final int customerId = arguments['customerId'];
|
||||||
|
bloc = BlocProvider.of<ExercisePlanBloc>(context);
|
||||||
|
bloc.customerId = customerId;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
key: _scaffoldKey,
|
||||||
|
appBar: AppBarCommonNav(),
|
||||||
|
body: Container(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: customerId == Cache().userLoggedIn.customerId ? AssetImage('asset/image/WT_light_background.png'):
|
||||||
|
AssetImage('asset/image/WT_menu_dark.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: BlocConsumer<ExercisePlanBloc, ExercisePlanState>(listener: (context, state) {
|
||||||
|
if (state is ExercisePlanError) {
|
||||||
|
//showInSnackBar(state.message);
|
||||||
|
//return exerciseWidget(bloc);
|
||||||
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text(
|
||||||
|
state.message,
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.orange,
|
||||||
|
));
|
||||||
|
} else if (state is ExercisePlanLoading) {
|
||||||
|
LoadingDialog();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ignore: missing_return
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is ExercisePlanInitial) {
|
||||||
|
return Container();
|
||||||
|
} else if (state is ExercisePlanReady) {
|
||||||
|
return exerciseWidget(bloc);
|
||||||
|
} else if (state is ExercisePlanError) {
|
||||||
|
return exerciseWidget(bloc);
|
||||||
|
} else if (state is ExercisePlanLoading) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget exerciseWidget(ExercisePlanBloc bloc) {
|
||||||
|
TreeViewController _treeViewController = TreeViewController(children: nodeExercisePlan(bloc));
|
||||||
|
|
||||||
|
TreeViewTheme _treeViewTheme = TreeViewTheme(
|
||||||
|
expanderTheme: ExpanderThemeData(
|
||||||
|
type: ExpanderType.plusMinus,
|
||||||
|
modifier: ExpanderModifier.circleOutlined,
|
||||||
|
position: ExpanderPosition.start,
|
||||||
|
color: Colors.black26,
|
||||||
|
size: 10,
|
||||||
|
),
|
||||||
|
labelStyle: TextStyle(fontSize: 14, letterSpacing: 0, color: Colors.blue.shade800),
|
||||||
|
parentLabelStyle: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
letterSpacing: 0.3,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
color: Colors.orange.shade600,
|
||||||
|
),
|
||||||
|
iconTheme: IconThemeData(
|
||||||
|
size: 20,
|
||||||
|
color: Colors.blue.shade800,
|
||||||
|
),
|
||||||
|
colorScheme: bloc.customerId == Cache().userLoggedIn.customerId ? ColorScheme.light(background: Colors.transparent) : ColorScheme.dark(background: Colors.transparent),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
body: TreeView(
|
||||||
|
controller: _treeViewController,
|
||||||
|
allowParentSelect: true,
|
||||||
|
supportParentDoubleTap: false,
|
||||||
|
//onExpansionChanged: _expandNodeHandler,
|
||||||
|
onNodeTap: (key) {
|
||||||
|
Node<dynamic> node = _treeViewController.getNode(key);
|
||||||
|
WorkoutTree workoutTree = node.data as WorkoutTree;
|
||||||
|
bloc.exercisePlanRepository.setActualPlanDetail(workoutTree.exerciseType);
|
||||||
|
print("change node " + node.label + " key " + key);
|
||||||
|
bloc.add(ExercisePlanUpdate(workoutTree: workoutTree));
|
||||||
|
Navigator.of(context).pushNamed("exercisePlanDetailAdd", arguments: bloc);
|
||||||
|
},
|
||||||
|
theme: _treeViewTheme,
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
backgroundColor: Colors.blueAccent,
|
||||||
|
child: Icon(Icons.save_alt),
|
||||||
|
onPressed: () => {
|
||||||
|
bloc.add(ExercisePlanSave()),
|
||||||
|
if (bloc.exercisePlanRepository.getExercisePlanDetailSize() > 0) {
|
||||||
|
Navigator.of(context).pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
//bottomNavigationBar: BottomNavigator(bottomNavIndex: 2),
|
||||||
|
floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Node> nodeExercisePlan(ExercisePlanBloc bloc) {
|
||||||
|
List<Node> nodes = List<Node>();
|
||||||
|
Node actualNode;
|
||||||
|
bool isEnglish = AppLanguage().appLocal == Locale("en");
|
||||||
|
|
||||||
|
bloc.menuTreeRepository.sortedTree.forEach((name, list) {
|
||||||
|
List<WorkoutTree> listWorkoutItem = list;
|
||||||
|
List<Node> listExerciseTypePerMuscle = List<Node>();
|
||||||
|
NodeIcon icon;
|
||||||
|
listWorkoutItem.forEach((element) {
|
||||||
|
WorkoutTree treeItem = element;
|
||||||
|
icon =
|
||||||
|
treeItem.selected == true ? NodeIcon(codePoint: Icons.bubble_chart.codePoint, color: "blueAccent") : null;
|
||||||
|
|
||||||
|
String exerciseLabel = isEnglish
|
||||||
|
? treeItem.name
|
||||||
|
: treeItem.exerciseType == null ? treeItem.name : treeItem.exerciseType.nameTranslation;
|
||||||
|
|
||||||
|
List<Node<dynamic>> planDetailList = List<Node<dynamic>>();
|
||||||
|
String planDetail = bloc.exercisePlanRepository.getPlanDetail(treeItem.exerciseTypeId);
|
||||||
|
|
||||||
|
if (planDetail.length > 0) {
|
||||||
|
exerciseLabel += " (" + planDetail +")";
|
||||||
|
}
|
||||||
|
|
||||||
|
actualNode = Node(
|
||||||
|
label: exerciseLabel,
|
||||||
|
key: treeItem.id.toString(),
|
||||||
|
data: treeItem,
|
||||||
|
expanded: planDetailList.length > 0 ? true : false,
|
||||||
|
children: [],
|
||||||
|
icon: icon);
|
||||||
|
listExerciseTypePerMuscle.add(actualNode);
|
||||||
|
});
|
||||||
|
//print ("Node name " + name);
|
||||||
|
if (name != null) {
|
||||||
|
actualNode = Node(
|
||||||
|
label: name, // AppLocalizations.of(context).translate(name),
|
||||||
|
key: name,
|
||||||
|
expanded: true,
|
||||||
|
children: listExerciseTypePerMuscle,
|
||||||
|
icon: NodeIcon(codePoint: Icons.perm_identity.codePoint, color: "orange"));
|
||||||
|
nodes.add(actualNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
144
lib/view/exercise_plan_detail_add_page.dart
Normal file
144
lib/view/exercise_plan_detail_add_page.dart
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
|
||||||
|
import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart';
|
||||||
|
import 'package:aitrainer_app/bloc/exercise_plan_custom_form.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_language.dart';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||||
|
|
||||||
|
class ExercisePlanDetailAddPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_ExercisePlanDetailAddPage createState() => _ExercisePlanDetailAddPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final ExercisePlanBloc planBloc = ModalRoute.of(context).settings.arguments;
|
||||||
|
final ExercisePlanRepository exercisePlanRepository = planBloc.exercisePlanRepository;
|
||||||
|
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => ExercisePlanCustomerFormBloc(exercisePlanRepository: exercisePlanRepository, planBloc: planBloc),
|
||||||
|
child: Builder(builder: (context) {
|
||||||
|
// ignore: close_sinks
|
||||||
|
final bloc = BlocProvider.of<ExercisePlanCustomerFormBloc>(context);
|
||||||
|
|
||||||
|
String exerciseName = "";
|
||||||
|
if (bloc != null) {
|
||||||
|
exerciseName = AppLanguage().appLocal == Locale("en")
|
||||||
|
? bloc.exercisePlanRepository.actualPlanDetail.exerciseType.name
|
||||||
|
: bloc.exercisePlanRepository.actualPlanDetail.exerciseType.nameTranslation;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
autovalidate: true,
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: true,
|
||||||
|
appBar: AppBarCommonNav(),
|
||||||
|
body: Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(top: 25, left: 25, right: 25),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
child: Column(mainAxisAlignment: MainAxisAlignment.spaceAround, children: <Widget>[
|
||||||
|
Text(AppLocalizations.of(context).translate('Save The Exercise To The Exercise Plan'),
|
||||||
|
style: TextStyle(fontSize: 14, color: Colors.blueAccent)),
|
||||||
|
Text(
|
||||||
|
exerciseName,
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.deepOrange),
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
maxLines: 1,
|
||||||
|
softWrap: true,
|
||||||
|
),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
textFieldBloc: bloc.serieField,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||||
|
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 serie done with"),
|
||||||
|
labelStyle: TextStyle(fontSize: 16, color: Colors.lightBlue),
|
||||||
|
labelText: AppLocalizations.of(context).translate("Serie"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
textFieldBloc: bloc.quantityField,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||||
|
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 repeats of one serie"),
|
||||||
|
labelStyle: TextStyle(fontSize: 16, color: Colors.lightBlue),
|
||||||
|
labelText: AppLocalizations.of(context).translate("Repeats"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextFieldBlocBuilder(
|
||||||
|
textFieldBloc: bloc.weightField,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
|
||||||
|
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: false,
|
||||||
|
hintStyle: TextStyle(fontSize: 16, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||||
|
hintText: AppLocalizations.of(context).translate("The weight"),
|
||||||
|
labelStyle: TextStyle(fontSize: 16, color: Colors.lightBlue),
|
||||||
|
labelText: AppLocalizations.of(context).translate("Weight"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
RaisedButton(
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.red.shade300,
|
||||||
|
focusColor: Colors.white,
|
||||||
|
onPressed: () => {
|
||||||
|
print("Remove " + bloc.exercisePlanRepository.actualPlanDetail.exerciseType.name),
|
||||||
|
planBloc.add(ExercisePlanRemoveExercise(exercisePlanDetail: bloc.exercisePlanRepository.actualPlanDetail)),
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
},
|
||||||
|
child: Text("Delete"), //Text(AppLocalizations.of(context).translate("Delete"), style: TextStyle(fontSize: 16),)
|
||||||
|
),
|
||||||
|
RaisedButton(
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.blueAccent,
|
||||||
|
focusColor: Colors.white,
|
||||||
|
onPressed: () => {
|
||||||
|
bloc.submit(),
|
||||||
|
Navigator.of(context).pop(),
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).translate("Save"),
|
||||||
|
style: TextStyle(fontSize: 16),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@ -1,147 +0,0 @@
|
|||||||
import 'package:aitrainer_app/localization/app_language.dart';
|
|
||||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
|
||||||
import 'package:aitrainer_app/model/exercise.dart';
|
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
|
||||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_treeview/tree_view.dart';
|
|
||||||
|
|
||||||
class MyDevelopmentPage extends StatefulWidget {
|
|
||||||
@override
|
|
||||||
_MyDevelopmentPage createState() => _MyDevelopmentPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _MyDevelopmentPage extends State<MyDevelopmentPage> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBarNav(),
|
|
||||||
body: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
image: DecorationImage(
|
|
||||||
image: AssetImage('asset/image/WT_light_background.png'),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.all(10),
|
|
||||||
child:
|
|
||||||
exerciseWidget(exerciseRepository),
|
|
||||||
|
|
||||||
)
|
|
||||||
),
|
|
||||||
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget exerciseWidget(ExerciseRepository exerciseRepository) {
|
|
||||||
TreeViewController _treeViewController = TreeViewController(children: nodeExercises(exerciseRepository) );
|
|
||||||
|
|
||||||
TreeViewTheme _treeViewTheme = TreeViewTheme(
|
|
||||||
expanderTheme: ExpanderThemeData(
|
|
||||||
type: ExpanderType.caret,
|
|
||||||
modifier: ExpanderModifier.none,
|
|
||||||
position: ExpanderPosition.start,
|
|
||||||
color: Colors.red.shade800,
|
|
||||||
size: 20,
|
|
||||||
),
|
|
||||||
labelStyle: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
letterSpacing: 0.1,
|
|
||||||
),
|
|
||||||
parentLabelStyle: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
letterSpacing: 0.1,
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
color: Colors.orange.shade600,
|
|
||||||
),
|
|
||||||
iconTheme: IconThemeData(
|
|
||||||
size: 18,
|
|
||||||
color: Colors.grey.shade800,
|
|
||||||
),
|
|
||||||
colorScheme: ColorScheme.light(
|
|
||||||
background: Colors.transparent
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return TreeView(
|
|
||||||
controller: _treeViewController,
|
|
||||||
allowParentSelect: false,
|
|
||||||
supportParentDoubleTap: false,
|
|
||||||
//onExpansionChanged: _expandNodeHandler,
|
|
||||||
onNodeTap: (key) {
|
|
||||||
setState(() {
|
|
||||||
_treeViewController = _treeViewController.copyWith(selectedKey: key);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
theme: _treeViewTheme,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Node> nodeExercises(ExerciseRepository exerciseRepository) {
|
|
||||||
List<Node> nodes = List<Node>();
|
|
||||||
List<Exercise> exercises = exerciseRepository.getExerciseList();
|
|
||||||
|
|
||||||
String prevDay = "";
|
|
||||||
Node actualNode;
|
|
||||||
List<Node> listExercisesPerDay;
|
|
||||||
exercises.forEach((element) {
|
|
||||||
Exercise exercise = element;
|
|
||||||
ExerciseType exerciseType =
|
|
||||||
exerciseRepository.getExerciseTypeById(exercise.exerciseTypeId);
|
|
||||||
String actualDay = exercise.dateAdd.year.toString()+"-"+
|
|
||||||
exercise.dateAdd.month.toString()+"-"+
|
|
||||||
exercise.dateAdd.day.toString();
|
|
||||||
|
|
||||||
if ( prevDay.compareTo(actualDay) != 0) {
|
|
||||||
listExercisesPerDay = List<Node>();
|
|
||||||
actualNode =
|
|
||||||
Node(
|
|
||||||
label: actualDay,
|
|
||||||
key: exercise.dateAdd.toString(),
|
|
||||||
expanded: true,
|
|
||||||
children: listExercisesPerDay,
|
|
||||||
icon: NodeIcon(
|
|
||||||
codePoint: Icons.date_range.codePoint,
|
|
||||||
color: "blue"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
nodes.add(actualNode);
|
|
||||||
prevDay = actualDay;
|
|
||||||
}
|
|
||||||
|
|
||||||
String exerciseName = AppLanguage().appLocal == Locale("en") ?
|
|
||||||
exerciseType.name :
|
|
||||||
exerciseType.nameTranslation;
|
|
||||||
String unitQuantity = exerciseType.unitQuantity == "1" ?
|
|
||||||
exercise.unitQuantity.toStringAsFixed(0)
|
|
||||||
+ " " + AppLocalizations.of(context).translate(exerciseType.unitQuantityUnit) + " "
|
|
||||||
: "";
|
|
||||||
|
|
||||||
String labelExercise =
|
|
||||||
exerciseName + " " + unitQuantity
|
|
||||||
+ exercise.quantity.toStringAsFixed(0) + " "
|
|
||||||
+ AppLocalizations.of(context).translate(exercise.unit);
|
|
||||||
listExercisesPerDay.add(
|
|
||||||
Node(
|
|
||||||
label: labelExercise,
|
|
||||||
key: exercise.exerciseId.toString(),
|
|
||||||
expanded: false,
|
|
||||||
icon: NodeIcon(
|
|
||||||
codePoint: Icons.repeat.codePoint,
|
|
||||||
color: "blue"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
196
lib/view/myexcercise_plan_page.dart
Normal file
196
lib/view/myexcercise_plan_page.dart
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||||
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class MyExercisePlanPage extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_MyExercisePlanPage createState() => _MyExercisePlanPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyExercisePlanPage extends State<MyExercisePlanPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
|
final LinkedHashMap args = LinkedHashMap();
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBarCommonNav(),
|
||||||
|
body: Container(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage('asset/image/WT_light_background.png'),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: CustomScrollView(
|
||||||
|
scrollDirection: Axis.vertical,
|
||||||
|
slivers:
|
||||||
|
[
|
||||||
|
SliverGrid(
|
||||||
|
delegate: SliverChildListDelegate(
|
||||||
|
[
|
||||||
|
FlatButton(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.black12,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
args['customerId'] = Cache().userLoggedIn.customerId,
|
||||||
|
Navigator.of(context).pushNamed('exerciseByPlanPage',
|
||||||
|
arguments: args)
|
||||||
|
},
|
||||||
|
child: Text("Execute My Selected Training Plan",
|
||||||
|
style: TextStyle(fontSize: 18),)
|
||||||
|
),
|
||||||
|
|
||||||
|
FlatButton(
|
||||||
|
padding: EdgeInsets.all(0),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.black12,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
args['exerciseRepository'] = exerciseRepository,
|
||||||
|
args['customerId'] = Cache().userLoggedIn.customerId,
|
||||||
|
Navigator.of(context).pushNamed('exercisePlanCustomPage',
|
||||||
|
arguments: args)
|
||||||
|
},
|
||||||
|
child: Text("Edit My Custom Plan",
|
||||||
|
style: TextStyle(fontSize: 18),)
|
||||||
|
),
|
||||||
|
FlatButton(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.black12,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Text("Suggested Plan",
|
||||||
|
style: TextStyle(fontSize: 18),)
|
||||||
|
),
|
||||||
|
Stack(
|
||||||
|
fit: StackFit.passthrough,
|
||||||
|
overflow: Overflow.clip,
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
children: [
|
||||||
|
Image.asset('asset/image/lock.png',
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
),
|
||||||
|
FlatButton(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.black12,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Text("My Special Plan",
|
||||||
|
style: TextStyle(fontSize: 18),)
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
Stack(
|
||||||
|
fit: StackFit.passthrough,
|
||||||
|
overflow: Overflow.clip,
|
||||||
|
children: [
|
||||||
|
Image.asset('asset/image/lock.png',
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
),
|
||||||
|
FlatButton(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.black12,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Text("My Arnold's Plan",
|
||||||
|
style: TextStyle(fontSize: 18),)
|
||||||
|
),
|
||||||
|
|
||||||
|
]
|
||||||
|
),
|
||||||
|
|
||||||
|
hiddenPlanWidget(exerciseRepository),
|
||||||
|
hiddenTrainingWidget(),
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
),
|
||||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount: 2,
|
||||||
|
mainAxisSpacing: 20.0,
|
||||||
|
crossAxisSpacing: 20.0,
|
||||||
|
childAspectRatio: 1.2,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
bottomNavigationBar: BottomNavigator(bottomNavIndex: 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget hiddenPlanWidget(ExerciseRepository exerciseRepository) {
|
||||||
|
final LinkedHashMap args = LinkedHashMap();
|
||||||
|
if ( Cache().getTrainee() != null ) {
|
||||||
|
return FlatButton(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.black12,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
args['exerciseRepository'] = exerciseRepository,
|
||||||
|
args['customerId'] = Cache().getTrainee().customerId,
|
||||||
|
Navigator.of(context).pushNamed('exercisePlanCustomPage',
|
||||||
|
arguments: args)
|
||||||
|
},
|
||||||
|
child: Text("My Trainee's Plan",
|
||||||
|
style: TextStyle(fontSize: 18),)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget hiddenTrainingWidget() {
|
||||||
|
final LinkedHashMap args = LinkedHashMap();
|
||||||
|
if ( Cache().getTrainee() != null ) {
|
||||||
|
print ("!!Trainee: " + Cache().getTrainee().firstname + " " + Cache().getTrainee().name);
|
||||||
|
return FlatButton(
|
||||||
|
padding: EdgeInsets.all(20),
|
||||||
|
textColor: Colors.white,
|
||||||
|
color: Colors.black12,
|
||||||
|
focusColor: Colors.blueAccent,
|
||||||
|
onPressed: () =>
|
||||||
|
{
|
||||||
|
args['customerId'] = Cache().getTrainee().customerId,
|
||||||
|
Navigator.of(context).pushNamed('exerciseByPlanPage',
|
||||||
|
arguments: args)
|
||||||
|
},
|
||||||
|
child: Text("Execute My Trainee's Training Plan",
|
||||||
|
style: TextStyle(fontSize: 18),)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -109,6 +109,13 @@ class SettingsPage extends StatelessWidget{
|
|||||||
)
|
)
|
||||||
|
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.get_app),
|
||||||
|
title: RaisedButton(
|
||||||
|
child: Text("Check lang", style: TextStyle(fontSize: 12),),
|
||||||
|
onPressed: () => settingsBloc.add(SettingsGetLanguage()),
|
||||||
|
)
|
||||||
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -56,14 +56,15 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
}); */
|
}); */
|
||||||
colorAnim = RainbowColorTween([Colors.white70,
|
colorAnim = RainbowColorTween([Colors.white70,
|
||||||
Colors.greenAccent,
|
Colors.blueGrey,
|
||||||
Colors.lightGreen,
|
Colors.blueAccent,
|
||||||
Colors.lightGreenAccent,
|
Colors.lightBlue,
|
||||||
Colors.yellow,
|
Colors.lightBlueAccent,
|
||||||
Colors.yellowAccent,
|
Colors.yellowAccent,
|
||||||
Colors.orange,
|
Colors.orange,
|
||||||
Colors.orangeAccent,
|
Colors.orangeAccent,
|
||||||
Colors.white70])
|
Colors.yellowAccent,
|
||||||
|
Color(0xffcce6ff)])
|
||||||
.animate(colorController)
|
.animate(colorController)
|
||||||
..addListener(() { setState(() {}); })
|
..addListener(() { setState(() {}); })
|
||||||
..addStatusListener((status) {
|
..addStatusListener((status) {
|
||||||
@ -103,7 +104,9 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
|||||||
icon: Icon(Icons.arrow_back, color: Colors.white),
|
icon: Icon(Icons.arrow_back, color: Colors.white),
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
{
|
{
|
||||||
menuBloc.add(MenuTreeUp(parent: 0))
|
if ( menuBloc != null ) {
|
||||||
|
menuBloc.add(MenuTreeUp(parent: 0)),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -151,7 +154,7 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
|||||||
trailing: Icon(percent > 0.6 ? Icons.mood : Icons.mood_bad, color: colorAnim.value,),
|
trailing: Icon(percent > 0.6 ? Icons.mood : Icons.mood_bad, color: colorAnim.value,),
|
||||||
linearStrokeCap: LinearStrokeCap.roundAll,
|
linearStrokeCap: LinearStrokeCap.roundAll,
|
||||||
backgroundColor: colorAnim.value,
|
backgroundColor: colorAnim.value,
|
||||||
progressColor: Colors.blue,
|
progressColor: Color(0xff73e600),
|
||||||
animation: true,
|
animation: true,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
133
lib/widgets/app_bar_common.dart
Normal file
133
lib/widgets/app_bar_common.dart
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:percent_indicator/linear_percent_indicator.dart';
|
||||||
|
import 'package:rainbow_color/rainbow_color.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class AppBarCommonNav extends StatefulWidget implements PreferredSizeWidget {
|
||||||
|
|
||||||
|
@override
|
||||||
|
_AppBarCommonNav createState() => _AppBarCommonNav();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size get preferredSize => const Size.fromHeight(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppBarCommonNav extends State<AppBarCommonNav> with SingleTickerProviderStateMixin {
|
||||||
|
Animation<Color> colorAnim;
|
||||||
|
AnimationController colorController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
|
||||||
|
colorController =
|
||||||
|
AnimationController(duration: Duration(seconds: 4), vsync: this);
|
||||||
|
|
||||||
|
colorAnim = RainbowColorTween([Colors.white70,
|
||||||
|
Colors.blueGrey,
|
||||||
|
Colors.blueAccent,
|
||||||
|
Colors.lightBlue,
|
||||||
|
Colors.lightBlueAccent,
|
||||||
|
Colors.yellowAccent,
|
||||||
|
Colors.orange,
|
||||||
|
Colors.orangeAccent,
|
||||||
|
Colors.yellowAccent,
|
||||||
|
Color(0xffcce6ff)])
|
||||||
|
.animate(colorController)
|
||||||
|
..addListener(() { setState(() {}); })
|
||||||
|
..addStatusListener((status) {
|
||||||
|
if (status == AnimationStatus.completed) {
|
||||||
|
Timer(Duration(seconds: 10), () {
|
||||||
|
//colorController.reset();
|
||||||
|
if ( mounted ) {
|
||||||
|
colorController.forward();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (status == AnimationStatus.dismissed) {
|
||||||
|
colorController.forward();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
colorController.forward();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AppBar(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
|
||||||
|
getAnimatedWidget(),
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
//sizeController.dispose();
|
||||||
|
colorController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget getAnimatedWidget() {
|
||||||
|
double percent = Cache().getPercentExercises();
|
||||||
|
if ( percent == -1) {
|
||||||
|
ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
|
exerciseRepository.getBaseExerciseFinishedPercent();
|
||||||
|
percent = Cache().getPercentExercises();
|
||||||
|
}
|
||||||
|
int sizeExerciseList = Cache().getExercises() == null? 0 : Cache().getExercises().length;
|
||||||
|
if ( sizeExerciseList == 0 ) {
|
||||||
|
return Stack(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
children: [
|
||||||
|
Text(AppLocalizations.of(context).translate("Make your first test"),
|
||||||
|
style: TextStyle(fontSize: 16, color: colorAnim.value, shadows: [Shadow(color: Colors.purple , blurRadius: 15)]),
|
||||||
|
|
||||||
|
),
|
||||||
|
//TestProgress(animation: sizeAnim),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return Stack(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
children: [
|
||||||
|
LinearPercentIndicator(
|
||||||
|
width: 120.0,
|
||||||
|
lineHeight: 14.0,
|
||||||
|
percent: percent,
|
||||||
|
center: Text(
|
||||||
|
(percent * 100).toStringAsFixed(0) + "% finished",
|
||||||
|
style: new TextStyle(fontSize: 12.0),
|
||||||
|
),
|
||||||
|
trailing: Icon(percent > 0.6 ? Icons.mood : Icons.mood_bad, color: colorAnim.value,),
|
||||||
|
linearStrokeCap: LinearStrokeCap.roundAll,
|
||||||
|
backgroundColor: colorAnim.value,
|
||||||
|
progressColor: Color(0xff73e600),
|
||||||
|
animation: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -91,12 +91,13 @@ class _NawDrawerWidget extends State<BottomNavigator> {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
Navigator.of(context).pop();
|
//Navigator.of(context).pop();
|
||||||
Navigator.of(context).pushNamed('mydevelopment');
|
Navigator.of(context).pushNamed('myDevelopment');
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
|
||||||
//throw new StateError('This is a Dart exception on event.');
|
//Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pushNamed('myExercisePlan');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -24,7 +24,6 @@ class AitrainerHome extends StatefulWidget {
|
|||||||
|
|
||||||
class _HomePageState extends State<AitrainerHome> {
|
class _HomePageState extends State<AitrainerHome> {
|
||||||
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
final AppLanguage appLanguage = AppLanguage();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -45,7 +44,9 @@ class _HomePageState extends State<AitrainerHome> {
|
|||||||
sessionBloc.add(SessionStart());
|
sessionBloc.add(SessionStart());
|
||||||
// ignore: close_sinks
|
// ignore: close_sinks
|
||||||
SettingsBloc settingsBloc = BlocProvider.of<SettingsBloc>(context);
|
SettingsBloc settingsBloc = BlocProvider.of<SettingsBloc>(context);
|
||||||
settingsBloc.loadLang();
|
String lang = AppLanguage().appLocal.languageCode;
|
||||||
|
print (" -- Loading delayed lang $lang");
|
||||||
|
settingsBloc.add(SettingsChangeLanguage(language: lang));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,8 +6,8 @@ class LoadingScreenMain extends StatelessWidget {
|
|||||||
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',
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
//height: double.infinity,
|
height: double.infinity,
|
||||||
//width: double.infinity,
|
width: double.infinity,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
);
|
);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -37,7 +37,7 @@ class MenuPageWidget extends StatelessWidget {
|
|||||||
child: Center(
|
child: Center(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.bottomLeft,
|
alignment: Alignment.bottomLeft,
|
||||||
fit: StackFit.loose,
|
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||||
children: [
|
children: [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: _getButtonImage(workoutTree),
|
child: _getButtonImage(workoutTree),
|
||||||
@ -45,21 +45,35 @@ class MenuPageWidget extends StatelessWidget {
|
|||||||
shape: getShape(workoutTree),
|
shape: getShape(workoutTree),
|
||||||
onPressed: () => menuClick(workoutTree, menuBloc, context),
|
onPressed: () => menuClick(workoutTree, menuBloc, context),
|
||||||
),
|
),
|
||||||
InkWell(
|
Positioned(
|
||||||
onTap:() => menuClick(workoutTree, menuBloc, context),
|
top: workoutTree.name.length > 30 ? 140 : 150,
|
||||||
child: Text(
|
left: 5,
|
||||||
" " + workoutTree.name,
|
child: Container(
|
||||||
maxLines: 2,
|
height: 300,
|
||||||
style: TextStyle(
|
width: 280,
|
||||||
color: workoutTree.color,
|
child: InkWell(
|
||||||
fontSize: workoutTree.fontSize,
|
onTap:() => menuClick(workoutTree, menuBloc, context),
|
||||||
fontFamily: 'Arial',
|
child: Text(
|
||||||
fontWeight: FontWeight.w900),
|
" " + workoutTree.name,
|
||||||
|
maxLines: 2,
|
||||||
|
style: TextStyle(
|
||||||
|
color: workoutTree.color,
|
||||||
|
fontSize: workoutTree.fontSize,
|
||||||
|
fontFamily: 'Arial',
|
||||||
|
fontWeight: FontWeight.w900),
|
||||||
|
),
|
||||||
|
|
||||||
|
highlightColor: workoutTree.color,
|
||||||
|
),
|
||||||
|
color: Colors.transparent,
|
||||||
),
|
),
|
||||||
highlightColor: workoutTree.color,
|
|
||||||
),
|
),
|
||||||
|
|
||||||
]))));
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
SliverList sliverList =
|
SliverList sliverList =
|
||||||
|
888
pubspec.lock
888
pubspec.lock
@ -1,888 +0,0 @@
|
|||||||
# Generated by pub
|
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
|
||||||
packages:
|
|
||||||
_fe_analyzer_shared:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: _fe_analyzer_shared
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "7.0.0"
|
|
||||||
analyzer:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: analyzer
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.39.17"
|
|
||||||
archive:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: archive
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.13"
|
|
||||||
args:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: args
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.6.0"
|
|
||||||
async:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: async
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.4.1"
|
|
||||||
bloc:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: bloc
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "6.0.3"
|
|
||||||
bloc_test:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: bloc_test
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "7.0.3"
|
|
||||||
boolean_selector:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: boolean_selector
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
build:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: build
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.0"
|
|
||||||
build_config:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: build_config
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.4.2"
|
|
||||||
build_daemon:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: build_daemon
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.4"
|
|
||||||
build_resolvers:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: build_resolvers
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.11"
|
|
||||||
build_runner:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: build_runner
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.10.0"
|
|
||||||
build_runner_core:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: build_runner_core
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "5.2.0"
|
|
||||||
built_collection:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: built_collection
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.3.2"
|
|
||||||
built_value:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: built_value
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "7.1.0"
|
|
||||||
charcode:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: charcode
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.3"
|
|
||||||
checked_yaml:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: checked_yaml
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.2"
|
|
||||||
cli_util:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: cli_util
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.0"
|
|
||||||
code_builder:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: code_builder
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.4.1"
|
|
||||||
collection:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: collection
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.14.12"
|
|
||||||
convert:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: convert
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.1"
|
|
||||||
coverage:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: coverage
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.13.11"
|
|
||||||
crypto:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: crypto
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.4"
|
|
||||||
csslib:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: csslib
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.16.2"
|
|
||||||
cupertino_icons:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: cupertino_icons
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.3"
|
|
||||||
dart_style:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: dart_style
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.6"
|
|
||||||
devicelocale:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: devicelocale
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.3.1"
|
|
||||||
equatable:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: equatable
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.4"
|
|
||||||
file:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: file
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "5.1.0"
|
|
||||||
fixnum:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: fixnum
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.10.11"
|
|
||||||
flutter:
|
|
||||||
dependency: "direct main"
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_bloc:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_bloc
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "6.0.4"
|
|
||||||
flutter_driver:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
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.2"
|
|
||||||
flutter_launcher_icons:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: flutter_launcher_icons
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.5"
|
|
||||||
flutter_local_notifications:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_local_notifications
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.1"
|
|
||||||
flutter_local_notifications_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_local_notifications_platform_interface
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.1"
|
|
||||||
flutter_localizations:
|
|
||||||
dependency: "direct main"
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_test:
|
|
||||||
dependency: transitive
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_treeview:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_treeview
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.6.0+1"
|
|
||||||
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"
|
|
||||||
freezed:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: freezed
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.11.6"
|
|
||||||
freezed_annotation:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: freezed_annotation
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.11.0+1"
|
|
||||||
fuchsia_remote_debug_protocol:
|
|
||||||
dependency: transitive
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
glob:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: glob
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.0"
|
|
||||||
gradient_bottom_navigation_bar:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: gradient_bottom_navigation_bar
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0+4"
|
|
||||||
graphs:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: graphs
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.0"
|
|
||||||
html:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: html
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.14.0+3"
|
|
||||||
http:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: http
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.12.1"
|
|
||||||
http_multi_server:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: http_multi_server
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.2.0"
|
|
||||||
http_parser:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: http_parser
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.4"
|
|
||||||
image:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: image
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.12"
|
|
||||||
intl:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: intl
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.16.1"
|
|
||||||
io:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: io
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.3.4"
|
|
||||||
js:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: js
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.6.2"
|
|
||||||
json_annotation:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: json_annotation
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.1"
|
|
||||||
json_rpc_2:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: json_rpc_2
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.0"
|
|
||||||
logging:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: logging
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.11.4"
|
|
||||||
matcher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: matcher
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.12.6"
|
|
||||||
meta:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: meta
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.8"
|
|
||||||
mime:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: mime
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.9.7"
|
|
||||||
mockito:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: mockito
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.1"
|
|
||||||
multi_server_socket:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: multi_server_socket
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.2"
|
|
||||||
nested:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: nested
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.4"
|
|
||||||
node_interop:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: node_interop
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.1"
|
|
||||||
node_io:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: node_io
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.1"
|
|
||||||
node_preamble:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: node_preamble
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.12"
|
|
||||||
package_config:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: package_config
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.9.3"
|
|
||||||
path:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: path
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.6.4"
|
|
||||||
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.3"
|
|
||||||
pedantic:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pedantic
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.9.0"
|
|
||||||
percent_indicator:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: percent_indicator
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.5"
|
|
||||||
petitparser:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: petitparser
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.4.0"
|
|
||||||
platform:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: platform
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.2.1"
|
|
||||||
plugin_platform_interface:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: plugin_platform_interface
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.2"
|
|
||||||
pool:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pool
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.0"
|
|
||||||
process:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: process
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.12"
|
|
||||||
provider:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: provider
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.3.2+1"
|
|
||||||
pub_semver:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pub_semver
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.4"
|
|
||||||
pubspec_parse:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pubspec_parse
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.5"
|
|
||||||
quiver:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: quiver
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.3"
|
|
||||||
rainbow_color:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: rainbow_color
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.1"
|
|
||||||
rainbow_vis:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: rainbow_vis
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.3"
|
|
||||||
rxdart:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: rxdart
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.24.1"
|
|
||||||
sentry:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: sentry
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.1"
|
|
||||||
shared_preferences:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: shared_preferences
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.5.10"
|
|
||||||
shared_preferences_linux:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shared_preferences_linux
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.2+2"
|
|
||||||
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:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.9"
|
|
||||||
shelf_packages_handler:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_packages_handler
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
shelf_static:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_static
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.8"
|
|
||||||
shelf_web_socket:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_web_socket
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.3"
|
|
||||||
sky_engine:
|
|
||||||
dependency: transitive
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.99"
|
|
||||||
source_gen:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_gen
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.9.6"
|
|
||||||
source_map_stack_trace:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_map_stack_trace
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
source_maps:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_maps
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.10.9"
|
|
||||||
source_span:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_span
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
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:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stack_trace
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.9.3"
|
|
||||||
stream_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stream_channel
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
stream_transform:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stream_transform
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.0"
|
|
||||||
string_scanner:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: string_scanner
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.5"
|
|
||||||
sync_http:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: sync_http
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.0"
|
|
||||||
term_glyph:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: term_glyph
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.0"
|
|
||||||
test:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: test
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.14.4"
|
|
||||||
test_api:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_api
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.15"
|
|
||||||
test_core:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_core
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.3.4"
|
|
||||||
timing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: timing
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.1+2"
|
|
||||||
typed_data:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: typed_data
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.6"
|
|
||||||
usage:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: usage
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.4.2"
|
|
||||||
uuid:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: uuid
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.2.2"
|
|
||||||
vector_math:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vector_math
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.8"
|
|
||||||
vm_service:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vm_service
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "4.2.0"
|
|
||||||
vm_service_client:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vm_service_client
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.6+2"
|
|
||||||
watcher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: watcher
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.9.7+15"
|
|
||||||
web_socket_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: web_socket_channel
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.0"
|
|
||||||
webdriver:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: webdriver
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
webkit_inspection_protocol:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: webkit_inspection_protocol
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.3"
|
|
||||||
xdg_directories:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: xdg_directories
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.0"
|
|
||||||
xml:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: xml
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.6.1"
|
|
||||||
yaml:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: yaml
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.2.1"
|
|
||||||
sdks:
|
|
||||||
dart: ">=2.7.0 <3.0.0"
|
|
||||||
flutter: ">=1.16.0 <2.0.0"
|
|
16
pubspec.yaml
16
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+12
|
version: 1.1.0+20
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.7.0 <3.0.0"
|
sdk: ">=2.7.0 <3.0.0"
|
||||||
@ -26,19 +26,19 @@ dependencies:
|
|||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^0.1.3
|
cupertino_icons: ^1.0.0
|
||||||
devicelocale: ^0.3.1
|
devicelocale: ^0.3.2
|
||||||
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_facebook_login: ^3.0.0
|
||||||
flutter_bloc: ^6.0.4
|
flutter_bloc: ^6.0.5
|
||||||
equatable: ^1.2.4
|
equatable: ^1.2.4
|
||||||
freezed: ^0.11.6
|
freezed: ^0.11.6
|
||||||
flutter_form_bloc: ^0.19.0
|
flutter_form_bloc: ^0.19.0
|
||||||
spider_chart: ^0.1.5
|
spider_chart: ^0.1.5
|
||||||
rainbow_color: ^0.1.1
|
rainbow_color: ^0.1.1
|
||||||
percent_indicator: ^2.1.5
|
percent_indicator: ^2.1.6
|
||||||
gradient_bottom_navigation_bar: ^1.0.0+4
|
gradient_bottom_navigation_bar: ^1.0.0+4
|
||||||
flutter_treeview: ^0.6.0+1
|
flutter_treeview: ^0.6.0+1
|
||||||
|
|
||||||
@ -51,17 +51,16 @@ dev_dependencies:
|
|||||||
flutter_driver:
|
flutter_driver:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
test: any
|
test: any
|
||||||
bloc_test: ^7.0.1
|
bloc_test: ^7.0.3
|
||||||
|
|
||||||
build_runner:
|
build_runner:
|
||||||
|
|
||||||
|
|
||||||
http: 0.12.1
|
http: 0.12.1
|
||||||
provider: ^4.3.2+1
|
|
||||||
intl: 0.16.1
|
intl: 0.16.1
|
||||||
shared_preferences: ^0.5.10
|
shared_preferences: ^0.5.10
|
||||||
|
|
||||||
flutter_launcher_icons: ^0.7.5
|
flutter_launcher_icons: ^0.8.0
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
android: "launcher_icon"
|
android: "launcher_icon"
|
||||||
@ -94,6 +93,7 @@ flutter:
|
|||||||
- 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/image/login_fb.png
|
||||||
|
- asset/image/lock.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());
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
52
test/customer_service_test.dart
Normal file
52
test/customer_service_test.dart
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/customer.dart';
|
||||||
|
import 'package:aitrainer_app/service/customer_service.dart';
|
||||||
|
import 'package:aitrainer_app/util/env.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:mockito/mockito.dart';
|
||||||
|
//import 'package:mockito/mockito.dart';
|
||||||
|
|
||||||
|
// Create a MockClient using the Mock class provided by the Mockito package.
|
||||||
|
// Create new instances of this class in each test.
|
||||||
|
/* class MockClient extends Mock implements CustomerApi {
|
||||||
|
Future<List<Customer>> getTrainees(int trainerId) async {
|
||||||
|
if (trainerId == 62) {
|
||||||
|
List<Customer> list = List<Customer>();
|
||||||
|
Customer customer1 = Customer(firstname: "Zalán", name: "Boss");
|
||||||
|
Customer customer2 = Customer(firstname: "Zétény", name: "Boss");
|
||||||
|
list.add(customer1);
|
||||||
|
list.add(customer2);
|
||||||
|
return list;
|
||||||
|
} else {
|
||||||
|
throw Exception("No trainees found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
main() {
|
||||||
|
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
Cache().setTestBaseUrl();
|
||||||
|
});
|
||||||
|
|
||||||
|
group('fetchPost', () {
|
||||||
|
test('returns a List<Customer> if the http call completes successfully', () async {
|
||||||
|
final client = CustomerApi();
|
||||||
|
|
||||||
|
// Use Mockito to return a successful response when it calls the
|
||||||
|
// provided http.Client.
|
||||||
|
List<Customer> trainees = List<Customer>();
|
||||||
|
trainees = await client.getTrainees(62);
|
||||||
|
|
||||||
|
expect(trainees.length, 2);
|
||||||
|
expect(trainees[0].firstname, "Zalán");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('throws an exception if the http call completes with an error', () async {
|
||||||
|
final client = CustomerApi();
|
||||||
|
|
||||||
|
expect(client.getTrainees(22), throwsException);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
72
test/exercise_plan_test.dart
Normal file
72
test/exercise_plan_test.dart
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan.dart';
|
||||||
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||||
|
import 'package:aitrainer_app/service/exercise_plan_service.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
Cache().setTestBaseUrl();
|
||||||
|
});
|
||||||
|
|
||||||
|
group('new Plan', () {
|
||||||
|
test('add new plan and plan details', () async {
|
||||||
|
final client = ExercisePlanApi();
|
||||||
|
|
||||||
|
ExercisePlan exercisePlan = ExercisePlan(
|
||||||
|
"Test plan " + DateTime.now().toIso8601String(),
|
||||||
|
62
|
||||||
|
);
|
||||||
|
exercisePlan.dateAdd = DateTime.now();
|
||||||
|
|
||||||
|
ExercisePlan savedPlan = await client.saveExercisePlan(exercisePlan);
|
||||||
|
expect(savedPlan.name.substring(0, 9), "Test plan");
|
||||||
|
expect(savedPlan.customerId, 62);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int newPlanId = savedPlan.exercisePlanId;
|
||||||
|
//savedPlan.exercisePlanId = newPlanId;
|
||||||
|
|
||||||
|
ExercisePlanDetail detail = ExercisePlanDetail(
|
||||||
|
39 //exerciseTypeId
|
||||||
|
);
|
||||||
|
detail.serie = 3;
|
||||||
|
detail.repeats = 12;
|
||||||
|
detail.weightEquation = "90";
|
||||||
|
detail.exercisePlanId = newPlanId;
|
||||||
|
|
||||||
|
ExercisePlanDetail savedDetail = await client.saveExercisePlanDetail(detail);
|
||||||
|
|
||||||
|
expect(savedDetail.weightEquation, "90");
|
||||||
|
expect(savedDetail.repeats, 12);
|
||||||
|
expect(savedDetail.exercisePlanId, newPlanId);
|
||||||
|
|
||||||
|
await client.deleteExercisePlanDetail(savedDetail.exercisePlanDetailId);
|
||||||
|
await client.deleteExercisePlan(savedPlan.exercisePlanId);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('get the last plan and change plan details', () async {
|
||||||
|
final client = ExercisePlanApi();
|
||||||
|
|
||||||
|
ExercisePlan exercisePlan = await client.getLastExercisePlan(61);
|
||||||
|
List<ExercisePlanDetail> list = await client.getExercisePlanDetail(exercisePlan.exercisePlanId);
|
||||||
|
|
||||||
|
expect(list.length, 2);
|
||||||
|
ExercisePlanDetail detail = ExercisePlanDetail(3);
|
||||||
|
detail.serie = 4;
|
||||||
|
detail.repeats = 12;
|
||||||
|
detail.weightEquation = "10";
|
||||||
|
detail.exercisePlanId = exercisePlan.exercisePlanId;
|
||||||
|
//list.add(detail);
|
||||||
|
ExercisePlanDetail newObjectToSave = await client.saveExercisePlanDetail(detail);
|
||||||
|
List<ExercisePlanDetail> list2 = await client.getExercisePlanDetail(exercisePlan.exercisePlanId);
|
||||||
|
expect(list2.length, 3);
|
||||||
|
expect(list2.last.weightEquation, "10");
|
||||||
|
await client.deleteExercisePlanDetail(newObjectToSave.exercisePlanDetailId);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user