wt1.1.2d ProgressInfo+
BIN
asset/image/Congrats_N1.jpg
Normal file
After Width: | Height: | Size: 2.3 MiB |
BIN
asset/image/development_muscles.jpg
Normal file
After Width: | Height: | Size: 4.2 MiB |
BIN
asset/image/exercise_log.jpg
Normal file
After Width: | Height: | Size: 3.9 MiB |
BIN
asset/menu/Back_pullup.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
asset/menu/biceps.jpg
Normal file
After Width: | Height: | Size: 217 KiB |
BIN
asset/menu/cable triceps.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
asset/menu/calf.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
asset/menu/legpress.jpg
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
asset/menu/shoulder press.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
asset/menu/squat.jpg
Normal file
After Width: | Height: | Size: 331 KiB |
BIN
asset/menu/tricdip.jpg
Normal file
After Width: | Height: | Size: 177 KiB |
26
i18n/en.json
@ -170,5 +170,29 @@
|
||||
|
||||
"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.",
|
||||
"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."
|
||||
}
|
26
i18n/hu.json
@ -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.",
|
||||
"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.",
|
||||
"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"
|
||||
}
|
43
lib/bloc/body_development/body_development_bloc.dart
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
12
lib/bloc/body_development/body_development_event.dart
Normal 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();
|
||||
}
|
30
lib/bloc/body_development/body_development_state.dart
Normal 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];
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ class CustomerChangeFormBloc extends FormBloc<String, String> {
|
||||
birthYearField.close();
|
||||
weightField.close();
|
||||
genderField.close();
|
||||
goalField.close();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
|
@ -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/util/calculate.dart';
|
||||
import 'package:aitrainer_app/util/common.dart';
|
||||
import 'package:aitrainer_app/util/group_data.dart';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
@ -20,19 +21,240 @@ part 'development_by_muscle_event.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 {
|
||||
static String sumMass = "sumMass";
|
||||
static String oneRepMax = "oneRepMax";
|
||||
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 {
|
||||
final List<BarChartGroupData> data;
|
||||
final double interval;
|
||||
@ -40,16 +262,29 @@ class ChartDataExtended {
|
||||
|
||||
const ChartDataExtended({this.data, this.interval, this.gridInterval});
|
||||
|
||||
Map<String, dynamic> toJson() =>
|
||||
{
|
||||
"data": data.toString(),
|
||||
"interval" : interval.toString(),
|
||||
"gridInterval" : gridInterval,
|
||||
Map<String, dynamic> toJson() {
|
||||
List listBarChartData = List();
|
||||
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(),
|
||||
"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 ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||
LinkedHashMap<int, ChartDataExtended> listChartData = LinkedHashMap();
|
||||
@ -81,57 +316,21 @@ class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, Development
|
||||
|
||||
void getChartData() {
|
||||
List<Exercise> exercises = exerciseRepository.getExerciseList();
|
||||
exercises.sort( (a, b) => a.exerciseTypeId.compareTo(b.exerciseTypeId));
|
||||
|
||||
//print("-- Start calculate --- ");
|
||||
exercises = this.groupByDate(exercises);
|
||||
|
||||
int origExerciseTypeId = 0;
|
||||
int x = 0;
|
||||
chartData = List();
|
||||
double maxData = 0;
|
||||
double minData = 9999999999999;
|
||||
exercises.forEach((exercise) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
if (origExerciseTypeId != exercise.exerciseTypeId && diagramType == DiagramType.percent) {
|
||||
this.basePercent = getBasePercent(exercise);
|
||||
}
|
||||
double diagramValue = this.getDiagramValue(exercise);
|
||||
exercises = sort(exercises, true);
|
||||
/* exercises.forEach((exercise) {
|
||||
print ("Chart exercise " + exercise.toJsonDatePart().toString());
|
||||
});*/
|
||||
|
||||
listChartData = LinkedHashMap();
|
||||
GroupChart groupChart = GroupChart(inputList: exercises, outputList: listChartData);
|
||||
groupChart.diagramType = this.diagramType;
|
||||
groupChart.iteration();
|
||||
listChartData = groupChart.outputList;
|
||||
|
||||
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) {
|
||||
print ("typeid " + key.toString() + " chardata " + value.toJson().toString());
|
||||
@ -139,126 +338,38 @@ class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, Development
|
||||
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> groupedExercises = List();
|
||||
|
||||
String origDatePart;
|
||||
|
||||
int countExercises = 0;
|
||||
double sumQuantity = 0;
|
||||
double maxQuantity = 0;
|
||||
Exercise origExercise;
|
||||
exercises = sort(exercises, false);
|
||||
exercises.forEach((exercise) {
|
||||
String exerciseDatePart = getDatePart(exercise.dateAdd);
|
||||
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++;
|
||||
|
||||
print ("Date exercise " + exercise.toJsonDatePart().toString());
|
||||
});
|
||||
|
||||
groupedExercises.forEach((element) {
|
||||
print("grouped " + element.toJson().toString());
|
||||
});
|
||||
GroupDate groupDate = GroupDate(inputList: exercises, outputList: groupedExercises);
|
||||
groupDate.dateRate = this.dateRate;
|
||||
groupDate.diagramType = this.diagramType;
|
||||
groupDate.iteration();
|
||||
groupedExercises = groupDate.outputList;
|
||||
|
||||
/* groupedExercises.forEach((element) {
|
||||
print("Grouped " + element.toJsonDatePart().toString());
|
||||
});*/
|
||||
|
||||
|
||||
return groupedExercises;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
List<Exercise> sort(List<Exercise> exercises, bool asc) {
|
||||
exercises.sort( (a, b) {
|
||||
var aDateId = a.exerciseTypeId.toString() + "_" + a.datePart.toString();
|
||||
var bDateId = b.exerciseTypeId.toString() + "_" + b.datePart.toString();
|
||||
|
||||
double getBasePercent(Exercise exercise) {
|
||||
if ( exercise.unitQuantity != null ) {
|
||||
this.basePercent = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
||||
} 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;
|
||||
return asc ? aDateId.compareTo(bDateId) : bDateId.compareTo(aDateId);
|
||||
});
|
||||
return exercises;
|
||||
}
|
||||
|
||||
String getDateFormat(DateTime datetime) {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
|
||||
class ExerciseControlFormBloc extends FormBloc<String, String> {
|
||||
|
@ -1,8 +1,11 @@
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
||||
|
||||
import 'menu/menu_bloc.dart';
|
||||
|
||||
class ExerciseFormBloc extends FormBloc<String, String> {
|
||||
final ExerciseRepository exerciseRepository;
|
||||
final MenuBloc menuBloc;
|
||||
|
||||
final quantityField = TextFieldBloc(
|
||||
validators: [
|
||||
@ -19,7 +22,7 @@ class ExerciseFormBloc extends FormBloc<String, String> {
|
||||
final unitQuantityField = TextFieldBloc();
|
||||
final unitQuantityUnitField = TextFieldBloc();
|
||||
|
||||
ExerciseFormBloc({this.exerciseRepository}) {
|
||||
ExerciseFormBloc({this.exerciseRepository, this.menuBloc}) {
|
||||
addFieldBlocs(fieldBlocs: [
|
||||
quantityField,
|
||||
unitField,
|
||||
@ -46,6 +49,7 @@ class ExerciseFormBloc extends FormBloc<String, String> {
|
||||
emitLoading(progress: 30);
|
||||
// Emit either Loaded or Error
|
||||
await exerciseRepository.addExercise();
|
||||
menuBloc.add(MenuTreeDown(parent: 0));
|
||||
emitSuccess(canSubmitAgain: false);
|
||||
|
||||
} on Exception catch (ex) {
|
||||
|
@ -1,22 +1,72 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:aitrainer_app/model/cache.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/util/trans.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
part 'menu_event.dart';
|
||||
part 'menu_state.dart';
|
||||
|
||||
class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans {
|
||||
final WorkoutTreeRepository menuTreeRepository;
|
||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||
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()) {
|
||||
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
|
||||
Stream<MenuState> mapEventToState(
|
||||
MenuEvent event,
|
||||
@ -25,6 +75,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
if ( event is MenuCreate ) {
|
||||
yield MenuLoading();
|
||||
await menuTreeRepository.createTree();
|
||||
setMenuInfo();
|
||||
yield MenuReady();
|
||||
} else if (event is MenuRecreateTree) {
|
||||
// ie. at language changes
|
||||
@ -34,14 +85,28 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
// get child menus or exercises
|
||||
yield MenuLoading();
|
||||
parent = event.parent;
|
||||
workoutItem = event.item;
|
||||
//print("menuitem " + workoutItem.id.toString() + " parent "+workoutItem.parent.toString());
|
||||
menuTreeRepository.getBranch(event.parent);
|
||||
yield MenuReady();
|
||||
} else if (event is MenuTreeUp) {
|
||||
yield MenuLoading();
|
||||
// get parent menus or exercises
|
||||
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();
|
||||
} else if (event is MenuClickExercise) {
|
||||
yield MenuLoading();
|
||||
|
@ -16,16 +16,26 @@ class MenuCreate extends MenuEvent {
|
||||
}
|
||||
|
||||
class MenuTreeDown extends MenuEvent {
|
||||
final WorkoutMenuTree item;
|
||||
final int parent;
|
||||
const MenuTreeDown({this.parent});
|
||||
const MenuTreeDown({this.parent, this.item});
|
||||
|
||||
@override
|
||||
List<Object> get props => [parent];
|
||||
List<Object> get props => [parent, item];
|
||||
}
|
||||
|
||||
class MenuTreeUp extends MenuEvent {
|
||||
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
|
||||
List<Object> get props => [parent];
|
||||
|
@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
325
lib/library/radar_chart.dart
Normal 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;
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ class AppLanguage{
|
||||
String langCode = prefs.getString('language_code');
|
||||
if ( langCode == null) {
|
||||
_appLocale = Locale('en');
|
||||
langCode = "en";
|
||||
}
|
||||
_appLocale = Locale(langCode);
|
||||
print(" ---- Get lang: " + _appLocale.toString() + " lang code $langCode");
|
||||
|
@ -20,6 +20,7 @@ import 'package:aitrainer_app/view/gdpr.dart';
|
||||
import 'package:aitrainer_app/view/login.dart';
|
||||
import 'package:aitrainer_app/view/exercise_new_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_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:sentry/sentry.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/exercise_by_plan/exercise_by_plan_bloc.dart';
|
||||
import 'bloc/exercise_plan/exercise_plan_bloc.dart';
|
||||
@ -133,6 +135,10 @@ Future<Null> main() async {
|
||||
create: (BuildContext context) => DevelopmentByMuscleBloc(
|
||||
workoutTreeRepository: menuTreeRepository),
|
||||
),
|
||||
BlocProvider<BodyDevelopmentBloc>(
|
||||
create: (BuildContext context) => BodyDevelopmentBloc(
|
||||
workoutTreeRepository: menuTreeRepository),
|
||||
),
|
||||
],
|
||||
|
||||
child: AitrainerApp(),
|
||||
@ -173,7 +179,7 @@ class AitrainerApp extends StatelessWidget {
|
||||
}
|
||||
});
|
||||
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;
|
||||
},
|
||||
@ -202,6 +208,7 @@ class AitrainerApp extends StatelessWidget {
|
||||
'exerciseByPlanPage': (context) => ExerciseByPlanPage(),
|
||||
'exerciseAddByPlanPage': (context) => ExerciseAddByPlanPage(),
|
||||
'mydevelopmentMusclePage': (context) => MyDevelopmentMusclePage(),
|
||||
'mydevelopmentBodyPage': (context) => MyDevelopmentBodyPage(),
|
||||
},
|
||||
initialRoute: 'home',
|
||||
title: 'WorkoutTest',
|
||||
@ -220,3 +227,4 @@ class AitrainerApp extends StatelessWidget {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -126,8 +126,8 @@ class Cache {
|
||||
_exercisesTrainee = null;
|
||||
_traineeExercisePlan = null;
|
||||
_exercises = List();
|
||||
_myExercisesPlanDetails = LinkedHashMap();
|
||||
print("Trainees is null? " + (_trainee == null).toString() );
|
||||
//firstLoad = true;
|
||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||
await setPreferences(prefs, SharePrefsChange.logout, 0);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import 'package:aitrainer_app/util/common.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class Exercise {
|
||||
@ -12,6 +11,7 @@ class Exercise {
|
||||
int exercisePlanDetailId;
|
||||
|
||||
String datePart;
|
||||
double calculated;
|
||||
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ class Exercise {
|
||||
this.unitQuantity = json['unitQuantity'];
|
||||
this.dateAdd = DateTime.parse( json['dateAdd'] );
|
||||
this.datePart = DateFormat('yyyy-MM-dd').format(this.dateAdd);
|
||||
this.calculated = quantity;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() =>
|
||||
@ -38,6 +39,18 @@ class Exercise {
|
||||
"exercisePlanDetailId": exercisePlanDetailId,
|
||||
};
|
||||
|
||||
Map<String, dynamic> toJsonDatePart() =>
|
||||
{
|
||||
"exerciseTypeId": exerciseTypeId,
|
||||
"customerId": customerId,
|
||||
"quantity": quantity,
|
||||
'calculated': calculated,
|
||||
"unit": unit,
|
||||
"unitQuantity": unitQuantity,
|
||||
"datePart": this.datePart,
|
||||
};
|
||||
|
||||
|
||||
Exercise copy() {
|
||||
Exercise newExercise = Exercise();
|
||||
newExercise.exerciseTypeId = this.exerciseTypeId;
|
||||
|
@ -28,7 +28,9 @@ class ExercisePlanRepository {
|
||||
ExercisePlan getExercisePlan() => exercisePlan;
|
||||
|
||||
void addDetailToPlan() {
|
||||
actualPlanDetail.exercisePlanId = exercisePlan.exercisePlanId;
|
||||
if ( exercisePlan != null ) {
|
||||
actualPlanDetail.exercisePlanId = exercisePlan.exercisePlanId;
|
||||
}
|
||||
exercisePlanDetails[actualPlanDetail.exerciseTypeId] = actualPlanDetail;
|
||||
Cache().addToMyExercisePlanDetails(actualPlanDetail);
|
||||
}
|
||||
|
@ -56,17 +56,11 @@ class ExerciseRepository {
|
||||
this.exercise.dateAdd = datetimeExercise;
|
||||
}
|
||||
|
||||
double get unitQuantity {
|
||||
return this.exercise.unitQuantity;
|
||||
}
|
||||
double get unitQuantity => this.exercise.unitQuantity;
|
||||
|
||||
double get quantity {
|
||||
return this.exercise.quantity;
|
||||
}
|
||||
double get quantity => this.exercise.quantity;
|
||||
|
||||
Exercise getExercise() {
|
||||
return this.exercise;
|
||||
}
|
||||
Exercise getExercise() => this.exercise;
|
||||
|
||||
Future<void> addExercise() async {
|
||||
final Exercise modelExercise = this.exercise;
|
||||
@ -81,13 +75,9 @@ class ExerciseRepository {
|
||||
}
|
||||
|
||||
|
||||
setCustomer(Customer customer) {
|
||||
this.customer = customer;
|
||||
}
|
||||
setCustomer(Customer customer) => this.customer = customer;
|
||||
|
||||
setExerciseType( ExerciseType exerciseType) {
|
||||
this.exerciseType = exerciseType;
|
||||
}
|
||||
setExerciseType( ExerciseType exerciseType) => this.exerciseType = exerciseType;
|
||||
|
||||
|
||||
Future<List<Exercise>> getExercisesByCustomer( int customerId ) async {
|
||||
@ -102,17 +92,53 @@ class ExerciseRepository {
|
||||
}
|
||||
|
||||
List<Exercise> getExerciseList() {
|
||||
//if ( this.exerciseList == null || this.exerciseList.length == 0 ) {
|
||||
return this.exerciseList = Cache().getExercises();
|
||||
//}
|
||||
//return this.exerciseList;
|
||||
this.exerciseList = Cache().getExercises();
|
||||
return this.exerciseList;
|
||||
}
|
||||
|
||||
List<Exercise> getExerciseListTrainee() {
|
||||
//if ( this.exerciseList == null || this.exerciseList.length == 0 ) {
|
||||
return this.exerciseList = Cache().getExercisesTrainee();
|
||||
//}
|
||||
//return this.exerciseList;
|
||||
this.exerciseList = Cache().getExercisesTrainee();
|
||||
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() {
|
||||
@ -153,7 +179,7 @@ class ExerciseRepository {
|
||||
&& treeItem.exerciseType.base == true
|
||||
&& exercise.exerciseTypeId == treeItem.exerciseType.exerciseTypeId
|
||||
&& !checkedBaseTreeItem.contains(treeItem.parent)) {
|
||||
print ("id: " + exercise.exerciseTypeId.toString());
|
||||
//print ("id: " + exercise.exerciseTypeId.toString());
|
||||
checkedBaseTreeItem.add(treeItem.parent);
|
||||
count1RMExercises++;
|
||||
}
|
||||
@ -197,8 +223,6 @@ class ExerciseRepository {
|
||||
return actualExerciseType;
|
||||
}
|
||||
|
||||
void sortByDate() {
|
||||
exerciseList.sort( (b, a) => a.dateAdd.compareTo(b.dateAdd) );
|
||||
}
|
||||
void sortByDate() => exerciseList.sort( (a, b) => b.dateAdd.compareTo(a.dateAdd) );
|
||||
|
||||
}
|
@ -44,6 +44,7 @@ class WorkoutTreeRepository {
|
||||
Antagonist.calf: Antagonist.calfNr
|
||||
};
|
||||
|
||||
|
||||
Future<void> createTree() async {
|
||||
|
||||
isEnglish = AppLanguage().appLocal == Locale('en');
|
||||
@ -145,16 +146,21 @@ class WorkoutTreeRepository {
|
||||
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() {
|
||||
sortedTree = SplayTreeMap<String, List<WorkoutMenuTree>>();
|
||||
tree.forEach((key, value) {
|
||||
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) {
|
||||
String treeName = _antagonist[workoutTree.nameEnglish].toString() + ". " + workoutTree.name;
|
||||
sortedTree[treeName] = this.getBranchList(workoutTree.id);
|
||||
@ -163,4 +169,16 @@ class WorkoutTreeRepository {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -48,7 +48,7 @@ class CustomerApi {
|
||||
customer = Customer.fromJson(jsonDecode(responseBody));
|
||||
Cache().afterRegistration(customer);
|
||||
}
|
||||
} on FormatException catch (exception) {
|
||||
} on FormatException {
|
||||
throw new Exception(responseBody);
|
||||
}
|
||||
}
|
||||
@ -63,7 +63,7 @@ class CustomerApi {
|
||||
try {
|
||||
customer = Customer.fromJson(jsonDecode(responseBody));
|
||||
await Cache().afterLogin(customer);
|
||||
} on FormatException catch (exception) {
|
||||
} on FormatException {
|
||||
throw new Exception(responseBody);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,18 @@ class ExerciseApi {
|
||||
body);
|
||||
}
|
||||
|
||||
Future<List<Exercise>> getExercisesByCustomer(int customerId ) async {
|
||||
final body = await _client.get("exercises/customer/", customerId.toString() );
|
||||
final Iterable json = jsonDecode(body);
|
||||
final List<Exercise> exercises = json.map( (exercise) {
|
||||
Exercise item = Exercise.fromJson(exercise);
|
||||
return item;
|
||||
}).toList();
|
||||
//exercises.sort( (a, b) => b.dateAdd.compareTo(a.dateAdd) );
|
||||
|
||||
return exercises;
|
||||
}
|
||||
|
||||
Future<Exercise> addExercise(Exercise exercise) async {
|
||||
String body = JsonEncoder().convert(exercise.toJson());
|
||||
print(" ===== add new exercise: " + body );
|
||||
@ -32,12 +44,4 @@ class ExerciseApi {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -7,6 +7,13 @@ import 'package:aitrainer_app/repository/user_repository.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class DateRate {
|
||||
static String daily = "daily";
|
||||
static String weekly = "weekly";
|
||||
static String monthly = "monthly";
|
||||
static String yearly = "yearly";
|
||||
}
|
||||
|
||||
mixin Common {
|
||||
|
||||
final EMAIL_ERROR = "Please type a right email address here.";
|
||||
@ -24,7 +31,7 @@ mixin Common {
|
||||
}
|
||||
|
||||
ExerciseType getExerciseType( int exerciseTypeId ) {
|
||||
ExerciseType returnElement = null;
|
||||
ExerciseType returnElement;
|
||||
List<ExerciseType> listExerciseType = Cache().getExerciseTypes();
|
||||
if ( listExerciseType != null ) {
|
||||
for ( var element in listExerciseType ) {
|
||||
@ -32,7 +39,7 @@ mixin Common {
|
||||
returnElement = element;
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return returnElement;
|
||||
}
|
||||
@ -79,4 +86,18 @@ mixin Common {
|
||||
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
@ -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();
|
||||
|
||||
}
|
@ -122,7 +122,7 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> {
|
||||
color: Colors.lightBlue,
|
||||
fontWeight: FontWeight.bold),
|
||||
inputFormatters: [
|
||||
WhitelistingTextInputFormatter(RegExp(r"[\d.]"))
|
||||
FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
|
||||
],
|
||||
onChanged: (input) => {
|
||||
print("UnitQuantity value $input"),
|
||||
@ -150,7 +150,6 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> {
|
||||
),
|
||||
]);
|
||||
}
|
||||
;
|
||||
return column;
|
||||
}
|
||||
|
||||
@ -164,7 +163,7 @@ class _CustomExerciseNewPageState extends State<CustomExercisePage> {
|
||||
color: Colors.deepOrange,
|
||||
fontWeight: FontWeight.bold),
|
||||
inputFormatters: [
|
||||
WhitelistingTextInputFormatter (RegExp(r"[\d.]"))
|
||||
FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
|
||||
],
|
||||
onChanged: (input) => {
|
||||
print("Quantity value $input"),
|
||||
|
@ -23,7 +23,6 @@ class _CustomerGoalPage extends State<CustomerGoalPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double cWidth = MediaQuery.of(context).size.width * 0.75;
|
||||
final CustomerRepository customerRepository =
|
||||
ModalRoute.of(context).settings.arguments;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:aitrainer_app/bloc/account/account_bloc.dart';
|
||||
import 'package:aitrainer_app/bloc/customer_change_form_bloc.dart';
|
||||
import 'package:aitrainer_app/localization/app_localization.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@ -169,7 +168,7 @@ class CustomerModifyPage extends StatelessWidget with Trans {
|
||||
child: TextFieldBlocBuilder(
|
||||
style: TextStyle(fontSize: 12),
|
||||
textFieldBloc: customerBloc.birthYearField,
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d]"))],
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white24,
|
||||
filled: true,
|
||||
@ -186,7 +185,7 @@ class CustomerModifyPage extends StatelessWidget with Trans {
|
||||
child: TextFieldBlocBuilder(
|
||||
style: TextStyle(fontSize: 12),
|
||||
textFieldBloc: customerBloc.weightField,
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d]"))],
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white24,
|
||||
filled: true,
|
||||
|
@ -148,7 +148,7 @@ class _ExerciseAddByPlanPage extends State<ExerciseAddByPlanPage> with Trans {
|
||||
color: Colors.black54,
|
||||
fontWeight: FontWeight.bold),
|
||||
inputFormatters: [
|
||||
WhitelistingTextInputFormatter(RegExp(r"[\d.]"))
|
||||
FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
|
||||
],
|
||||
|
||||
decoration: InputDecoration(
|
||||
@ -169,7 +169,7 @@ class _ExerciseAddByPlanPage extends State<ExerciseAddByPlanPage> with Trans {
|
||||
color: Colors.deepOrange,
|
||||
fontWeight: FontWeight.bold),
|
||||
inputFormatters: [
|
||||
WhitelistingTextInputFormatter(RegExp(r"[\d.]"))
|
||||
FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
|
||||
],
|
||||
|
||||
decoration: InputDecoration(
|
||||
|
@ -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_localization.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:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -48,24 +50,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
|
||||
autovalidate: true,
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
appBar: AppBar(
|
||||
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(),
|
||||
),
|
||||
),
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
@ -130,7 +115,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
|
||||
textFieldBloc: exerciseBloc.quantity1Field,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold),
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: false,
|
||||
@ -173,7 +158,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
|
||||
textFieldBloc: exerciseBloc.quantity2Field,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold),
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
|
||||
onChanged: (input) => {
|
||||
print("Quantity 2 value $input"),
|
||||
//exerciseBloc.exerciseRepository.setQuantity(double.parse(input)),
|
||||
@ -220,7 +205,7 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
|
||||
textFieldBloc: exerciseBloc.quantity3Field,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 14, color: Colors.deepOrange, fontWeight: FontWeight.bold),
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
|
||||
onChanged: (input) => {
|
||||
print("Quantity 3 value $input"),
|
||||
//exerciseBloc.exerciseRepository.setQuantity(double.parse(input)),
|
||||
@ -255,7 +240,9 @@ class _ExerciseControlPage extends State<ExerciseControlPage> {
|
||||
),
|
||||
]),
|
||||
))),
|
||||
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
import 'dart:collection';
|
||||
import 'package:aitrainer_app/bloc/exercise_by_plan/exercise_by_plan_bloc.dart';
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/workout_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/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/treeview_parent_widget.dart';
|
||||
import 'package:aitrainer_app/widgets/splash.dart';
|
||||
@ -44,7 +43,7 @@ class _ExerciseByPlanPage extends State<ExerciseByPlanPage> with Trans {
|
||||
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: AppBarCommonNav(),
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
@ -92,8 +91,6 @@ class _ExerciseByPlanPage extends State<ExerciseByPlanPage> with Trans {
|
||||
|
||||
List<Widget> nodeExercisePlan(ExerciseByPlanBloc bloc) {
|
||||
List<Widget> exerciseTypes = List();
|
||||
bool isEnglish = AppLanguage().appLocal == Locale("en");
|
||||
|
||||
Card explanation = Card(
|
||||
color: Colors.white38,
|
||||
child: Container(
|
||||
|
@ -1,14 +1,15 @@
|
||||
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:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/exercise.dart';
|
||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||
import 'package:aitrainer_app/repository/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/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:aitrainer_app/widgets/treeview_parent_widget.dart';
|
||||
|
||||
@ -26,7 +27,7 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
|
||||
setContext(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBarCommonNav(),
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
@ -38,7 +39,8 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
|
||||
),
|
||||
),
|
||||
child: exerciseWidget(exerciseRepository, customerId),
|
||||
)
|
||||
),
|
||||
bottomNavigationBar: BottomNavigator(bottomNavIndex: 1),
|
||||
);
|
||||
}
|
||||
|
||||
@ -95,12 +97,11 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
|
||||
|
||||
List<Exercise> listExercises = List();
|
||||
String origDate = "";
|
||||
print("start exercises");
|
||||
exerciseRepository.exerciseList.forEach((exercise) {
|
||||
String exerciseDate = DateFormat("yyyy-MM-dd", AppLanguage().appLocal.toString()).format(exercise.dateAdd);
|
||||
|
||||
if ( origDate != exerciseDate) {
|
||||
if ( origDate.length == 0) {
|
||||
if ( origDate.length == 0 ) {
|
||||
listExercises.add(exercise);
|
||||
origDate = exerciseDate;
|
||||
} else {
|
||||
@ -109,18 +110,35 @@ class _ExerciseLogPage extends State<ExerciseLogPage> with Trans, Common {
|
||||
margin: const EdgeInsets.only(left: 4.0),
|
||||
child: TreeViewChild(
|
||||
startExpanded: true,
|
||||
parent: TreeviewParentWidget(text: exerciseDate),
|
||||
parent: TreeviewParentWidget(text: origDate),
|
||||
children: _getChildList(listExercises, exerciseRepository),
|
||||
)
|
||||
)
|
||||
);
|
||||
listExercises = List();
|
||||
listExercises.add(exercise);
|
||||
origDate = exerciseDate;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import 'dart:collection';
|
||||
|
||||
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_localization.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@ -21,13 +23,16 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ExerciseType exerciseType = ModalRoute.of(context).settings.arguments;
|
||||
// ignore: close_sinks
|
||||
final menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||
|
||||
return BlocProvider(
|
||||
create: (context) => ExerciseFormBloc(exerciseRepository: ExerciseRepository()),
|
||||
create: (context) => ExerciseFormBloc(exerciseRepository: ExerciseRepository(), menuBloc: menuBloc),
|
||||
child: Builder(builder: (context) {
|
||||
// ignore: close_sinks
|
||||
final exerciseBloc = BlocProvider.of<ExerciseFormBloc>(context);
|
||||
|
||||
|
||||
exerciseBloc.exerciseRepository.setExerciseType(exerciseType);
|
||||
String exerciseName = AppLanguage().appLocal == Locale("en") ?
|
||||
exerciseBloc.exerciseRepository.exerciseType.name :
|
||||
@ -37,23 +42,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
|
||||
autovalidate: true,
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Image.asset(
|
||||
'asset/image/WT_long_logo.png',
|
||||
fit: BoxFit.cover,
|
||||
height: 65.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: Colors.white),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
),
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
@ -139,39 +128,40 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
|
||||
if ( bloc.exerciseRepository.exerciseType != null &&
|
||||
bloc.exerciseRepository.exerciseType.unitQuantity == "1") {
|
||||
column = Column(
|
||||
children: [
|
||||
TextFieldBlocBuilder(
|
||||
textFieldBloc: bloc.unitQuantityField,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30,
|
||||
color: Colors.lightBlue,
|
||||
fontWeight: FontWeight.bold),
|
||||
inputFormatters: [
|
||||
WhitelistingTextInputFormatter (RegExp(r"[\d.]"))
|
||||
],
|
||||
onChanged: (input) => {
|
||||
print ("UnitQuantity value $input"),
|
||||
bloc.exerciseRepository.setUnitQuantity(
|
||||
double.parse(input))
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: false,
|
||||
hintStyle: TextStyle(fontSize: 16, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||
hintText: AppLocalizations.of(context).translate("The number of the exercise done with"),
|
||||
labelStyle: TextStyle(fontSize: 16, color: Colors.lightBlue),
|
||||
labelText: AppLocalizations.of(context).translate(
|
||||
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||
),
|
||||
),
|
||||
new InkWell(
|
||||
child: new Text(AppLocalizations.of(context).translate(
|
||||
children: [
|
||||
TextFieldBlocBuilder(
|
||||
textFieldBloc: bloc.unitQuantityField,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30,
|
||||
color: Colors.lightBlue,
|
||||
fontWeight: FontWeight.bold),
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))
|
||||
],
|
||||
onChanged: (input) =>
|
||||
{
|
||||
print("UnitQuantity value $input"),
|
||||
bloc.exerciseRepository.setUnitQuantity(
|
||||
double.parse(input))
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: false,
|
||||
hintStyle: TextStyle(fontSize: 16, color: Colors.black54, fontWeight: FontWeight.w100),
|
||||
hintText: AppLocalizations.of(context).translate("The number of the exercise done with"),
|
||||
labelStyle: TextStyle(fontSize: 16, color: Colors.lightBlue),
|
||||
labelText: AppLocalizations.of(context).translate(
|
||||
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||
style: TextStyle(fontSize: 16)),
|
||||
),
|
||||
),
|
||||
new InkWell(
|
||||
child: new Text(AppLocalizations.of(context).translate(
|
||||
bloc.exerciseRepository.exerciseType.unitQuantityUnit),
|
||||
style: TextStyle(fontSize: 16)),
|
||||
),
|
||||
|
||||
]);
|
||||
};
|
||||
]);
|
||||
}
|
||||
return column;
|
||||
}
|
||||
|
||||
@ -185,7 +175,7 @@ class _ExerciseNewPageState extends State<ExerciseNewPage> {
|
||||
color: Colors.deepOrange,
|
||||
fontWeight: FontWeight.bold),
|
||||
inputFormatters: [
|
||||
WhitelistingTextInputFormatter (RegExp(r"[\d.]"))
|
||||
FilteringTextInputFormatter.allow (RegExp(r"[\d.]"))
|
||||
],
|
||||
onChanged: (input) =>
|
||||
{
|
||||
|
@ -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/repository/exercise_plan_repository.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_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@ -43,7 +43,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
|
||||
autovalidate: true,
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
appBar: AppBarCommonNav(),
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
@ -72,7 +72,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
|
||||
textFieldBloc: bloc.serieField,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: false,
|
||||
@ -86,7 +86,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
|
||||
textFieldBloc: bloc.quantityField,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: false,
|
||||
@ -101,7 +101,7 @@ class _ExercisePlanDetailAddPage extends State<ExercisePlanDetailAddPage> with T
|
||||
textFieldBloc: bloc.weightField,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 30, color: Colors.lightBlue, fontWeight: FontWeight.bold),
|
||||
inputFormatters: [WhitelistingTextInputFormatter(RegExp(r"[\d.]"))],
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r"[\d.]"))],
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: false,
|
||||
|
@ -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/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/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/treeview_parent_widget.dart';
|
||||
import 'package:aitrainer_app/widgets/splash.dart';
|
||||
@ -45,7 +45,7 @@ class _ExercisePlanCustomPage extends State<ExercisePlanCustomPage> with Trans {
|
||||
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: AppBarCommonNav(),
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
@ -181,10 +181,11 @@ class _ExercisePlanCustomPage extends State<ExercisePlanCustomPage> with Trans {
|
||||
),
|
||||
InkWell(
|
||||
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() +
|
||||
" 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: () => {
|
||||
bloc.add(ExercisePlanUpdateUI(workoutTree: element)),
|
||||
Navigator.of(context).pushNamed("exercisePlanDetailAdd", arguments: bloc),
|
||||
|
@ -28,7 +28,7 @@ class _MenuPage extends State<MenuPage> {
|
||||
Widget build(BuildContext context) {
|
||||
menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||
return Scaffold(
|
||||
appBar: AppBarNav(),
|
||||
appBar: AppBarNav(isMenu: true,),
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
|
129
lib/view/mydevelopment_body_page.dart
Normal 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),
|
||||
),
|
||||
|
||||
],
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import 'dart:collection';
|
||||
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:fl_chart/fl_chart.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/model/workout_menu_tree.dart';
|
||||
import 'package:aitrainer_app/treeview/tree_view.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||
import 'package:aitrainer_app/library/tree_view.dart';
|
||||
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
||||
import 'package:aitrainer_app/widgets/splash.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@ -43,7 +43,7 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
|
||||
setContext(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBarCommonNav(),
|
||||
appBar: AppBarNav(depth: 1),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
@ -75,7 +75,6 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
|
||||
children: _getTreeChildren(bloc.workoutTreeRepository.sortedTree, bloc),
|
||||
);
|
||||
}
|
||||
;
|
||||
},
|
||||
),
|
||||
),
|
||||
@ -209,11 +208,10 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
|
||||
exerciseTypes.add(explanation);
|
||||
|
||||
tree.forEach((name, list) {
|
||||
List<WorkoutMenuTree> listWorkoutMenuTree = list;
|
||||
exerciseTypes.add(Container(
|
||||
margin: const EdgeInsets.only(left: 4.0),
|
||||
child: TreeViewChild(
|
||||
startExpanded: true,
|
||||
startExpanded: false,
|
||||
parent: _getExerciseWidget(exerciseTypeName: name),
|
||||
children: _getChildList(list, bloc),
|
||||
)));
|
||||
@ -274,7 +272,7 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
|
||||
getTitles: (double value) {
|
||||
var date = new DateTime.fromMillisecondsSinceEpoch(value.toInt());
|
||||
//String strDate = DateFormat('MM.dd.', AppLanguage().appLocal.toString()).format(date);
|
||||
String strDate = bloc.getDatePart(date);
|
||||
String strDate = getDatePart(date, bloc.dateRate);
|
||||
return strDate;
|
||||
},
|
||||
),
|
||||
|
@ -4,11 +4,11 @@ import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/repository/customer_repository.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:aitrainer_app/util/trans.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar_common.dart';
|
||||
import 'package:aitrainer_app/widgets/app_bar.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/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class MyDevelopmentPage extends StatefulWidget {
|
||||
@override
|
||||
@ -24,7 +24,7 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
||||
setContext(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBarCommonNav(),
|
||||
appBar: AppBarNav(depth: 0),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
@ -41,7 +41,16 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
||||
SliverGrid(
|
||||
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),
|
||||
textColor: Colors.white,
|
||||
color: Colors.black12,
|
||||
@ -56,8 +65,8 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
||||
},
|
||||
child: Text(t("My Exercise Logs"),
|
||||
style: TextStyle(fontSize: 18),)
|
||||
),
|
||||
Stack(
|
||||
),*/
|
||||
/*Stack(
|
||||
fit: StackFit.passthrough,
|
||||
overflow: Overflow.clip,
|
||||
alignment: Alignment.topLeft,
|
||||
@ -73,22 +82,51 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
||||
focusColor: Colors.blueAccent,
|
||||
onPressed: () =>
|
||||
{
|
||||
args['customerId'] = Cache().userLoggedIn.customerId,
|
||||
Navigator.of(context).pushNamed('mydevelopmentBodyPage',
|
||||
arguments: args)
|
||||
},
|
||||
child: Text(t("My Whole Body Development"),
|
||||
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,
|
||||
),
|
||||
|
||||
Stack(
|
||||
ImageButton(
|
||||
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,
|
||||
overflow: Overflow.clip,
|
||||
children: [
|
||||
/*Image.asset('asset/image/lock.png',
|
||||
*//*Image.asset('asset/image/lock.png',
|
||||
height: 40,
|
||||
width: 40,
|
||||
),*/
|
||||
),*//*
|
||||
FlatButton(
|
||||
padding: EdgeInsets.all(20),
|
||||
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,
|
||||
|
||||
overflow: Overflow.clip,
|
||||
@ -126,7 +176,7 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
|
||||
style: TextStyle(fontSize: 18),)
|
||||
),
|
||||
]
|
||||
),
|
||||
),*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@ import 'dart:collection';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.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:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -20,7 +20,7 @@ class _MyExercisePlanPage extends State<MyExercisePlanPage> with Trans {
|
||||
setContext(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBarCommonNav(),
|
||||
appBar: AppBarNav(depth: 0),
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
|
@ -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/localization/app_language.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/splash.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -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/model/cache.dart';
|
||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
||||
import 'package:aitrainer_app/util/common.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.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 {
|
||||
final MenuBloc menuBloc;
|
||||
const AppBarNav({this.menuBloc});
|
||||
final bool isMenu;
|
||||
final int depth;
|
||||
const AppBarNav({this.menuBloc, this.isMenu, this.depth});
|
||||
|
||||
@override
|
||||
_AppBarNav createState() => _AppBarNav();
|
||||
|
||||
@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<double> sizeAnim;
|
||||
AnimationController colorController;
|
||||
//AnimationController sizeController;
|
||||
MenuBloc menuBloc;
|
||||
|
||||
@override
|
||||
@ -34,26 +35,7 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
||||
|
||||
colorController =
|
||||
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,
|
||||
Colors.blueGrey,
|
||||
Colors.blueAccent,
|
||||
@ -69,7 +51,6 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
Timer(Duration(seconds: 10), () {
|
||||
//colorController.reset();
|
||||
if ( mounted ) {
|
||||
colorController.forward();
|
||||
}
|
||||
@ -85,7 +66,6 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||
//setContext(context);
|
||||
|
||||
return AppBar(
|
||||
backgroundColor: Colors.black,
|
||||
@ -96,8 +76,8 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
||||
getAnimatedWidget(),
|
||||
Image.asset(
|
||||
'asset/image/WT_long_logo.png',
|
||||
fit: BoxFit.cover,
|
||||
height: 65.0,
|
||||
//fit: BoxFit.cover,
|
||||
height: 45.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -105,8 +85,16 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
||||
icon: Icon(Icons.arrow_back, color: Colors.white),
|
||||
onPressed: () =>
|
||||
{
|
||||
if ( menuBloc != null ) {
|
||||
menuBloc.add(MenuTreeUp(parent: 0)),
|
||||
if ( widget.isMenu != null ) {
|
||||
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
|
||||
void dispose() {
|
||||
//sizeController.dispose();
|
||||
colorController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Widget getAnimatedWidget() {
|
||||
double cWidth = mediaSizeWidth(context);
|
||||
double percent = Cache().getPercentExercises();
|
||||
if ( percent == -1) {
|
||||
ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||
@ -130,9 +118,10 @@ class _AppBarNav extends State<AppBarNav> with SingleTickerProviderStateMixin {
|
||||
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 > 15 ? 10 : 16;
|
||||
double fontSize = text.length > 24 ? 10 : 16;
|
||||
return Stack(
|
||||
alignment: Alignment.topLeft,
|
||||
overflow: Overflow.clip,
|
||||
children: [
|
||||
Text(text,
|
||||
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,
|
||||
children: [
|
||||
LinearPercentIndicator(
|
||||
width: 120.0,
|
||||
width: cWidth / 4,
|
||||
lineHeight: 14.0,
|
||||
percent: percent,
|
||||
center: Text(
|
||||
(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,),
|
||||
linearStrokeCap: LinearStrokeCap.roundAll,
|
||||
|
@ -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,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import 'package:aitrainer_app/bloc/session/session_bloc.dart';
|
||||
import 'package:aitrainer_app/bloc/settings/settings_bloc.dart';
|
||||
import 'package:aitrainer_app/localization/app_language.dart';
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/view/login.dart';
|
||||
import 'package:aitrainer_app/view/menu_page.dart';
|
||||
@ -13,6 +12,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'loading.dart';
|
||||
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class AitrainerHome extends StatefulWidget {
|
||||
_HomePageState _state;
|
||||
@override
|
||||
|
119
lib/widgets/image_button.dart
Normal 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;
|
||||
}
|
||||
}
|
113
lib/widgets/menu_info_widget.dart
Normal 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))
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -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/model/cache.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/material.dart';
|
||||
import 'package:flutter/painting.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import 'menu_info_widget.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class MenuPageWidget extends StatelessWidget {
|
||||
class MenuPageWidget extends StatelessWidget with Trans {
|
||||
int parent;
|
||||
|
||||
MenuPageWidget({this.parent});
|
||||
@ -18,16 +21,37 @@ class MenuPageWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
|
||||
setContext(context);
|
||||
|
||||
return CustomScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
slivers: <Widget>[buildMenuColumn(parent, context, menuBloc)]);
|
||||
}
|
||||
|
||||
SliverList buildMenuColumn(
|
||||
int parent, BuildContext context, MenuBloc menuBloc) {
|
||||
SliverList buildMenuColumn(int parent, BuildContext context, MenuBloc menuBloc) {
|
||||
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
|
||||
.getBranch(menuBloc.parent)
|
||||
.forEach((treeName, value) {
|
||||
@ -86,7 +110,7 @@ class MenuPageWidget extends StatelessWidget {
|
||||
WorkoutMenuTree workoutTree, MenuBloc menuBloc, BuildContext context) {
|
||||
print("Hi!, Menu clicked " + workoutTree.id.toString());
|
||||
if (workoutTree.child == false) {
|
||||
menuBloc.add(MenuTreeDown(parent: workoutTree.id));
|
||||
menuBloc.add(MenuTreeDown(item: workoutTree, parent: workoutTree.id));
|
||||
} else {
|
||||
menuBloc.add(MenuClickExercise(exerciseTypeId: workoutTree.id));
|
||||
if (Cache().userLoggedIn == null) {
|
||||
|
68
pubspec.lock
@ -35,7 +35,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.5.0-nullsafety"
|
||||
version: "2.4.2"
|
||||
bloc:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -56,7 +56,7 @@ packages:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety"
|
||||
version: "2.0.0"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -91,14 +91,14 @@ packages:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.2"
|
||||
version: "1.10.0"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.1"
|
||||
version: "5.2.0"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -119,14 +119,14 @@ packages:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety.2"
|
||||
version: "1.0.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety"
|
||||
version: "1.1.3"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -147,7 +147,7 @@ packages:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety"
|
||||
version: "1.0.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -161,7 +161,7 @@ packages:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.15.0-nullsafety.2"
|
||||
version: "1.14.13"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -224,7 +224,7 @@ packages:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety"
|
||||
version: "1.1.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -238,7 +238,7 @@ packages:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.0.0-nullsafety.1"
|
||||
version: "5.2.1"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -415,7 +415,7 @@ packages:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.3-nullsafety.1"
|
||||
version: "0.6.2"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -443,14 +443,14 @@ packages:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.10-nullsafety"
|
||||
version: "0.12.8"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.2"
|
||||
version: "1.1.8"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -506,7 +506,7 @@ packages:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0-nullsafety"
|
||||
version: "1.7.0"
|
||||
path_drawing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -548,7 +548,7 @@ packages:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0-nullsafety.1"
|
||||
version: "1.9.0"
|
||||
percent_indicator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -562,14 +562,14 @@ packages:
|
||||
name: petitparser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
version: "3.0.4"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.0-nullsafety.1"
|
||||
version: "2.2.1"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -583,14 +583,14 @@ packages:
|
||||
name: pool
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.0-nullsafety.1"
|
||||
version: "1.4.0"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0-nullsafety.1"
|
||||
version: "3.0.13"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -735,21 +735,21 @@ packages:
|
||||
name: source_map_stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.2"
|
||||
version: "2.0.0"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.10.10-nullsafety.1"
|
||||
version: "0.10.9"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0-nullsafety"
|
||||
version: "1.7.0"
|
||||
spider_chart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -763,14 +763,14 @@ packages:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.10.0-nullsafety"
|
||||
version: "1.9.5"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety"
|
||||
version: "2.0.0"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -784,7 +784,7 @@ packages:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0-nullsafety"
|
||||
version: "1.0.5"
|
||||
sync_http:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -798,28 +798,28 @@ packages:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0-nullsafety"
|
||||
version: "1.1.0"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.16.0-nullsafety.4"
|
||||
version: "1.15.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.19-nullsafety"
|
||||
version: "0.2.17"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.12-nullsafety.4"
|
||||
version: "0.3.10"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -833,7 +833,7 @@ packages:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0-nullsafety.2"
|
||||
version: "1.2.0"
|
||||
usage:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -854,14 +854,14 @@ packages:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.0-nullsafety.2"
|
||||
version: "2.0.8"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "5.2.0"
|
||||
version: "4.2.0"
|
||||
vm_service_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -910,7 +910,7 @@ packages:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.2"
|
||||
version: "0.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -926,5 +926,5 @@ packages:
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
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"
|
||||
|
15
pubspec.yaml
@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.1.0+23
|
||||
version: 1.1.2+2
|
||||
|
||||
environment:
|
||||
sdk: ">=2.7.0 <3.1.0"
|
||||
@ -24,8 +24,6 @@ dependencies:
|
||||
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
|
||||
devicelocale: ^0.3.2
|
||||
sentry: ^3.0.1
|
||||
@ -94,6 +92,9 @@ flutter:
|
||||
- asset/image/WT_welcome.png
|
||||
- asset/image/login_fb.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.1.aerob.png
|
||||
- asset/menu/1.2.anaerob.png
|
||||
@ -118,6 +119,14 @@ flutter:
|
||||
- asset/menu/3.1.BMI.png
|
||||
- asset/menu/3.2.BMR.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/hu.json
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/customer.dart';
|
||||
import 'package:aitrainer_app/service/customer_service.dart';
|
||||
import 'package:aitrainer_app/util/env.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
|
||||
//import 'package:mockito/mockito.dart';
|
||||
|
||||
// Create a MockClient using the Mock class provided by the Mockito package.
|
||||
|
@ -11,8 +11,6 @@ main() {
|
||||
SimExercisePlanRepository _exercisePlanRepository;
|
||||
ExercisePlanBloc bloc;
|
||||
|
||||
int _customerId;
|
||||
|
||||
Future<void> setUpPlan() async {
|
||||
final String planName2 = "Test Plan2";
|
||||
ExercisePlan plan2 = ExercisePlan(planName2, 101);
|
||||
@ -42,7 +40,6 @@ main() {
|
||||
WorkoutTreeRepository menuTreeRepository = WorkoutTreeRepository();
|
||||
bloc = ExercisePlanBloc(menuTreeRepository: menuTreeRepository);
|
||||
bloc.setExercisePlanRepository(_exercisePlanRepository);
|
||||
_customerId = 62;
|
||||
await setUpPlan();
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:aitrainer_app/model/cache.dart';
|
||||
import 'package:aitrainer_app/model/exercise_plan.dart';
|
||||
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'mocks.dart';
|
||||
|
||||
|
@ -13,7 +13,7 @@ class MockExercisePlanApi extends Mock implements ExercisePlanApi {
|
||||
return _singleton;
|
||||
}
|
||||
|
||||
MockExercisePlanApi._internal() {}
|
||||
MockExercisePlanApi._internal();
|
||||
|
||||
final List<ExercisePlan> memoryExercisePlan = List();
|
||||
final List<ExercisePlanDetail> memoryExercisePlanDetail = List();
|
||||
|
@ -52,13 +52,11 @@ class MockCommon with Common {
|
||||
void main() {
|
||||
group('LoginScreen', () {
|
||||
MockLoginBloc loginBloc;
|
||||
MockUserRepository userRepository;
|
||||
Widget loginWidget;
|
||||
MockCommon common;
|
||||
|
||||
setUp(() {
|
||||
loginBloc = MockLoginBloc();
|
||||
userRepository = MockUserRepository();
|
||||
common = MockCommon();
|
||||
|
||||
loginWidget =
|
||||
|
@ -1,5 +1,4 @@
|
||||
// Imports the Flutter Driver API.
|
||||
import 'package:flutter_driver/flutter_driver.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
|