wt1.1.2d ProgressInfo+

This commit is contained in:
Bossanyi Tibor 2020-10-09 07:54:54 +02:00
parent 0cdc3a9d24
commit 35f0d0042f
66 changed files with 1615 additions and 576 deletions

BIN
asset/image/Congrats_N1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

BIN
asset/menu/Back_pullup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
asset/menu/biceps.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
asset/menu/calf.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
asset/menu/legpress.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
asset/menu/squat.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

BIN
asset/menu/tricdip.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

View File

@ -170,5 +170,29 @@
"Custom Exercise Plan": "Custom Exercise Plan", "Custom Exercise Plan": "Custom Exercise Plan",
"Select manually the exercises what you would like to have in your plan. At the end don't forget to save.": "Select manually the exercises what you would like to have in your plan. At the end don't forget to save.", "Select manually the exercises what you would like to have in your plan. At the end don't forget to save.": "Select manually the exercises what you would like to have in your plan. At the end don't forget to save.",
"In this list you will find all your executed exercises grouped by the date.": "In this list you will find all your executed exercises grouped by the date." "In this list you will find all your executed exercises grouped by the date.": "In this list you will find all your executed exercises grouped by the date.",
"Persistence!": "Persistence!",
"Greetings!": "Greetings!",
"The purpose is to measure you physical condition": "The purpose is to measure you physical condition.",
"The suggested order of the exercises: chest - biceps - triceps - back - shoulders - core - tigh - calf.": "The suggested order of the exercises: chest - biceps - triceps - back - shoulders - core - tigh - calf.",
"Go to the menu Strength - One Rep Max - Chest, and select your favourite exercise.": "Go to the menu Strength - One Rep Max - Chest, and select your favourite exercise.",
"Please continue your tests with a": "Please continue your tests with a",
"I suggest begin your tests with a": "I suggest begin your tests with a 'chest' exercise",
"Nice! This is a good start": "Nice! This is a good start",
"Go on!":"Go on!",
"You are on track": "You are on track",
"Not so much left": "Not so much left",
"Almost!": "Almost done!",
"You have only 1-2 exercise left to finish!": "You have only 1-2 exercise left to finish!",
"exercise!": "exercise!",
"Chest": "Chest",
"Back": "Back",
"Thigh": "Thigh",
"Calf": "Calf",
"Bring me there": "Bring me there",
"My Body Development": "My Body Development",
"You see here your whole body development by muscle groups.": "You see here your whole body development by muscle groups."
} }

View File

@ -169,5 +169,29 @@
"Select the muscle type and tap on the exercise. One the next page enter the weight and repeat.": "Válaszd ki az izomcsoporton belül a gyakorlatot, és a következő oldalon add meg a súlyt és az ismétlés számot.", "Select the muscle type and tap on the exercise. One the next page enter the weight and repeat.": "Válaszd ki az izomcsoporton belül a gyakorlatot, és a következő oldalon add meg a súlyt és az ismétlés számot.",
"Custom Exercise Plan": "Egyedi edzésterv", "Custom Exercise Plan": "Egyedi edzésterv",
"Select manually the exercises what you would like to have in your plan. At the end don't forget to save.": "Válaszd ki a gyakorlatokat, amelyeket szeretnél végrehajtani a tervedben. Utána ne felejtsd el elmenteni.", "Select manually the exercises what you would like to have in your plan. At the end don't forget to save.": "Válaszd ki a gyakorlatokat, amelyeket szeretnél végrehajtani a tervedben. Utána ne felejtsd el elmenteni.",
"In this list you will find all your executed exercises grouped by the date.": "Ebben a listában találod az eddig végrehajtott gyakorlataid dátum szerint csoportosítva." "In this list you will find all your executed exercises grouped by the date.": "Ebben a listában találod az eddig végrehajtott gyakorlataid dátum szerint csoportosítva.",
"Persistence!": "Kitartás!",
"Greetings!": "Üdvözöllek!",
"The purpose is to measure you physical condition": "A cél a jelenlegi fizikai kondíciód felmérése.",
"The suggested order of the exercises: chest - biceps - triceps - back - shoulders - core - tigh - calf.": "A gyakorlatok javasolt végrehajtási sorrendje: mell - bicepsz - tricepsz - hát - váll - has - comb - vádli.",
"Go to the menu Strength - One Rep Max - Chest, and select your favourite exercise.": "Menj a menüben az Erő - Max Erő - Mell menüpontba, és válaszd ki a kedvenc gyakorlatod.",
"Please continue your tests with a": "Kérlek folytasd a gyakorlatokat egy",
"I suggest begin your tests with a": "Azt javaslom, kezdd a teszteket egy 'mell' gyakorlattal",
"Nice! This is a good start": "Nagyon jó! Ez egy kitűnő start a teszthez",
"Go on!":"Gyerünk tovább!",
"You are on track": "Jó úton haladsz",
"Not so much left": "Már nincs sok hátra",
"Almost!": "Majdnem a végén vagy!",
"You have only 1-2 exercise left to finish!": "Már csak 1-2 gyakorlat van a végéig!",
"exercise!": "gyakorlattal!",
"Chest": "mell",
"Back": "hát",
"Thigh": "comb",
"Calf": "vádli",
"Bring me there": "Vigyél oda",
"My Body Development": "Testem fejlődése",
"You see here your whole body development by muscle groups.": "Itt láthatod a tested fejlődését izomcsoportonként"
} }

View File

@ -0,0 +1,43 @@
import 'dart:async';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
part 'body_development_event.dart';
part 'body_development_state.dart';
class BodyDevelopmentBloc extends Bloc<BodyDevelopmentEvent, BodyDevelopmentState> {
final WorkoutTreeRepository workoutTreeRepository;
final ExerciseRepository exerciseRepository = ExerciseRepository();
List<int> radarTicks = List();
List<String> radarFeatures = List();
List<List<int>> radarData = List();
@override
BodyDevelopmentBloc({this.workoutTreeRepository}): super(BodyDevelopmentInitial());
Future<void> getData() async{
radarTicks = [20, 40, 60, 80, 100];
radarFeatures = ["Mell", "Bicepsz", "Tricepsz", "Hát", "Váll"];
radarData = [
[80, 95, 45, 67, 83]
];
}
@override
Stream<BodyDevelopmentState> mapEventToState(BodyDevelopmentEvent event) async* {
try {
if (event is BodyDevelopmentLoad) {
yield BodyDevelopmentLoading();
await getData();
yield BodyDevelopmentReady();
}
} on Exception catch (e) {
yield BodyDevelopmentError(message: e.toString());
}
}
}

View File

@ -0,0 +1,12 @@
part of 'body_development_bloc.dart';
@immutable
abstract class BodyDevelopmentEvent extends Equatable{
const BodyDevelopmentEvent();
@override
List<Object> get props => [];
}
class BodyDevelopmentLoad extends BodyDevelopmentEvent {
const BodyDevelopmentLoad();
}

View File

@ -0,0 +1,30 @@
part of 'body_development_bloc.dart';
@immutable
abstract class BodyDevelopmentState extends Equatable {
const BodyDevelopmentState();
@override
List<Object> get props => [];
}
class BodyDevelopmentInitial extends BodyDevelopmentState {
const BodyDevelopmentInitial();
}
class BodyDevelopmentLoading extends BodyDevelopmentState {
const BodyDevelopmentLoading();
}
class BodyDevelopmentReady extends BodyDevelopmentState {
const BodyDevelopmentReady();
}
class BodyDevelopmentError extends BodyDevelopmentState {
final String message;
const BodyDevelopmentError({this.message});
@override
List<Object> get props => [message];
}

View File

@ -95,6 +95,7 @@ class CustomerChangeFormBloc extends FormBloc<String, String> {
birthYearField.close(); birthYearField.close();
weightField.close(); weightField.close();
genderField.close(); genderField.close();
goalField.close();
return super.close(); return super.close();
} }

View File

@ -8,6 +8,7 @@ import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:aitrainer_app/util/calculate.dart'; import 'package:aitrainer_app/util/calculate.dart';
import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/group_data.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
@ -20,19 +21,240 @@ part 'development_by_muscle_event.dart';
part 'development_by_muscle_state.dart'; part 'development_by_muscle_state.dart';
class DateRate {
static String daily = "daily";
static String weekly = "weekly";
static String monthly = "monthly";
static String yearly = "yearly";
}
class DiagramType { class DiagramType {
static String sumMass = "sumMass"; static String sumMass = "sumMass";
static String oneRepMax = "oneRepMax"; static String oneRepMax = "oneRepMax";
static String percent = "percent"; static String percent = "percent";
} }
/*
=========== GROUPDATE CLASS
*/
class GroupDate extends GroupData with Calculate, Common {
final List<dynamic> inputList;
final List<dynamic> outputList;
String _origDatePart;
int _origExerciseTypeId;
Exercise _origExercise;
double _sumQuantity;
double _maxQuantity;
int _countExercises;
String diagramType;
String dateRate;
GroupDate({this.inputList, this.outputList});
double getQuantityByDate(Exercise exercise) {
double sum = 0;
if ( this.diagramType == DiagramType.sumMass ) {
if ( exercise.unitQuantity != null ) {
sum = exercise.quantity * exercise.unitQuantity;
} else {
sum = exercise.quantity;
}
} else if ( this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent ) {
if ( exercise.unitQuantity != null ) {
sum = calculate1RM(exercise.quantity, exercise.unitQuantity);
} else {
sum = exercise.quantity;
}
}
return sum;
}
@override
void addTempData(Exercise exercise) {
double newQuantity = getQuantityByDate(exercise);
_sumQuantity += newQuantity;
if (_maxQuantity < newQuantity) {
_maxQuantity = newQuantity;
}
_countExercises++;
_origDatePart = getDatePart(exercise.dateAdd, dateRate);
_origExerciseTypeId = exercise.exerciseTypeId;
_origExercise = exercise;
}
@override
bool checkNewType(Exercise exercise) {
String exerciseDatePart = getDatePart(exercise.dateAdd, dateRate);
return _origDatePart != exerciseDatePart || _origExerciseTypeId != exercise.exerciseTypeId;
}
@override
void iteration() {
this.resetTemp();
Exercise tempExercise;
inputList.forEach((element) {
tempExercise = element;
if ( this.checkNewType(element)) {
if ( _origDatePart == null ) {
this.addTempData(element);
} else {
this.temp2Output(_origExercise);
this.resetTemp();
this.addTempData(element);
}
} else {
this.addTempData(element);
}
});
if ( tempExercise != null) {
this.temp2Output(tempExercise);
}
}
@override
void temp2Output(Exercise exercise) {
Exercise newExercise = exercise.copy();
newExercise.datePart = _origDatePart;
if (this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent) {
newExercise.calculated = _maxQuantity;
} else {
newExercise.calculated = _sumQuantity / _countExercises;
}
outputList.add(newExercise);
}
@override
void resetTemp() {
_countExercises = 0;
_sumQuantity = 0;
_maxQuantity = 0;
}
}
/*
=========== CHART DATA CLASS
*/
class GroupChart extends GroupData with Calculate {
final List<dynamic> inputList;
LinkedHashMap<int, ChartDataExtended> outputList = LinkedHashMap();
int _origExerciseTypeId;
double _minData = 999999999999;
double _maxData = 0;
List<BarChartGroupData> _chartData;
double _basePercent;
String diagramType = DiagramType.sumMass;
GroupChart({this.inputList, this.outputList});
double getBasePercent(Exercise exercise) {
if ( exercise.unitQuantity != null ) {
this._basePercent = calculate1RM(exercise.quantity, exercise.unitQuantity);
} else {
this._basePercent = exercise.quantity;
}
return this._basePercent;
}
double getDiagramValue(Exercise exercise) {
double value = 0;
if ( diagramType == DiagramType.percent) {
if ( exercise.unitQuantity != null ) {
double oneRepMax = calculate1RM(exercise.quantity, exercise.unitQuantity);
value = (oneRepMax / this._basePercent) * 100;
} else {
value = (exercise.quantity / this._basePercent ) * 100;
}
} else if ( diagramType == DiagramType.oneRepMax || diagramType == DiagramType.sumMass) {
value = exercise.calculated;
}
return value;
}
@override
void addTempData(Exercise exercise) {
double diagramValue = this.getDiagramValue(exercise);
if (_maxData < diagramValue) {
_maxData = diagramValue;
}
if (_minData > diagramValue) {
_minData = diagramValue;
}
BarChartGroupData data = BarChartGroupData(
x: exercise.dateAdd.millisecondsSinceEpoch,
barRods: [
BarChartRodData(y: diagramValue, width: 12, color: Colors.lightBlue)
]
);
_chartData.add(data);
_origExerciseTypeId = exercise.exerciseTypeId;
}
@override
bool checkNewType(Exercise exercise) {
return _origExerciseTypeId != exercise.exerciseTypeId;
}
@override
void iteration() {
this.resetTemp();
Exercise tempExercise;
inputList.forEach((element) {
tempExercise = element;
if ( this.checkNewType(element)) {
if ( _origExerciseTypeId == null ) {
_basePercent = getBasePercent(element);
this.addTempData(element);
} else {
this.temp2Output(element);
this.resetTemp();
_basePercent = getBasePercent(element);
this.addTempData(element);
}
} else {
this.addTempData(element);
}
});
if ( tempExercise != null) {
this.temp2Output(tempExercise);
}
}
@override
void temp2Output(Exercise exercise) {
double dInterval = ((_maxData + _minData) / 8).roundToDouble();
int gridInterval = (dInterval / 3).floor();
ChartDataExtended extended;
if ( outputList[_origExerciseTypeId] == null ) {
extended = ChartDataExtended(
data: _chartData, interval: dInterval, gridInterval: gridInterval);
outputList[_origExerciseTypeId] = extended;
} else {
extended = outputList[_origExerciseTypeId];
_chartData.forEach((element) {
extended.data.add(element);
});
}
}
@override
void resetTemp() {
_minData = 999999999999;
_maxData = 0;
_chartData = List();
}
}
class ChartDataExtended { class ChartDataExtended {
final List<BarChartGroupData> data; final List<BarChartGroupData> data;
final double interval; final double interval;
@ -40,16 +262,29 @@ class ChartDataExtended {
const ChartDataExtended({this.data, this.interval, this.gridInterval}); const ChartDataExtended({this.data, this.interval, this.gridInterval});
Map<String, dynamic> toJson() => Map<String, dynamic> toJson() {
{ List listBarChartData = List();
"data": data.toString(), data.forEach((element) {
element.barRods.forEach((rods) {
var barChartData = {
'x': element.x,
'y': rods.y,
};
listBarChartData.add(barChartData);
});
});
var chartData = {
"data": listBarChartData.toString(),
"interval": interval.toString(), "interval": interval.toString(),
"gridInterval": gridInterval, "gridInterval": gridInterval,
}; };
return chartData;
}
} }
class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, DevelopmentByMuscleState> with Calculate, Common { class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, DevelopmentByMuscleState> with Calculate {
final WorkoutTreeRepository workoutTreeRepository; final WorkoutTreeRepository workoutTreeRepository;
final ExerciseRepository exerciseRepository = ExerciseRepository(); final ExerciseRepository exerciseRepository = ExerciseRepository();
LinkedHashMap<int, ChartDataExtended> listChartData = LinkedHashMap(); LinkedHashMap<int, ChartDataExtended> listChartData = LinkedHashMap();
@ -81,57 +316,21 @@ class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, Development
void getChartData() { void getChartData() {
List<Exercise> exercises = exerciseRepository.getExerciseList(); List<Exercise> exercises = exerciseRepository.getExerciseList();
exercises.sort( (a, b) => a.exerciseTypeId.compareTo(b.exerciseTypeId));
//print("-- Start calculate --- ");
exercises = this.groupByDate(exercises); exercises = this.groupByDate(exercises);
int origExerciseTypeId = 0; exercises = sort(exercises, true);
int x = 0; /* exercises.forEach((exercise) {
chartData = List(); print ("Chart exercise " + exercise.toJsonDatePart().toString());
double maxData = 0; });*/
double minData = 9999999999999;
exercises.forEach((exercise) { listChartData = LinkedHashMap();
if ( exercise.unitQuantity != null ) { GroupChart groupChart = GroupChart(inputList: exercises, outputList: listChartData);
if (origExerciseTypeId != exercise.exerciseTypeId && diagramType == DiagramType.percent) { groupChart.diagramType = this.diagramType;
this.basePercent = getBasePercent(exercise); groupChart.iteration();
} listChartData = groupChart.outputList;
double diagramValue = this.getDiagramValue(exercise);
if (maxData < diagramValue) {
maxData = diagramValue;
}
if (minData > diagramValue) {
minData = diagramValue;
}
//print("exercise " + exercise.exerciseTypeId.toString() + " d " + getDateFormat(exercise.dateAdd) + " mass " + sumMass.toString());
//print("date " + exercise.dateAdd.toIso8601String() + " epoch " + exercise.dateAdd.millisecondsSinceEpoch.toString() );
BarChartGroupData data = BarChartGroupData(
x: exercise.dateAdd.millisecondsSinceEpoch,
barRods: [
BarChartRodData(y: diagramValue, width: 12, color: Colors.lightBlue)
]
);
if (origExerciseTypeId != exercise.exerciseTypeId) {
if (origExerciseTypeId == 0) {
origExerciseTypeId = exercise.exerciseTypeId;
chartData.add(data);
} else {
double dInterval = ((maxData + minData) / 8).roundToDouble();
int gridInterval = (dInterval / 3).floor();
ChartDataExtended extended = ChartDataExtended(
data: chartData, interval: dInterval, gridInterval: gridInterval);
listChartData[origExerciseTypeId] = extended;
maxData = 0;
minData = 9999999999999;
chartData = List();
chartData.add(data);
origExerciseTypeId = exercise.exerciseTypeId;
}
} else {
origExerciseTypeId = exercise.exerciseTypeId;
chartData.add(data);
}
}
});
listChartData.forEach((key, value) { listChartData.forEach((key, value) {
print ("typeid " + key.toString() + " chardata " + value.toJson().toString()); print ("typeid " + key.toString() + " chardata " + value.toJson().toString());
@ -139,126 +338,38 @@ class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, Development
return; return;
} }
String getDatePart(DateTime date) {
String datePart = DateFormat('MM.dd', AppLanguage().appLocal.toString()).format(date);;
if ( this.dateRate == DateRate.weekly ) {
datePart = weekNumber(date).toString();
} else if ( this.dateRate == DateRate.monthly ) {
datePart = DateFormat('MMM', AppLanguage().appLocal.toString()).format(date);
} else if ( this.dateRate == DateRate.yearly ) {
datePart = DateFormat('y', AppLanguage().appLocal.toString()).format(date);
} else if ( this.dateRate == DateRate.daily ) {
datePart = DateFormat('MM.dd', AppLanguage().appLocal.toString()).format(date);
}
return datePart;
}
List<Exercise> groupByDate(List<Exercise> exercises) { List<Exercise> groupByDate(List<Exercise> exercises) {
List<Exercise> groupedExercises = List(); List<Exercise> groupedExercises = List();
String origDatePart; exercises = sort(exercises, false);
int countExercises = 0;
double sumQuantity = 0;
double maxQuantity = 0;
Exercise origExercise;
exercises.forEach((exercise) { exercises.forEach((exercise) {
String exerciseDatePart = getDatePart(exercise.dateAdd); print ("Date exercise " + exercise.toJsonDatePart().toString());
if ( origExercise != null ) {
if ( origExercise.exerciseTypeId != exercise.exerciseTypeId || origDatePart != exerciseDatePart ) {
Exercise newExercise = origExercise.copy();
newExercise.datePart = origDatePart;
if (this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent) {
newExercise.quantity = maxQuantity;
} else {
newExercise.quantity = sumQuantity / countExercises;
}
groupedExercises.add(newExercise);
countExercises = 0;
sumQuantity = 0;
maxQuantity = 0;
}
}
origExercise = exercise;
origDatePart = exerciseDatePart;
double newQuantity = getQuantityByDate(exercise);
sumQuantity += newQuantity;
if (maxQuantity < newQuantity) {
maxQuantity = newQuantity;
}
countExercises++;
}); });
groupedExercises.forEach((element) { GroupDate groupDate = GroupDate(inputList: exercises, outputList: groupedExercises);
print("grouped " + element.toJson().toString()); groupDate.dateRate = this.dateRate;
}); groupDate.diagramType = this.diagramType;
groupDate.iteration();
groupedExercises = groupDate.outputList;
/* groupedExercises.forEach((element) {
print("Grouped " + element.toJsonDatePart().toString());
});*/
return groupedExercises; return groupedExercises;
} }
double getQuantityByDate(Exercise exercise) { List<Exercise> sort(List<Exercise> exercises, bool asc) {
double sum = 0; exercises.sort( (a, b) {
if ( this.diagramType == DiagramType.sumMass ) { var aDateId = a.exerciseTypeId.toString() + "_" + a.datePart.toString();
if ( exercise.unitQuantity != null ) { var bDateId = b.exerciseTypeId.toString() + "_" + b.datePart.toString();
sum = exercise.quantity * exercise.unitQuantity;
} else {
sum = exercise.quantity;
}
} else if ( this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent ) {
if ( exercise.unitQuantity != null ) {
sum = calculate1RM(exercise.quantity, exercise.unitQuantity);
} else {
sum = exercise.quantity;
}
}
return sum;
}
double getBasePercent(Exercise exercise) { return asc ? aDateId.compareTo(bDateId) : bDateId.compareTo(aDateId);
if ( exercise.unitQuantity != null ) { });
this.basePercent = calculate1RM(exercise.quantity, exercise.unitQuantity); return exercises;
} else {
this.basePercent = exercise.quantity;
}
//print("Base percent of " + exercise.exerciseTypeId.toString() + ": " + basePercent.toString());
return this.basePercent;
}
double getDiagramValue(Exercise exercise) {
double value = 0;
/*if ( diagramType == DiagramType.sumMass) {
value = exercise.quantity;
if ( exercise.unitQuantity != null ) {
value *= exercise.unitQuantity;
}
} else if ( diagramType == DiagramType.oneRepMax) {
if ( exercise.unitQuantity != null ) {
value = calculate1RM(exercise.quantity, exercise.unitQuantity);
}
} else if ( diagramType == DiagramType.percent) {
if ( exercise.unitQuantity != null ) {
double oneRepMax = calculate1RM(exercise.quantity, exercise.unitQuantity);
value = (oneRepMax / this.basePercent) * 100;
//print("Percent of " + exercise.exerciseTypeId.toString() + ": " + value.toString() + " date " + exercise.dateAdd.toIso8601String() + " 1RM " + oneRepMax.toString());
} else {
value = (exercise.quantity / this.basePercent ) * 100;
}*/
if ( diagramType == DiagramType.percent) {
if ( exercise.unitQuantity != null ) {
double oneRepMax = calculate1RM(exercise.quantity, exercise.unitQuantity);
value = (oneRepMax / this.basePercent) * 100;
//print("Percent of " + exercise.exerciseTypeId.toString() + ": " + value.toString() + " date " + exercise.dateAdd.toIso8601String() + " 1RM " + oneRepMax.toString());
} else {
value = (exercise.quantity / this.basePercent ) * 100;
}
} else {
return exercise.quantity;
}
return value;
} }
String getDateFormat(DateTime datetime) { String getDateFormat(DateTime datetime) {

View File

@ -1,5 +1,4 @@
import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart';
class ExerciseControlFormBloc extends FormBloc<String, String> { class ExerciseControlFormBloc extends FormBloc<String, String> {

View File

@ -1,8 +1,11 @@
import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'menu/menu_bloc.dart';
class ExerciseFormBloc extends FormBloc<String, String> { class ExerciseFormBloc extends FormBloc<String, String> {
final ExerciseRepository exerciseRepository; final ExerciseRepository exerciseRepository;
final MenuBloc menuBloc;
final quantityField = TextFieldBloc( final quantityField = TextFieldBloc(
validators: [ validators: [
@ -19,7 +22,7 @@ class ExerciseFormBloc extends FormBloc<String, String> {
final unitQuantityField = TextFieldBloc(); final unitQuantityField = TextFieldBloc();
final unitQuantityUnitField = TextFieldBloc(); final unitQuantityUnitField = TextFieldBloc();
ExerciseFormBloc({this.exerciseRepository}) { ExerciseFormBloc({this.exerciseRepository, this.menuBloc}) {
addFieldBlocs(fieldBlocs: [ addFieldBlocs(fieldBlocs: [
quantityField, quantityField,
unitField, unitField,
@ -46,6 +49,7 @@ class ExerciseFormBloc extends FormBloc<String, String> {
emitLoading(progress: 30); emitLoading(progress: 30);
// Emit either Loaded or Error // Emit either Loaded or Error
await exerciseRepository.addExercise(); await exerciseRepository.addExercise();
menuBloc.add(MenuTreeDown(parent: 0));
emitSuccess(canSubmitAgain: false); emitSuccess(canSubmitAgain: false);
} on Exception catch (ex) { } on Exception catch (ex) {

View File

@ -1,22 +1,72 @@
import 'dart:async'; import 'dart:async';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
part 'menu_event.dart'; part 'menu_event.dart';
part 'menu_state.dart'; part 'menu_state.dart';
class MenuBloc extends Bloc<MenuEvent, MenuState> { class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
final WorkoutTreeRepository menuTreeRepository; final WorkoutTreeRepository menuTreeRepository;
final ExerciseRepository exerciseRepository = ExerciseRepository();
int parent; int parent;
WorkoutMenuTree workoutItem;
String infoTitle = "";
String infoText = "";
String infoText2 = "";
String infoText3 = "";
String infoLink = "";
int missingParent = 0;
String missingTreeName = "";
BuildContext context;
MenuBloc({this.menuTreeRepository}) : super(MenuInitial()) { MenuBloc({this.menuTreeRepository}) : super(MenuInitial()) {
parent = 0; parent = 0;
} }
void setMenuInfo() {
double percent = Cache().getPercentExercises();
if ( context == null ) return;
percent = percent * 100;
print("Percent " + percent.toString());
if ( percent == -1 || percent == 0) {
infoTitle = t("Greetings!");
infoText = t("The purpose is to measure you physical condition") + " " + t("The suggested order of the exercises: chest - biceps - triceps - back - shoulders - core - tigh - calf.");
infoText2 = t("I suggest begin your tests with a");
infoText3 = t("Go to the menu Strength - One Rep Max - Chest, and select your favourite exercise.");
infoLink = t("Bring me there");
} else if ( percent > 0 && percent < 20) {
infoTitle = t("Nice! This is a good start");
} else if ( percent > 20 && percent < 40) {
infoTitle = t("Go on!") + " " + t("You are on track");
} else if ( percent > 60 && percent < 80) {
infoTitle = t("Persistence!") + " " + t("Not so much left");
} else if ( percent > 80 && percent < 100) {
infoTitle = t("Almost!") + " " + t("You have only 1-2 exercise left to finish!");
}
menuTreeRepository.sortByMuscleType();
missingTreeName = exerciseRepository.nextMissingBaseExercise(menuTreeRepository.sortedTree);
print("Missing " + missingTreeName);
if ( percent > 0) {
infoText = t("Please continue your tests with a") + " '" + missingTreeName + "' " + t("exercise!");
infoLink = t("Bring me there");
}
}
void setContext(BuildContext context) {
this.context = context;
}
@override @override
Stream<MenuState> mapEventToState( Stream<MenuState> mapEventToState(
MenuEvent event, MenuEvent event,
@ -25,6 +75,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
if ( event is MenuCreate ) { if ( event is MenuCreate ) {
yield MenuLoading(); yield MenuLoading();
await menuTreeRepository.createTree(); await menuTreeRepository.createTree();
setMenuInfo();
yield MenuReady(); yield MenuReady();
} else if (event is MenuRecreateTree) { } else if (event is MenuRecreateTree) {
// ie. at language changes // ie. at language changes
@ -34,14 +85,28 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
// get child menus or exercises // get child menus or exercises
yield MenuLoading(); yield MenuLoading();
parent = event.parent; parent = event.parent;
workoutItem = event.item;
//print("menuitem " + workoutItem.id.toString() + " parent "+workoutItem.parent.toString());
menuTreeRepository.getBranch(event.parent); menuTreeRepository.getBranch(event.parent);
yield MenuReady(); yield MenuReady();
} else if (event is MenuTreeUp) { } else if (event is MenuTreeUp) {
yield MenuLoading(); yield MenuLoading();
// get parent menus or exercises // get parent menus or exercises
parent = event.parent; parent = event.parent;
menuTreeRepository.getBranch(parent); workoutItem = menuTreeRepository.getParentItem(parent);
if ( workoutItem != null) {
//print("UP menuitem " + workoutItem.id.toString() + " parent " + workoutItem.parent.toString());
menuTreeRepository.getBranch(workoutItem.parent);
}
yield MenuReady();
} else if (event is MenuTreeJump) {
yield MenuLoading();
parent = event.parent;
workoutItem = menuTreeRepository.getParentItem(parent);
if ( workoutItem != null) {
//print("JUMP menuitem " + workoutItem.id.toString() + " parent " + workoutItem.parent.toString());
menuTreeRepository.getBranch(workoutItem.parent);
}
yield MenuReady(); yield MenuReady();
} else if (event is MenuClickExercise) { } else if (event is MenuClickExercise) {
yield MenuLoading(); yield MenuLoading();

View File

@ -16,16 +16,26 @@ class MenuCreate extends MenuEvent {
} }
class MenuTreeDown extends MenuEvent { class MenuTreeDown extends MenuEvent {
final WorkoutMenuTree item;
final int parent; final int parent;
const MenuTreeDown({this.parent}); const MenuTreeDown({this.parent, this.item});
@override @override
List<Object> get props => [parent]; List<Object> get props => [parent, item];
} }
class MenuTreeUp extends MenuEvent { class MenuTreeUp extends MenuEvent {
final int parent; final int parent;
const MenuTreeUp({this.parent}); final WorkoutMenuTree item;
const MenuTreeUp({this.parent, this.item});
@override
List<Object> get props => [parent, item];
}
class MenuTreeJump extends MenuEvent {
final int parent;
const MenuTreeJump({this.parent});
@override @override
List<Object> get props => [parent]; List<Object> get props => [parent];

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';

View File

@ -0,0 +1,325 @@
library flutter_radar_chart;
import 'dart:ui';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'dart:math' show pi, cos, sin;
const defaultGraphColors = [
Colors.green,
Colors.blue,
Colors.red,
Colors.orange,
];
class RadarChart extends StatefulWidget {
final List<int> ticks;
final List<String> features;
final List<List<int>> data;
final bool reverseAxis;
final TextStyle ticksTextStyle;
final TextStyle featuresTextStyle;
final Color outlineColor;
final Color axisColor;
final List<Color> graphColors;
final int sides;
const RadarChart({
Key key,
@required this.ticks,
@required this.features,
@required this.data,
this.reverseAxis = false,
this.ticksTextStyle = const TextStyle(color: Colors.grey, fontSize: 12),
this.featuresTextStyle = const TextStyle(color: Colors.black, fontSize: 16),
this.outlineColor = Colors.black,
this.axisColor = Colors.grey,
this.graphColors = defaultGraphColors,
this.sides = 0,
}) : super(key: key);
factory RadarChart.light({
@required List<int> ticks,
@required List<String> features,
@required List<List<int>> data,
bool reverseAxis = false,
bool useSides = false,
}) {
return RadarChart(
ticks: ticks,
features: features,
data: data,
reverseAxis: reverseAxis,
sides: useSides ? features.length : 0);
}
factory RadarChart.dark({
@required List<int> ticks,
@required List<String> features,
@required List<List<int>> data,
bool reverseAxis = false,
bool useSides = false,
}) {
return RadarChart(
ticks: ticks,
features: features,
data: data,
featuresTextStyle: const TextStyle(color: Colors.white, fontSize: 16),
outlineColor: Colors.white,
axisColor: Colors.grey,
reverseAxis: reverseAxis,
sides: useSides ? features.length : 0);
}
@override
_RadarChartState createState() => _RadarChartState();
}
class _RadarChartState extends State<RadarChart>
with SingleTickerProviderStateMixin {
double fraction = 0;
Animation<double> animation;
AnimationController animationController;
@override
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 1000), vsync: this);
animation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
curve: Curves.fastOutSlowIn,
parent: animationController,
))
..addListener(() {
setState(() {
fraction = animation.value;
});
});
animationController.forward();
}
@override
void didUpdateWidget(RadarChart oldWidget) {
super.didUpdateWidget(oldWidget);
animationController.reset();
animationController.forward();
}
@override
Widget build(BuildContext context) {
return CustomPaint(
size: Size(double.infinity, double.infinity),
painter: RadarChartPainter(
widget.ticks,
widget.features,
widget.data,
widget.reverseAxis,
widget.ticksTextStyle,
widget.featuresTextStyle,
widget.outlineColor,
widget.axisColor,
widget.graphColors,
widget.sides,
this.fraction),
);
}
@override
void dispose() {
animationController.dispose();
super.dispose();
}
}
class RadarChartPainter extends CustomPainter {
final List<int> ticks;
final List<String> features;
final List<List<int>> data;
final bool reverseAxis;
final TextStyle ticksTextStyle;
final TextStyle featuresTextStyle;
final Color outlineColor;
final Color axisColor;
final List<Color> graphColors;
final int sides;
final double fraction;
RadarChartPainter(
this.ticks,
this.features,
this.data,
this.reverseAxis,
this.ticksTextStyle,
this.featuresTextStyle,
this.outlineColor,
this.axisColor,
this.graphColors,
this.sides,
this.fraction,
);
Path variablePath(Size size, double radius, int sides) {
var path = Path();
var angle = (math.pi * 2) / sides;
Offset center = Offset(size.width / 2, size.height / 2);
if (sides < 3) {
// Draw a circle
path.addOval(Rect.fromCircle(
center: Offset(size.width / 2, size.height / 2),
radius: radius,
));
} else {
// Draw a polygon
Offset startPoint = Offset(radius * cos(-pi / 2), radius * sin(-pi / 2));
path.moveTo(startPoint.dx + center.dx, startPoint.dy + center.dy);
for (int i = 1; i <= sides; i++) {
double x = radius * cos(angle * i - pi / 2) + center.dx;
double y = radius * sin(angle * i - pi / 2) + center.dy;
path.lineTo(x, y);
}
path.close();
}
return path;
}
@override
void paint(Canvas canvas, Size size) {
final centerX = size.width / 2.0;
final centerY = size.height / 2.0;
final centerOffset = Offset(centerX, centerY);
final radius = math.min(centerX, centerY) * 0.8;
final scale = radius / ticks.last;
// Painting the chart outline
var outlinePaint = Paint()
..color = outlineColor
..style = PaintingStyle.stroke
..strokeWidth = 2.0
..isAntiAlias = true;
var ticksPaint = Paint()
..color = axisColor
..style = PaintingStyle.stroke
..strokeWidth = 1.0
..isAntiAlias = true;
canvas.drawPath(variablePath(size, radius, this.sides), outlinePaint);
// Painting the circles and labels for the given ticks (could be auto-generated)
// The last tick is ignored, since it overlaps with the feature label
var tickDistance = radius / (ticks.length);
var tickLabels = reverseAxis ? ticks.reversed.toList() : ticks;
if (reverseAxis) {
TextPainter(
text: TextSpan(text: tickLabels[0].toString(), style: ticksTextStyle),
textDirection: TextDirection.ltr,
)
..layout(minWidth: 0, maxWidth: size.width)
..paint(canvas, Offset(centerX, centerY - ticksTextStyle.fontSize));
}
tickLabels
.sublist(
reverseAxis ? 1 : 0, reverseAxis ? ticks.length : ticks.length - 1)
.asMap()
.forEach((index, tick) {
var tickRadius = tickDistance * (index + 1);
canvas.drawPath(variablePath(size, tickRadius, this.sides), ticksPaint);
TextPainter(
text: TextSpan(text: tick.toString(), style: ticksTextStyle),
textDirection: TextDirection.ltr,
)
..layout(minWidth: 0, maxWidth: size.width)
..paint(canvas,
Offset(centerX, centerY - tickRadius - ticksTextStyle.fontSize));
});
// Painting the axis for each given feature
var angle = (2 * pi) / features.length;
features.asMap().forEach((index, feature) {
var xAngle = cos(angle * index - pi / 2);
var yAngle = sin(angle * index - pi / 2);
var featureOffset =
Offset(centerX + radius * xAngle, centerY + radius * yAngle);
canvas.drawLine(centerOffset, featureOffset, ticksPaint);
var featureLabelFontHeight = featuresTextStyle.fontSize;
var featureLabelFontWidth = featuresTextStyle.fontSize - 5;
var labelYOffset = yAngle < 0 ? -featureLabelFontHeight : 0;
var labelXOffset =
xAngle < 0 ? -featureLabelFontWidth * feature.length : 0;
TextPainter(
text: TextSpan(text: feature, style: featuresTextStyle),
textAlign: TextAlign.left,
textDirection: TextDirection.ltr,
)
..layout(minWidth: 0, maxWidth: size.width)
..paint(
canvas,
Offset(featureOffset.dx + labelXOffset,
featureOffset.dy + labelYOffset));
});
// Painting each graph
data.asMap().forEach((index, graph) {
var graphPaint = Paint()
..color = graphColors[index % graphColors.length].withOpacity(0.3)
..style = PaintingStyle.fill;
var graphOutlinePaint = Paint()
..color = graphColors[index % graphColors.length]
..style = PaintingStyle.stroke
..strokeWidth = 2.0
..isAntiAlias = true;
// Start the graph on the initial point
var scaledPoint = scale * graph[0] * fraction;
var path = Path();
if (reverseAxis) {
path.moveTo(centerX, centerY - (radius * fraction - scaledPoint));
} else {
path.moveTo(centerX, centerY - scaledPoint);
}
graph.asMap().forEach((index, point) {
if (index == 0) return;
var xAngle = cos(angle * index - pi / 2);
var yAngle = sin(angle * index - pi / 2);
var scaledPoint = scale * point * fraction;
if (reverseAxis) {
path.lineTo(centerX + (radius * fraction - scaledPoint) * xAngle,
centerY + (radius * fraction - scaledPoint) * yAngle);
} else {
path.lineTo(
centerX + scaledPoint * xAngle, centerY + scaledPoint * yAngle);
}
});
path.close();
canvas.drawPath(path, graphPaint);
canvas.drawPath(path, graphOutlinePaint);
});
}
@override
bool shouldRepaint(RadarChartPainter oldDelegate) {
return oldDelegate.fraction != fraction;
}
}

View File

@ -34,6 +34,7 @@ class AppLanguage{
String langCode = prefs.getString('language_code'); String langCode = prefs.getString('language_code');
if ( langCode == null) { if ( langCode == null) {
_appLocale = Locale('en'); _appLocale = Locale('en');
langCode = "en";
} }
_appLocale = Locale(langCode); _appLocale = Locale(langCode);
print(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode"); print(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode");

View File

@ -20,6 +20,7 @@ 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_body_page.dart';
import 'package:aitrainer_app/view/mydevelopment_muscle_page.dart'; import 'package:aitrainer_app/view/mydevelopment_muscle_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/myexcercise_plan_page.dart';
@ -34,6 +35,7 @@ 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/body_development/body_development_bloc.dart';
import 'bloc/development_by_muscle/development_by_muscle_bloc.dart'; import 'bloc/development_by_muscle/development_by_muscle_bloc.dart';
import 'bloc/exercise_by_plan/exercise_by_plan_bloc.dart'; import 'bloc/exercise_by_plan/exercise_by_plan_bloc.dart';
import 'bloc/exercise_plan/exercise_plan_bloc.dart'; import 'bloc/exercise_plan/exercise_plan_bloc.dart';
@ -133,6 +135,10 @@ Future<Null> main() async {
create: (BuildContext context) => DevelopmentByMuscleBloc( create: (BuildContext context) => DevelopmentByMuscleBloc(
workoutTreeRepository: menuTreeRepository), workoutTreeRepository: menuTreeRepository),
), ),
BlocProvider<BodyDevelopmentBloc>(
create: (BuildContext context) => BodyDevelopmentBloc(
workoutTreeRepository: menuTreeRepository),
),
], ],
child: AitrainerApp(), child: AitrainerApp(),
@ -173,7 +179,7 @@ class AitrainerApp extends StatelessWidget {
} }
}); });
if ( locale != null && realSupportedLocale.countryCode != locale.countryCode ) { if ( locale != null && realSupportedLocale.countryCode != locale.countryCode ) {
print ("Locale " + locale.countryCode + " not supported on this device :("); //print ("Locale " + locale.countryCode + " not supported on this device :(");
} }
return realSupportedLocale; return realSupportedLocale;
}, },
@ -202,6 +208,7 @@ class AitrainerApp extends StatelessWidget {
'exerciseByPlanPage': (context) => ExerciseByPlanPage(), 'exerciseByPlanPage': (context) => ExerciseByPlanPage(),
'exerciseAddByPlanPage': (context) => ExerciseAddByPlanPage(), 'exerciseAddByPlanPage': (context) => ExerciseAddByPlanPage(),
'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(), 'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(),
'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(),
}, },
initialRoute: 'home', initialRoute: 'home',
title: 'WorkoutTest', title: 'WorkoutTest',
@ -220,3 +227,4 @@ class AitrainerApp extends StatelessWidget {
} }

View File

@ -126,8 +126,8 @@ class Cache {
_exercisesTrainee = null; _exercisesTrainee = null;
_traineeExercisePlan = null; _traineeExercisePlan = null;
_exercises = List(); _exercises = List();
_myExercisesPlanDetails = LinkedHashMap();
print("Trainees is null? " + (_trainee == null).toString() ); print("Trainees is null? " + (_trainee == null).toString() );
//firstLoad = true;
Future<SharedPreferences> prefs = SharedPreferences.getInstance(); Future<SharedPreferences> prefs = SharedPreferences.getInstance();
await setPreferences(prefs, SharePrefsChange.logout, 0); await setPreferences(prefs, SharePrefsChange.logout, 0);
} }

View File

@ -1,4 +1,3 @@
import 'package:aitrainer_app/util/common.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class Exercise { class Exercise {
@ -12,6 +11,7 @@ class Exercise {
int exercisePlanDetailId; int exercisePlanDetailId;
String datePart; String datePart;
double calculated;
@ -25,6 +25,7 @@ class Exercise {
this.unitQuantity = json['unitQuantity']; this.unitQuantity = json['unitQuantity'];
this.dateAdd = DateTime.parse( json['dateAdd'] ); this.dateAdd = DateTime.parse( json['dateAdd'] );
this.datePart = DateFormat('yyyy-MM-dd').format(this.dateAdd); this.datePart = DateFormat('yyyy-MM-dd').format(this.dateAdd);
this.calculated = quantity;
} }
Map<String, dynamic> toJson() => Map<String, dynamic> toJson() =>
@ -38,6 +39,18 @@ class Exercise {
"exercisePlanDetailId": exercisePlanDetailId, "exercisePlanDetailId": exercisePlanDetailId,
}; };
Map<String, dynamic> toJsonDatePart() =>
{
"exerciseTypeId": exerciseTypeId,
"customerId": customerId,
"quantity": quantity,
'calculated': calculated,
"unit": unit,
"unitQuantity": unitQuantity,
"datePart": this.datePart,
};
Exercise copy() { Exercise copy() {
Exercise newExercise = Exercise(); Exercise newExercise = Exercise();
newExercise.exerciseTypeId = this.exerciseTypeId; newExercise.exerciseTypeId = this.exerciseTypeId;

View File

@ -28,7 +28,9 @@ class ExercisePlanRepository {
ExercisePlan getExercisePlan() => exercisePlan; ExercisePlan getExercisePlan() => exercisePlan;
void addDetailToPlan() { void addDetailToPlan() {
if ( exercisePlan != null ) {
actualPlanDetail.exercisePlanId = exercisePlan.exercisePlanId; actualPlanDetail.exercisePlanId = exercisePlan.exercisePlanId;
}
exercisePlanDetails[actualPlanDetail.exerciseTypeId] = actualPlanDetail; exercisePlanDetails[actualPlanDetail.exerciseTypeId] = actualPlanDetail;
Cache().addToMyExercisePlanDetails(actualPlanDetail); Cache().addToMyExercisePlanDetails(actualPlanDetail);
} }

View File

@ -56,17 +56,11 @@ class ExerciseRepository {
this.exercise.dateAdd = datetimeExercise; this.exercise.dateAdd = datetimeExercise;
} }
double get unitQuantity { double get unitQuantity => this.exercise.unitQuantity;
return this.exercise.unitQuantity;
}
double get quantity { double get quantity => this.exercise.quantity;
return this.exercise.quantity;
}
Exercise getExercise() { Exercise getExercise() => this.exercise;
return this.exercise;
}
Future<void> addExercise() async { Future<void> addExercise() async {
final Exercise modelExercise = this.exercise; final Exercise modelExercise = this.exercise;
@ -81,13 +75,9 @@ class ExerciseRepository {
} }
setCustomer(Customer customer) { setCustomer(Customer customer) => this.customer = customer;
this.customer = customer;
}
setExerciseType( ExerciseType exerciseType) { setExerciseType( ExerciseType exerciseType) => this.exerciseType = exerciseType;
this.exerciseType = exerciseType;
}
Future<List<Exercise>> getExercisesByCustomer( int customerId ) async { Future<List<Exercise>> getExercisesByCustomer( int customerId ) async {
@ -102,17 +92,53 @@ class ExerciseRepository {
} }
List<Exercise> getExerciseList() { List<Exercise> getExerciseList() {
//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() { List<Exercise> getExerciseListTrainee() {
//if ( this.exerciseList == null || this.exerciseList.length == 0 ) { this.exerciseList = Cache().getExercisesTrainee();
return this.exerciseList = Cache().getExercisesTrainee(); return this.exerciseList;
//} }
//return this.exerciseList;
String nextMissingBaseExercise(SplayTreeMap sortedTree) {
if ( exerciseList == null ) {
exerciseList = Cache().getExercises();
}
if ( exerciseList == null ) {
return "";
}
String missingTreeName;
String foundTreeName;
bool isBreak = false;
sortedTree.forEach((key, list) {
List<WorkoutMenuTree> listByMuscle = list as List<WorkoutMenuTree>;
String treeName = key as String;
treeName = treeName.substring(3);
foundTreeName = null;
listByMuscle.forEach((exercise) {
if ( missingTreeName == null ) {
missingTreeName = treeName;
}
if ( exercise.base ) {
exerciseList.forEach((element) {
if ( element.exerciseTypeId == exercise.exerciseTypeId ) {
foundTreeName = treeName;
//print("Found " + foundTreeName + " Missing actual: " + missingTreeName);
isBreak = true;
}
});
}
});
if ( foundTreeName == null &&! isBreak ) {
missingTreeName = treeName;
isBreak = true;
}
});
return missingTreeName;
} }
void getBaseExerciseFinishedPercent() { void getBaseExerciseFinishedPercent() {
@ -153,7 +179,7 @@ class ExerciseRepository {
&& treeItem.exerciseType.base == true && treeItem.exerciseType.base == true
&& exercise.exerciseTypeId == treeItem.exerciseType.exerciseTypeId && exercise.exerciseTypeId == treeItem.exerciseType.exerciseTypeId
&& !checkedBaseTreeItem.contains(treeItem.parent)) { && !checkedBaseTreeItem.contains(treeItem.parent)) {
print ("id: " + exercise.exerciseTypeId.toString()); //print ("id: " + exercise.exerciseTypeId.toString());
checkedBaseTreeItem.add(treeItem.parent); checkedBaseTreeItem.add(treeItem.parent);
count1RMExercises++; count1RMExercises++;
} }
@ -197,8 +223,6 @@ class ExerciseRepository {
return actualExerciseType; return actualExerciseType;
} }
void sortByDate() { void sortByDate() => exerciseList.sort( (a, b) => b.dateAdd.compareTo(a.dateAdd) );
exerciseList.sort( (b, a) => a.dateAdd.compareTo(b.dateAdd) );
}
} }

View File

@ -44,6 +44,7 @@ class WorkoutTreeRepository {
Antagonist.calf: Antagonist.calfNr Antagonist.calf: Antagonist.calfNr
}; };
Future<void> createTree() async { Future<void> createTree() async {
isEnglish = AppLanguage().appLocal == Locale('en'); isEnglish = AppLanguage().appLocal == Locale('en');
@ -145,16 +146,21 @@ class WorkoutTreeRepository {
return branch; return branch;
} }
WorkoutMenuTree getParentItem(int parent) {
WorkoutMenuTree parentItem;
tree.forEach((key, value) {
WorkoutMenuTree workoutTree = value as WorkoutMenuTree;
if ( parent == workoutTree.id) {
parentItem = workoutTree;
}
});
return parentItem;
}
void sortByMuscleType() { void sortByMuscleType() {
sortedTree = SplayTreeMap<String, List<WorkoutMenuTree>>(); sortedTree = SplayTreeMap<String, List<WorkoutMenuTree>>();
tree.forEach((key, value) { tree.forEach((key, value) {
WorkoutMenuTree workoutTree = value as WorkoutMenuTree; WorkoutMenuTree workoutTree = value as WorkoutMenuTree;
//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) { if ( workoutTree.nameEnglish != 'One Rep Max' && workoutTree.is1RM && workoutTree.exerciseTypeId == 0) {
String treeName = _antagonist[workoutTree.nameEnglish].toString() + ". " + workoutTree.name; String treeName = _antagonist[workoutTree.nameEnglish].toString() + ". " + workoutTree.name;
sortedTree[treeName] = this.getBranchList(workoutTree.id); sortedTree[treeName] = this.getBranchList(workoutTree.id);
@ -163,4 +169,16 @@ class WorkoutTreeRepository {
return; return;
} }
int getMissingTreeIdByName(String name) {
int missingId = 0;
tree.forEach((key, value) {
WorkoutMenuTree item = value as WorkoutMenuTree;
if ( item.name == name || name == item.nameEnglish ) {
missingId = item.id;
}
});
return missingId;
}
} }

View File

@ -48,7 +48,7 @@ class CustomerApi {
customer = Customer.fromJson(jsonDecode(responseBody)); customer = Customer.fromJson(jsonDecode(responseBody));
Cache().afterRegistration(customer); Cache().afterRegistration(customer);
} }
} on FormatException catch (exception) { } on FormatException {
throw new Exception(responseBody); throw new Exception(responseBody);
} }
} }
@ -63,7 +63,7 @@ class CustomerApi {
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 {
throw new Exception(responseBody); throw new Exception(responseBody);
} }
} }

View File

@ -22,6 +22,18 @@ class ExerciseApi {
body); body);
} }
Future<List<Exercise>> getExercisesByCustomer(int customerId ) async {
final body = await _client.get("exercises/customer/", customerId.toString() );
final Iterable json = jsonDecode(body);
final List<Exercise> exercises = json.map( (exercise) {
Exercise item = Exercise.fromJson(exercise);
return item;
}).toList();
//exercises.sort( (a, b) => b.dateAdd.compareTo(a.dateAdd) );
return exercises;
}
Future<Exercise> addExercise(Exercise exercise) async { 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 );
@ -32,12 +44,4 @@ class ExerciseApi {
return savedExercise; return savedExercise;
} }
Future<List<Exercise>> getExercisesByCustomer(int customerId ) async {
final body = await _client.get("exercises/customer/", customerId.toString() );
final Iterable json = jsonDecode(body);
final List<Exercise> exercises = json.map( (exercise) => Exercise.fromJson(exercise) ).toList();
return exercises;
}
} }

View File

@ -7,6 +7,13 @@ import 'package:aitrainer_app/repository/user_repository.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class DateRate {
static String daily = "daily";
static String weekly = "weekly";
static String monthly = "monthly";
static String yearly = "yearly";
}
mixin Common { mixin Common {
final EMAIL_ERROR = "Please type a right email address here."; final EMAIL_ERROR = "Please type a right email address here.";
@ -24,7 +31,7 @@ mixin Common {
} }
ExerciseType getExerciseType( int exerciseTypeId ) { ExerciseType getExerciseType( int exerciseTypeId ) {
ExerciseType returnElement = null; ExerciseType returnElement;
List<ExerciseType> listExerciseType = Cache().getExerciseTypes(); List<ExerciseType> listExerciseType = Cache().getExerciseTypes();
if ( listExerciseType != null ) { if ( listExerciseType != null ) {
for ( var element in listExerciseType ) { for ( var element in listExerciseType ) {
@ -32,7 +39,7 @@ mixin Common {
returnElement = element; returnElement = element;
break; break;
} }
}; }
} }
return returnElement; return returnElement;
} }
@ -79,4 +86,18 @@ mixin Common {
return ((dayOfYear - date.weekday + 10) / 7).floor(); return ((dayOfYear - date.weekday + 10) / 7).floor();
} }
String getDatePart(DateTime date, String dateRate) {
String datePart = DateFormat('MM.dd', AppLanguage().appLocal.toString()).format(date);
if ( dateRate == DateRate.weekly ) {
datePart = weekNumber(date).toString();
} else if ( dateRate == DateRate.monthly ) {
datePart = DateFormat('MMM', AppLanguage().appLocal.toString()).format(date);
} else if ( dateRate == DateRate.yearly ) {
datePart = DateFormat('y', AppLanguage().appLocal.toString()).format(date);
} else if ( dateRate == DateRate.daily ) {
datePart = DateFormat('MM.dd', AppLanguage().appLocal.toString()).format(date);
}
return datePart;
}
} }

15
lib/util/group_data.dart Normal file
View File

@ -0,0 +1,15 @@
import 'package:aitrainer_app/model/exercise.dart';
abstract class GroupData {
void iteration();
bool checkNewType(Exercise exercise);
void addTempData(Exercise element);
void temp2Output(Exercise exercise);
void resetTemp();
}

View File

@ -122,7 +122,7 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> {
color: Colors.lightBlue, color: Colors.lightBlue,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
inputFormatters: [ inputFormatters: [
WhitelistingTextInputFormatter(RegExp(r"[\d.]")) FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
], ],
onChanged: (input) => { onChanged: (input) => {
print("UnitQuantity value $input"), print("UnitQuantity value $input"),
@ -150,7 +150,6 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> {
), ),
]); ]);
} }
;
return column; return column;
} }
@ -164,7 +163,7 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> {
color: Colors.deepOrange, color: Colors.deepOrange,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
inputFormatters: [ inputFormatters: [
WhitelistingTextInputFormatter (RegExp(r"[\d.]")) FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
], ],
onChanged: (input) => { onChanged: (input) => {
print("Quantity value $input"), print("Quantity value $input"),

View File

@ -23,7 +23,6 @@ class _CustomerGoalPage extends State<CustomerGoalPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final double cWidth = MediaQuery.of(context).size.width * 0.75;
final CustomerRepository customerRepository = final CustomerRepository customerRepository =
ModalRoute.of(context).settings.arguments; ModalRoute.of(context).settings.arguments;

View File

@ -1,6 +1,5 @@
import 'package:aitrainer_app/bloc/account/account_bloc.dart'; import 'package:aitrainer_app/bloc/account/account_bloc.dart';
import 'package:aitrainer_app/bloc/customer_change_form_bloc.dart'; import 'package:aitrainer_app/bloc/customer_change_form_bloc.dart';
import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -169,7 +168,7 @@ class CustomerModifyPage extends StatelessWidget with Trans {
child: TextFieldBlocBuilder( child: TextFieldBlocBuilder(
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
textFieldBloc: customerBloc.birthYearField, textFieldBloc: customerBloc.birthYearField,
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d]"))],
decoration: InputDecoration( decoration: InputDecoration(
fillColor: Colors.white24, fillColor: Colors.white24,
filled: true, filled: true,
@ -186,7 +185,7 @@ class CustomerModifyPage extends StatelessWidget with Trans {
child: TextFieldBlocBuilder( child: TextFieldBlocBuilder(
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
textFieldBloc: customerBloc.weightField, textFieldBloc: customerBloc.weightField,
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d]"))],
decoration: InputDecoration( decoration: InputDecoration(
fillColor: Colors.white24, fillColor: Colors.white24,
filled: true, filled: true,

View File

@ -148,7 +148,7 @@ class _ExerciseAddByPlanPage extends State<ExerciseAddByPlanPage> with Trans {
color: Colors.black54, color: Colors.black54,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
inputFormatters: [ inputFormatters: [
WhitelistingTextInputFormatter(RegExp(r"[\d.]")) FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
], ],
decoration: InputDecoration( decoration: InputDecoration(
@ -169,7 +169,7 @@ class _ExerciseAddByPlanPage extends State<ExerciseAddByPlanPage> with Trans {
color: Colors.deepOrange, color: Colors.deepOrange,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
inputFormatters: [ inputFormatters: [
WhitelistingTextInputFormatter(RegExp(r"[\d.]")) FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
], ],
decoration: InputDecoration( decoration: InputDecoration(

View File

@ -4,6 +4,8 @@ import 'package:aitrainer_app/bloc/exercise_control_form_bloc.dart';
import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/repository/exercise_repository.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:aitrainer_app/widgets/splash.dart'; import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -48,24 +50,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
autovalidate: true, autovalidate: true,
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
appBar: AppBar( appBar: AppBarNav(depth: 1),
backgroundColor: Colors.transparent,
title: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text("1RM Control"),
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( body: Container(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.height,
@ -130,7 +115,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
textFieldBloc: exerciseBloc.quantity1Field, textFieldBloc: exerciseBloc.quantity1Field,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold),
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
decoration: InputDecoration( decoration: InputDecoration(
fillColor: Colors.white, fillColor: Colors.white,
filled: false, filled: false,
@ -173,7 +158,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
textFieldBloc: exerciseBloc.quantity2Field, textFieldBloc: exerciseBloc.quantity2Field,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold),
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
onChanged: (input) => { onChanged: (input) => {
print("Quantity 2 value $input"), print("Quantity 2 value $input"),
//exerciseBloc.exerciseRepository.setQuantity(double.parse(input)), //exerciseBloc.exerciseRepository.setQuantity(double.parse(input)),
@ -220,7 +205,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
textFieldBloc: exerciseBloc.quantity3Field, textFieldBloc: exerciseBloc.quantity3Field,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold),
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
onChanged: (input) => { onChanged: (input) => {
print("Quantity 3 value $input"), print("Quantity 3 value $input"),
//exerciseBloc.exerciseRepository.setQuantity(double.parse(input)), //exerciseBloc.exerciseRepository.setQuantity(double.parse(input)),
@ -255,7 +240,9 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
), ),
]), ]),
))), ))),
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1),
), ),
); );
} }

View File

@ -1,11 +1,10 @@
import 'dart:collection'; import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_by_plan/exercise_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/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/treeview/tree_view.dart'; import 'package:aitrainer_app/library/tree_view.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_common.dart'; import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
import 'package:aitrainer_app/widgets/splash.dart'; import 'package:aitrainer_app/widgets/splash.dart';
@ -44,7 +43,7 @@ class _ExerciseByPlanPage extends State<ExerciseByPlanPage> with Trans {
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
appBar: AppBarCommonNav(), appBar: AppBarNav(depth: 1),
body: Container( body: Container(
padding: EdgeInsets.all(20), padding: EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -92,8 +91,6 @@ class _ExerciseByPlanPage extends State<ExerciseByPlanPage> with Trans {
List<Widget> nodeExercisePlan(ExerciseByPlanBloc bloc) { List<Widget> nodeExercisePlan(ExerciseByPlanBloc bloc) {
List<Widget> exerciseTypes = List(); List<Widget> exerciseTypes = List();
bool isEnglish = AppLanguage().appLocal == Locale("en");
Card explanation = Card( Card explanation = Card(
color: Colors.white38, color: Colors.white38,
child: Container( child: Container(

View File

@ -1,14 +1,15 @@
import 'dart:collection'; import 'dart:collection';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise.dart'; import 'package:aitrainer_app/model/exercise.dart';
import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/treeview/tree_view.dart'; import 'package:aitrainer_app/library/tree_view.dart';
import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_common.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
@ -26,7 +27,7 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
setContext(context); setContext(context);
return Scaffold( return Scaffold(
appBar: AppBarCommonNav(), appBar: AppBarNav(depth: 1),
body: Container( body: Container(
padding: EdgeInsets.all(20), padding: EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -38,7 +39,8 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
), ),
), ),
child: exerciseWidget(exerciseRepository, customerId), child: exerciseWidget(exerciseRepository, customerId),
) ),
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1),
); );
} }
@ -95,7 +97,6 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
List<Exercise> listExercises = List(); List<Exercise> listExercises = List();
String origDate = ""; String origDate = "";
print("start exercises");
exerciseRepository.exerciseList.forEach((exercise) { exerciseRepository.exerciseList.forEach((exercise) {
String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd); String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd);
@ -109,18 +110,35 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
margin: const EdgeInsets.only(left: 4.0), margin: const EdgeInsets.only(left: 4.0),
child: TreeViewChild( child: TreeViewChild(
startExpanded: true, startExpanded: true,
parent: TreeviewParentWidget(text: exerciseDate), parent: TreeviewParentWidget(text: origDate),
children: _getChildList(listExercises, exerciseRepository), children: _getChildList(listExercises, exerciseRepository),
) )
) )
); );
listExercises = List(); listExercises = List();
}
}
origDate = exerciseDate;
listExercises.add(exercise); listExercises.add(exercise);
origDate = exerciseDate;
}
} else {
listExercises.add(exercise);
origDate = exerciseDate;
}
}); });
if ( listExercises.length > 0) {
listWidget.add(
Container(
margin: const EdgeInsets.only(left: 4.0),
child: TreeViewChild(
startExpanded: true,
parent: TreeviewParentWidget(text: origDate),
children: _getChildList(listExercises, exerciseRepository),
)
)
);
}
return listWidget; return listWidget;
} }

View File

@ -1,11 +1,13 @@
import 'dart:collection'; import 'dart:collection';
import 'package:aitrainer_app/bloc/exercise_form_bloc.dart'; import 'package:aitrainer_app/bloc/exercise_form_bloc.dart';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_type.dart'; import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -21,13 +23,16 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ExerciseType exerciseType = ModalRoute.of(context).settings.arguments; final ExerciseType exerciseType = ModalRoute.of(context).settings.arguments;
// ignore: close_sinks
final menuBloc = BlocProvider.of<MenuBloc>(context);
return BlocProvider( return BlocProvider(
create: (context) => ExerciseFormBloc(exerciseRepository: ExerciseRepository()), create: (context) => ExerciseFormBloc(exerciseRepository: ExerciseRepository(), menuBloc: menuBloc),
child: Builder(builder: (context) { child: Builder(builder: (context) {
// ignore: close_sinks // ignore: close_sinks
final exerciseBloc = BlocProvider.of<ExerciseFormBloc>(context); final exerciseBloc = BlocProvider.of<ExerciseFormBloc>(context);
exerciseBloc.exerciseRepository.setExerciseType(exerciseType); exerciseBloc.exerciseRepository.setExerciseType(exerciseType);
String exerciseName = AppLanguage().appLocal == Locale("en") ? String exerciseName = AppLanguage().appLocal == Locale("en") ?
exerciseBloc.exerciseRepository.exerciseType.name : exerciseBloc.exerciseRepository.exerciseType.name :
@ -37,23 +42,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
autovalidate: true, autovalidate: true,
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
appBar: AppBar( appBar: AppBarNav(depth: 1),
backgroundColor: Colors.transparent,
title: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Image.asset(
'asset/image/WT_long_logo.png',
fit: BoxFit.cover,
height: 65.0,
),
],
),
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () => Navigator.of(context).pop(),
),
),
body: Container( body: Container(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.height,
@ -147,9 +136,10 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
color: Colors.lightBlue, color: Colors.lightBlue,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
inputFormatters: [ inputFormatters: [
WhitelistingTextInputFormatter (RegExp(r"[\d.]")) FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
], ],
onChanged: (input) => { onChanged: (input) =>
{
print("UnitQuantity value $input"), print("UnitQuantity value $input"),
bloc.exerciseRepository.setUnitQuantity( bloc.exerciseRepository.setUnitQuantity(
double.parse(input)) double.parse(input))
@ -171,7 +161,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
), ),
]); ]);
}; }
return column; return column;
} }
@ -185,7 +175,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
color: Colors.deepOrange, color: Colors.deepOrange,
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
inputFormatters: [ inputFormatters: [
WhitelistingTextInputFormatter (RegExp(r"[\d.]")) FilteringTextInputFormatter.allow (RegExp(r"[\d.]"))
], ],
onChanged: (input) => onChanged: (input) =>
{ {

View File

@ -5,7 +5,7 @@ import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:aitrainer_app/repository/exercise_plan_repository.dart'; import 'package:aitrainer_app/repository/exercise_plan_repository.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_common.dart'; import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -43,7 +43,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
autovalidate: true, autovalidate: true,
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: true, resizeToAvoidBottomInset: true,
appBar: AppBarCommonNav(), appBar: AppBarNav(depth: 1),
body: Container( body: Container(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height, height: MediaQuery.of(context).size.height,
@ -72,7 +72,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
textFieldBloc: bloc.serieField, textFieldBloc: bloc.serieField,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
decoration: InputDecoration( decoration: InputDecoration(
fillColor: Colors.white, fillColor: Colors.white,
filled: false, filled: false,
@ -86,7 +86,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
textFieldBloc: bloc.quantityField, textFieldBloc: bloc.quantityField,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
decoration: InputDecoration( decoration: InputDecoration(
fillColor: Colors.white, fillColor: Colors.white,
filled: false, filled: false,
@ -101,7 +101,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
textFieldBloc: bloc.weightField, textFieldBloc: bloc.weightField,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold), style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))], inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
decoration: InputDecoration( decoration: InputDecoration(
fillColor: Colors.white, fillColor: Colors.white,
filled: false, filled: false,

View File

@ -4,9 +4,9 @@ import 'package:aitrainer_app/bloc/exercise_plan/exercise_plan_bloc.dart';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/treeview/tree_view.dart'; import 'package:aitrainer_app/library/tree_view.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_common.dart'; import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
import 'package:aitrainer_app/widgets/splash.dart'; import 'package:aitrainer_app/widgets/splash.dart';
@ -45,7 +45,7 @@ class _ExercisePlanCustomPage extends State<ExercisePlanCustomPage> with Trans {
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
appBar: AppBarCommonNav(), appBar: AppBarNav(depth: 1),
body: Container( body: Container(
padding: EdgeInsets.all(20), padding: EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -181,10 +181,11 @@ class _ExercisePlanCustomPage extends State<ExercisePlanCustomPage> with Trans {
), ),
InkWell( InkWell(
child: child:
element.selected && bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].change != null ? !element.selected || bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId] == null ||
bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].change == null ? Text("") :
Text(bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].repeats.toString() + Text(bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].repeats.toString() +
" x " + bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].weightEquation + " x " + bloc.exercisePlanRepository.exercisePlanDetails[element.exerciseTypeId].weightEquation +
" " + element.exerciseType.unitQuantityUnit, style: TextStyle(fontSize: 9, color: Colors.green),) : Text(""), " " + element.exerciseType.unitQuantityUnit, style: TextStyle(fontSize: 9, color: Colors.green),),
onTap: () => { onTap: () => {
bloc.add(ExercisePlanUpdateUI(workoutTree: element)), bloc.add(ExercisePlanUpdateUI(workoutTree: element)),
Navigator.of(context).pushNamed("exercisePlanDetailAdd", arguments: bloc), Navigator.of(context).pushNamed("exercisePlanDetailAdd", arguments: bloc),

View File

@ -28,7 +28,7 @@ class _MenuPage extends State<MenuPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
menuBloc = BlocProvider.of<MenuBloc>(context); menuBloc = BlocProvider.of<MenuBloc>(context);
return Scaffold( return Scaffold(
appBar: AppBarNav(), appBar: AppBarNav(isMenu: true,),
body: Container( body: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(

View File

@ -0,0 +1,129 @@
import 'dart:collection';
import 'package:aitrainer_app/library/radar_chart.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter/scheduler.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:aitrainer_app/bloc/body_development/body_development_bloc.dart';
class MyDevelopmentBodyPage extends StatefulWidget {
@override
_MyDevelopmentBodyPage createState() => _MyDevelopmentBodyPage();
}
class _MyDevelopmentBodyPage extends State<MyDevelopmentBodyPage> with Trans, Common {
// ignore: close_sinks
BodyDevelopmentBloc bloc;
@override
void initState() {
super.initState();
/// We require the initializers to run after the loading screen is rendered
SchedulerBinding.instance.addPostFrameCallback((_) {
BlocProvider.of<BodyDevelopmentBloc>(context).add(BodyDevelopmentLoad());
});
}
@override
Widget build(BuildContext context) {
bloc = BlocProvider.of<BodyDevelopmentBloc>(context);
LinkedHashMap arguments = ModalRoute.of(context).settings.arguments;
final int customerId = arguments['customerId'];
setContext(context);
return Scaffold(
appBar: AppBarNav(depth: 1),
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<BodyDevelopmentBloc, BodyDevelopmentState>(
listener: (context, state) {
if (state is BodyDevelopmentLoading) {
LoadingDialog();
}
},
builder: (context, state) {
if ( state is BodyDevelopmentInitial) {
return Container();
} else {
return developmentWidget(customerId);
}
},
)
),
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1),
);
}
Widget developmentWidget(int customerId) {
return Column(
children: [
explanationWidget(),
Expanded(
child: exerciseWidget(customerId),
),
]
);
}
Widget exerciseWidget(int customerId) {
return RadarChart.light(
ticks: bloc.radarTicks,
features: bloc.radarFeatures,
data: bloc.radarData,
);
}
Widget explanationWidget() {
return Card(
color: Colors.white60,
child: Container(
padding: EdgeInsets.only(left: 10, right: 5, top: 12, bottom: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
children: [
Icon(
Icons.info,
color: Colors.orangeAccent,
),
Text(" "),
Text(
t("My Body Development"),
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
],
),
Divider(
color: Colors.transparent,
),
Text(
t("You see here your whole body development by muscle groups."),
style: TextStyle(fontSize: 12, fontWeight: FontWeight.normal),
),
],
)
)
);
}
}

View File

@ -1,12 +1,12 @@
import 'dart:collection'; import 'dart:collection';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/bloc/development_by_muscle/development_by_muscle_bloc.dart'; import 'package:aitrainer_app/bloc/development_by_muscle/development_by_muscle_bloc.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/treeview/tree_view.dart'; import 'package:aitrainer_app/library/tree_view.dart';
import 'package:aitrainer_app/widgets/app_bar_common.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/splash.dart'; import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@ -43,7 +43,7 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
setContext(context); setContext(context);
return Scaffold( return Scaffold(
appBar: AppBarCommonNav(), appBar: AppBarNav(depth: 1),
body: Container( body: Container(
padding: EdgeInsets.all(20), padding: EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -75,7 +75,6 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
children: _getTreeChildren(bloc.workoutTreeRepository.sortedTree, bloc), children: _getTreeChildren(bloc.workoutTreeRepository.sortedTree, bloc),
); );
} }
;
}, },
), ),
), ),
@ -209,11 +208,10 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
exerciseTypes.add(explanation); exerciseTypes.add(explanation);
tree.forEach((name, list) { tree.forEach((name, list) {
List<WorkoutMenuTree> listWorkoutMenuTree = list;
exerciseTypes.add(Container( exerciseTypes.add(Container(
margin: const EdgeInsets.only(left: 4.0), margin: const EdgeInsets.only(left: 4.0),
child: TreeViewChild( child: TreeViewChild(
startExpanded: true, startExpanded: false,
parent: _getExerciseWidget(exerciseTypeName: name), parent: _getExerciseWidget(exerciseTypeName: name),
children: _getChildList(list, bloc), children: _getChildList(list, bloc),
))); )));
@ -274,7 +272,7 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
getTitles: (double value) { getTitles: (double value) {
var date = new DateTime.fromMillisecondsSinceEpoch(value.toInt()); var date = new DateTime.fromMillisecondsSinceEpoch(value.toInt());
//String strDate = DateFormat('MM.dd.', AppLanguage().appLocal.toString()).format(date); //String strDate = DateFormat('MM.dd.', AppLanguage().appLocal.toString()).format(date);
String strDate = bloc.getDatePart(date); String strDate = getDatePart(date, bloc.dateRate);
return strDate; return strDate;
}, },
), ),

View File

@ -4,11 +4,11 @@ import 'package:aitrainer_app/model/cache.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:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_common.dart'; import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/image_button.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class MyDevelopmentPage extends StatefulWidget { class MyDevelopmentPage extends StatefulWidget {
@override @override
@ -24,7 +24,7 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
setContext(context); setContext(context);
return Scaffold( return Scaffold(
appBar: AppBarCommonNav(), appBar: AppBarNav(depth: 0),
body: Container( body: Container(
padding: EdgeInsets.all(20), padding: EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -41,7 +41,16 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
SliverGrid( SliverGrid(
delegate: SliverChildListDelegate( delegate: SliverChildListDelegate(
[ [
FlatButton( ImageButton(
textAlignment: Alignment.topCenter,
text: t("My Exercise Logs"),
style: TextStyle(fontSize: 20, color: Colors.orange, fontWeight: FontWeight.bold, backgroundColor: Colors.black54.withOpacity(0.4)),
image: "asset/image/exercise_log.jpg",
top: 40,
onTap:() => this.callBackExerciseLog(exerciseRepository, customerRepository),
isLocked: false,
),
/*FlatButton(
padding: EdgeInsets.all(0), padding: EdgeInsets.all(0),
textColor: Colors.white, textColor: Colors.white,
color: Colors.black12, color: Colors.black12,
@ -56,8 +65,8 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
}, },
child: Text(t("My Exercise Logs"), child: Text(t("My Exercise Logs"),
style: TextStyle(fontSize: 18),) style: TextStyle(fontSize: 18),)
), ),*/
Stack( /*Stack(
fit: StackFit.passthrough, fit: StackFit.passthrough,
overflow: Overflow.clip, overflow: Overflow.clip,
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
@ -73,22 +82,51 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
focusColor: Colors.blueAccent, focusColor: Colors.blueAccent,
onPressed: () => onPressed: () =>
{ {
args['customerId'] = Cache().userLoggedIn.customerId,
Navigator.of(context).pushNamed('mydevelopmentBodyPage',
arguments: args)
}, },
child: Text(t("My Whole Body Development"), child: Text(t("My Whole Body Development"),
style: TextStyle(fontSize: 18),) style: TextStyle(fontSize: 18),)
), ),
], ],
),*/
ImageButton(
textAlignment: Alignment.topLeft,
text: t("My Whole Body Development"),
style: TextStyle(fontSize: 20, color: Colors.orange, fontWeight: FontWeight.bold,
backgroundColor: Colors.black54.withOpacity(0.4)),
image: "asset/menu/3.1.BMI.png",
top: 50,
onTap:() => {
args['customerId'] = Cache().userLoggedIn.customerId,
Navigator.of(context).pushNamed('mydevelopmentBodyPage',
arguments: args)
},
isLocked: true,
), ),
ImageButton(
Stack( textAlignment: Alignment.topLeft,
text: t("Development Of Muscles"),
style: TextStyle(fontSize: 20, color: Colors.orange, fontWeight: FontWeight.bold,
backgroundColor: Colors.black54.withOpacity(0.4)),
image: "asset/image/development_muscles.jpg",
top: 50,
onTap:() => {
Navigator.of(context).pushNamed('mydevelopmentMusclePage',
arguments: args)
},
isLocked: true,
),
/*Stack(
fit: StackFit.passthrough, fit: StackFit.passthrough,
overflow: Overflow.clip, overflow: Overflow.clip,
children: [ children: [
/*Image.asset('asset/image/lock.png', *//*Image.asset('asset/image/lock.png',
height: 40, height: 40,
width: 40, width: 40,
),*/ ),*//*
FlatButton( FlatButton(
padding: EdgeInsets.all(20), padding: EdgeInsets.all(20),
textColor: Colors.white, textColor: Colors.white,
@ -104,8 +142,20 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
), ),
] ]
),*/
ImageButton(
textAlignment: Alignment.topLeft,
text: t("Predictions"),
style: TextStyle(fontSize: 20, color: Colors.orange, fontWeight: FontWeight.bold,
backgroundColor: Colors.black54.withOpacity(0.4)),
image: "asset/menu/2.2.1.1RM.png",
top: 50,
onTap:() => {
},
isLocked: true,
), ),
Stack( /*Stack(
fit: StackFit.passthrough, fit: StackFit.passthrough,
overflow: Overflow.clip, overflow: Overflow.clip,
@ -126,7 +176,7 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
style: TextStyle(fontSize: 18),) style: TextStyle(fontSize: 18),)
), ),
] ]
), ),*/
hiddenWidget(customerRepository, exerciseRepository), hiddenWidget(customerRepository, exerciseRepository),
] ]
), ),
@ -167,6 +217,15 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
} }
} }
void callBackExerciseLog(ExerciseRepository exerciseRepository, CustomerRepository customerRepository) {
final LinkedHashMap args = LinkedHashMap();
args['exerciseRepository'] = exerciseRepository;
args['customerRepository'] = customerRepository;
args['customerId'] = Cache().userLoggedIn.customerId;
Navigator.of(context).pushNamed('exerciseLogPage',
arguments: args);
}
} }

View File

@ -2,7 +2,7 @@ import 'dart:collection';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/util/trans.dart';
import 'package:aitrainer_app/widgets/app_bar_common.dart'; import 'package:aitrainer_app/widgets/app_bar.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -20,7 +20,7 @@ class _MyExercisePlanPage extends State<MyExercisePlanPage> with Trans {
setContext(context); setContext(context);
return Scaffold( return Scaffold(
appBar: AppBarCommonNav(), appBar: AppBarNav(depth: 0),
body: Container( body: Container(
padding: EdgeInsets.all(20), padding: EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(

View File

@ -2,7 +2,6 @@ import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart'; import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
import 'package:aitrainer_app/localization/app_language.dart'; import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart';
import 'package:aitrainer_app/widgets/splash.dart'; import 'package:aitrainer_app/widgets/splash.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';

View File

@ -4,6 +4,7 @@ import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -13,20 +14,20 @@ import 'package:rainbow_color/rainbow_color.dart';
class AppBarNav extends StatefulWidget implements PreferredSizeWidget { class AppBarNav extends StatefulWidget implements PreferredSizeWidget {
final MenuBloc menuBloc; final MenuBloc menuBloc;
const AppBarNav({this.menuBloc}); final bool isMenu;
final int depth;
const AppBarNav({this.menuBloc, this.isMenu, this.depth});
@override @override
_AppBarNav createState() => _AppBarNav(); _AppBarNav createState() => _AppBarNav();
@override @override
Size get preferredSize => const Size.fromHeight(60); Size get preferredSize => const Size.fromHeight(50);
} }
class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin { class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin, Common {
Animation<Color> colorAnim; Animation<Color> colorAnim;
//Animation<double> sizeAnim;
AnimationController colorController; AnimationController colorController;
//AnimationController sizeController;
MenuBloc menuBloc; MenuBloc menuBloc;
@override @override
@ -34,26 +35,7 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
colorController = colorController =
AnimationController(duration: Duration(seconds: 4), vsync:this); AnimationController(duration: Duration(seconds: 4), vsync:this);
//sizeController =
// AnimationController(duration: Duration(seconds: 3), vsync: this);
/* final curvedAnimation = CurvedAnimation(
parent: sizeController,
curve: Curves.easeIn,
reverseCurve: Curves.easeInOutBack,
);
sizeAnim =
Tween<double>(begin: 0, end: 1.5).animate(curvedAnimation)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
sizeController.reverse();
} else if (status == AnimationStatus.dismissed) {
Timer(Duration(seconds: 5), () {
sizeController.forward();
});
}
}); */
colorAnim = RainbowColorTween([Colors.white70, colorAnim = RainbowColorTween([Colors.white70,
Colors.blueGrey, Colors.blueGrey,
Colors.blueAccent, Colors.blueAccent,
@ -69,7 +51,6 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
..addStatusListener((status) { ..addStatusListener((status) {
if (status == AnimationStatus.completed) { if (status == AnimationStatus.completed) {
Timer(Duration(seconds: 10), () { Timer(Duration(seconds: 10), () {
//colorController.reset();
if ( mounted ) { if ( mounted ) {
colorController.forward(); colorController.forward();
} }
@ -85,7 +66,6 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
menuBloc = BlocProvider.of<MenuBloc>(context); menuBloc = BlocProvider.of<MenuBloc>(context);
//setContext(context);
return AppBar( return AppBar(
backgroundColor: Colors.black, backgroundColor: Colors.black,
@ -96,8 +76,8 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
getAnimatedWidget(), getAnimatedWidget(),
Image.asset( Image.asset(
'asset/image/WT_long_logo.png', 'asset/image/WT_long_logo.png',
fit: BoxFit.cover, //fit: BoxFit.cover,
height: 65.0, height: 45.0,
), ),
], ],
), ),
@ -105,8 +85,16 @@ 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: () =>
{ {
if ( menuBloc != null ) { if ( widget.isMenu != null ) {
menuBloc.add(MenuTreeUp(parent: 0)), if ( menuBloc.workoutItem != null ) {
menuBloc.add(MenuTreeUp(parent: menuBloc.workoutItem.parent)),
}
} else if ( widget.depth != null ) {
if ( widget.depth == 0 ) {
Navigator.of(context).pushNamed('home')
} else {
Navigator.of(context).pop()
}
} }
}, },
) )
@ -115,12 +103,12 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
@override @override
void dispose() { void dispose() {
//sizeController.dispose();
colorController.dispose(); colorController.dispose();
super.dispose(); super.dispose();
} }
Widget getAnimatedWidget() { Widget getAnimatedWidget() {
double cWidth = mediaSizeWidth(context);
double percent = Cache().getPercentExercises(); double percent = Cache().getPercentExercises();
if ( percent == -1) { if ( percent == -1) {
ExerciseRepository exerciseRepository = ExerciseRepository(); ExerciseRepository exerciseRepository = ExerciseRepository();
@ -130,9 +118,10 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
int sizeExerciseList = Cache().getExercises() == null? 0 : Cache().getExercises().length; int sizeExerciseList = Cache().getExercises() == null? 0 : Cache().getExercises().length;
if ( sizeExerciseList == 0 ) { if ( sizeExerciseList == 0 ) {
String text = AppLocalizations.of(context).translate("Make your first test"); String text = AppLocalizations.of(context).translate("Make your first test");
double fontSize = text.length > 15 ? 10 : 16; double fontSize = text.length > 24 ? 10 : 16;
return Stack( return Stack(
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
overflow: Overflow.clip,
children: [ children: [
Text(text, Text(text,
style: TextStyle(fontSize: fontSize, color: colorAnim.value, shadows: [Shadow(color: Colors.purple , blurRadius: 15)]), style: TextStyle(fontSize: fontSize, color: colorAnim.value, shadows: [Shadow(color: Colors.purple , blurRadius: 15)]),
@ -147,12 +136,12 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
children: [ children: [
LinearPercentIndicator( LinearPercentIndicator(
width: 120.0, width: cWidth / 4,
lineHeight: 14.0, lineHeight: 14.0,
percent: percent, percent: percent,
center: Text( center: Text(
(percent * 100).toStringAsFixed(0) + "% " + AppLocalizations.of(context).translate("finished"), (percent * 100).toStringAsFixed(0) + "% " + AppLocalizations.of(context).translate("finished"),
style: new TextStyle(fontSize: 12.0), style: new TextStyle(fontSize: 10.0),
), ),
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,

View File

@ -1,135 +0,0 @@
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).pushNamed('home')
},
)
);
}
@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 ) {
String text = AppLocalizations.of(context).translate("Make your first test");
double fontSize = text.length > 17 ? 10 : 16;
return Stack(
alignment: Alignment.topLeft,
children: [
Text(text,
style: TextStyle(fontSize: fontSize, 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) + "% " + AppLocalizations.of(context).translate("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,
),
],
);
}
}
}

View File

@ -1,6 +1,5 @@
import 'package:aitrainer_app/bloc/session/session_bloc.dart'; import 'package:aitrainer_app/bloc/session/session_bloc.dart';
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart'; import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
import 'package:aitrainer_app/localization/app_language.dart';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/view/login.dart'; import 'package:aitrainer_app/view/login.dart';
import 'package:aitrainer_app/view/menu_page.dart'; import 'package:aitrainer_app/view/menu_page.dart';
@ -13,6 +12,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'loading.dart'; import 'loading.dart';
// ignore: must_be_immutable
class AitrainerHome extends StatefulWidget { class AitrainerHome extends StatefulWidget {
_HomePageState _state; _HomePageState _state;
@override @override

View File

@ -0,0 +1,119 @@
import 'package:aitrainer_app/model/cache.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:bloc/bloc.dart';
class ImageButton extends StatelessWidget {
final String text;
final TextStyle style;
final String image;
final double top;
final double height;
final double width;
final bool isShape;
final Bloc bloc;
final Alignment textAlignment;
final VoidCallback onTap;
bool isLocked;
ImageButton({
this.text,
this.style,
this.image,
this.top,
this.height,
this.width,
this.bloc,
this.isShape,
this.textAlignment,
this.onTap,
@required this.isLocked
});
@override
Widget build(BuildContext context) {
return Stack(
//alignment: textAlignment,
fit: StackFit.passthrough,
overflow: Overflow.clip,
children: [
FlatButton(
child: image == null ?
_getButtonImage("asset/image/WT_menu_dark.png") :
_getButtonImage(image),
padding: EdgeInsets.only(left: 0.0, bottom: 0),
shape: getShape(isShape),
onPressed: onTap ?? onTap,
),
Stack(
alignment: Alignment.topLeft,
children: [
this.isLocked?
Image.asset(
'asset/image/lock.png',
height: 40,
width: 40,
)
: Container(),
]),
Positioned(
top: top,
left: 10,
child: Container(
height: 100,
width: 150,
child: InkWell(
onTap: onTap ?? onTap,
child: Text(
text,
maxLines: 2,
style: style,
),
),
color: Colors.transparent,
),
),
]
//)
// )
);
}
dynamic getShape(bool isShape) {
dynamic returnCode = (isShape == true)
? RoundedRectangleBorder(
side: BorderSide(width: 4, color: Colors.orangeAccent),
)
: null;
return returnCode;
}
dynamic _getButtonImage(String imageName) {
dynamic image;
try {
image = Image.asset(
imageName,
fit: BoxFit.fitWidth,
alignment: Alignment.center,
errorBuilder: (context, error, stackTrace) {
String url = Cache.mediaUrl + 'images/' + imageName.substring(11);
Widget image = FadeInImage.assetNetwork(
placeholder: 'asset/image/dots.gif',
image: url,
height: 180,
);
return image;
},
);
} on Exception catch (_) {
String url = Cache.mediaUrl + '/images/' + imageName;
image = FadeInImage.assetNetwork(
placeholder: 'asset/image/dots.gif',
image: url,
height: 180,
);
}
return image;
}
}

View File

@ -0,0 +1,113 @@
import 'dart:ui';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/util/common.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class MenuInfoWidget extends StatelessWidget with Common {
final String title;
final double titleSize;
final Color titleColor;
final FontWeight titleWeight;
final String text;
final double textSize;
final Color textColor;
final FontWeight textWeight;
final Icon leadingIcon;
final Color leadingIconColor;
final String text2;
final String text3;
final String link;
final int parentMenu;
final MenuBloc bloc;
MenuInfoWidget(
{this.title,
this.titleSize,
this.titleColor,
this.titleWeight,
@required this.text,
this.textSize,
this.textColor,
this.textWeight,
this.leadingIcon,
this.leadingIconColor,
this.text2,
this.text3,
this.link,
this.parentMenu,
this.bloc});
@override
Widget build(BuildContext context) {
int length = title.length + text2.length + text3.length + link.length;
return Container(
height: length > 100? 350 : 250,
width: 180,
padding: EdgeInsets.all(25.0),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"asset/menu/3.bcs1.png",
),
fit: BoxFit.contain),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 9, sigmaY: 9),
child: Container(
padding: EdgeInsets.only(top: 10.0, left: 15, right: 10, bottom: 5),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.5),
border: Border.all(color: Colors.white60),
borderRadius: BorderRadius.all(Radius.circular(10.0)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
title,
maxLines: 1,
style:
TextStyle(color: titleColor, fontSize: titleSize, fontFamily: 'Arial', fontWeight: titleWeight),
),
Divider(),
Text(
text,
maxLines: 6,
style: TextStyle(color: textColor, fontSize: textSize, fontFamily: 'Arial', fontWeight: textWeight),
),
Divider(),
Text(
text2,
maxLines: 6,
style: TextStyle(color: textColor, fontSize: textSize, fontFamily: 'Arial', fontWeight: textWeight),
),
Divider(),
Text(
text3,
maxLines: 6,
style: TextStyle(color: textColor, fontSize: textSize, fontFamily: 'Arial', fontWeight: textWeight),
),
getLink(),
],
),
),
));
}
Widget getLink() {
int missingId;
return InkWell(
child: new Text(link, style: TextStyle(color: Colors.lightBlueAccent, fontSize: textSize, fontFamily: 'Arial', fontWeight: textWeight),),
onTap: () =>
{
missingId = bloc.menuTreeRepository.getMissingTreeIdByName(bloc.missingTreeName),
print("menu " + missingId.toString()),
bloc.add(MenuTreeJump(parent: missingId))
}
);
}
}

View File

@ -4,13 +4,16 @@ import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/localization/app_localization.dart'; import 'package:aitrainer_app/localization/app_localization.dart';
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart';
import 'package:aitrainer_app/util/trans.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/painting.dart'; import 'package:flutter/painting.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'menu_info_widget.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class MenuPageWidget extends StatelessWidget { class MenuPageWidget extends StatelessWidget with Trans {
int parent; int parent;
MenuPageWidget({this.parent}); MenuPageWidget({this.parent});
@ -18,16 +21,37 @@ class MenuPageWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context); MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
setContext(context);
return CustomScrollView( return CustomScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
slivers: <Widget>[buildMenuColumn(parent, context, menuBloc)]); slivers: <Widget>[buildMenuColumn(parent, context, menuBloc)]);
} }
SliverList buildMenuColumn( SliverList buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc) {
int parent, BuildContext context, MenuBloc menuBloc) {
final List<Widget> _columnChildren = List(); final List<Widget> _columnChildren = List();
if ( context != null ) {
menuBloc.setContext(context);
menuBloc.setMenuInfo();
Widget info = MenuInfoWidget(
title: menuBloc.infoTitle,
titleSize: 18,
titleWeight: FontWeight.bold,
titleColor: Colors.orangeAccent,
text: menuBloc.infoText,
textSize: 13,
textColor: Colors.yellowAccent,
text2: menuBloc.infoText2,
text3: menuBloc.infoText3,
link: menuBloc.infoLink,
bloc: menuBloc,
);
_columnChildren.add(info);
}
menuBloc.menuTreeRepository menuBloc.menuTreeRepository
.getBranch(menuBloc.parent) .getBranch(menuBloc.parent)
.forEach((treeName, value) { .forEach((treeName, value) {
@ -86,7 +110,7 @@ class MenuPageWidget extends StatelessWidget {
WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) { WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) {
print("Hi!, Menu clicked " + workoutTree.id.toString()); print("Hi!, Menu clicked " + workoutTree.id.toString());
if (workoutTree.child == false) { if (workoutTree.child == false) {
menuBloc.add(MenuTreeDown(parent: workoutTree.id)); menuBloc.add(MenuTreeDown(item: workoutTree, parent: workoutTree.id));
} else { } else {
menuBloc.add(MenuClickExercise(exerciseTypeId: workoutTree.id)); menuBloc.add(MenuClickExercise(exerciseTypeId: workoutTree.id));
if (Cache().userLoggedIn == null) { if (Cache().userLoggedIn == null) {

View File

@ -35,7 +35,7 @@ packages:
name: async name: async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.5.0-nullsafety" version: "2.4.2"
bloc: bloc:
dependency: transitive dependency: transitive
description: description:
@ -56,7 +56,7 @@ packages:
name: boolean_selector name: boolean_selector
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety" version: "2.0.0"
build: build:
dependency: transitive dependency: transitive
description: description:
@ -91,14 +91,14 @@ packages:
name: build_runner name: build_runner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.10.2" version: "1.10.0"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.1" version: "5.2.0"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -119,14 +119,14 @@ packages:
name: characters name: characters
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety.2" version: "1.0.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0-nullsafety" version: "1.1.3"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
@ -147,7 +147,7 @@ packages:
name: clock name: clock
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety" version: "1.0.1"
code_builder: code_builder:
dependency: transitive dependency: transitive
description: description:
@ -161,7 +161,7 @@ packages:
name: collection name: collection
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0-nullsafety.2" version: "1.14.13"
convert: convert:
dependency: transitive dependency: transitive
description: description:
@ -224,7 +224,7 @@ packages:
name: fake_async name: fake_async
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety" version: "1.1.0"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@ -238,7 +238,7 @@ packages:
name: file name: file
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.0.0-nullsafety.1" version: "5.2.1"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
@ -415,7 +415,7 @@ packages:
name: js name: js
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.6.3-nullsafety.1" version: "0.6.2"
json_annotation: json_annotation:
dependency: transitive dependency: transitive
description: description:
@ -443,14 +443,14 @@ packages:
name: matcher name: matcher
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.10-nullsafety" version: "0.12.8"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0-nullsafety.2" version: "1.1.8"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -506,7 +506,7 @@ packages:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0-nullsafety" version: "1.7.0"
path_drawing: path_drawing:
dependency: transitive dependency: transitive
description: description:
@ -548,7 +548,7 @@ packages:
name: pedantic name: pedantic
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.10.0-nullsafety.1" version: "1.9.0"
percent_indicator: percent_indicator:
dependency: "direct main" dependency: "direct main"
description: description:
@ -562,14 +562,14 @@ packages:
name: petitparser name: petitparser
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.0" version: "3.0.4"
platform: platform:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0-nullsafety.1" version: "2.2.1"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -583,14 +583,14 @@ packages:
name: pool name: pool
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.5.0-nullsafety.1" version: "1.4.0"
process: process:
dependency: transitive dependency: transitive
description: description:
name: process name: process
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0-nullsafety.1" version: "3.0.13"
provider: provider:
dependency: transitive dependency: transitive
description: description:
@ -735,21 +735,21 @@ packages:
name: source_map_stack_trace name: source_map_stack_trace
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety.2" version: "2.0.0"
source_maps: source_maps:
dependency: transitive dependency: transitive
description: description:
name: source_maps name: source_maps
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.10.10-nullsafety.1" version: "0.10.9"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0-nullsafety" version: "1.7.0"
spider_chart: spider_chart:
dependency: "direct main" dependency: "direct main"
description: description:
@ -763,14 +763,14 @@ packages:
name: stack_trace name: stack_trace
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.10.0-nullsafety" version: "1.9.5"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety" version: "2.0.0"
stream_transform: stream_transform:
dependency: transitive dependency: transitive
description: description:
@ -784,7 +784,7 @@ packages:
name: string_scanner name: string_scanner
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0-nullsafety" version: "1.0.5"
sync_http: sync_http:
dependency: transitive dependency: transitive
description: description:
@ -798,28 +798,28 @@ packages:
name: term_glyph name: term_glyph
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0-nullsafety" version: "1.1.0"
test: test:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: test name: test
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.16.0-nullsafety.4" version: "1.15.2"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.19-nullsafety" version: "0.2.17"
test_core: test_core:
dependency: transitive dependency: transitive
description: description:
name: test_core name: test_core
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.3.12-nullsafety.4" version: "0.3.10"
timing: timing:
dependency: transitive dependency: transitive
description: description:
@ -833,7 +833,7 @@ packages:
name: typed_data name: typed_data
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0-nullsafety.2" version: "1.2.0"
usage: usage:
dependency: transitive dependency: transitive
description: description:
@ -854,14 +854,14 @@ packages:
name: vector_math name: vector_math
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0-nullsafety.2" version: "2.0.8"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "5.2.0" version: "4.2.0"
vm_service_client: vm_service_client:
dependency: transitive dependency: transitive
description: description:
@ -910,7 +910,7 @@ packages:
name: xdg_directories name: xdg_directories
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.2" version: "0.1.0"
xml: xml:
dependency: transitive dependency: transitive
description: description:
@ -926,5 +926,5 @@ packages:
source: hosted source: hosted
version: "2.2.1" version: "2.2.1"
sdks: sdks:
dart: ">=2.10.0-4.0.dev <2.10.0" dart: ">=2.9.0-14.0.dev <3.0.0"
flutter: ">=1.16.0 <2.0.0" flutter: ">=1.16.0 <2.0.0"

View File

@ -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+23 version: 1.1.2+2
environment: environment:
sdk: ">=2.7.0 <3.1.0" sdk: ">=2.7.0 <3.1.0"
@ -24,8 +24,6 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0 cupertino_icons: ^1.0.0
devicelocale: ^0.3.2 devicelocale: ^0.3.2
sentry: ^3.0.1 sentry: ^3.0.1
@ -94,6 +92,9 @@ flutter:
- 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/image/lock.png
- asset/image/Congrats_N1.jpg
- asset/image/development_muscles.jpg
- asset/image/exercise_log.jpg
- 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
@ -118,6 +119,14 @@ flutter:
- asset/menu/3.1.BMI.png - asset/menu/3.1.BMI.png
- asset/menu/3.2.BMR.png - asset/menu/3.2.BMR.png
- asset/menu/3.3.sizes.png - asset/menu/3.3.sizes.png
- asset/menu/cable triceps.png
- asset/menu/Back_pullup.png
- asset/menu/biceps.jpg
- asset/menu/calf.png
- asset/menu/legpress.jpg
- asset/menu/shoulder press.png
- asset/menu/squat.jpg
- asset/menu/tricdip.jpg
- i18n/en.json - i18n/en.json
- i18n/hu.json - i18n/hu.json

View File

@ -1,9 +1,8 @@
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/service/customer_service.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:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
//import 'package:mockito/mockito.dart'; //import 'package:mockito/mockito.dart';
// Create a MockClient using the Mock class provided by the Mockito package. // Create a MockClient using the Mock class provided by the Mockito package.

View File

@ -11,8 +11,6 @@ main() {
SimExercisePlanRepository _exercisePlanRepository; SimExercisePlanRepository _exercisePlanRepository;
ExercisePlanBloc bloc; ExercisePlanBloc bloc;
int _customerId;
Future<void> setUpPlan() async { Future<void> setUpPlan() async {
final String planName2 = "Test Plan2"; final String planName2 = "Test Plan2";
ExercisePlan plan2 = ExercisePlan(planName2, 101); ExercisePlan plan2 = ExercisePlan(planName2, 101);
@ -42,7 +40,6 @@ main() {
WorkoutTreeRepository menuTreeRepository = WorkoutTreeRepository(); WorkoutTreeRepository menuTreeRepository = WorkoutTreeRepository();
bloc = ExercisePlanBloc(menuTreeRepository: menuTreeRepository); bloc = ExercisePlanBloc(menuTreeRepository: menuTreeRepository);
bloc.setExercisePlanRepository(_exercisePlanRepository); bloc.setExercisePlanRepository(_exercisePlanRepository);
_customerId = 62;
await setUpPlan(); await setUpPlan();
}); });

View File

@ -1,7 +1,6 @@
import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_plan.dart'; import 'package:aitrainer_app/model/exercise_plan.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart'; import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'mocks.dart'; import 'mocks.dart';

View File

@ -13,7 +13,7 @@ class MockExercisePlanApi extends Mock implements ExercisePlanApi {
return _singleton; return _singleton;
} }
MockExercisePlanApi._internal() {} MockExercisePlanApi._internal();
final List<ExercisePlan> memoryExercisePlan = List(); final List<ExercisePlan> memoryExercisePlan = List();
final List<ExercisePlanDetail> memoryExercisePlanDetail = List(); final List<ExercisePlanDetail> memoryExercisePlanDetail = List();

View File

@ -52,13 +52,11 @@ class MockCommon with Common {
void main() { void main() {
group('LoginScreen', () { group('LoginScreen', () {
MockLoginBloc loginBloc; MockLoginBloc loginBloc;
MockUserRepository userRepository;
Widget loginWidget; Widget loginWidget;
MockCommon common; MockCommon common;
setUp(() { setUp(() {
loginBloc = MockLoginBloc(); loginBloc = MockLoginBloc();
userRepository = MockUserRepository();
common = MockCommon(); common = MockCommon();
loginWidget = loginWidget =

View File

@ -1,5 +1,4 @@
// Imports the Flutter Driver API. // Imports the Flutter Driver API.
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
void main() { void main() {