diff --git a/lib/models/workouts/routine.dart b/lib/models/workouts/routine.dart index 34139b8b..3d0aa224 100644 --- a/lib/models/workouts/routine.dart +++ b/lib/models/workouts/routine.dart @@ -158,24 +158,23 @@ class Routine { /// Map> get logData { final out = >{}; - for (final log in logs) { - final exercise = log.exercise; - final date = log.date; - + for (final sessionData in sessions) { + final date = sessionData.session.date; if (!out.containsKey(date)) { out[date] = { - 'session': null, + 'session': sessionData.session, 'exercises': >{}, }; } - if (!out[date]!['exercises']!.containsKey(exercise)) { - out[date]!['exercises']![exercise] = []; + for (final log in sessionData.logs) { + final exercise = log.exercise; + if (!out[date]!['exercises']!.containsKey(exercise)) { + out[date]!['exercises']![exercise] = []; + } + out[date]!['exercises']![exercise].add(log); } - - out[date]!['exercises']![exercise].add(log); } - return out; } } diff --git a/lib/models/workouts/session.dart b/lib/models/workouts/session.dart index 9c11acb8..46c4a346 100644 --- a/lib/models/workouts/session.dart +++ b/lib/models/workouts/session.dart @@ -43,10 +43,10 @@ class WorkoutSession { late String notes; @JsonKey(required: true, name: 'time_start', toJson: timeToString, fromJson: stringToTime) - late TimeOfDay timeStart; + late TimeOfDay? timeStart; @JsonKey(required: true, name: 'time_end', toJson: timeToString, fromJson: stringToTime) - late TimeOfDay timeEnd; + late TimeOfDay? timeEnd; @JsonKey(required: false, includeToJson: false, defaultValue: []) List logs = []; @@ -74,7 +74,7 @@ class WorkoutSession { Map toJson() => _$WorkoutSessionToJson(this); - String? get impressionAsString { - return IMPRESSION_MAP[impression]; + String get impressionAsString { + return IMPRESSION_MAP[impression]!; } } diff --git a/lib/providers/exercises.dart b/lib/providers/exercises.dart index c5b03ecf..1441c84b 100644 --- a/lib/providers/exercises.dart +++ b/lib/providers/exercises.dart @@ -284,7 +284,7 @@ class ExercisesProvider with ChangeNotifier { // Note: no await since we don't care for the updated data right now. It // will be written to the db whenever the request finishes and we will get // the updated exercise the next time - //handleUpdateExerciseFromApi(database, exerciseId); + handleUpdateExerciseFromApi(database, exerciseId); return exercise; } on NoSuchEntryException { diff --git a/lib/providers/routines.dart b/lib/providers/routines.dart index c3ea65ea..29690a99 100644 --- a/lib/providers/routines.dart +++ b/lib/providers/routines.dart @@ -270,12 +270,6 @@ class RoutinesProvider with ChangeNotifier { objectMethod: _routinesLogsSubpath, ), ), - baseProvider.fetchPaginated( - baseProvider.makeUrl( - _logsUrlPath, - query: {'routine': routineId.toString(), 'limit': '900'}, - ), - ), ]); final routine = Routine.fromJson(results[0] as Map); @@ -285,7 +279,6 @@ class RoutinesProvider with ChangeNotifier { final currentIterationDayData = results[3] as List; final currentIterationDayDataGym = results[4] as List; final sessionData = results[5] as List; - final logData = results[6] as List; /* * Set exercise, repetition and weight unit objects @@ -329,18 +322,24 @@ class RoutinesProvider with ChangeNotifier { routine.dayDataCurrentIterationGym = currentIterationGym; // Logs - routine.sessions = sessionDataEntries; + // routine.sessions = sessionDataEntries; + routine.sessions = List.from(sessionDataEntries); - for (final logEntry in logData) { + // TODO: workaround, routine.logs is marked as an unmodifiable list + routine.logs = []; + for (final sessionData in routine.sessions) { try { - final log = Log.fromJson(logEntry); - log.weightUnit = _weightUnits.firstWhere((e) => e.id == log.weightUnitId); - log.repetitionUnit = _repetitionUnits.firstWhere((e) => e.id == log.weightUnitId); - log.exerciseBase = (await _exercises.fetchAndSetExercise(log.exerciseId))!; - routine.logs.add(log); - } catch (e) { - _logger.warning('Error while processing the logs for a routine!'); + for (final log in sessionData.logs) { + log.weightUnit = _weightUnits.firstWhere((e) => e.id == log.weightUnitId); + log.repetitionUnit = _repetitionUnits.firstWhere((e) => e.id == log.weightUnitId); + log.exerciseBase = (await _exercises.fetchAndSetExercise(log.exerciseId))!; + + routine.logs.add(log); + } + } catch (e, stackTrace) { + _logger.warning('Error while processing the session data for a routine!'); _logger.warning(e.toString()); + _logger.warning(stackTrace.toString()); } } diff --git a/lib/widgets/routines/charts.dart b/lib/widgets/routines/charts.dart index 41c20a3e..8475dacb 100644 --- a/lib/widgets/routines/charts.dart +++ b/lib/widgets/routines/charts.dart @@ -102,9 +102,16 @@ class _LogChartWidgetFlState extends State { ); }, interval: chartGetInterval( - // TODO: make sure this works when the data is empty etc - widget._data[widget._data.keys.first]!.first.date, - widget._data[widget._data.keys.last]!.first.date, + widget._data.containsKey(widget._data.keys.first) && + widget._data[widget._data.keys.first]!.isNotEmpty + ? widget._data[widget._data.keys.first]!.first.date + : DateTime.now(), + widget._data.containsKey(widget._data.keys.last) && + widget._data[widget._data.keys.last]!.isNotEmpty + ? widget._data[widget._data.keys.last]!.first.date + : DateTime.now(), + // widget._data[widget._data.keys.first]!.first.date, + // widget._data[widget._data.keys.last]!.first.date, ), ), ), diff --git a/lib/widgets/routines/gym_mode.dart b/lib/widgets/routines/gym_mode.dart index 6ff2b648..2e17686f 100644 --- a/lib/widgets/routines/gym_mode.dart +++ b/lib/widgets/routines/gym_mode.dart @@ -857,7 +857,7 @@ class _SessionPageState extends State { // Open time picker final pickedTime = await showTimePicker( context: context, - initialTime: widget._session.timeStart, + initialTime: widget._session.timeStart ?? TimeOfDay.now(), ); if (pickedTime != null) { @@ -893,7 +893,7 @@ class _SessionPageState extends State { // Open time picker final pickedTime = await showTimePicker( context: context, - initialTime: widget._session.timeEnd, + initialTime: widget._session.timeEnd ?? TimeOfDay.now(), ); if (pickedTime != null) { diff --git a/lib/widgets/routines/log.dart b/lib/widgets/routines/log.dart index 5b5514a8..7bd8ff8b 100644 --- a/lib/widgets/routines/log.dart +++ b/lib/widgets/routines/log.dart @@ -17,15 +17,89 @@ */ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:intl/intl.dart'; import 'package:wger/helpers/colors.dart'; +import 'package:wger/helpers/misc.dart'; import 'package:wger/helpers/ui.dart'; import 'package:wger/models/exercises/exercise.dart'; import 'package:wger/models/workouts/log.dart'; import 'package:wger/models/workouts/routine.dart'; import 'package:wger/models/workouts/session.dart'; import 'package:wger/widgets/measurements/charts.dart'; -import 'package:wger/widgets/routines/charts.dart'; + +class SessionInfo extends StatelessWidget { + final WorkoutSession _session; + + const SessionInfo(this._session); + + @override + Widget build(BuildContext context) { + final i18n = AppLocalizations.of(context); + + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Text( + i18n.workoutSession, + style: Theme.of(context).textTheme.headlineSmall, + ), + Text( + DateFormat.yMd(Localizations.localeOf(context).languageCode).format(_session.date), + style: Theme.of(context).textTheme.headlineSmall, + ), + const SizedBox(height: 8.0), + _buildInfoRow( + context, + i18n.timeStart, + _session.timeStart != null + ? MaterialLocalizations.of(context).formatTimeOfDay(_session.timeStart!) + : '-/-', + ), + _buildInfoRow( + context, + i18n.timeEnd, + _session.timeEnd != null + ? MaterialLocalizations.of(context).formatTimeOfDay(_session.timeEnd!) + : '-/-', + ), + _buildInfoRow( + context, + i18n.impression, + _session.impressionAsString, + ), + _buildInfoRow( + context, + i18n.notes, + _session.notes.isNotEmpty ? _session.notes : '-/-', + ), + ], + ), + ); + } + + Widget _buildInfoRow(BuildContext context, String label, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '$label: ', + style: Theme.of(context).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold), + ), + Expanded( + child: Text( + value, + style: Theme.of(context).textTheme.titleMedium, + ), + ), + ], + ), + ); + } +} class ExerciseLogChart extends StatelessWidget { final Map> _logs; @@ -40,7 +114,8 @@ class ExerciseLogChart extends StatelessWidget { return Column( mainAxisSize: MainAxisSize.max, children: [ - LogChartWidgetFl(_logs, _selectedDate), + // TODO: why does this not work??? 😫 + // LogChartWidgetFl(_logs, _selectedDate), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -64,34 +139,30 @@ class DayLogWidget extends StatelessWidget { final DateTime _date; final Routine _routine; - final WorkoutSession? _session; - final Map> _exerciseData; + final WorkoutSession _session; + final Map> _exerciseMap; - const DayLogWidget(this._date, this._exerciseData, this._session, this._routine); + const DayLogWidget(this._date, this._exerciseMap, this._session, this._routine); @override Widget build(BuildContext context) { return Card( child: Column( children: [ - Text( - DateFormat.yMd(Localizations.localeOf(context).languageCode).format(_date), - style: Theme.of(context).textTheme.headlineSmall, - ), - if (_session != null) const Text('Session data here'), - ..._exerciseData.keys.map((exercise) { + SessionInfo(_session), + ..._exerciseMap.keys.map((exercise) { final translation = exercise.getTranslation(Localizations.localeOf(context).languageCode); return Column( children: [ - if (_exerciseData[exercise]!.isNotEmpty) + if (_exerciseMap[exercise]!.isNotEmpty) Text( translation.name, style: Theme.of(context).textTheme.headlineSmall, ) else Container(), - ..._exerciseData[exercise]!.map( + ..._exerciseMap[exercise]!.map( (log) => Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -104,7 +175,7 @@ class DayLogWidget extends StatelessWidget { translation.name, log, translation, - _exerciseData, + _exerciseMap, ); }, ), diff --git a/lib/widgets/routines/workout_logs.dart b/lib/widgets/routines/workout_logs.dart index 0fd63ca8..d69de3a4 100644 --- a/lib/widgets/routines/workout_logs.dart +++ b/lib/widgets/routines/workout_logs.dart @@ -82,7 +82,7 @@ class _WorkoutLogsState extends State { /// An event in the workout log calendar class WorkoutLogEvent { final DateTime dateTime; - final WorkoutSession? session; + final WorkoutSession session; final Map> exercises; const WorkoutLogEvent(this.dateTime, this.session, this.exercises);