Polish the gym mode and other widgets

This commit is contained in:
Roland Geider
2021-04-06 20:41:44 +02:00
parent 9edcaaaf0f
commit 5557686ff7
10 changed files with 116 additions and 63 deletions

View File

@@ -88,7 +88,7 @@
"@noWorkoutPlans": {
"description": "Message shown when the user has no workout plans"
},
"addExercise": "Add exercise to this day",
"addExercise": "Add exercise",
"repetitions": "Repetitions",
"@repetitions": {
"description": "Repetitions for an exercise set"

View File

@@ -5,6 +5,16 @@ part 'day.g.dart';
@JsonSerializable()
class Day {
static const Map<int, String> weekdays = {
1: 'Monday',
2: 'Tuesday',
3: 'Wednesday',
4: 'Thursday',
5: 'Friday',
6: 'Saturday',
7: 'Sunday',
};
@JsonKey(required: true)
int? id;
@@ -28,27 +38,6 @@ class Day {
this.sets = [];
}
Day.withData({
required this.id,
required this.workoutId,
required this.description,
List<int>? daysOfWeek,
List<Set>? sets,
}) {
this.daysOfWeek = daysOfWeek ?? [];
this.sets = sets ?? [];
}
static const Map<int, String> weekdays = {
1: 'Monday',
2: 'Tuesday',
3: 'Wednesday',
4: 'Thursday',
5: 'Friday',
6: 'Saturday',
7: 'Sunday',
};
String getDayName(int weekDay) {
return weekdays[weekDay]!;
}

View File

@@ -60,6 +60,23 @@ class Set {
}
}
/// Return only one setting object per exercise, this makes rendering workout
/// plans easier and the gym mode uses the synthetic settings anyway.
List<Setting> get settingsFiltered {
List<Setting> out = [];
settings.forEach((setting) {
final foundSettings = out.where(
(element) => element.exerciseId == setting.exerciseId,
);
if (foundSettings.length == 0) {
out.add(setting);
}
});
return out;
}
void addExercise(Exercise exercise) {
exercisesObj.add(exercise);
exercisesIds.add(exercise.id);

View File

@@ -8,7 +8,8 @@ part 'setting.g.dart';
@JsonSerializable()
class Setting {
static final possibleValues = ['1', '1.5', '2', '2.5', '3', '3.5'];
static final possibleRiRValues = ['1', '1.5', '2', '2.5', '3', '3.5'];
static final defaultRiR = '2';
@JsonKey(required: true)
int? id;
@@ -87,7 +88,7 @@ class Setting {
}
void setRir(String rir) {
if (possibleValues.contains(rir)) {
if (possibleRiRValues.contains(rir)) {
this.rir = rir;
} else {
throw Exception('RiR value not allowed');

View File

@@ -140,6 +140,7 @@ class WorkoutPlans extends WgerBaseProvider with ChangeNotifier {
final setData = await fetch(makeUrl(_setsUrlPath, query: {'exerciseday': day.id.toString()}));
for (final setEntry in setData['results']) {
final workoutSet = Set.fromJson(setEntry);
fetchComputedSettings(workoutSet);
// Settings
List<Setting> settings = [];
@@ -182,18 +183,6 @@ class WorkoutPlans extends WgerBaseProvider with ChangeNotifier {
notifyListeners();
}
Future<void> fetchAndSetWorkouts() async {
final data = await fetch(makeUrl(_workoutPlansUrlPath, query: {'ordering': '-creation_date'}));
final List<WorkoutPlan> loadedWorkoutPlans = [];
for (final entry in data['results']) {
loadedWorkoutPlans.add(WorkoutPlan.fromJson(entry));
}
_workoutPlans = loadedWorkoutPlans;
notifyListeners();
}
Future<WorkoutPlan> addWorkout(WorkoutPlan workout) async {
final data = await post(workout.toJson(), makeUrl(_workoutPlansUrlPath));
final plan = WorkoutPlan.fromJson(data);
@@ -325,10 +314,38 @@ class WorkoutPlans extends WgerBaseProvider with ChangeNotifier {
Future<Set> addSet(Set workoutSet) async {
final data = await post(workoutSet.toJson(), makeUrl(_setsUrlPath));
final set = Set.fromJson(data);
fetchComputedSettings(set);
notifyListeners();
return set;
}
Future<void> fetchComputedSettings(Set workoutSet) async {
final data = await fetch(makeUrl(
_setsUrlPath,
id: workoutSet.id!,
objectMethod: 'computed_settings',
));
List<Setting> settings = [];
data['results'].forEach((e) => settings.add(Setting.fromJson(e)));
workoutSet.settingsComputed = settings;
notifyListeners();
}
Future<String> fetchSmartText(Set workoutSet, Exercise exercise) async {
final data = await fetch(
makeUrl(
_setsUrlPath,
id: workoutSet.id!,
objectMethod: 'smart_text',
query: {'exercise': exercise.id.toString()},
),
);
return data['results'];
}
Future<void> deleteSet(Set workoutSet) async {
await deleteRequest(_setsUrlPath, workoutSet.id!);

View File

@@ -35,6 +35,7 @@ class _GymModeScreenState extends State<GymModeScreen> {
final _day = ModalRoute.of(context)!.settings.arguments as Day;
return Scaffold(
backgroundColor: Colors.green,
body: Consumer<WorkoutPlans>(
builder: (context, value, child) => GymMode(_day),
),

View File

@@ -258,7 +258,7 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
day.sets.forEach((set) {
out.add(Column(
children: [
...set.settings.map((s) {
...set.settingsFiltered.map((s) {
return Column(
children: [
Text(s.exerciseObj.name),

View File

@@ -75,7 +75,7 @@ class _WorkoutDayWidgetState extends State<WorkoutDayWidget> {
Expanded(
child: Column(
children: [
...set.settings
...set.settingsFiltered
.map(
(setting) => SettingWidget(
setting: setting,

View File

@@ -606,13 +606,15 @@ class _RiRInputWidgetState extends State<RiRInputWidget> {
return DropdownButtonFormField(
decoration: InputDecoration(labelText: AppLocalizations.of(context)!.rir),
value: dropdownValue,
onSaved: (String? newValue) {
widget._setting.setRir(newValue!);
},
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
widget._setting.setRir(newValue);
});
},
items: Setting.possibleValues.map<DropdownMenuItem<String>>((String value) {
items: Setting.possibleRiRValues.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),

View File

@@ -117,7 +117,7 @@ class StartPage extends StatelessWidget {
(set) {
return Column(
children: [
...set.settings.map((s) {
...set.settingsFiltered.map((s) {
return Column(
children: [
Text(s.exerciseObj.name, style: TextStyle(fontWeight: FontWeight.bold)),
@@ -142,14 +142,13 @@ class StartPage extends StatelessWidget {
}
}
class LogPage extends StatelessWidget {
class LogPage extends StatefulWidget {
PageController _controller;
Setting _setting;
Exercise _exercise;
WorkoutPlan _workoutPlan;
Log _log = Log.empty();
final _form = GlobalKey<FormState>();
final _repsController = TextEditingController();
final _weightController = TextEditingController();
final _rirController = TextEditingController();
@@ -174,6 +173,14 @@ class LogPage extends StatelessWidget {
_log.weightUnit = 1;
}
@override
_LogPageState createState() => _LogPageState();
}
class _LogPageState extends State<LogPage> {
final _form = GlobalKey<FormState>();
String rirValue = Setting.defaultRiR;
@override
Widget build(BuildContext context) {
return Container(
@@ -184,7 +191,7 @@ class LogPage extends StatelessWidget {
Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
_exercise.name,
widget._exercise.name,
style: Theme.of(context).textTheme.headline5,
),
),
@@ -196,11 +203,28 @@ class LogPage extends StatelessWidget {
children: [
TextFormField(
decoration: InputDecoration(labelText: AppLocalizations.of(context)!.repetitions),
controller: _repsController,
controller: widget._repsController,
keyboardType: TextInputType.number,
onFieldSubmitted: (_) {},
onSaved: (newValue) {
_log.reps = int.parse(newValue!);
widget._log.reps = int.parse(newValue!);
},
validator: (value) {
try {
int.parse(value!);
} catch (error) {
return AppLocalizations.of(context)!.enterValidNumber;
}
return null;
},
),
TextFormField(
decoration: InputDecoration(labelText: AppLocalizations.of(context)!.weight),
controller: widget._weightController,
keyboardType: TextInputType.number,
onFieldSubmitted: (_) {},
onSaved: (newValue) {
widget._log.weight = double.parse(newValue!);
},
validator: (value) {
try {
@@ -211,21 +235,23 @@ class LogPage extends StatelessWidget {
return null;
},
),
TextFormField(
decoration: InputDecoration(labelText: AppLocalizations.of(context)!.weight),
controller: _weightController,
keyboardType: TextInputType.number,
onFieldSubmitted: (_) {},
onSaved: (newValue) {
_log.weight = double.parse(newValue!);
},
),
TextFormField(
DropdownButtonFormField(
decoration: InputDecoration(labelText: AppLocalizations.of(context)!.rir),
controller: _rirController,
keyboardType: TextInputType.number,
onFieldSubmitted: (_) {},
onSaved: (newValue) {},
value: rirValue,
onSaved: (String? newValue) {
widget._log.rir = newValue!;
},
onChanged: (String? newValue) {
setState(() {
rirValue = newValue!;
});
},
items: Setting.possibleRiRValues.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
/*
TextFormField(
@@ -252,10 +278,10 @@ class LogPage extends StatelessWidget {
// Save the entry on the server
try {
await Provider.of<WorkoutPlans>(context, listen: false).addLog(_log);
await Provider.of<WorkoutPlans>(context, listen: false).addLog(widget._log);
//final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
//ScaffoldMessenger.of(context).showSnackBar(snackBar);
_controller.nextPage(
widget._controller.nextPage(
duration: Duration(milliseconds: 200),
curve: Curves.bounceIn,
);
@@ -269,7 +295,7 @@ class LogPage extends StatelessWidget {
],
),
),
NavigationFooter(_controller),
NavigationFooter(widget._controller),
],
),
);