mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
log meal: separate confirmation page with portion choice
This commit is contained in:
@@ -38,6 +38,7 @@ import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/screens/gallery_screen.dart';
|
||||
import 'package:wger/screens/gym_mode.dart';
|
||||
import 'package:wger/screens/home_tabs_screen.dart';
|
||||
import 'package:wger/screens/log_meal_screen.dart';
|
||||
import 'package:wger/screens/measurement_categories_screen.dart';
|
||||
import 'package:wger/screens/measurement_entries_screen.dart';
|
||||
import 'package:wger/screens/nutritional_diary_screen.dart';
|
||||
@@ -158,6 +159,7 @@ class MyApp extends StatelessWidget {
|
||||
NutritionalPlansScreen.routeName: (ctx) => NutritionalPlansScreen(),
|
||||
NutritionalDiaryScreen.routeName: (ctx) => NutritionalDiaryScreen(),
|
||||
NutritionalPlanScreen.routeName: (ctx) => NutritionalPlanScreen(),
|
||||
LogMealScreen.routeName: (ctx) => LogMealScreen(),
|
||||
WeightScreen.routeName: (ctx) => WeightScreen(),
|
||||
WorkoutPlanScreen.routeName: (ctx) => WorkoutPlanScreen(),
|
||||
WorkoutPlansScreen.routeName: (ctx) => WorkoutPlansScreen(),
|
||||
|
||||
@@ -88,4 +88,22 @@ class Meal {
|
||||
factory Meal.fromJson(Map<String, dynamic> json) => _$MealFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$MealToJson(this);
|
||||
|
||||
Meal copyWith({
|
||||
int? id,
|
||||
int? planId,
|
||||
TimeOfDay? time,
|
||||
String? name,
|
||||
List<MealItem>? mealItems,
|
||||
List<Log>? diaryEntries,
|
||||
}) {
|
||||
return Meal(
|
||||
id: id ?? this.id,
|
||||
plan: planId ?? this.planId,
|
||||
time: time ?? this.time,
|
||||
name: name ?? this.name,
|
||||
mealItems: mealItems ?? this.mealItems,
|
||||
diaryEntries: diaryEntries ?? this.diaryEntries,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,4 +91,25 @@ class MealItem {
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
MealItem copyWith({
|
||||
int? id,
|
||||
int? mealId,
|
||||
int? ingredientId,
|
||||
int? weightUnitId,
|
||||
num? amount,
|
||||
Ingredient? ingredient,
|
||||
IngredientWeightUnit? weightUnitObj,
|
||||
}) {
|
||||
final m = MealItem(
|
||||
id: id ?? this.id,
|
||||
mealId: mealId ?? this.mealId,
|
||||
ingredientId: ingredientId ?? this.ingredientId,
|
||||
weightUnitId: weightUnitId ?? this.weightUnitId,
|
||||
amount: amount ?? this.amount,
|
||||
ingredient: ingredient ?? this.ingredient,
|
||||
);
|
||||
m.weightUnitObj = weightUnitObj ?? this.weightUnitObj;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
146
lib/screens/log_meal_screen.dart
Normal file
146
lib/screens/log_meal_screen.dart
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (C) 2020, 2021 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wger Workout Manager is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/models/nutrition/meal_item.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/widgets/nutrition/meal.dart';
|
||||
import 'package:wger/widgets/nutrition/widgets.dart';
|
||||
|
||||
class LogMealArguments {
|
||||
final Meal meal;
|
||||
|
||||
LogMealArguments(this.meal);
|
||||
}
|
||||
|
||||
class LogMealScreen extends StatefulWidget {
|
||||
static const routeName = '/log-meal';
|
||||
|
||||
@override
|
||||
State<LogMealScreen> createState() => _LogMealScreenState();
|
||||
}
|
||||
|
||||
class _LogMealScreenState extends State<LogMealScreen> {
|
||||
late TextEditingController _controller;
|
||||
int portionPct = 100;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = TextEditingController();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final args = ModalRoute.of(context)!.settings.arguments as LogMealArguments;
|
||||
_controller.text = portionPct.toString();
|
||||
final meal = args.meal.copyWith(
|
||||
mealItems: args.meal.mealItems
|
||||
.map((mealItem) => mealItem.copyWith(amount: mealItem.amount * portionPct / 100))
|
||||
.toList());
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Log meal to diary'),
|
||||
),
|
||||
body: Consumer<NutritionPlansProvider>(
|
||||
builder: (context, nutritionProvider, child) => SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(meal.name, style: Theme.of(context).textTheme.headlineSmall),
|
||||
if (meal.mealItems.isEmpty)
|
||||
const ListTile(title: Text('No ingredients defined yet'))
|
||||
else
|
||||
Column(
|
||||
children: [
|
||||
const NutritionDiaryheader(),
|
||||
...meal.mealItems
|
||||
.map((item) => MealItemWidget(item, viewMode.withAllDetails, false)),
|
||||
Row(
|
||||
children: [
|
||||
Text('Portion size'),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLength: 4,
|
||||
maxLengthEnforcement: MaxLengthEnforcement.enforced,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Enter the portion size as a percent',
|
||||
),
|
||||
controller: _controller,
|
||||
onChanged: (value) {
|
||||
var v = int.tryParse(value);
|
||||
if (v == null) return;
|
||||
setState(() {
|
||||
portionPct = v;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (meal.mealItems.isNotEmpty)
|
||||
TextButton(
|
||||
child: const Text('Log'),
|
||||
onPressed: () async {
|
||||
await Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.logMealToDiary(meal);
|
||||
// ignore: use_build_context_synchronously
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
// ignore: use_build_context_synchronously
|
||||
AppLocalizations.of(context).mealLogged,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/models/nutrition/meal_item.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/screens/log_meal_screen.dart';
|
||||
import 'package:wger/widgets/nutrition/charts.dart';
|
||||
import 'package:wger/widgets/nutrition/forms.dart';
|
||||
import 'package:wger/widgets/nutrition/helpers.dart';
|
||||
@@ -360,17 +361,14 @@ class MealHeader extends StatelessWidget {
|
||||
)
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false).logMealToDiary(_meal);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).mealLogged,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
onTap: _meal.isRealMeal
|
||||
? () {
|
||||
Navigator.of(context).pushNamed(
|
||||
LogMealScreen.routeName,
|
||||
arguments: LogMealArguments(_meal),
|
||||
);
|
||||
}
|
||||
: null,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user