mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Allow day objects to load slots
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -13,7 +13,6 @@ BaseConfig _$BaseConfigFromJson(Map<String, dynamic> json) {
|
||||
'id',
|
||||
'slot_entry',
|
||||
'iteration',
|
||||
'trigger',
|
||||
'value',
|
||||
'operation',
|
||||
'step',
|
||||
@@ -24,11 +23,10 @@ BaseConfig _$BaseConfigFromJson(Map<String, dynamic> 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<String, dynamic> _$BaseConfigToJson(BaseConfig instance) => <String, dynamic
|
||||
'id': instance.id,
|
||||
'slot_entry': instance.slotEntryId,
|
||||
'iteration': instance.iteration,
|
||||
'trigger': instance.trigger,
|
||||
'value': instance.value,
|
||||
'operation': instance.operation,
|
||||
'step': instance.step,
|
||||
|
||||
@@ -21,13 +21,12 @@ import 'package:wger/models/workouts/slot.dart';
|
||||
|
||||
part 'day.g.dart';
|
||||
|
||||
const MIN_LENGTH_NAME = 3;
|
||||
const MAX_LENGTH_NAME = 20;
|
||||
|
||||
const MAX_LENGTH_DESCRIPTION = 1000;
|
||||
|
||||
@JsonSerializable()
|
||||
class Day {
|
||||
static const MIN_LENGTH_NAME = 3;
|
||||
static const MAX_LENGTH_NAME = 20;
|
||||
static const MAX_LENGTH_DESCRIPTION = 1000;
|
||||
|
||||
@JsonKey(required: true)
|
||||
int? id;
|
||||
|
||||
@@ -55,12 +54,9 @@ class Day {
|
||||
@JsonKey(required: true)
|
||||
late Object? config;
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@JsonKey(required: false, defaultValue: [], includeFromJson: true, includeToJson: false)
|
||||
List<Slot> slots = [];
|
||||
|
||||
//@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
//late WorkoutPlan workout;
|
||||
|
||||
Day() {
|
||||
slots = [];
|
||||
}
|
||||
|
||||
@@ -30,7 +30,11 @@ Day _$DayFromJson(Map<String, dynamic> 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<dynamic>?)
|
||||
?.map((e) => Slot.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$DayToJson(Day instance) => <String, dynamic>{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class Slot {
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
List<int> exercisesIds = [];
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@JsonKey(required: false, includeFromJson: true, defaultValue: [], includeToJson: false)
|
||||
List<SlotEntry> 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;
|
||||
|
||||
@@ -17,7 +17,9 @@ Slot _$SlotFromJson(Map<String, dynamic> json) {
|
||||
comment: json['comment'] as String? ?? '',
|
||||
order: (json['order'] as num).toInt(),
|
||||
config: json['config'],
|
||||
);
|
||||
)..entries = (json['entries'] as List<dynamic>)
|
||||
.map((e) => SlotEntry.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$SlotToJson(Slot instance) => <String, dynamic>{
|
||||
|
||||
@@ -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<BaseConfig> maxRestTimeConfigs;
|
||||
|
||||
@JsonKey(required: true)
|
||||
late String comment = '';
|
||||
|
||||
@JsonKey(required: true)
|
||||
late Object? config;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ SlotEntry _$SlotEntryFromJson(Map<String, dynamic> json) {
|
||||
'id',
|
||||
'slot',
|
||||
'order',
|
||||
'comment',
|
||||
'type',
|
||||
'exercise',
|
||||
'repetition_unit',
|
||||
@@ -27,7 +28,6 @@ SlotEntry _$SlotEntryFromJson(Map<String, dynamic> json) {
|
||||
'rir_configs',
|
||||
'rest_configs',
|
||||
'max_rest_configs',
|
||||
'comment',
|
||||
'config'
|
||||
],
|
||||
);
|
||||
@@ -38,9 +38,9 @@ SlotEntry _$SlotEntryFromJson(Map<String, dynamic> 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<dynamic>)
|
||||
@@ -74,6 +74,7 @@ Map<String, dynamic> _$SlotEntryToJson(SlotEntry instance) => <String, dynamic>{
|
||||
'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<String, dynamic> _$SlotEntryToJson(SlotEntry instance) => <String, dynamic>{
|
||||
'rir_configs': instance.rirConfigs,
|
||||
'rest_configs': instance.restTimeConfigs,
|
||||
'max_rest_configs': instance.maxRestTimeConfigs,
|
||||
'comment': instance.comment,
|
||||
'config': instance.config,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<DayFormWidget> {
|
||||
},
|
||||
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<DayFormWidget> {
|
||||
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<DayFormWidget> {
|
||||
}
|
||||
},
|
||||
),
|
||||
SlotFormWidgetNg(widget.day),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -53,11 +53,11 @@ class _RoutineFormState extends State<RoutineForm> {
|
||||
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<RoutineForm> {
|
||||
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<RoutineForm> {
|
||||
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;
|
||||
},
|
||||
|
||||
@@ -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<SlotFormWidgetNg> {
|
||||
@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
|
||||
|
||||
@@ -87,7 +87,6 @@ Routine getWorkout({List<Exercise>? 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<Exercise>? 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<Exercise>? 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];
|
||||
|
||||
Reference in New Issue
Block a user