Merge pull request #125 from agwanyaseen/feature/exercise-crowdsourcing

feat: Form Related Changes in Add Exercise Screen
This commit is contained in:
Roland Geider
2022-01-29 21:07:33 +01:00
committed by GitHub
6 changed files with 98 additions and 12 deletions

View File

@@ -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;
String? _targetArea;
List<String?>? _primaryMuscles = [];
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);
@@ -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);
}
}
}
}

View File

@@ -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() {

View File

@@ -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';
@@ -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,
@@ -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'),
@@ -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(() {
@@ -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,
),
],
),

View File

@@ -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();
@@ -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;

View File

@@ -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();
@@ -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(() {

View File

@@ -8,6 +8,8 @@ class AddExerciseTextArea extends StatelessWidget {
this.helperText = '',
this.isRequired = true,
this.isMultiline = false,
this.validator,
this.onSaved,
}) : super(key: key);
final ValueChanged<String> onChange;
@@ -15,6 +17,8 @@ class AddExerciseTextArea extends StatelessWidget {
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;
@@ -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(