mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
overhaul macros viewing
* fix macros alignments across different UI elements, by relying on a new standardized NutritionTile * honor true needed widths based on string lengths of the column names * show total macros for meal
This commit is contained in:
@@ -22,7 +22,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/widgets/nutrition/meal.dart';
|
||||
import 'package:wger/widgets/nutrition/widgets.dart';
|
||||
import 'package:wger/widgets/nutrition/nutrition_tiles.dart';
|
||||
|
||||
class LogMealArguments {
|
||||
final Meal meal;
|
||||
@@ -68,9 +68,9 @@ class _LogMealScreenState extends State<LogMealScreen> {
|
||||
else
|
||||
Column(
|
||||
children: [
|
||||
const NutritionDiaryheader(),
|
||||
...meal.mealItems
|
||||
.map((item) => MealItemWidget(item, viewMode.withAllDetails, false)),
|
||||
const DiaryheaderTile(),
|
||||
...meal.mealItems.map(
|
||||
(item) => MealItemEditableFullTile(item, viewMode.withAllDetails, false)),
|
||||
const SizedBox(height: 32),
|
||||
Text(
|
||||
'Portion: ${portionPct.round()} %',
|
||||
|
||||
@@ -21,10 +21,12 @@ import 'package:flutter/material.dart';
|
||||
class MutedText extends StatelessWidget {
|
||||
final String _text;
|
||||
final TextAlign textAlign;
|
||||
final TextOverflow? overflow;
|
||||
|
||||
const MutedText(
|
||||
this._text, {
|
||||
this.textAlign = TextAlign.left,
|
||||
this.overflow,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -33,6 +35,7 @@ class MutedText extends StatelessWidget {
|
||||
_text,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.outline),
|
||||
textAlign: textAlign,
|
||||
overflow: overflow,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/screens/nutritional_plan_screen.dart';
|
||||
import 'package:wger/widgets/nutrition/helpers.dart';
|
||||
import 'package:wger/widgets/nutrition/nutrition_tiles.dart';
|
||||
import 'package:wger/widgets/nutrition/widgets.dart';
|
||||
|
||||
class MealForm extends StatelessWidget {
|
||||
@@ -341,7 +342,7 @@ class IngredientFormState extends State<IngredientForm> {
|
||||
builder: (BuildContext context, AsyncSnapshot<Ingredient> snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
_mealItem.ingredient = snapshot.data!;
|
||||
return MealItemTile(
|
||||
return MealItemValuesTile(
|
||||
ingredient: _mealItem.ingredient,
|
||||
nutritionalValues: _mealItem.nutritionalValues,
|
||||
);
|
||||
|
||||
@@ -23,24 +23,60 @@ import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
import 'package:wger/widgets/core/core.dart';
|
||||
|
||||
/*
|
||||
// flex factors, based on number of characters in English
|
||||
// other languages are usually similar, though for fat, often
|
||||
// use a bit more characters
|
||||
// energy: 6
|
||||
// protein: 7
|
||||
// carbohydrates: 13
|
||||
// fat: 6
|
||||
const nutritionColumnRatios = [6, 7, 13, 6];
|
||||
*/
|
||||
|
||||
List<int> nutritionColumnFlexes(BuildContext context) {
|
||||
return [
|
||||
AppLocalizations.of(context).energy.characters.length,
|
||||
AppLocalizations.of(context).protein.characters.length,
|
||||
AppLocalizations.of(context).carbohydrates.characters.length,
|
||||
AppLocalizations.of(context).fat.characters.length,
|
||||
].map((e) {
|
||||
// if the word is really small (e.g. "fat"),
|
||||
// we still want to have a minimum value to keep some spacing,
|
||||
// especially because column values might become like "123 g"
|
||||
return (e <= 3) ? 4 : e;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
List<Widget> getMutedNutritionalValues(NutritionalValues values, BuildContext context) => [
|
||||
MutedText(
|
||||
AppLocalizations.of(context).kcalValue(values.energy.toStringAsFixed(0)),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
MutedText(
|
||||
AppLocalizations.of(context).gValue(values.protein.toStringAsFixed(0)),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
MutedText(
|
||||
AppLocalizations.of(context).gValue(values.carbohydrates.toStringAsFixed(0)),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
MutedText(
|
||||
AppLocalizations.of(context).gValue(values.fat.toStringAsFixed(0)),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
];
|
||||
AppLocalizations.of(context).kcalValue(values.energy.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.protein.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.carbohydrates.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.fat.toStringAsFixed(0)),
|
||||
]
|
||||
.map((e) => MutedText(
|
||||
e,
|
||||
textAlign: TextAlign.right,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))
|
||||
.toList();
|
||||
|
||||
// return a row of elements in the standard macros spacing
|
||||
Row getNutritionRow(BuildContext context, List<Widget> children) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: children.indexed
|
||||
.map(
|
||||
(e) => Flexible(
|
||||
fit: FlexFit.tight,
|
||||
flex: nutritionColumnFlexes(context)[e.$1],
|
||||
child: e.$2,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
String getShortNutritionValues(NutritionalValues values, BuildContext context) {
|
||||
final loc = AppLocalizations.of(context);
|
||||
|
||||
@@ -30,6 +30,8 @@ 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';
|
||||
import 'package:wger/widgets/nutrition/nutrition_tile.dart';
|
||||
import 'package:wger/widgets/nutrition/nutrition_tiles.dart';
|
||||
import 'package:wger/widgets/nutrition/widgets.dart';
|
||||
|
||||
enum viewMode {
|
||||
@@ -157,15 +159,29 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
)),
|
||||
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
|
||||
const Divider(),
|
||||
if (_viewMode == viewMode.withAllDetails) const NutritionDiaryheader(),
|
||||
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
|
||||
const DiaryheaderTile(),
|
||||
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
|
||||
if (widget._meal.mealItems.isEmpty && widget._meal.isRealMeal)
|
||||
const ListTile(title: Text('No ingredients defined yet'))
|
||||
const NutritionTile(title: Center(child: Text('No ingredients defined yet')))
|
||||
else
|
||||
...widget._meal.mealItems.map((item) => MealItemWidget(item, _viewMode, _editing)),
|
||||
...widget._meal.mealItems
|
||||
.map((item) => MealItemEditableFullTile(item, _viewMode, _editing)),
|
||||
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
|
||||
Divider(),
|
||||
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
|
||||
NutritionTile(
|
||||
vPadding: 0,
|
||||
leading: const Text('total'),
|
||||
title: getNutritionRow(
|
||||
context,
|
||||
getMutedNutritionalValues(widget._meal.plannedNutritionalValues, context),
|
||||
),
|
||||
),
|
||||
if (_viewMode == viewMode.withAllDetails)
|
||||
Column(
|
||||
children: [
|
||||
Divider(),
|
||||
Center(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).loggedToday,
|
||||
@@ -181,7 +197,7 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
NutritionDiaryEntry(diaryEntry: item),
|
||||
DiaryEntryTile(diaryEntry: item),
|
||||
],
|
||||
),
|
||||
)),
|
||||
@@ -194,12 +210,13 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
class MealItemWidget extends StatelessWidget {
|
||||
/// An editable NutritionTile showing the avatar, name, nutritional values
|
||||
class MealItemEditableFullTile extends StatelessWidget {
|
||||
final bool _editing;
|
||||
final viewMode _viewMode;
|
||||
final MealItem _item;
|
||||
|
||||
const MealItemWidget(this._item, this._viewMode, this._editing);
|
||||
const MealItemEditableFullTile(this._item, this._viewMode, this._editing);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -213,22 +230,18 @@ class MealItemWidget extends StatelessWidget {
|
||||
final String unit = AppLocalizations.of(context).g;
|
||||
final values = _item.nutritionalValues;
|
||||
|
||||
return ListTile(
|
||||
return NutritionTile(
|
||||
leading: IngredientAvatar(ingredient: _item.ingredient),
|
||||
title: Text(
|
||||
'${_item.amount.toStringAsFixed(0)}$unit ${_item.ingredient.name}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
subtitle: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
if (_viewMode == viewMode.withAllDetails) ...getMutedNutritionalValues(values, context)
|
||||
],
|
||||
),
|
||||
subtitle: (_viewMode != viewMode.withAllDetails && !_editing)
|
||||
? null
|
||||
: getNutritionRow(context, getMutedNutritionalValues(values, context)),
|
||||
trailing: _editing
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
icon: const Icon(Icons.delete, size: ICON_SIZE_SMALL),
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
iconSize: ICON_SIZE_SMALL,
|
||||
onPressed: () {
|
||||
@@ -267,7 +280,7 @@ class LogDiaryItemWidget extends StatelessWidget {
|
||||
final String unit = AppLocalizations.of(context).g;
|
||||
final values = _item.nutritionalValues;
|
||||
|
||||
return ListTile(
|
||||
return NutritionTile(
|
||||
leading: IngredientAvatar(ingredient: _item.ingredient),
|
||||
title: Text(
|
||||
'${_item.amount.toStringAsFixed(0)}$unit ${_item.ingredient.name}',
|
||||
|
||||
51
lib/widgets/nutrition/nutrition_tile.dart
Normal file
51
lib/widgets/nutrition/nutrition_tile.dart
Normal file
@@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// NutritionTile is similar to a non-interactive ListTile,
|
||||
/// but uses a fixed, easy to understand layout.
|
||||
/// any trailing value is overlayed over the title & subtitle, on the right
|
||||
/// as to not disturb the overall layout
|
||||
class NutritionTile extends StatelessWidget {
|
||||
final Widget? leading; // will always be constrained to 40px wide
|
||||
final double vPadding;
|
||||
final Widget? title;
|
||||
final Widget? subtitle;
|
||||
final Widget? trailing;
|
||||
|
||||
const NutritionTile({
|
||||
this.leading,
|
||||
this.title,
|
||||
this.subtitle,
|
||||
this.trailing,
|
||||
this.vPadding = 8,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: vPadding),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 40, maxWidth: 40),
|
||||
child: leading ?? const SizedBox(width: 40),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
if (title != null) title!,
|
||||
if (subtitle != null) subtitle!,
|
||||
],
|
||||
),
|
||||
if (trailing != null) Align(alignment: Alignment.centerRight, child: trailing!),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
119
lib/widgets/nutrition/nutrition_tiles.dart
Normal file
119
lib/widgets/nutrition/nutrition_tiles.dart
Normal file
@@ -0,0 +1,119 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/models/nutrition/log.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/widgets/core/core.dart';
|
||||
import 'package:wger/widgets/nutrition/helpers.dart';
|
||||
import 'package:wger/widgets/nutrition/nutrition_tile.dart';
|
||||
import 'package:wger/widgets/nutrition/widgets.dart';
|
||||
|
||||
/// a NutritionTitle showing an ingredient, with its
|
||||
/// avatar and nutritional values
|
||||
class MealItemValuesTile extends StatelessWidget {
|
||||
final Ingredient ingredient;
|
||||
final NutritionalValues nutritionalValues;
|
||||
|
||||
const MealItemValuesTile({
|
||||
super.key,
|
||||
required this.ingredient,
|
||||
required this.nutritionalValues,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return NutritionTile(
|
||||
leading: IngredientAvatar(ingredient: ingredient),
|
||||
title: Text(getShortNutritionValues(nutritionalValues, context)), // TODO align
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// a NutritionTitle showing the header for the diary
|
||||
class DiaryheaderTile extends StatelessWidget {
|
||||
final Widget? leading;
|
||||
|
||||
const DiaryheaderTile({this.leading});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return NutritionTile(
|
||||
title: getNutritionRow(
|
||||
context,
|
||||
[
|
||||
AppLocalizations.of(context).energy,
|
||||
AppLocalizations.of(context).protein,
|
||||
AppLocalizations.of(context).carbohydrates,
|
||||
AppLocalizations.of(context).fat,
|
||||
]
|
||||
.map((e) => MutedText(
|
||||
e,
|
||||
textAlign: TextAlign.right,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))
|
||||
.toList()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// a NutritionTitle showing diary entries
|
||||
class DiaryEntryTile extends StatelessWidget {
|
||||
const DiaryEntryTile({
|
||||
super.key,
|
||||
required this.diaryEntry,
|
||||
this.nutritionalPlan,
|
||||
});
|
||||
|
||||
final Log diaryEntry;
|
||||
final NutritionalPlan? nutritionalPlan;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
DateFormat.Hm(Localizations.localeOf(context).languageCode).format(diaryEntry.datetime),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${AppLocalizations.of(context).gValue(diaryEntry.amount.toStringAsFixed(0))} ${diaryEntry.ingredient.name}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
...getMutedNutritionalValues(diaryEntry.nutritionalValues, context),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (nutritionalPlan != null)
|
||||
IconButton(
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
onPressed: () {
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.deleteLog(diaryEntry.id!, nutritionalPlan!.id!);
|
||||
},
|
||||
icon: const Icon(Icons.delete_outline),
|
||||
iconSize: ICON_SIZE_SMALL,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
import 'package:wger/widgets/nutrition/charts.dart';
|
||||
import 'package:wger/widgets/nutrition/widgets.dart';
|
||||
import 'package:wger/widgets/nutrition/nutrition_tiles.dart';
|
||||
|
||||
class NutritionalDiaryDetailWidget extends StatelessWidget {
|
||||
final NutritionalPlan _nutritionalPlan;
|
||||
@@ -60,12 +60,12 @@ class NutritionalDiaryDetailWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const NutritionDiaryheader(),
|
||||
const DiaryheaderTile(),
|
||||
...logs.map((e) => Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
NutritionDiaryEntry(diaryEntry: e, nutritionalPlan: _nutritionalPlan),
|
||||
DiaryEntryTile(diaryEntry: e, nutritionalPlan: _nutritionalPlan),
|
||||
],
|
||||
),
|
||||
)),
|
||||
|
||||
@@ -22,7 +22,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:flutter_zxing/flutter_zxing.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/misc.dart';
|
||||
@@ -30,12 +29,9 @@ import 'package:wger/helpers/platform.dart';
|
||||
import 'package:wger/helpers/ui.dart';
|
||||
import 'package:wger/models/exercises/ingredient_api.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/models/nutrition/log.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/widgets/core/core.dart';
|
||||
import 'package:wger/widgets/nutrition/helpers.dart';
|
||||
import 'package:wger/widgets/nutrition/nutrition_tiles.dart';
|
||||
|
||||
class ScanReader extends StatelessWidget {
|
||||
@override
|
||||
@@ -214,7 +210,7 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(AppLocalizations.of(context).productFoundDescription(result.name)),
|
||||
MealItemTile(
|
||||
MealItemValuesTile(
|
||||
ingredient: result,
|
||||
nutritionalValues: result.nutritionalValues,
|
||||
),
|
||||
@@ -272,92 +268,6 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
|
||||
}
|
||||
}
|
||||
|
||||
class NutritionDiaryheader extends StatelessWidget {
|
||||
final Widget? leading;
|
||||
|
||||
const NutritionDiaryheader({this.leading});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: leading ??
|
||||
const CircleIconAvatar(
|
||||
Icon(Icons.image, color: Colors.transparent),
|
||||
color: Colors.transparent,
|
||||
),
|
||||
subtitle: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
AppLocalizations.of(context).energy,
|
||||
AppLocalizations.of(context).protein,
|
||||
AppLocalizations.of(context).carbohydrates,
|
||||
AppLocalizations.of(context).fat
|
||||
]
|
||||
.map((e) => MutedText(
|
||||
e,
|
||||
textAlign: TextAlign.right,
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NutritionDiaryEntry extends StatelessWidget {
|
||||
const NutritionDiaryEntry({
|
||||
super.key,
|
||||
required this.diaryEntry,
|
||||
this.nutritionalPlan,
|
||||
});
|
||||
|
||||
final Log diaryEntry;
|
||||
final NutritionalPlan? nutritionalPlan;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
DateFormat.Hm(Localizations.localeOf(context).languageCode).format(diaryEntry.datetime),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${AppLocalizations.of(context).gValue(diaryEntry.amount.toStringAsFixed(0))} ${diaryEntry.ingredient.name}',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
...getMutedNutritionalValues(diaryEntry.nutritionalValues, context),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (nutritionalPlan != null)
|
||||
IconButton(
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
onPressed: () {
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.deleteLog(diaryEntry.id!, nutritionalPlan!.id!);
|
||||
},
|
||||
icon: const Icon(Icons.delete_outline)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class IngredientAvatar extends StatelessWidget {
|
||||
final Ingredient ingredient;
|
||||
|
||||
@@ -377,23 +287,3 @@ class IngredientAvatar extends StatelessWidget {
|
||||
: const CircleIconAvatar(Icon(Icons.image, color: Colors.grey));
|
||||
}
|
||||
}
|
||||
|
||||
class MealItemTile extends StatelessWidget {
|
||||
final Ingredient ingredient;
|
||||
final NutritionalValues nutritionalValues;
|
||||
|
||||
const MealItemTile({
|
||||
super.key,
|
||||
required this.ingredient,
|
||||
required this.nutritionalValues,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: IngredientAvatar(ingredient: ingredient),
|
||||
title: Text(getShortNutritionValues(nutritionalValues, context)),
|
||||
// subtitle: Text(ingredient.id.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user