Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Measurement tweaks #657

Merged
merged 4 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions lib/widgets/dashboard/widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import 'package:wger/widgets/core/core.dart';
import 'package:wger/widgets/measurements/categories_card.dart';
import 'package:wger/widgets/measurements/charts.dart';
import 'package:wger/widgets/measurements/forms.dart';
import 'package:wger/widgets/measurements/helpers.dart';
import 'package:wger/widgets/nutrition/charts.dart';
import 'package:wger/widgets/nutrition/forms.dart';
import 'package:wger/widgets/weight/forms.dart';
Expand Down Expand Up @@ -161,9 +162,9 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
final profile = context.read<UserProvider>().profile;
final weightProvider = context.read<BodyWeightProvider>();

final entriesAll =
weightProvider.items.map((e) => MeasurementChartEntry(e.weight, e.date)).toList();
final entries7dAvg = moving7dAverage(entriesAll);
final (entriesAll, entries7dAvg) = sensibleRange(
weightProvider.items.map((e) => MeasurementChartEntry(e.weight, e.date)).toList(),
);

return Consumer<BodyWeightProvider>(
builder: (context, workoutProvider, child) => Card(
Expand Down Expand Up @@ -193,11 +194,12 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
avgs: entries7dAvg,
),
),
MeasurementOverallChangeWidget(
entries7dAvg.first,
entries7dAvg.last,
weightUnit(profile.isMetric, context),
),
if (entries7dAvg.isNotEmpty)
MeasurementOverallChangeWidget(
entries7dAvg.first,
entries7dAvg.last,
weightUnit(profile.isMetric, context),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expand Down
18 changes: 10 additions & 8 deletions lib/widgets/measurements/categories_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:wger/models/measurements/measurement_category.dart';
import 'package:wger/screens/form_screen.dart';
import 'package:wger/screens/measurement_entries_screen.dart';
import 'package:wger/widgets/measurements/helpers.dart';
import 'charts.dart';
import 'forms.dart';

Expand All @@ -15,9 +16,9 @@ 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);
final (entriesAll, entries7dAvg) = sensibleRange(
currentCategory.entries.map((e) => MeasurementChartEntry(e.value, e.date)).toList(),
);

return Card(
elevation: elevation,
Expand All @@ -39,11 +40,12 @@ class CategoriesCard extends StatelessWidget {
avgs: entries7dAvg,
),
),
MeasurementOverallChangeWidget(
entries7dAvg.first,
entries7dAvg.last,
currentCategory.unit,
),
if (entries7dAvg.isNotEmpty)
MeasurementOverallChangeWidget(
entries7dAvg.first,
entries7dAvg.last,
currentCategory.unit,
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
Expand Down
26 changes: 18 additions & 8 deletions lib/widgets/measurements/charts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,24 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {

LineTouchData tooltipData() {
return LineTouchData(
touchTooltipData: LineTouchTooltipData(getTooltipItems: (touchedSpots) {
return touchedSpots.map((touchedSpot) {
return LineTooltipItem(
'${touchedSpot.y.toStringAsFixed(1)} ${widget._unit}',
TextStyle(color: touchedSpot.bar.color, fontWeight: FontWeight.bold),
);
}).toList();
}),
touchTooltipData: LineTouchTooltipData(
getTooltipColor: (touchedSpot) => Theme.of(context).colorScheme.primaryContainer,
getTooltipItems: (touchedSpots) {
return touchedSpots.map((touchedSpot) {
final DateTime date = DateTime.fromMillisecondsSinceEpoch(touchedSpot.x.toInt());
final dateStr =
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date);

return LineTooltipItem(
'$dateStr: ${touchedSpot.y.toStringAsFixed(1)} ${widget._unit}',
TextStyle(
color: touchedSpot.bar.color,
fontWeight: FontWeight.bold,
),
);
}).toList();
},
),
);
}

Expand Down
49 changes: 41 additions & 8 deletions lib/widgets/measurements/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ List<Widget> getOverviewWidgetsSeries(
BuildContext context,
) {
final monthAgo = DateTime.now().subtract(const Duration(days: 30));
final showPlan = plan != null && entriesAll.any((e) => e.date.isAfter(plan.creationDate));

return [
...getOverviewWidgets(
AppLocalizations.of(context).chartAllTimeTitle(name),
Expand All @@ -43,7 +45,7 @@ List<Widget> getOverviewWidgetsSeries(
unit,
context,
),
if (plan != null)
if (showPlan)
...getOverviewWidgets(
AppLocalizations.of(context).chartDuringPlanTitle(name, plan.description),
entriesAll.where((e) => e.date.isAfter(plan.creationDate)).toList(),
Expand All @@ -52,14 +54,18 @@ List<Widget> getOverviewWidgetsSeries(
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))) &&
// and any plan was also > 75 days,
// then let's show a separate chart just focusing on the last 30 days,
// if there is data for it.
if (entriesAll.isNotEmpty &&
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)))))
(showPlan &&
entriesAll
.firstWhere((e) => e.date.isAfter(plan.creationDate))
.date
.isBefore(entriesAll.last.date.subtract(const Duration(days: 30))))) &&
entriesAll.any((e) => e.date.isAfter(monthAgo)))
...getOverviewWidgets(
AppLocalizations.of(context).chart30DaysTitle(name),
entriesAll.where((e) => e.date.isAfter(monthAgo)).toList(),
Expand All @@ -77,3 +83,30 @@ List<Widget> getOverviewWidgetsSeries(
),
];
}

// return the raw and average meaasurements for a "sensible range"
// a sensible range is something relatively recent, which is most relevant
// for the user to track their progress, but a range should always include
// at least 5 points, and if not we chose a bigger one.
// we return a range of the last 2 months, 4 months, or the full history
(List<MeasurementChartEntry>, List<MeasurementChartEntry>) sensibleRange(
List<MeasurementChartEntry> entriesAll,
) {
final entries7dAvg = moving7dAverage(entriesAll);
final twoMonthsAgo = DateTime.now().subtract(const Duration(days: 61));
final fourMonthsAgo = DateTime.now().subtract(const Duration(days: 122));

if (entriesAll.where((e) => e.date.isAfter(twoMonthsAgo)).length > 4) {
return (
entriesAll.where((e) => e.date.isAfter(twoMonthsAgo)).toList(),
entries7dAvg.where((e) => e.date.isAfter(twoMonthsAgo)).toList(),
);
}
if (entriesAll.where((e) => e.date.isAfter(fourMonthsAgo)).length > 4) {
return (
entriesAll.where((e) => e.date.isAfter(fourMonthsAgo)).toList(),
entries7dAvg.where((e) => e.date.isAfter(fourMonthsAgo)).toList(),
);
}
return (entriesAll, entries7dAvg);
}
Loading