mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
# Conflicts: # Gemfile.lock # android/settings.gradle # fastlane/report.xml # integration_test/1_dashboard.dart # integration_test/2_workout.dart # integration_test/3_gym_mode.dart # integration_test/5_nutritional_plan.dart # integration_test/6_weight.dart # lib/helpers/i18n.dart # lib/helpers/ui.dart # lib/main.dart # lib/models/nutrition/meal.g.dart # lib/models/nutrition/nutritional_plan.dart # lib/providers/auth.dart # lib/providers/nutrition.dart # lib/screens/add_exercise_screen.dart # lib/screens/auth_screen.dart # lib/screens/dashboard.dart # lib/screens/exercises_screen.dart # lib/screens/home_tabs_screen.dart # lib/screens/log_meal_screen.dart # lib/screens/log_meals_screen.dart # lib/screens/nutritional_plan_screen.dart # lib/screens/routine_list_screen.dart # lib/screens/workout_plan_screen.dart # lib/widgets/add_exercise/steps/step1basics.dart # lib/widgets/add_exercise/steps/step5images.dart # lib/widgets/add_exercise/steps/step_2_variations.dart # lib/widgets/add_exercise/steps/step_3_description.dart # lib/widgets/add_exercise/steps/step_4_translations.dart # lib/widgets/core/about.dart # lib/widgets/core/settings.dart # lib/widgets/dashboard/calendar.dart # lib/widgets/dashboard/widgets.dart # lib/widgets/exercises/exercises.dart # lib/widgets/gallery/overview.dart # lib/widgets/measurements/categories_card.dart # lib/widgets/measurements/charts.dart # lib/widgets/measurements/entries.dart # lib/widgets/measurements/forms.dart # lib/widgets/measurements/helpers.dart # lib/widgets/nutrition/charts.dart # lib/widgets/nutrition/forms.dart # lib/widgets/nutrition/helpers.dart # lib/widgets/nutrition/meal.dart # lib/widgets/nutrition/nutritional_diary_table.dart # lib/widgets/nutrition/nutritional_plan_detail.dart # lib/widgets/nutrition/nutritional_plans_list.dart # lib/widgets/nutrition/widgets.dart # lib/widgets/routines/charts.dart # lib/widgets/routines/workout_logs.dart # lib/widgets/weight/forms.dart # lib/widgets/weight/weight_overview.dart # lib/widgets/workouts/app_bar.dart # lib/widgets/workouts/day.dart # lib/widgets/workouts/forms.dart # lib/widgets/workouts/gym_mode.dart # lib/widgets/workouts/workout_plan_detail.dart # lib/widgets/workouts/workout_plans_list.dart # linux/flutter/generated_plugin_registrant.cc # linux/flutter/generated_plugins.cmake # pubspec.lock # pubspec.yaml # test/auth/auth_screen_test.dart # test/core/settings_test.dart # test/core/settings_test.mocks.dart # test/nutrition/nutritional_meal_form_test.mocks.dart # test/nutrition/nutritional_meal_item_form_test.dart # test/nutrition/nutritional_plan_form_test.mocks.dart # test/nutrition/nutritional_plan_screen_test.dart # test/nutrition/nutritional_plans_screen_test.dart # test/routine/repetition_unit_form_widget_test.dart # test/routine/routine_screen_test.dart # test/routine/routines_screen_test.dart # test/routine/weight_unit_form_widget_test.dart # test/workout/gym_mode_screen_test.dart # test/workout/workout_day_form_test.dart # test/workout/workout_form_test.dart # test/workout/workout_set_form_test.dart
119 lines
4.0 KiB
Dart
119 lines
4.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:wger/helpers/measurements.dart';
|
|
import 'package:wger/l10n/generated/app_localizations.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: raw.isEmpty
|
|
? Center(
|
|
child: Text(
|
|
'No data available',
|
|
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
|
color: Theme.of(context).colorScheme.secondary.withValues(alpha: 0.7),
|
|
),
|
|
),
|
|
)
|
|
: 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,
|
|
List<NutritionalPlan> plans,
|
|
String unit,
|
|
BuildContext context,
|
|
) {
|
|
final monthAgo = DateTime.now().subtract(const Duration(days: 30));
|
|
return [
|
|
...getOverviewWidgets(
|
|
AppLocalizations.of(context).chartAllTimeTitle(name),
|
|
entriesAll,
|
|
entries7dAvg,
|
|
unit,
|
|
context,
|
|
),
|
|
// Show overview widgets for each plan in plans
|
|
for (final plan in plans)
|
|
...getOverviewWidgets(
|
|
AppLocalizations.of(context).chartDuringPlanTitle(name, plan.description),
|
|
entriesAll.whereDateWithInterpolation(plan.startDate, plan.endDate),
|
|
entries7dAvg.whereDateWithInterpolation(plan.startDate, plan.endDate),
|
|
unit,
|
|
context,
|
|
),
|
|
// if all time is significantly longer than 30 days (let's say > 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))) &&
|
|
entriesAll.any((e) => e.date.isAfter(monthAgo)))
|
|
...getOverviewWidgets(
|
|
AppLocalizations.of(context).chart30DaysTitle(name),
|
|
entriesAll.whereDateWithInterpolation(monthAgo, null),
|
|
entries7dAvg.whereDateWithInterpolation(monthAgo, null),
|
|
unit,
|
|
context,
|
|
),
|
|
// legend
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Indicator(
|
|
color: Theme.of(context).colorScheme.primary,
|
|
text: AppLocalizations.of(context).indicatorRaw,
|
|
isSquare: true,
|
|
),
|
|
Indicator(
|
|
color: Theme.of(context).colorScheme.tertiary,
|
|
text: AppLocalizations.of(context).indicatorAvg,
|
|
isSquare: true,
|
|
),
|
|
],
|
|
),
|
|
];
|
|
}
|
|
|
|
// return the raw and average measurements 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.whereDate(twoMonthsAgo, null).length > 4) {
|
|
return (
|
|
entriesAll.whereDate(twoMonthsAgo, null),
|
|
entries7dAvg.whereDate(twoMonthsAgo, null),
|
|
);
|
|
}
|
|
if (entriesAll.whereDate(fourMonthsAgo, null).length > 4) {
|
|
return (
|
|
entriesAll.whereDate(fourMonthsAgo, null),
|
|
entries7dAvg.whereDate(fourMonthsAgo, null),
|
|
);
|
|
}
|
|
return (entriesAll, entries7dAvg);
|
|
}
|