diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 10b3fe7e..aff127e2 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -516,5 +516,7 @@ }, "appUpdateTitle" : "Update needed", "appUpdateContent" : "This version of the app is not compatible with the server, please update your application.", - "add_excercise_image_license": "Images must be compatible with the CC BY SA_license. If in doubt, upload only photos you've taken yourself." + "add_excercise_image_license": "Images must be compatible with the CC BY SA_license. If in doubt, upload only photos you've taken yourself.", + "previous": "Previous" + } diff --git a/lib/widgets/exercises/exercises.dart b/lib/widgets/exercises/exercises.dart index 3b34a76e..34bfc3ce 100644 --- a/lib/widgets/exercises/exercises.dart +++ b/lib/widgets/exercises/exercises.dart @@ -31,14 +31,12 @@ import 'package:wger/widgets/exercises/list_tile.dart'; class ExerciseDetail extends StatelessWidget { final Exercise _exercise; + static const PADDING = 9.0; const ExerciseDetail(this._exercise); @override Widget build(BuildContext context) { - final exerciseProvider = Provider.of(context, listen: false); - const PADDING = 9.0; - return SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, @@ -50,106 +48,154 @@ class ExerciseDetail extends StatelessWidget { const SizedBox(height: PADDING), // Aliases - const MutedText('Also known as: Burpees, Basic burpees'), - const SizedBox(height: PADDING), + ...getAliases(), - // Image - // TODO: add carousel for the other ones - ExerciseImageWidget( - image: _exercise.getMainImage, - ), - const SizedBox(height: PADDING), + // Images + ...getImages(), // Description - Text( - AppLocalizations.of(context).description, - style: Theme.of(context).textTheme.headline5, - ), - Html(data: _exercise.description), + ...getDescription(context), // Notes - Text( - AppLocalizations.of(context).notes, - style: Theme.of(context).textTheme.headline5, - ), - ..._exercise.tips.map((e) => Text(e.comment)).toList(), - const SizedBox(height: PADDING), + ...getNotes(context), // Muscles - Text( - AppLocalizations.of(context).muscles, - style: Theme.of(context).textTheme.headline5, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: PADDING), - child: MuscleWidget( - muscles: _exercise.muscles, - musclesSecondary: _exercise.musclesSecondary, - isFront: true, - ), - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: PADDING), - child: MuscleWidget( - muscles: _exercise.muscles, - musclesSecondary: _exercise.musclesSecondary, - isFront: false, - ), - ), - ), - ], - ), - - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - children: [ - Text( - AppLocalizations.of(context).muscles, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - ..._exercise.muscles.map((e) => Text(e.name)).toList(), - ], - ), - Column( - children: [ - Text( - AppLocalizations.of(context).musclesSecondary, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - ..._exercise.musclesSecondary.map((e) => Text(e.name)).toList(), - ], - ), - ], - ), - const SizedBox(height: PADDING), + ...getMuscles(context), // Variants - Text('Variants', style: Theme.of(context).textTheme.headline5), - if (_exercise.base.variationId != null) - ...exerciseProvider - .findExercisesByVariationId( - _exercise.base.variationId!, - languageId: _exercise.languageId, - exerciseIdToExclude: _exercise.id, - ) - .map((exercise) => ExerciseListTile(exercise: exercise)) - .toList() - else - const Text('no variations!'), + ...getVariations(context) ], ), ); } + + List getVariations(BuildContext context) { + final List out = []; + + out.add(Text('Variants', style: Theme.of(context).textTheme.headline5)); + if (_exercise.base.variationId != null) { + Provider.of(context, listen: false) + .findExercisesByVariationId( + _exercise.base.variationId!, + languageId: _exercise.languageId, + exerciseIdToExclude: _exercise.id, + ) + .forEach((element) { + out.add(ExerciseListTile( + exercise: element, + )); + }); + } else { + out.add(const Text('no variations!')); + } + + out.add(const SizedBox(height: PADDING)); + return out; + } + + List getNotes(BuildContext context) { + final List out = []; + out.add(Text( + AppLocalizations.of(context).notes, + style: Theme.of(context).textTheme.headline5, + )); + for (final e in _exercise.tips) { + out.add(Text(e.comment)); + } + out.add(const SizedBox(height: PADDING)); + + return out; + } + + List getMuscles(BuildContext context) { + final List out = []; + out.add(Text( + AppLocalizations.of(context).muscles, + style: Theme.of(context).textTheme.headline5, + )); + out.add(Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: PADDING), + child: MuscleWidget( + muscles: _exercise.muscles, + musclesSecondary: _exercise.musclesSecondary, + isFront: true, + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: PADDING), + child: MuscleWidget( + muscles: _exercise.muscles, + musclesSecondary: _exercise.musclesSecondary, + isFront: false, + ), + ), + ), + ], + )); + + out.add(Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + Text( + AppLocalizations.of(context).muscles, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ..._exercise.muscles.map((e) => Text(e.name)).toList(), + ], + ), + Column( + children: [ + Text( + AppLocalizations.of(context).musclesSecondary, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ..._exercise.musclesSecondary.map((e) => Text(e.name)).toList(), + ], + ), + ], + )); + out.add(const SizedBox(height: PADDING)); + + return out; + } + + List getDescription(BuildContext context) { + final List out = []; + out.add(Text( + AppLocalizations.of(context).description, + style: Theme.of(context).textTheme.headline5, + )); + out.add(Html(data: _exercise.description)); + + return out; + } + + List getImages() { + // TODO: add carousel for the other images + final List out = []; + out.add(ExerciseImageWidget(image: _exercise.getMainImage)); + out.add(const SizedBox(height: PADDING)); + + return out; + } + + List getAliases() { + final List out = []; + out.add(MutedText('Also known as: ${_exercise.alias.map((e) => e.alias).toList().join(', ')}')); + out.add(const SizedBox(height: PADDING)); + + return out; + } } class MuscleWidget extends StatelessWidget {