Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions lib/providers/add_excercise_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,31 @@ import 'package:flutter/foundation.dart';

import 'dart:io';

import 'package:wger/models/exercises/muscle.dart';

class AddExcerciseProvider with ChangeNotifier {
List<File> get excerciseImages => [..._excerciseImages];
final List<File> _excerciseImages = [];
String? _name;
String? _alternativeName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the alternative names should be a string since some exercises can have several names

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already string!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant a list of strings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every string seperated by space is new name. Correct?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either space or newline, yes. I think newline is more obvious since some names can have whitespaces in them

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to think, how we can implement these.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These part is still pending, but branch is merged?

String? _targetArea;
List<String?>? _primaryMuscles = [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't it be better to store this a a list of Muscles? Same goes to the other stuff we get from the form, it will be easier for us later when we need to do work with those objects later

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently DropDowns and MultiSelect widgets are designed to handle only Strings and not Object, that is the reason I kept it as string.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok. Can we store the object IDs and do a lookup when saving?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's possible , but then in UI we will only see ID and not name.
Instead we need to re-design the widgets.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Showing only the IDs is not optimal 😄, I guess we will have to think of something

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool then we need to re-design the widgets,
I'll try to do them.

List<String?>? _secondaryMuscles = [];

set exerciseName(String name) => _name = name;
set alternateName(String? name) => _alternativeName = name;
set targetArea(String target) => _targetArea = target;
set primaryMuclses(List<String?>? muscles) {
if (muscles?.isNotEmpty ?? false) {
_primaryMuscles = muscles;
}
}

set secondayMuclses(List<String?>? muscles) {
if (muscles?.isNotEmpty ?? false) {
_secondaryMuscles = muscles;
}
}

void addExcerciseImages(List<File> excercizes) {
_excerciseImages.addAll(excercizes);
Expand All @@ -16,4 +38,23 @@ class AddExcerciseProvider with ChangeNotifier {
_excerciseImages.remove(file);
notifyListeners();
}

//Just to Debug Provider
printValues() {
print('Name ${_name}');
print('alternate name : ${_alternativeName}');
print('target area : ${_targetArea}');
print('primary mucsles');
if (_primaryMuscles != null) {
for (final a in _primaryMuscles!) {
print(a);
}
}
print('seconday mucsles');
if (_secondaryMuscles != null) {
for (final a in _secondaryMuscles!) {
print(a);
}
}
}
}
1 change: 1 addition & 0 deletions lib/providers/exercises.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class ExercisesProvider with ChangeNotifier {

List<Exercise> get items => [..._exercises];
List<ExerciseCategory> get categories => [..._categories];
List<Muscle> get muscles => [..._muscles];

// Initialize filters for exercises search in exercises list
void _initFilters() {
Expand Down
53 changes: 41 additions & 12 deletions lib/screens/add_exercise_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:wger/providers/add_excercise_provider.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/widgets/add_exercise/add_exercise_dropdown_button.dart';
import 'package:wger/widgets/add_exercise/add_exercise_multiselect_button.dart';
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
Expand All @@ -19,10 +20,19 @@ class AddExerciseScreen extends StatefulWidget {
_AddExerciseScreenState createState() => _AddExerciseScreenState();
}

abstract class ValidateStep {
abstract VoidCallback _submit;
}

class _AddExerciseScreenState extends State<AddExerciseScreen> {
int _currentStep = 0;
int lastStepIndex = AddExerciseScreen.STEPS_IN_FORM - 1;

final List<GlobalKey<FormState>> _keys = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>()
];
Widget _controlsBuilder(
BuildContext context, {
VoidCallback? onStepCancel,
Expand Down Expand Up @@ -55,7 +65,9 @@ class _AddExerciseScreenState extends State<AddExerciseScreen> {
steps: [
Step(
title: const Text('Basics'),
content: _BasicStepContent(),
content: _BasicStepContent(
formkey: _keys[0],
),
),
Step(
title: const Text('Duplicates and variations'),
Expand All @@ -75,9 +87,13 @@ class _AddExerciseScreenState extends State<AddExerciseScreen> {
if (_currentStep == lastStepIndex) {
_addExercise();
} else {
setState(() {
_currentStep += 1;
});
if (_keys[_currentStep].currentState?.validate() ?? false) {
_keys[_currentStep].currentState?.save();
context.read<AddExcerciseProvider>().printValues();
setState(() {
_currentStep += 1;
});
}
}
},
onStepCancel: () => setState(() {
Expand All @@ -89,38 +105,51 @@ class _AddExerciseScreenState extends State<AddExerciseScreen> {
}

class _BasicStepContent extends StatelessWidget {
final GlobalKey<FormState> _basicStepFormKey = GlobalKey<FormState>();
// final GlobalKey<FormState> _basicStepFormKey = GlobalKey<FormState>();
final GlobalKey<FormState> formkey;
_BasicStepContent({required this.formkey});
@override
Widget build(BuildContext context) {
final addExercideProvider = context.read<AddExcerciseProvider>();
final exerciseProvider = context.read<ExercisesProvider>();
final categories = exerciseProvider.categories;
final muscles = exerciseProvider.muscles;
return Form(
key: _basicStepFormKey,
key: formkey,
child: Column(
children: [
AddExerciseTextArea(
onChange: (value) => print(value),
title: AppLocalizations.of(context).name,
title: '${AppLocalizations.of(context).name}*',
isRequired: true,
validator: (name) => name?.isEmpty ?? true ? 'Name is required' : null,
onSaved: (String? name) => addExercideProvider.exerciseName = name!,
),
AddExerciseTextArea(
onChange: (value) => print(value),
title: 'Alternative names',
isMultiline: true,
helperText: 'One name per line',
onSaved: (String? alternateName) => addExercideProvider.alternateName = alternateName,
),
AddExerciseDropdownButton(
title: 'Target area',
items: ['Arms'],
title: 'Target area*',
items: categories.map((e) => e.name).toList(),
onChange: (value) => print(value),
validator: (value) => value?.isEmpty ?? true ? 'Target Area is Required ' : null,
onSaved: (String? targetArea) => addExercideProvider.targetArea = targetArea!,
),
AddExerciseMultiselectButton(
title: AppLocalizations.of(context).muscles,
items: ['Arms', 'Chest', 'Shoulders'],
items: muscles.map((e) => e.name).toList(),
onChange: (value) => print(value),
onSaved: (List<String?>? muscles) => addExercideProvider.primaryMuclses = muscles,
),
AddExerciseMultiselectButton(
title: AppLocalizations.of(context).musclesSecondary,
items: ['Arms', 'Chest', 'Shoulders'],
items: muscles.map((e) => e.name).toList(),
onChange: (value) => print(value),
onSaved: (List<String?>? muscles) => addExercideProvider.secondayMuclses = muscles,
),
],
),
Expand Down
6 changes: 6 additions & 0 deletions lib/widgets/add_exercise/add_exercise_dropdown_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ class AddExerciseDropdownButton extends StatefulWidget {
required this.items,
required this.title,
required this.onChange,
this.validator,
this.onSaved,
}) : super(key: key);

final List<String> items;
final String title;
final ValueChanged<String?> onChange;
final FormFieldValidator<String?>? validator;
final FormFieldSetter<String?>? onSaved;

@override
_AddExerciseDropdownButtonState createState() => _AddExerciseDropdownButtonState();
Expand All @@ -25,7 +29,9 @@ class _AddExerciseDropdownButtonState extends State<AddExerciseDropdownButton> {
return Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownButtonFormField<String>(
validator: widget.validator,
isExpanded: true,
onSaved: widget.onSaved,
onChanged: (value) {
setState(() {
_selectedItem = value;
Expand Down
3 changes: 3 additions & 0 deletions lib/widgets/add_exercise/add_exercise_multiselect_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ class AddExerciseMultiselectButton extends StatefulWidget {
required this.items,
required this.title,
required this.onChange,
this.onSaved,
}) : super(key: key);

final List<String> items;
final String title;
final ValueChanged<List<String?>> onChange;
final FormFieldSetter<List<String?>?>? onSaved;

@override
_AddExerciseMultiselectButtonState createState() => _AddExerciseMultiselectButtonState();
Expand All @@ -25,6 +27,7 @@ class _AddExerciseMultiselectButtonState extends State<AddExerciseMultiselectBut
return Padding(
padding: const EdgeInsets.all(8.0),
child: MultiSelectDialogField<String?>(
onSaved: widget.onSaved,
items: widget.items.map((item) => MultiSelectItem<String?>(item, item)).toList(),
onConfirm: (value) {
setState(() {
Expand Down
6 changes: 6 additions & 0 deletions lib/widgets/add_exercise/add_exercise_text_area.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ class AddExerciseTextArea extends StatelessWidget {
this.helperText = '',
this.isRequired = true,
this.isMultiline = false,
this.validator,
this.onSaved,
}) : super(key: key);

final ValueChanged<String> onChange;
final bool isRequired;
final bool isMultiline;
final String title;
final String helperText;
final FormFieldValidator<String?>? validator;
final FormFieldSetter<String?>? onSaved;

static const MULTILINE_MIN_LINES = 4;
static const DEFAULT_LINES = 1;
Expand All @@ -27,6 +31,8 @@ class AddExerciseTextArea extends StatelessWidget {
keyboardType: isMultiline ? TextInputType.multiline : TextInputType.text,
maxLines: isMultiline ? null : DEFAULT_LINES,
minLines: isMultiline ? MULTILINE_MIN_LINES : DEFAULT_LINES,
validator: validator,
onSaved: onSaved,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
border: OutlineInputBorder(
Expand Down