mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
make it work for measurements + couple fixes
This commit is contained in:
@@ -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),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
78
lib/widgets/measurements/helpers.dart
Normal file
78
lib/widgets/measurements/helpers.dart
Normal 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),
|
||||
],
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user