From 7e2ba3468d0e3739246e7cba6bec52cfd10aa437 Mon Sep 17 00:00:00 2001 From: Roland Geider Date: Thu, 15 Apr 2021 13:28:12 +0200 Subject: [PATCH] Show past logs in gym mode See #13 --- lib/helpers/misc.dart | 60 ++++++++++++++++++++++++++++++ lib/models/workouts/log.dart | 6 +++ lib/models/workouts/setting.dart | 32 +--------------- lib/providers/workout_plans.dart | 15 +++++++- lib/screens/dashboard.dart | 2 - lib/widgets/workouts/gym_mode.dart | 31 ++++++++++++++- test/workout_plan_model_test.dart | 42 +++++++++++++++++++++ test_data/exercises.dart | 17 ++++++++- test_data/workouts.dart | 44 +++++++++++++++++++--- 9 files changed, 208 insertions(+), 41 deletions(-) create mode 100644 lib/helpers/misc.dart create mode 100644 test/workout_plan_model_test.dart diff --git a/lib/helpers/misc.dart b/lib/helpers/misc.dart new file mode 100644 index 00000000..4e40b552 --- /dev/null +++ b/lib/helpers/misc.dart @@ -0,0 +1,60 @@ +/* + * This file is part of wger Workout Manager . + * Copyright (C) 2020, 2021 wger Team + * + * wger Workout Manager is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wger Workout Manager is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'package:wger/helpers/consts.dart'; +import 'package:wger/models/workouts/repetition_unit.dart'; +import 'package:wger/models/workouts/weight_unit.dart'; + +/// Returns the text representation for a single setting, used in the gym mode +String repText( + int? reps, + RepetitionUnit repetitionUnitObj, + num? weight, + WeightUnit weightUnitObj, + String? rir, +) { + // TODO: how to (easily?) translate strings like the units or 'RiR'? + + List out = []; + + if (reps != null) { + out.add(reps.toString()); + + // The default repetition unit is 'reps', which we don't show unless there + // is no weight defined so that we don't just output something like "8" but + // rather "8 repetitions". If there is weight we want to output "8 x 50kg", + // since the repetitions are implied. If other units are used, we always + // print them + if (repetitionUnitObj.id != DEFAULT_REPETITION_UNIT || weight == 0 || weight == null) { + out.add(repetitionUnitObj.name); + } + } + + if (weight != null && weight != 0) { + out.add('×'); + out.add(weight.toString()); + out.add(weightUnitObj.name); + } + + if (rir != null && rir != '') { + out.add('\n'); + out.add('($rir RiR)'); + } + + return out.join(' '); +} diff --git a/lib/models/workouts/log.dart b/lib/models/workouts/log.dart index bed4b540..94cd8568 100644 --- a/lib/models/workouts/log.dart +++ b/lib/models/workouts/log.dart @@ -18,6 +18,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:wger/helpers/json.dart'; +import 'package:wger/helpers/misc.dart'; import 'package:wger/models/exercises/exercise.dart'; import 'package:wger/models/workouts/repetition_unit.dart'; import 'package:wger/models/workouts/weight_unit.dart'; @@ -100,4 +101,9 @@ class Log { void setRir(String rir) { this.rir = rir; } + + /// Returns the text representation for a single setting, used in the gym mode + String get singleLogRepText { + return repText(reps, repetitionUnitObj, weight, weightUnitObj, rir); + } } diff --git a/lib/models/workouts/setting.dart b/lib/models/workouts/setting.dart index 8af734b4..d02ba5eb 100644 --- a/lib/models/workouts/setting.dart +++ b/lib/models/workouts/setting.dart @@ -17,8 +17,8 @@ */ import 'package:json_annotation/json_annotation.dart'; -import 'package:wger/helpers/consts.dart'; import 'package:wger/helpers/json.dart'; +import 'package:wger/helpers/misc.dart'; import 'package:wger/models/exercises/exercise.dart'; import 'package:wger/models/workouts/repetition_unit.dart'; import 'package:wger/models/workouts/weight_unit.dart'; @@ -116,34 +116,6 @@ class Setting { /// Returns the text representation for a single setting, used in the gym mode String get singleSettingRepText { - // TODO: how to (easily?) translate strings like the units or 'RiR'? - - List out = []; - - if (reps != null) { - out.add(reps.toString()); - - // The default repetition unit is 'reps', which we don't show unless there - // is no weight defined so that we don't just output something like "8" but - // rather "8 repetitions". If there is weight we want to output "8 x 50kg", - // since the repetitions are implied. If other units are used, we always - // print them - if (repetitionUnitId != DEFAULT_REPETITION_UNIT || weight == 0 || weight == null) { - out.add(repetitionUnitObj.name); - } - } - - if (weight != null && weight != 0) { - out.add('×'); - out.add(weight.toString()); - out.add(weightUnitObj.name); - } - - if (rir != null && rir != '') { - out.add('\n'); - out.add('($rir RiR)'); - } - - return out.join(' '); + return repText(reps, repetitionUnitObj, weight, weightUnitObj, rir); } } diff --git a/lib/providers/workout_plans.dart b/lib/providers/workout_plans.dart index fb9046c4..4c7fa532 100644 --- a/lib/providers/workout_plans.dart +++ b/lib/providers/workout_plans.dart @@ -174,7 +174,12 @@ class WorkoutPlans extends WgerBaseProvider with ChangeNotifier { // Logs final logData = await fetch(makeUrl(_logsUrlPath, query: {'workout': workoutId.toString()})); for (final entry in logData['results']) { - plan.logs.add(Log.fromJson(entry)); + var log = Log.fromJson(entry); + log.weightUnit = _weightUnits.firstWhere((e) => e.id == log.weightUnitId); + log.repetitionUnit = _repetitionUnit.firstWhere((e) => e.id == log.weightUnitId); + log.exercise = _exercises.findById(log.exerciseId); + + plan.logs.add(log); } // ... and done @@ -396,6 +401,14 @@ class WorkoutPlans extends WgerBaseProvider with ChangeNotifier { Future addLog(Log log) async { final data = await post(log.toJson(), makeUrl(_logsUrlPath)); final newLog = Log.fromJson(data); + + log.id = newLog.id; + log.weightUnit = _weightUnits.firstWhere((e) => e.id == log.weightUnitId); + log.repetitionUnit = _repetitionUnit.firstWhere((e) => e.id == log.weightUnitId); + log.exercise = _exercises.findById(log.exerciseId); + + final plan = findById(log.workoutPlan); + plan.logs.add(log); notifyListeners(); return newLog; } diff --git a/lib/screens/dashboard.dart b/lib/screens/dashboard.dart index bf82bb76..8c4661db 100644 --- a/lib/screens/dashboard.dart +++ b/lib/screens/dashboard.dart @@ -70,8 +70,6 @@ class _DashboardScreenState extends State { // Workouts await Provider.of(context, listen: false).fetchAndSetUnits(); await Provider.of(context, listen: false).fetchAndSetAllPlans(); - //await Provider.of(context, listen: false).fetchAndSetWorkouts(); - //await Provider.of(context, listen: false).setAllFullWorkouts(); if (Provider.of(context, listen: false).activePlan != null) { Provider.of(context, listen: false).setCurrentPlan( Provider.of(context, listen: false).activePlan!.id!, diff --git a/lib/widgets/workouts/gym_mode.dart b/lib/widgets/workouts/gym_mode.dart index 1c812abc..0432c27a 100644 --- a/lib/widgets/workouts/gym_mode.dart +++ b/lib/widgets/workouts/gym_mode.dart @@ -249,7 +249,36 @@ class _LogPageState extends State { textAlign: TextAlign.center, ), ), - Expanded(child: Container()), + Expanded( + child: (widget._workoutPlan.filterLogsByExercise(widget._exercise).length > 0) + ? ListView( + children: [ + Text( + 'Logs', + style: Theme.of(context).textTheme.headline6, + textAlign: TextAlign.center, + ), + ...widget._workoutPlan.filterLogsByExercise(widget._exercise).map((log) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 40), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(DateFormat.yMd(Localizations.localeOf(context).languageCode) + .format(log.date)), + Text( + log.singleLogRepText, + textAlign: TextAlign.center, + ), + ], + ), + ); + }).toList(), + ], + ) + : Container()), + SizedBox(height: 15), Form( key: _form, child: Column( diff --git a/test/workout_plan_model_test.dart b/test/workout_plan_model_test.dart new file mode 100644 index 00000000..b0250774 --- /dev/null +++ b/test/workout_plan_model_test.dart @@ -0,0 +1,42 @@ +/* + * This file is part of wger Workout Manager . + * Copyright (C) 2020, 2021 wger Team + * + * wger Workout Manager is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * wger Workout Manager is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import 'package:flutter_test/flutter_test.dart'; + +import '../test_data/exercises.dart'; +import '../test_data/workouts.dart'; + +void main() { + group('model tests', () { + test('Test the filterLogsByExercise method', () { + final workout = getWorkout(); + + expect(workout.logs.length, 3); + final logExercise1 = workout.filterLogsByExercise(exercise1); + expect(logExercise1.length, 2); + expect(logExercise1[0].id, 1); + expect(logExercise1[1].id, 2); + + final logExercise2 = workout.filterLogsByExercise(exercise2); + expect(logExercise2.length, 1); + expect(logExercise2[0].id, 3); + + expect(workout.filterLogsByExercise(exercise3).length, 0); + }); + }); +} diff --git a/test_data/exercises.dart b/test_data/exercises.dart index be305fd6..0bccf721 100644 --- a/test_data/exercises.dart +++ b/test_data/exercises.dart @@ -37,10 +37,10 @@ final exercise1 = Exercise( creationDate: DateTime(2021, 1, 15), name: 'test exercise 1', description: 'add clever text', + category: category1, categoryId: 1, muscles: [muscle1, muscle2], equipment: [equipment1, equipment2], - category: category1, ); final exercise2 = Exercise( @@ -49,9 +49,22 @@ final exercise2 = Exercise( creationDate: DateTime(2021, 1, 15), name: 'test exercise 2', description: 'Lorem ipsum etc', + category: category2, categoryId: 2, muscles: [muscle1], musclesSecondary: [muscle2], equipment: [equipment2], - category: category2, +); + +final exercise3 = Exercise( + id: 3, + uuid: 'a3b6c7bb-9d22-4119-a5fc-818584d5e9bc', + creationDate: DateTime(2021, 4, 1), + name: 'test exercise 3', + description: 'The man in black fled across the desert, and the gunslinger followed', + category: category3, + categoryId: 3, + muscles: [muscle1], + musclesSecondary: [muscle2], + equipment: [equipment2], ); diff --git a/test_data/workouts.dart b/test_data/workouts.dart index 1cc3ba12..20f401a9 100644 --- a/test_data/workouts.dart +++ b/test_data/workouts.dart @@ -17,6 +17,7 @@ */ import 'package:wger/models/workouts/day.dart'; +import 'package:wger/models/workouts/log.dart'; import 'package:wger/models/workouts/repetition_unit.dart'; import 'package:wger/models/workouts/set.dart'; import 'package:wger/models/workouts/setting.dart'; @@ -46,6 +47,39 @@ WorkoutPlan getWorkout() { setting1.weightUnit = weightUnit1; setting1.exercise = exercise1; + var log1 = Log.empty() + ..id = 1 + ..weight = 10 + ..rir = '1.5' + ..date = DateTime(2021, 5, 1) + ..reps = 10 + ..workoutPlan = 1; + log1.exercise = exercise1; + log1.weightUnit = weightUnit1; + log1.repetitionUnit = repetitionUnit1; + + var log2 = Log.empty() + ..id = 2 + ..weight = 10 + ..rir = '1.5' + ..date = DateTime(2021, 5, 1) + ..reps = 12 + ..workoutPlan = 1; + log2.exercise = exercise1; + log2.weightUnit = weightUnit1; + log2.repetitionUnit = repetitionUnit1; + + var log3 = Log.empty() + ..id = 3 + ..weight = 50 + ..rir = '' + ..date = DateTime(2021, 5, 2) + ..reps = 8 + ..workoutPlan = 1; + log3.exercise = exercise2; + log3.weightUnit = weightUnit1; + log3.repetitionUnit = repetitionUnit1; + var set1 = Set.withData( id: 1, day: 1, @@ -69,11 +103,11 @@ WorkoutPlan getWorkout() { ..daysOfWeek = [4]; var workout = WorkoutPlan( - id: 1, - creationDate: DateTime(2021, 01, 01), - description: 'test workout 1', - days: [day1, day2], - ); + id: 1, + creationDate: DateTime(2021, 01, 01), + description: 'test workout 1', + days: [day1, day2], + logs: [log1, log2, log3]); return workout; }