From bc28fe8624abe280a00a2ceaade2478345f293d4 Mon Sep 17 00:00:00 2001 From: Roland Geider Date: Thu, 31 Mar 2022 00:07:12 +0200 Subject: [PATCH] Start adding variations handling --- lib/providers/add_exercise_provider.dart | 60 ++++++++++++++---- lib/providers/exercises.dart | 14 +++++ lib/screens/add_exercise_screen.dart | 80 +++++++++++++++++++++++- lib/widgets/exercises/list_tile.dart | 2 - 4 files changed, 140 insertions(+), 16 deletions(-) diff --git a/lib/providers/add_exercise_provider.dart b/lib/providers/add_exercise_provider.dart index e86f2516..31dde368 100644 --- a/lib/providers/add_exercise_provider.dart +++ b/lib/providers/add_exercise_provider.dart @@ -11,6 +11,7 @@ import 'package:wger/models/exercises/equipment.dart'; import 'package:wger/models/exercises/exercise.dart'; import 'package:wger/models/exercises/language.dart'; import 'package:wger/models/exercises/muscle.dart'; +import 'package:wger/models/exercises/variation.dart'; import 'base_provider.dart'; @@ -24,10 +25,12 @@ class AddExerciseProvider with ChangeNotifier { String? _nameTranslation; String? _descriptionEn; String? _descriptionTranslation; - late Language _language; + int? _variationId; + int? _newVariationForExercise; + late Language language; List _alternativeNamesEn = []; List _alternativeNamesTranslation = []; - late ExerciseCategory _category; + late ExerciseCategory category; List _variations = []; List _equipment = []; List _primaryMuscles = []; @@ -37,6 +40,7 @@ class AddExerciseProvider with ChangeNotifier { static const _imagesUrlPath = 'exerciseimage'; static const _exerciseTranslationUrlPath = 'exercise-translation'; static const _exerciseAliasPath = 'exercisealias'; + static const _exerciseVariationPath = 'variation'; void clear() { _exerciseImages = []; @@ -61,17 +65,30 @@ class AddExerciseProvider with ChangeNotifier { set equipment(List equipment) => _equipment = equipment; List get equipment => [..._equipment]; - set category(ExerciseCategory category) => _category = category; - ExerciseCategory get category => _category; - set language(Language language) => _language = language; - Language get language => _language; + + bool get newVariation => _newVariationForExercise != null; + + int? get newVariationForExercise => _newVariationForExercise; + set newVariationForExercise(int? value) { + _newVariationForExercise = value; + _variationId = null; + notifyListeners(); + } + + int? get variationId => _variationId; + set variationId(int? variation) { + _variationId = variation; + _newVariationForExercise = null; + notifyListeners(); + } ExerciseBase get base { return ExerciseBase( - category: _category, + category: category, equipment: _equipment, muscles: _primaryMuscles, musclesSecondary: _secondaryMuscles, + variationId: _variationId, ); } @@ -87,10 +104,14 @@ class AddExerciseProvider with ChangeNotifier { return Exercise( name: _nameTranslation!, description: _descriptionTranslation!, - language: _language, + language: language, ); } + Variation get variation { + return Variation(id: _variationId!); + } + List get primaryMuscles => [..._primaryMuscles]; set primaryMuscles(List muscles) { _primaryMuscles = muscles; @@ -120,7 +141,7 @@ class AddExerciseProvider with ChangeNotifier { log('------------------------'); log('Base data...'); - log('Target area : $_category'); + log('Target area : $category'); log('Primary muscles: $_primaryMuscles'); log('Secondary muscles: $_secondaryMuscles'); log('Equipment: $_equipment'); @@ -128,7 +149,7 @@ class AddExerciseProvider with ChangeNotifier { log(''); log('Language specific...'); - log('Language: ${_language.shortName}'); + log('Language: ${language.shortName}'); log('Name: en/$_nameEn translation/$_nameTranslation'); log('Description: en/$_descriptionEn translation/$_descriptionTranslation'); log('Alternate names: en/$_alternativeNamesEn translation/$_alternativeNamesTranslation'); @@ -137,12 +158,14 @@ class AddExerciseProvider with ChangeNotifier { Future addExercise() async { printValues(); + // Create the variations if needed + if (newVariation) { + await addVariation(); + } + // Create the base final base = await addExerciseBase(); - // Create the variations - // ... - // Create the base description in English Exercise exerciseTranslationEn = exerciseEn; exerciseTranslationEn.base = base; @@ -180,6 +203,17 @@ class AddExerciseProvider with ChangeNotifier { return newExerciseBase; } + Future addVariation() async { + final Uri postUri = baseProvider.makeUrl(_exerciseVariationPath); + + // We send an empty dictionary since at the moment the variations only have an ID + final Map variationMap = await baseProvider.post({}, postUri); + final Variation newVariation = Variation.fromJson(variationMap); + _variationId = newVariation.id; + notifyListeners(); + return newVariation; + } + Future addImages(ExerciseBase base) async { for (final image in _exerciseImages) { final request = http.MultipartRequest('POST', baseProvider.makeUrl(_imagesUrlPath)); diff --git a/lib/providers/exercises.dart b/lib/providers/exercises.dart index d62dc68d..7ee9a59c 100644 --- a/lib/providers/exercises.dart +++ b/lib/providers/exercises.dart @@ -87,6 +87,20 @@ class ExercisesProvider with ChangeNotifier { notifyListeners(); } + Map> get exerciseBasesByVariation { + final Map> variations = {}; + + for (final base in _exerciseBases.where((e) => e.variationId != null)) { + if (!variations.containsKey(base.variationId)) { + variations[base.variationId!] = []; + } + + variations[base.variationId]!.add(base); + } + + return variations; + } + ExercisesProvider(this.baseProvider); List get items => [..._exercises]; diff --git a/lib/screens/add_exercise_screen.dart b/lib/screens/add_exercise_screen.dart index 13aced60..3a23657e 100644 --- a/lib/screens/add_exercise_screen.dart +++ b/lib/screens/add_exercise_screen.dart @@ -268,6 +268,9 @@ class _DuplicatesAndVariationsStepContent extends StatelessWidget { @override Widget build(BuildContext context) { + final addExerciseProvider = context.read(); + final exerciseProvider = context.read(); + return Form( key: formkey, child: Column( @@ -276,7 +279,82 @@ class _DuplicatesAndVariationsStepContent extends StatelessWidget { AppLocalizations.of(context).whatVariationsExist, style: Theme.of(context).textTheme.caption, ), - const Placeholder(fallbackHeight: 200), + SizedBox( + height: 400, + child: SingleChildScrollView( + child: Column( + children: [ + // Exercise bases with variations + ...exerciseProvider.exerciseBasesByVariation.keys + .map( + (key) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + //mainAxisSize: MainAxisSize.max, + children: [ + ...exerciseProvider.exerciseBasesByVariation[key]! + .map( + (base) => Text( + base + .getExercises( + Localizations.localeOf(context).languageCode) + .name, + overflow: TextOverflow.ellipsis, + ), + ) + .toList(), + const SizedBox(height: 20), + ], + ), + ), + Consumer( + builder: (ctx, provider, __) => Switch( + value: provider.variationId == key, + onChanged: (state) => provider.variationId = key), + ), + ], + ), + ) + .toList(), + // Exercise bases without variations + ...exerciseProvider.bases + .where((b) => b.variationId == null) + .map( + (base) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + Text( + base + .getExercises(Localizations.localeOf(context).languageCode) + .name, + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 20), + ], + ), + ), + Consumer( + builder: (ctx, provider, __) => Switch( + value: provider.newVariationForExercise == base.id, + onChanged: (state) => provider.newVariationForExercise = base.id, + ), + ), + ], + ), + ) + .toList(), + ], + ), + ), + ), ], ), ); diff --git a/lib/widgets/exercises/list_tile.dart b/lib/widgets/exercises/list_tile.dart index 42784cc9..8f28f6a3 100644 --- a/lib/widgets/exercises/list_tile.dart +++ b/lib/widgets/exercises/list_tile.dart @@ -49,8 +49,6 @@ class ExerciseListTile extends StatelessWidget { ), ), ), - trailing: - Text('${exercise.languageObj.shortName} base: ${exercise.baseId}, exId: ${exercise.id}'), title: Text( exercise.name, //style: theme.textTheme.headline6,