diff --git a/lib/helpers/json.dart b/lib/helpers/json.dart index 4ece0b17..7e97c37f 100644 --- a/lib/helpers/json.dart +++ b/lib/helpers/json.dart @@ -23,6 +23,13 @@ num stringToNum(String? e) { return e == null ? 0 : num.parse(e); } +num stringOrIntToNum(dynamic e) { + if (e is int) { + return e.toDouble(); // Convert int to double (a type of num) + } + return num.tryParse(e) ?? 0; +} + num? stringToNumNull(String? e) { return e == null ? null : num.parse(e); } diff --git a/lib/models/workouts/base_config.dart b/lib/models/workouts/base_config.dart index 2be6018d..331f935c 100644 --- a/lib/models/workouts/base_config.dart +++ b/lib/models/workouts/base_config.dart @@ -17,6 +17,7 @@ */ import 'package:json_annotation/json_annotation.dart'; +import 'package:wger/helpers/json.dart'; part 'base_config.g.dart'; @@ -31,10 +32,10 @@ class BaseConfig { @JsonKey(required: true) late int iteration; - @JsonKey(required: true) - late String trigger; + // @JsonKey(required: true) + // late String trigger; - @JsonKey(required: true) + @JsonKey(required: true, fromJson: stringOrIntToNum) late num value; @JsonKey(required: true) @@ -44,13 +45,13 @@ class BaseConfig { late String step; @JsonKey(required: true, name: 'need_log_to_apply') - late String needLogToApply; + late bool needLogToApply; BaseConfig({ required this.id, required this.slotEntryId, required this.iteration, - required this.trigger, + // required this.trigger, required this.value, required this.operation, required this.step, diff --git a/lib/models/workouts/base_config.g.dart b/lib/models/workouts/base_config.g.dart index ec6a8ae6..0e1ccad0 100644 --- a/lib/models/workouts/base_config.g.dart +++ b/lib/models/workouts/base_config.g.dart @@ -13,7 +13,6 @@ BaseConfig _$BaseConfigFromJson(Map json) { 'id', 'slot_entry', 'iteration', - 'trigger', 'value', 'operation', 'step', @@ -24,11 +23,10 @@ BaseConfig _$BaseConfigFromJson(Map json) { id: (json['id'] as num).toInt(), slotEntryId: (json['slot_entry'] as num).toInt(), iteration: (json['iteration'] as num).toInt(), - trigger: json['trigger'] as String, - value: json['value'] as num, + value: stringOrIntToNum(json['value']), operation: json['operation'] as String, step: json['step'] as String, - needLogToApply: json['need_log_to_apply'] as String, + needLogToApply: json['need_log_to_apply'] as bool, ); } @@ -36,7 +34,6 @@ Map _$BaseConfigToJson(BaseConfig instance) => slots = []; - //@JsonKey(includeFromJson: false, includeToJson: false) - //late WorkoutPlan workout; - Day() { slots = []; } diff --git a/lib/models/workouts/day.g.dart b/lib/models/workouts/day.g.dart index e8e0f6ee..ced99ea2 100644 --- a/lib/models/workouts/day.g.dart +++ b/lib/models/workouts/day.g.dart @@ -30,7 +30,11 @@ Day _$DayFromJson(Map json) { ..needLogsToAdvance = json['need_logs_to_advance'] as bool ..type = json['type'] as String ..order = json['order'] as num - ..config = json['config']; + ..config = json['config'] + ..slots = (json['slots'] as List?) + ?.map((e) => Slot.fromJson(e as Map)) + .toList() ?? + []; } Map _$DayToJson(Day instance) => { diff --git a/lib/models/workouts/routine.dart b/lib/models/workouts/routine.dart index bb793251..46a4b2ae 100644 --- a/lib/models/workouts/routine.dart +++ b/lib/models/workouts/routine.dart @@ -25,20 +25,20 @@ import 'package:wger/models/workouts/log.dart'; part 'routine.g.dart'; -const MIN_LENGTH_DESCRIPTION = 0; -const MAX_LENGTH_DESCRIPTION = 1000; - -const MIN_LENGTH_NAME = 3; -const MAX_LENGTH_NAME = 25; - -/// In weeks -const MIN_DURATION = 2; - -/// In weeks -const MAX_DURATION = 16; - @JsonSerializable() class Routine { + static const MIN_LENGTH_DESCRIPTION = 0; + static const MAX_LENGTH_DESCRIPTION = 1000; + + static const MIN_LENGTH_NAME = 3; + static const MAX_LENGTH_NAME = 25; + + /// In weeks + static const MIN_DURATION = 2; + + /// In weeks + static const MAX_DURATION = 16; + @JsonKey(required: true) int? id; diff --git a/lib/models/workouts/slot.dart b/lib/models/workouts/slot.dart index c20869c6..587310ba 100644 --- a/lib/models/workouts/slot.dart +++ b/lib/models/workouts/slot.dart @@ -47,7 +47,7 @@ class Slot { @JsonKey(includeFromJson: false, includeToJson: false) List exercisesIds = []; - @JsonKey(includeFromJson: false, includeToJson: false) + @JsonKey(required: false, includeFromJson: true, defaultValue: [], includeToJson: false) List entries = []; /// Computed settings (instead of 4x10 this has [10, 10, 10, 10]), used for @@ -67,7 +67,6 @@ class Slot { Slot.withData({ this.id, - sets, day, comment, order, @@ -79,7 +78,7 @@ class Slot { this.comment = comment ?? ''; exercisesObj = exercises ?? []; exercisesIds = exercisesObj.map((e) => e.id!).toList(); - this.entries = settings ?? []; + entries = settings ?? []; this.settingsComputed = settingsComputed ?? []; if (day != null) { this.day = day; diff --git a/lib/models/workouts/slot.g.dart b/lib/models/workouts/slot.g.dart index b2d4e335..04d34f00 100644 --- a/lib/models/workouts/slot.g.dart +++ b/lib/models/workouts/slot.g.dart @@ -17,7 +17,9 @@ Slot _$SlotFromJson(Map json) { comment: json['comment'] as String? ?? '', order: (json['order'] as num).toInt(), config: json['config'], - ); + )..entries = (json['entries'] as List) + .map((e) => SlotEntry.fromJson(e as Map)) + .toList(); } Map _$SlotToJson(Slot instance) => { diff --git a/lib/models/workouts/slot_entry.dart b/lib/models/workouts/slot_entry.dart index cb494194..d1c2a339 100644 --- a/lib/models/workouts/slot_entry.dart +++ b/lib/models/workouts/slot_entry.dart @@ -17,6 +17,7 @@ */ import 'package:json_annotation/json_annotation.dart'; +import 'package:wger/helpers/json.dart'; import 'package:wger/models/exercises/exercise.dart'; import 'package:wger/models/workouts/base_config.dart'; import 'package:wger/models/workouts/repetition_unit.dart'; @@ -40,6 +41,9 @@ class SlotEntry { @JsonKey(required: true) late int order; + @JsonKey(required: true) + late String comment; + @JsonKey(required: true) late String type; @@ -55,7 +59,7 @@ class SlotEntry { @JsonKey(includeFromJson: false, includeToJson: false) late RepetitionUnit repetitionUnitObj; - @JsonKey(required: true, name: 'repetition_rounding') + @JsonKey(required: true, name: 'repetition_rounding', fromJson: stringToNum) late num repetitionRounding; @JsonKey(required: true, name: 'reps_configs') @@ -70,7 +74,7 @@ class SlotEntry { @JsonKey(includeFromJson: false, includeToJson: false) late WeightUnit weightUnitObj; - @JsonKey(required: true, name: 'weight_rounding') + @JsonKey(required: true, name: 'weight_rounding', fromJson: stringToNum) late num weightRounding; @JsonKey(required: true, name: 'weight_configs') @@ -91,9 +95,6 @@ class SlotEntry { @JsonKey(required: true, name: 'max_rest_configs') late List maxRestTimeConfigs; - @JsonKey(required: true) - late String comment = ''; - @JsonKey(required: true) late Object? config; diff --git a/lib/models/workouts/slot_entry.g.dart b/lib/models/workouts/slot_entry.g.dart index 89dd3c4f..44b2d60e 100644 --- a/lib/models/workouts/slot_entry.g.dart +++ b/lib/models/workouts/slot_entry.g.dart @@ -13,6 +13,7 @@ SlotEntry _$SlotEntryFromJson(Map json) { 'id', 'slot', 'order', + 'comment', 'type', 'exercise', 'repetition_unit', @@ -27,7 +28,6 @@ SlotEntry _$SlotEntryFromJson(Map json) { 'rir_configs', 'rest_configs', 'max_rest_configs', - 'comment', 'config' ], ); @@ -38,9 +38,9 @@ SlotEntry _$SlotEntryFromJson(Map json) { type: json['type'] as String, exerciseId: (json['exercise'] as num).toInt(), repetitionUnitId: (json['repetition_unit'] as num).toInt(), - repetitionRounding: json['repetition_rounding'] as num, + repetitionRounding: stringToNum(json['repetition_rounding'] as String?), weightUnitId: (json['weight_unit'] as num).toInt(), - weightRounding: json['weight_rounding'] as num, + weightRounding: stringToNum(json['weight_rounding'] as String?), comment: json['comment'] as String, ) ..repsConfig = (json['reps_configs'] as List) @@ -74,6 +74,7 @@ Map _$SlotEntryToJson(SlotEntry instance) => { 'id': instance.id, 'slot': instance.slotId, 'order': instance.order, + 'comment': instance.comment, 'type': instance.type, 'exercise': instance.exerciseId, 'repetition_unit': instance.repetitionUnitId, @@ -88,6 +89,5 @@ Map _$SlotEntryToJson(SlotEntry instance) => { 'rir_configs': instance.rirConfigs, 'rest_configs': instance.restTimeConfigs, 'max_rest_configs': instance.maxRestTimeConfigs, - 'comment': instance.comment, 'config': instance.config, }; diff --git a/lib/providers/routines.dart b/lib/providers/routines.dart index 8309b414..42dac4cd 100644 --- a/lib/providers/routines.dart +++ b/lib/providers/routines.dart @@ -344,7 +344,7 @@ class RoutinesProvider with ChangeNotifier { _routinesUrlPath, id: workout.id, objectMethod: 'log_data', - query: {'id': base.id.toString()}, + query: {'id': base.id!.toString()}, ), ); return data; diff --git a/lib/widgets/routines/forms/day.dart b/lib/widgets/routines/forms/day.dart index ac8a87a4..a2f753ad 100644 --- a/lib/widgets/routines/forms/day.dart +++ b/lib/widgets/routines/forms/day.dart @@ -4,6 +4,7 @@ import 'package:provider/provider.dart'; import 'package:wger/helpers/consts.dart'; import 'package:wger/models/workouts/day.dart'; import 'package:wger/providers/routines.dart'; +import 'package:wger/widgets/routines/forms/slot.dart'; class ReorderableDaysList extends StatefulWidget { final int routineId; @@ -184,11 +185,11 @@ class _DayFormWidgetState extends State { }, validator: (value) { if (value!.isEmpty || - value.length < MIN_LENGTH_NAME || - value.length > MAX_LENGTH_NAME) { + value.length < Day.MIN_LENGTH_NAME || + value.length > Day.MAX_LENGTH_NAME) { return AppLocalizations.of(context).enterCharacters( - MIN_LENGTH_NAME, - MAX_LENGTH_NAME, + Day.MIN_LENGTH_NAME, + Day.MAX_LENGTH_NAME, ); } @@ -209,8 +210,8 @@ class _DayFormWidgetState extends State { minLines: 2, maxLines: 10, validator: (value) { - if (value != null && value.length > MAX_LENGTH_DESCRIPTION) { - return AppLocalizations.of(context).enterCharacters(0, MAX_LENGTH_DESCRIPTION); + if (value != null && value.length > Day.MAX_LENGTH_DESCRIPTION) { + return AppLocalizations.of(context).enterCharacters(0, Day.MAX_LENGTH_DESCRIPTION); } return null; @@ -258,6 +259,7 @@ class _DayFormWidgetState extends State { } }, ), + SlotFormWidgetNg(widget.day), ], ), ); diff --git a/lib/widgets/routines/forms/routine.dart b/lib/widgets/routines/forms/routine.dart index 86438a59..6c568566 100644 --- a/lib/widgets/routines/forms/routine.dart +++ b/lib/widgets/routines/forms/routine.dart @@ -53,11 +53,11 @@ class _RoutineFormState extends State { controller: workoutNameController, validator: (value) { if (value!.isEmpty || - value.length < MIN_LENGTH_NAME || - value.length > MAX_LENGTH_NAME) { + value.length < Routine.MIN_LENGTH_NAME || + value.length > Routine.MAX_LENGTH_NAME) { return AppLocalizations.of(context).enterCharacters( - MIN_LENGTH_NAME, - MAX_LENGTH_NAME, + Routine.MIN_LENGTH_NAME, + Routine.MAX_LENGTH_NAME, ); } return null; @@ -73,10 +73,10 @@ class _RoutineFormState extends State { maxLines: 10, controller: workoutDescriptionController, validator: (value) { - if (value!.length > MAX_LENGTH_DESCRIPTION) { + if (value!.length > Routine.MAX_LENGTH_DESCRIPTION) { return AppLocalizations.of(context).enterCharacters( - MIN_LENGTH_DESCRIPTION, - MAX_LENGTH_DESCRIPTION, + Routine.MIN_LENGTH_DESCRIPTION, + Routine.MAX_LENGTH_DESCRIPTION, ); } return null; @@ -93,11 +93,11 @@ class _RoutineFormState extends State { if (endDate.isBefore(startDate)) { return 'End date must be after start date'; } - if (endDate.difference(startDate).inDays < MIN_DURATION * 7) { - return 'Duration of the routine must be more than $MIN_DURATION weeks'; + if (endDate.difference(startDate).inDays < Routine.MIN_DURATION * 7) { + return 'Duration of the routine must be more than ${Routine.MIN_DURATION} weeks'; } - if (endDate.difference(startDate).inDays > MAX_DURATION * 7) { - return 'Duration of the routine must be less than $MAX_DURATION weeks'; + if (endDate.difference(startDate).inDays > Routine.MAX_DURATION * 7) { + return 'Duration of the routine must be less than ${Routine.MAX_DURATION} weeks'; } return null; }, diff --git a/lib/widgets/routines/forms/slot.dart b/lib/widgets/routines/forms/slot.dart index 39a8bacb..79b482ae 100644 --- a/lib/widgets/routines/forms/slot.dart +++ b/lib/widgets/routines/forms/slot.dart @@ -31,12 +31,34 @@ import 'package:wger/screens/add_exercise_screen.dart'; import 'package:wger/widgets/exercises/images.dart'; import 'package:wger/widgets/routines/forms.dart'; +class SlotFormWidgetNg extends StatefulWidget { + final Day _day; + + SlotFormWidgetNg(this._day); + + @override + _SlotFormWidgetStateNg createState() => _SlotFormWidgetStateNg(); +} + +class _SlotFormWidgetStateNg extends State { + @override + Widget build(BuildContext context) { + return Form( + child: Column( + children: [ + Text(widget._day.id!.toString()), + ...widget._day.slots.map((slot) => Text(slot.id!.toString())).toList() + ], + )); + } +} + class SlotFormWidget extends StatefulWidget { final Day _day; late final Slot _slot; SlotFormWidget(this._day, [Slot? set]) { - _slot = set ?? Slot.withData(day: _day.id, order: _day.slots.length, sets: 4); + _slot = set ?? Slot.withData(day: _day.id, order: _day.slots.length); } @override diff --git a/test_data/routines.dart b/test_data/routines.dart index 7dc06349..9bce6b6e 100644 --- a/test_data/routines.dart +++ b/test_data/routines.dart @@ -87,7 +87,6 @@ Routine getWorkout({List? exercises}) { final setBenchPress = Slot.withData( id: 1, day: 1, - sets: 3, order: 1, comment: 'Make sure to warm up', ); @@ -110,7 +109,7 @@ Routine getWorkout({List? exercises}) { settingSquat.weightUnit = weightUnit1; settingSquat.exercise = testBases[4]; - final setSquat = Slot.withData(id: 2, day: 1, sets: 3, order: 1); + final setSquat = Slot.withData(id: 2, day: 1, order: 1); setSquat.addExerciseBase(testBases[4]); setSquat.entries.add(settingSquat); setSquat.settingsComputed = [settingSquat, settingSquat]; @@ -131,7 +130,7 @@ Routine getWorkout({List? exercises}) { settingSideRaises.exercise = testBases[5]; // settingSideRaises.weight = 6; - final setSideRaises = Slot.withData(id: 3, day: 1, sets: 3, order: 1); + final setSideRaises = Slot.withData(id: 3, day: 1, order: 1); setSideRaises.addExerciseBase(testBases[5]); setSideRaises.entries.add(settingSideRaises); setSideRaises.settingsComputed = [settingSideRaises, settingSideRaises];