make it work for measurements + couple fixes

This commit is contained in:
Dieter Plaetinck
2024-09-18 13:30:35 +03:00
parent 3dc1c4e79e
commit bf9e614f8b
8 changed files with 128 additions and 81 deletions

View File

@@ -133,8 +133,10 @@ class MeasurementEntriesScreen extends StatelessWidget {
);
},
),
body: Consumer<MeasurementProvider>(
builder: (context, provider, child) => EntriesList(category),
body: SingleChildScrollView(
child: Consumer<MeasurementProvider>(
builder: (context, provider, child) => EntriesList(category),
),
),
);
}

View File

@@ -22,8 +22,8 @@ import 'package:provider/provider.dart';
import 'package:wger/providers/body_weight.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/core/app_bar.dart';
import 'package:wger/widgets/weight/weight_overview.dart';
import 'package:wger/widgets/weight/forms.dart';
import 'package:wger/widgets/weight/weight_overview.dart';
class WeightScreen extends StatelessWidget {
const WeightScreen();

View File

@@ -280,6 +280,9 @@ class _DashboardMeasurementWidgetState extends State<DashboardMeasurementWidget>
FontAwesomeIcons.chartLine,
color: Theme.of(context).textTheme.headlineSmall!.color,
),
// TODO: this icon feels out of place and inconsistent with all
// other dashboard widgets.
// maybe we should just add a "Go to all" at the bottom of the widget
trailing: IconButton(
icon: const Icon(Icons.arrow_forward),
onPressed: () => Navigator.pushNamed(

View File

@@ -15,9 +15,12 @@ class CategoriesCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final entriesAll =
currentCategory.entries.map((e) => MeasurementChartEntry(e.value, e.date)).toList();
final entries7dAvg = moving7dAverage(entriesAll);
return Card(
elevation: elevation,
color: Theme.of(context).colorScheme.onInverseSurface,
child: Column(
children: [
Padding(
@@ -31,10 +34,16 @@ class CategoriesCard extends StatelessWidget {
padding: const EdgeInsets.all(10),
height: 220,
child: MeasurementChartWidgetFl(
currentCategory.entries.map((e) => MeasurementChartEntry(e.value, e.date)).toList(),
entriesAll,
currentCategory.unit,
avgs: entries7dAvg,
),
),
MeasurementOverallChangeWidget(
entries7dAvg.first,
entries7dAvg.last,
currentCategory.unit,
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,

View File

@@ -30,9 +30,14 @@ class MeasurementOverallChangeWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text(
'overall change ${(_last.value - _first.value).toStringAsFixed(1)} $_unit',
);
final delta = _last.value - _first.value;
final prefix = delta > 0
? '+'
: delta < 0
? '-'
: '';
return Text('overall change $prefix ${delta.abs().toStringAsFixed(1)} $_unit');
}
}

View File

@@ -22,8 +22,10 @@ import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/providers/measurement.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'package:wger/widgets/measurements/helpers.dart';
import 'forms.dart';
@@ -34,16 +36,23 @@ class EntriesList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final plan = Provider.of<NutritionPlansProvider>(context, listen: false).currentPlan;
final entriesAll =
_category.entries.map((e) => MeasurementChartEntry(e.value, e.date)).toList();
final entries7dAvg = moving7dAverage(entriesAll);
return Column(children: [
Container(
padding: const EdgeInsets.all(10),
height: 220,
child: MeasurementChartWidgetFl(
_category.entries.map((e) => MeasurementChartEntry(e.value, e.date)).toList(),
_category.unit,
),
...getOverviewWidgetsSeries(
_category.name,
entriesAll,
entries7dAvg,
plan,
_category.unit,
context,
),
Expanded(
SizedBox(
height: 300,
child: ListView.builder(
padding: const EdgeInsets.all(10.0),
itemCount: _category.entries.length,

View File

@@ -0,0 +1,78 @@
import 'package:flutter/material.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/widgets/measurements/charts.dart';
List<Widget> getOverviewWidgets(
String title,
List<MeasurementChartEntry> raw,
List<MeasurementChartEntry> avg,
String unit,
BuildContext context,
) {
return [
Text(
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
Container(
padding: const EdgeInsets.all(15),
height: 220,
child: MeasurementChartWidgetFl(raw, unit, avgs: avg),
),
if (avg.isNotEmpty) MeasurementOverallChangeWidget(avg.first, avg.last, unit),
const SizedBox(height: 8),
];
}
List<Widget> getOverviewWidgetsSeries(
String name,
List<MeasurementChartEntry> entriesAll,
List<MeasurementChartEntry> entries7dAvg,
NutritionalPlan? plan,
String unit,
BuildContext context,
) {
final monthAgo = DateTime.now().subtract(const Duration(days: 30));
return [
...getOverviewWidgets(
'$name all-time',
entriesAll,
entries7dAvg,
unit,
context,
),
if (plan != null)
...getOverviewWidgets(
'$name during nutritional plan ${plan.description}',
entriesAll.where((e) => e.date.isAfter(plan.creationDate)).toList(),
entries7dAvg.where((e) => e.date.isAfter(plan.creationDate)).toList(),
unit,
context,
),
// if all time is significantly longer than 30 days (let's say > 75 days)
// and if there is is a plan and it also was > 75 days,
// then let's show a separate chart just focusing on the last 30 days
if (entriesAll.first.date.isBefore(entriesAll.last.date.subtract(const Duration(days: 75))) &&
(plan == null ||
entriesAll
.firstWhere((e) => e.date.isAfter(plan.creationDate))
.date
.isBefore(entriesAll.last.date.subtract(const Duration(days: 30)))))
...getOverviewWidgets(
'$name last 30 days',
entriesAll.where((e) => e.date.isAfter(monthAgo)).toList(),
entries7dAvg.where((e) => e.date.isAfter(monthAgo)).toList(),
unit,
context,
),
// legend
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Indicator(color: Theme.of(context).colorScheme.primary, text: 'raw', isSquare: true),
Indicator(color: Theme.of(context).colorScheme.tertiary, text: 'avg', isSquare: true),
],
),
];
}

View File

@@ -26,6 +26,7 @@ import 'package:wger/providers/user.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/screens/measurement_categories_screen.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'package:wger/widgets/measurements/helpers.dart';
import 'package:wger/widgets/weight/forms.dart';
class WeightOverview extends StatelessWidget {
@@ -40,78 +41,18 @@ class WeightOverview extends StatelessWidget {
weightProvider.items.map((e) => MeasurementChartEntry(e.weight, e.date)).toList();
final entries7dAvg = moving7dAverage(entriesAll);
List<Widget> getOverviewWidgets(String title, bool isMetric, List<MeasurementChartEntry> raw,
List<MeasurementChartEntry> avg, BuildContext context) {
return [
Text(
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
),
Container(
padding: const EdgeInsets.all(15),
height: 220,
child: MeasurementChartWidgetFl(
raw,
weightUnit(isMetric, context),
avgs: avg,
),
),
MeasurementOverallChangeWidget(
avg.first,
avg.last,
weightUnit(isMetric, context),
),
const SizedBox(height: 8),
];
}
final unit = weightUnit(profile!.isMetric, context);
return Column(
children: [
...getOverviewWidgets(
'Weight all-time',
profile!.isMetric,
...getOverviewWidgetsSeries(
'Weight',
entriesAll,
entries7dAvg,
plan,
unit,
context,
),
if (plan != null)
...getOverviewWidgets(
'Weight during nutritional plan ${plan.description}',
profile.isMetric,
entriesAll.where((e) => e.date.isAfter(plan.creationDate)).toList(),
entries7dAvg.where((e) => e.date.isAfter(plan.creationDate)).toList(),
context,
),
// if all time is significantly longer than 30 days (let's say > 75 days)
// and if there is is a plan and it also was > 75 days,
// then let's show a separate chart just focusing on the last 30 days
if (entriesAll.first.date
.isBefore(entriesAll.last.date.subtract(const Duration(days: 75))) &&
(plan == null ||
entriesAll
.firstWhere((e) => e.date.isAfter(plan.creationDate))
.date
.isBefore(entriesAll.last.date.subtract(const Duration(days: 30)))))
...getOverviewWidgets(
'Weight last 30 days',
profile.isMetric,
entriesAll
.where((e) => e.date.isAfter(DateTime.now().subtract(const Duration(days: 30))))
.toList(),
entries7dAvg
.where((e) => e.date.isAfter(DateTime.now().subtract(const Duration(days: 30))))
.toList(),
context,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Indicator(color: Theme.of(context).colorScheme.primary, text: 'raw', isSquare: true),
Indicator(color: Theme.of(context).colorScheme.tertiary, text: 'avg', isSquare: true),
],
),
TextButton(
onPressed: () => Navigator.pushNamed(
context,