Skip to content

Commit 56adac2

Browse files
committed
display weight change per NP on the NP list page
1 parent d1cfce7 commit 56adac2

File tree

1 file changed

+91
-10
lines changed

1 file changed

+91
-10
lines changed

lib/widgets/nutrition/nutritional_plans_list.dart

Lines changed: 91 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,90 @@
1818

1919
import 'package:flutter/material.dart';
2020
import 'package:intl/intl.dart';
21+
import 'package:provider/provider.dart';
2122
import 'package:wger/l10n/generated/app_localizations.dart';
23+
import 'package:wger/providers/body_weight.dart';
2224
import 'package:wger/providers/nutrition.dart';
25+
import 'package:wger/providers/user.dart';
2326
import 'package:wger/screens/nutritional_plan_screen.dart';
2427
import 'package:wger/widgets/core/text_prompt.dart';
28+
import 'package:wger/widgets/measurements/charts.dart';
2529

2630
class NutritionalPlansList extends StatelessWidget {
2731
final NutritionPlansProvider _nutritionProvider;
2832

2933
const NutritionalPlansList(this._nutritionProvider);
3034

35+
/// Builds the weight change information for a nutritional plan period
36+
Widget _buildWeightChangeInfo(
37+
BuildContext context, DateTime startDate, DateTime? endDate) {
38+
final _provider = Provider.of<BodyWeightProvider>(context, listen: false);
39+
40+
final entriesAll = _provider.items
41+
.map((e) => MeasurementChartEntry(e.weight, e.date))
42+
.toList();
43+
final entries7dAvg = moving7dAverage(entriesAll);
44+
print('start: $startDate');
45+
print('end: $endDate');
46+
// Filter weight entries within the plan period
47+
final DateTime planEndDate = endDate ?? DateTime.now();
48+
final List<MeasurementChartEntry> entriesInPeriod = entries7dAvg
49+
.where((entry) =>
50+
entry.date.isAfter(startDate) && entry.date.isBefore(planEndDate))
51+
.toList();
52+
print('entriesInPeriod: ${entriesInPeriod.length}');
53+
if (entriesInPeriod.length < 2) {
54+
return const SizedBox.shrink();
55+
}
56+
57+
// Sort entries by date
58+
entriesInPeriod.sort((a, b) => a.date.compareTo(b.date));
59+
60+
// Calculate weight change
61+
final firstWeight = entriesInPeriod.first;
62+
final lastWeight = entriesInPeriod.last;
63+
final weightDifference = lastWeight.value - firstWeight.value;
64+
65+
// Format the weight change text and determine color
66+
final String weightChangeText;
67+
final Color weightChangeColor;
68+
final profile = context.read<UserProvider>().profile;
69+
70+
final unit = weightUnit(profile!.isMetric, context);
71+
72+
// TODO: only proceed if it's "representative" (if we covered the plan timespan well enough), or actually,
73+
// we could also interpolate the missing values
74+
if (weightDifference > 0) {
75+
weightChangeText = '+${weightDifference.toStringAsFixed(1)} $unit';
76+
weightChangeColor = Colors.red;
77+
} else if (weightDifference < 0) {
78+
weightChangeText = '${weightDifference.toStringAsFixed(1)} $unit';
79+
weightChangeColor = Colors.green;
80+
} else {
81+
weightChangeText = '0 $unit';
82+
weightChangeColor = Colors.grey;
83+
}
84+
85+
return Padding(
86+
padding: const EdgeInsets.only(top: 4.0),
87+
child: Row(
88+
children: [
89+
Text(
90+
AppLocalizations.of(context).weight + ' change: ',
91+
style: Theme.of(context).textTheme.bodySmall,
92+
),
93+
Text(
94+
weightChangeText,
95+
style: Theme.of(context).textTheme.bodySmall?.copyWith(
96+
fontWeight: FontWeight.bold,
97+
color: weightChangeColor,
98+
),
99+
),
100+
],
101+
),
102+
);
103+
}
104+
31105
@override
32106
Widget build(BuildContext context) {
33107
return RefreshIndicator(
@@ -48,16 +122,23 @@ class NutritionalPlansList extends StatelessWidget {
48122
);
49123
},
50124
title: Text(currentPlan.getLabel(context)),
51-
subtitle: Text(
52-
currentPlan.endDate != null
53-
? 'from ${DateFormat.yMd(
54-
Localizations.localeOf(context).languageCode,
55-
).format(currentPlan.startDate)} to ${DateFormat.yMd(
56-
Localizations.localeOf(context).languageCode,
57-
).format(currentPlan.endDate!)}'
58-
: 'from ${DateFormat.yMd(
59-
Localizations.localeOf(context).languageCode,
60-
).format(currentPlan.startDate)} (open ended)',
125+
subtitle: Column(
126+
crossAxisAlignment: CrossAxisAlignment.start,
127+
children: [
128+
Text(
129+
currentPlan.endDate != null
130+
? 'from ${DateFormat.yMd(
131+
Localizations.localeOf(context).languageCode,
132+
).format(currentPlan.startDate)} to ${DateFormat.yMd(
133+
Localizations.localeOf(context).languageCode,
134+
).format(currentPlan.endDate!)}'
135+
: 'from ${DateFormat.yMd(
136+
Localizations.localeOf(context).languageCode,
137+
).format(currentPlan.startDate)} (open ended)',
138+
),
139+
_buildWeightChangeInfo(context, currentPlan.startDate,
140+
currentPlan.endDate),
141+
],
61142
),
62143
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
63144
const VerticalDivider(),

0 commit comments

Comments
 (0)