mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Fix import for localization strings
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
@@ -42,8 +42,9 @@ Widget createDashboardScreen({locale = 'en'}) {
|
||||
|
||||
final mockNutritionProvider = MockNutritionPlansProvider();
|
||||
|
||||
when(mockNutritionProvider.currentPlan)
|
||||
.thenAnswer((realInvocation) => getNutritionalPlanScreenshot());
|
||||
when(
|
||||
mockNutritionProvider.currentPlan,
|
||||
).thenAnswer((realInvocation) => getNutritionalPlanScreenshot());
|
||||
when(mockNutritionProvider.items).thenReturn([getNutritionalPlanScreenshot()]);
|
||||
|
||||
final mockWeightProvider = MockBodyWeightProvider();
|
||||
@@ -57,21 +58,11 @@ Widget createDashboardScreen({locale = 'en'}) {
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<UserProvider>(
|
||||
create: (context) => mockUserProvider,
|
||||
),
|
||||
ChangeNotifierProvider<WorkoutPlansProvider>(
|
||||
create: (context) => mockWorkoutProvider,
|
||||
),
|
||||
ChangeNotifierProvider<NutritionPlansProvider>(
|
||||
create: (context) => mockNutritionProvider,
|
||||
),
|
||||
ChangeNotifierProvider<BodyWeightProvider>(
|
||||
create: (context) => mockWeightProvider,
|
||||
),
|
||||
ChangeNotifierProvider<MeasurementProvider>(
|
||||
create: (context) => mockMeasurementProvider,
|
||||
),
|
||||
ChangeNotifierProvider<UserProvider>(create: (context) => mockUserProvider),
|
||||
ChangeNotifierProvider<WorkoutPlansProvider>(create: (context) => mockWorkoutProvider),
|
||||
ChangeNotifierProvider<NutritionPlansProvider>(create: (context) => mockNutritionProvider),
|
||||
ChangeNotifierProvider<BodyWeightProvider>(create: (context) => mockWeightProvider),
|
||||
ChangeNotifierProvider<MeasurementProvider>(create: (context) => mockMeasurementProvider),
|
||||
],
|
||||
child: MaterialApp(
|
||||
locale: Locale(locale),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
import 'package:wger/screens/workout_plan_screen.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
@@ -20,9 +20,7 @@ Widget createWorkoutDetailScreen({locale = 'en'}) {
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<WorkoutPlansProvider>(
|
||||
create: (context) => mockWorkoutProvider,
|
||||
),
|
||||
ChangeNotifierProvider<WorkoutPlansProvider>(create: (context) => mockWorkoutProvider),
|
||||
],
|
||||
child: MaterialApp(
|
||||
locale: Locale(locale),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
import 'package:wger/screens/gym_mode.dart';
|
||||
@@ -26,11 +26,7 @@ Widget createGymModeScreen({locale = 'en'}) {
|
||||
//when(mockExerciseProvider.findExerciseBaseById(3)).thenReturn(bases[2]); // dead lift
|
||||
|
||||
return ChangeNotifierProvider<WorkoutPlansProvider>(
|
||||
create: (context) => WorkoutPlansProvider(
|
||||
mockBaseProvider,
|
||||
mockExerciseProvider,
|
||||
[workout],
|
||||
),
|
||||
create: (context) => WorkoutPlansProvider(mockBaseProvider, mockExerciseProvider, [workout]),
|
||||
child: ChangeNotifierProvider<ExercisesProvider>(
|
||||
create: (context) => mockExerciseProvider,
|
||||
child: MaterialApp(
|
||||
@@ -49,9 +45,7 @@ Widget createGymModeScreen({locale = 'en'}) {
|
||||
),
|
||||
child: const SizedBox(),
|
||||
),
|
||||
routes: {
|
||||
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
|
||||
},
|
||||
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
import 'package:wger/screens/measurement_categories_screen.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
@@ -15,9 +15,7 @@ Widget createMeasurementScreen({locale = 'en'}) {
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<MeasurementProvider>(
|
||||
create: (context) => mockMeasurementProvider,
|
||||
),
|
||||
ChangeNotifierProvider<MeasurementProvider>(create: (context) => mockMeasurementProvider),
|
||||
],
|
||||
child: MaterialApp(
|
||||
locale: Locale(locale),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/screens/nutritional_plan_screen.dart';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
@@ -22,12 +22,8 @@ Widget createWeightScreen({locale = 'en'}) {
|
||||
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<UserProvider>(
|
||||
create: (context) => mockUserProvider,
|
||||
),
|
||||
ChangeNotifierProvider<BodyWeightProvider>(
|
||||
create: (context) => mockWeightProvider,
|
||||
),
|
||||
ChangeNotifierProvider<UserProvider>(create: (context) => mockUserProvider),
|
||||
ChangeNotifierProvider<BodyWeightProvider>(create: (context) => mockWeightProvider),
|
||||
],
|
||||
child: MaterialApp(
|
||||
locale: Locale(locale),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
|
||||
/// The amount of characters an exercise description needs to have
|
||||
const MIN_CHARS_DESCRIPTION = 40;
|
||||
|
||||
@@ -7,7 +7,7 @@ library;
|
||||
/// probably better ways to do this, but that's the way it is right now).
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
|
||||
String getTranslation(String value, BuildContext context) {
|
||||
switch (value) {
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/exceptions/http_exception.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/exercise.dart';
|
||||
import 'package:wger/models/exercises/translation.dart';
|
||||
import 'package:wger/models/workouts/log.dart';
|
||||
@@ -50,10 +50,7 @@ void showErrorDialog(dynamic exception, BuildContext context) {
|
||||
);
|
||||
}
|
||||
|
||||
void showHttpExceptionErrorDialog(
|
||||
WgerHttpException exception,
|
||||
BuildContext context,
|
||||
) {
|
||||
void showHttpExceptionErrorDialog(WgerHttpException exception, BuildContext context) {
|
||||
log('showHttpExceptionErrorDialog: ');
|
||||
log(exception.toString());
|
||||
log('-------------------');
|
||||
@@ -119,9 +116,7 @@ dynamic showDeleteDialog(
|
||||
context: context,
|
||||
builder: (BuildContext contextDialog) {
|
||||
return AlertDialog(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).confirmDelete(confirmDeleteName),
|
||||
),
|
||||
content: Text(AppLocalizations.of(context).confirmDelete(confirmDeleteName)),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
@@ -134,9 +129,7 @@ dynamic showDeleteDialog(
|
||||
),
|
||||
onPressed: () {
|
||||
exerciseData[exercise]!.removeWhere((el) => el.id == log.id);
|
||||
Provider.of<WorkoutPlansProvider>(context, listen: false).deleteLog(
|
||||
log,
|
||||
);
|
||||
Provider.of<WorkoutPlansProvider>(context, listen: false).deleteLog(log);
|
||||
|
||||
Navigator.of(contextDialog).pop();
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/core/locator.dart';
|
||||
import 'package:wger/powersync.dart';
|
||||
@@ -53,8 +54,7 @@ import 'package:wger/screens/workout_plan_screen.dart';
|
||||
import 'package:wger/screens/workout_plans_screen.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
import 'package:wger/widgets/core/about.dart';
|
||||
import 'package:wger/widgets/core/settings.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:wger/widgets/core/settingsdart';
|
||||
|
||||
import 'providers/auth.dart';
|
||||
|
||||
@@ -92,9 +92,8 @@ class MyApp extends StatelessWidget {
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (ctx) => AuthProvider()),
|
||||
ChangeNotifierProxyProvider<AuthProvider, ExercisesProvider>(
|
||||
create: (context) => ExercisesProvider(
|
||||
WgerBaseProvider(Provider.of(context, listen: false)),
|
||||
),
|
||||
create: (context) =>
|
||||
ExercisesProvider(WgerBaseProvider(Provider.of(context, listen: false))),
|
||||
update: (context, base, previous) =>
|
||||
previous ?? ExercisesProvider(WgerBaseProvider(base)),
|
||||
),
|
||||
@@ -108,44 +107,34 @@ class MyApp extends StatelessWidget {
|
||||
previous ?? WorkoutPlansProvider(WgerBaseProvider(auth), exercises, []),
|
||||
),
|
||||
ChangeNotifierProxyProvider<AuthProvider, NutritionPlansProvider>(
|
||||
create: (context) => NutritionPlansProvider(
|
||||
WgerBaseProvider(Provider.of(context, listen: false)),
|
||||
[],
|
||||
),
|
||||
create: (context) =>
|
||||
NutritionPlansProvider(WgerBaseProvider(Provider.of(context, listen: false)), []),
|
||||
update: (context, auth, previous) =>
|
||||
previous ?? NutritionPlansProvider(WgerBaseProvider(auth), []),
|
||||
),
|
||||
ChangeNotifierProxyProvider<AuthProvider, MeasurementProvider>(
|
||||
create: (context) => MeasurementProvider(
|
||||
WgerBaseProvider(Provider.of(context, listen: false)),
|
||||
),
|
||||
create: (context) =>
|
||||
MeasurementProvider(WgerBaseProvider(Provider.of(context, listen: false))),
|
||||
update: (context, base, previous) =>
|
||||
previous ?? MeasurementProvider(WgerBaseProvider(base)),
|
||||
),
|
||||
ChangeNotifierProxyProvider<AuthProvider, UserProvider>(
|
||||
create: (context) => UserProvider(
|
||||
WgerBaseProvider(Provider.of(context, listen: false)),
|
||||
),
|
||||
create: (context) => UserProvider(WgerBaseProvider(Provider.of(context, listen: false))),
|
||||
update: (context, base, previous) => previous ?? UserProvider(WgerBaseProvider(base)),
|
||||
),
|
||||
ChangeNotifierProxyProvider<AuthProvider, BodyWeightProvider>(
|
||||
create: (context) => BodyWeightProvider(
|
||||
WgerBaseProvider(Provider.of(context, listen: false)),
|
||||
),
|
||||
create: (context) =>
|
||||
BodyWeightProvider(WgerBaseProvider(Provider.of(context, listen: false))),
|
||||
update: (context, base, previous) =>
|
||||
previous ?? BodyWeightProvider(WgerBaseProvider(base)),
|
||||
),
|
||||
ChangeNotifierProxyProvider<AuthProvider, GalleryProvider>(
|
||||
create: (context) => GalleryProvider(
|
||||
Provider.of(context, listen: false),
|
||||
[],
|
||||
),
|
||||
create: (context) => GalleryProvider(Provider.of(context, listen: false), []),
|
||||
update: (context, auth, previous) => previous ?? GalleryProvider(auth, []),
|
||||
),
|
||||
ChangeNotifierProxyProvider<AuthProvider, AddExerciseProvider>(
|
||||
create: (context) => AddExerciseProvider(
|
||||
WgerBaseProvider(Provider.of(context, listen: false)),
|
||||
),
|
||||
create: (context) =>
|
||||
AddExerciseProvider(WgerBaseProvider(Provider.of(context, listen: false))),
|
||||
update: (context, base, previous) =>
|
||||
previous ?? AddExerciseProvider(WgerBaseProvider(base)),
|
||||
),
|
||||
@@ -164,8 +153,8 @@ class MyApp extends StatelessWidget {
|
||||
future: auth.tryAutoLogin(),
|
||||
builder: (ctx, authResultSnapshot) =>
|
||||
authResultSnapshot.connectionState == ConnectionState.waiting
|
||||
? const SplashScreen()
|
||||
: const AuthScreen(),
|
||||
? const SplashScreen()
|
||||
: const AuthScreen(),
|
||||
),
|
||||
routes: {
|
||||
DashboardScreen.routeName: (ctx) => const DashboardScreen(),
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:powersync/sqlite3.dart' as sqlite;
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/log.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/models/nutrition/meal_item.dart';
|
||||
@@ -128,10 +128,7 @@ class NutritionalPlan {
|
||||
}
|
||||
|
||||
Future<NutritionalPlan> loadChildren() async {
|
||||
return copyWith(
|
||||
diaryEntries: await Log.readByPlanId(id!),
|
||||
meals: await Meal.readByPlanId(id!),
|
||||
);
|
||||
return copyWith(diaryEntries: await Log.readByPlanId(id!), meals: await Meal.readByPlanId(id!));
|
||||
}
|
||||
|
||||
NutritionalPlan.empty() {
|
||||
@@ -186,10 +183,7 @@ class NutritionalPlan {
|
||||
return NutritionalGoals();
|
||||
}
|
||||
// otherwise, add up all the nutritional values of the meals and use that as goals
|
||||
final sumValues = meals.fold(
|
||||
NutritionalValues(),
|
||||
(a, b) => a + b.plannedNutritionalValues,
|
||||
);
|
||||
final sumValues = meals.fold(NutritionalValues(), (a, b) => a + b.plannedNutritionalValues);
|
||||
return NutritionalGoals(
|
||||
energy: sumValues.energy,
|
||||
fat: sumValues.fat,
|
||||
@@ -304,21 +298,21 @@ class NutritionalPlan {
|
||||
return NutritionalPlan.fromRow(row).loadChildren();
|
||||
}
|
||||
|
||||
// this is a bit complicated.
|
||||
// what we need at the end of the day, is a stream of List<NutritionPlan>, where
|
||||
// a new value is emitted any time a plan is changed. But the plan is not just the plan record
|
||||
// we need to load data for Logs and Meals corresponding to the plan also.
|
||||
// so our options are:
|
||||
// 1) db.watch with a select query on plans; and extra dart code to load the logs/meals stuff,
|
||||
// but this only triggers for updates on the plans table, and misses logs/meals updates
|
||||
// 2) db.watch with a huge join query across all tables from which we need info,
|
||||
// so we have all the data in our resultset to create the datastructures with, but:
|
||||
// - this creates long rows with lots of duplicated data (e.g. all the plan data) for every row
|
||||
// which would only differ for e.g. the meal or the log item
|
||||
// - it would probably get a bit messy to parse the resultset into the datastructures
|
||||
// 3) the best of both worlds: load the data we need in dart at runtime, but explicitly
|
||||
// trigger our code execution when *any* of the relevant tables changes
|
||||
//
|
||||
// this is a bit complicated.
|
||||
// what we need at the end of the day, is a stream of List<NutritionPlan>, where
|
||||
// a new value is emitted any time a plan is changed. But the plan is not just the plan record
|
||||
// we need to load data for Logs and Meals corresponding to the plan also.
|
||||
// so our options are:
|
||||
// 1) db.watch with a select query on plans; and extra dart code to load the logs/meals stuff,
|
||||
// but this only triggers for updates on the plans table, and misses logs/meals updates
|
||||
// 2) db.watch with a huge join query across all tables from which we need info,
|
||||
// so we have all the data in our resultset to create the datastructures with, but:
|
||||
// - this creates long rows with lots of duplicated data (e.g. all the plan data) for every row
|
||||
// which would only differ for e.g. the meal or the log item
|
||||
// - it would probably get a bit messy to parse the resultset into the datastructures
|
||||
// 3) the best of both worlds: load the data we need in dart at runtime, but explicitly
|
||||
// trigger our code execution when *any* of the relevant tables changes
|
||||
//
|
||||
static Stream<List<NutritionalPlan>> watchNutritionPlans() {
|
||||
return db.onChange([tableNutritionPlans, tableLogItems, tableMeals]).asyncMap((event) async {
|
||||
final data = await db.getAll('SELECT * FROM $tableNutritionPlans ORDER BY creation_date');
|
||||
@@ -336,15 +330,16 @@ class NutritionalPlan {
|
||||
|
||||
static Stream<NutritionalPlan?> watchNutritionPlanLast() {
|
||||
return db.onChange([tableNutritionPlans, tableLogItems, tableMeals]).asyncMap((event) async {
|
||||
final res =
|
||||
await db.getAll('SELECT * FROM $tableNutritionPlans ORDER BY creation_date DESC LIMIT 1');
|
||||
final res = await db.getAll(
|
||||
'SELECT * FROM $tableNutritionPlans ORDER BY creation_date DESC LIMIT 1',
|
||||
);
|
||||
if (res.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return NutritionalPlan.fromRow(res.first).loadChildren();
|
||||
});
|
||||
}
|
||||
/*
|
||||
/*
|
||||
static Stream<List<NutritionalPlan>> watchNutritionPlan(int id) {
|
||||
return db
|
||||
.watch('SELECT * FROM $tableNutritionPlans WHERE id = ?', parameters: [id]).map((results) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/add_exercise.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
@@ -76,9 +76,7 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
|
||||
final baseId = await addExerciseProvider.addExercise();
|
||||
final base = await exerciseProvider.fetchAndSetExercise(baseId);
|
||||
final name = base
|
||||
.getExercise(
|
||||
Localizations.localeOf(context).languageCode,
|
||||
)
|
||||
.getExercise(Localizations.localeOf(context).languageCode)
|
||||
.name;
|
||||
|
||||
setState(() {
|
||||
@@ -91,9 +89,7 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(AppLocalizations.of(context).success),
|
||||
content: Text(
|
||||
AppLocalizations.of(context).cacheWarning,
|
||||
),
|
||||
content: Text(AppLocalizations.of(context).cacheWarning),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(name),
|
||||
@@ -112,11 +108,7 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
|
||||
);
|
||||
},
|
||||
child: _isLoading
|
||||
? const SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
? const SizedBox(height: 20, width: 20, child: CircularProgressIndicator())
|
||||
: Text(AppLocalizations.of(context).save),
|
||||
)
|
||||
else
|
||||
@@ -207,8 +199,11 @@ class EmailNotVerified extends StatelessWidget {
|
||||
ListTile(
|
||||
leading: const Icon(Icons.warning),
|
||||
title: Text(AppLocalizations.of(context).unVerifiedEmail),
|
||||
subtitle: Text(AppLocalizations.of(context)
|
||||
.contributeExerciseWarning(MIN_ACCOUNT_AGE.toString())),
|
||||
subtitle: Text(
|
||||
AppLocalizations.of(
|
||||
context,
|
||||
).contributeExerciseWarning(MIN_ACCOUNT_AGE.toString()),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
|
||||
@@ -19,21 +19,18 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/exceptions/http_exception.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/misc.dart';
|
||||
import 'package:wger/helpers/ui.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/screens/update_app_screen.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
|
||||
import '../providers/auth.dart';
|
||||
|
||||
enum AuthMode {
|
||||
Signup,
|
||||
Login,
|
||||
}
|
||||
enum AuthMode { Signup, Login }
|
||||
|
||||
class AuthScreen extends StatelessWidget {
|
||||
const AuthScreen();
|
||||
@@ -50,10 +47,7 @@ class AuthScreen extends StatelessWidget {
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
child: Container(
|
||||
height: 0.55 * deviceSize.height,
|
||||
color: wgerPrimaryColor,
|
||||
),
|
||||
child: Container(height: 0.55 * deviceSize.height, color: wgerPrimaryColor),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: SizedBox(
|
||||
@@ -64,16 +58,10 @@ class AuthScreen extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(height: 0.15 * deviceSize.height),
|
||||
const Image(
|
||||
image: AssetImage('assets/images/logo-white.png'),
|
||||
width: 85,
|
||||
),
|
||||
const Image(image: AssetImage('assets/images/logo-white.png'), width: 85),
|
||||
Container(
|
||||
margin: const EdgeInsets.only(bottom: 20.0),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 94.0,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 94.0),
|
||||
child: const Text(
|
||||
'wger',
|
||||
style: TextStyle(
|
||||
@@ -190,11 +178,10 @@ class _AuthCardState extends State<AuthCard> {
|
||||
// Login existing user
|
||||
late Map<String, LoginActions> res;
|
||||
if (_authMode == AuthMode.Login) {
|
||||
res = await Provider.of<AuthProvider>(context, listen: false).login(
|
||||
_authData['username']!,
|
||||
_authData['password']!,
|
||||
_authData['serverUrl']!,
|
||||
);
|
||||
res = await Provider.of<AuthProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).login(_authData['username']!, _authData['password']!, _authData['serverUrl']!);
|
||||
|
||||
// Register new user
|
||||
} else {
|
||||
@@ -210,9 +197,9 @@ class _AuthCardState extends State<AuthCard> {
|
||||
// Check if update is required else continue normally
|
||||
if (res.containsKey('action')) {
|
||||
if (res['action'] == LoginActions.update && mounted) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => const UpdateAppScreen()),
|
||||
);
|
||||
Navigator.of(
|
||||
context,
|
||||
).push(MaterialPageRoute(builder: (context) => const UpdateAppScreen()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -260,16 +247,11 @@ class _AuthCardState extends State<AuthCard> {
|
||||
Widget build(BuildContext context) {
|
||||
final deviceSize = MediaQuery.of(context).size;
|
||||
return Card(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(15.0),
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
|
||||
elevation: 8.0,
|
||||
child: Container(
|
||||
width: deviceSize.width * 0.9,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 15.0,
|
||||
vertical: 0.025 * deviceSize.height,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 0.025 * deviceSize.height),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: SingleChildScrollView(
|
||||
@@ -297,9 +279,7 @@ class _AuthCardState extends State<AuthCard> {
|
||||
|
||||
return null;
|
||||
},
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.deny(RegExp(r'\s\b|\b\s')),
|
||||
],
|
||||
inputFormatters: [FilteringTextInputFormatter.deny(RegExp(r'\s\b|\b\s'))],
|
||||
onSaved: (value) {
|
||||
_authData['username'] = value!;
|
||||
},
|
||||
@@ -327,63 +307,69 @@ class _AuthCardState extends State<AuthCard> {
|
||||
_authData['email'] = value!;
|
||||
},
|
||||
),
|
||||
StatefulBuilder(builder: (context, updateState) {
|
||||
return TextFormField(
|
||||
key: const Key('inputPassword'),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).password,
|
||||
prefixIcon: const Icon(Icons.password),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(isObscure ? Icons.visibility_off : Icons.visibility),
|
||||
onPressed: () {
|
||||
isObscure = !isObscure;
|
||||
updateState(() {});
|
||||
},
|
||||
),
|
||||
),
|
||||
autofillHints: const [AutofillHints.password],
|
||||
obscureText: isObscure,
|
||||
controller: _passwordController,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty || value.length < 8) {
|
||||
return AppLocalizations.of(context).passwordTooShort;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
_authData['password'] = value!;
|
||||
},
|
||||
);
|
||||
}),
|
||||
if (_authMode == AuthMode.Signup)
|
||||
StatefulBuilder(builder: (context, updateState) {
|
||||
StatefulBuilder(
|
||||
builder: (context, updateState) {
|
||||
return TextFormField(
|
||||
key: const Key('inputPassword2'),
|
||||
key: const Key('inputPassword'),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).confirmPassword,
|
||||
labelText: AppLocalizations.of(context).password,
|
||||
prefixIcon: const Icon(Icons.password),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(confirmIsObscure ? Icons.visibility_off : Icons.visibility),
|
||||
icon: Icon(isObscure ? Icons.visibility_off : Icons.visibility),
|
||||
onPressed: () {
|
||||
confirmIsObscure = !confirmIsObscure;
|
||||
isObscure = !isObscure;
|
||||
updateState(() {});
|
||||
},
|
||||
),
|
||||
),
|
||||
controller: _password2Controller,
|
||||
enabled: _authMode == AuthMode.Signup,
|
||||
obscureText: confirmIsObscure,
|
||||
validator: _authMode == AuthMode.Signup
|
||||
? (value) {
|
||||
if (value != _passwordController.text) {
|
||||
return AppLocalizations.of(context).passwordsDontMatch;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
: null,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
obscureText: isObscure,
|
||||
controller: _passwordController,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty || value.length < 8) {
|
||||
return AppLocalizations.of(context).passwordTooShort;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
_authData['password'] = value!;
|
||||
},
|
||||
);
|
||||
}),
|
||||
},
|
||||
),
|
||||
if (_authMode == AuthMode.Signup)
|
||||
StatefulBuilder(
|
||||
builder: (context, updateState) {
|
||||
return TextFormField(
|
||||
key: const Key('inputPassword2'),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).confirmPassword,
|
||||
prefixIcon: const Icon(Icons.password),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
confirmIsObscure ? Icons.visibility_off : Icons.visibility,
|
||||
),
|
||||
onPressed: () {
|
||||
confirmIsObscure = !confirmIsObscure;
|
||||
updateState(() {});
|
||||
},
|
||||
),
|
||||
),
|
||||
controller: _password2Controller,
|
||||
enabled: _authMode == AuthMode.Signup,
|
||||
obscureText: confirmIsObscure,
|
||||
validator: _authMode == AuthMode.Signup
|
||||
? (value) {
|
||||
if (value != _passwordController.text) {
|
||||
return AppLocalizations.of(context).passwordsDontMatch;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
: null,
|
||||
);
|
||||
},
|
||||
),
|
||||
// Off-stage widgets are kept in the tree, otherwise the server URL
|
||||
// would not be saved to _authData
|
||||
Offstage(
|
||||
@@ -426,8 +412,9 @@ class _AuthCardState extends State<AuthCard> {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.undo),
|
||||
onPressed: () {
|
||||
_serverUrlController.text =
|
||||
kDebugMode ? DEFAULT_SERVER_TEST : DEFAULT_SERVER_PROD;
|
||||
_serverUrlController.text = kDebugMode
|
||||
? DEFAULT_SERVER_TEST
|
||||
: DEFAULT_SERVER_PROD;
|
||||
},
|
||||
),
|
||||
Text(AppLocalizations.of(context).reset),
|
||||
@@ -485,14 +472,9 @@ class _AuthCardState extends State<AuthCard> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(text.substring(0, text.lastIndexOf('?') + 1)),
|
||||
Text(
|
||||
text.substring(0, text.lastIndexOf('?') + 1),
|
||||
),
|
||||
Text(
|
||||
text.substring(
|
||||
text.lastIndexOf('?') + 1,
|
||||
text.length,
|
||||
),
|
||||
text.substring(text.lastIndexOf('?') + 1, text.length),
|
||||
style: const TextStyle(
|
||||
//color: wgerPrimaryColor,
|
||||
fontWeight: FontWeight.w700,
|
||||
|
||||
@@ -20,6 +20,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generatedapp_localizations.dart';
|
||||
import 'package:wger/models/muscle.dart';
|
||||
import 'package:wger/widgets/core/app_bar.dart';
|
||||
import 'package:wger/widgets/dashboard/calendar.dart';
|
||||
@@ -90,9 +91,8 @@ class _DashboardMuscleWidgetState extends State<DashboardMuscleWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.brown,
|
||||
child: Column(
|
||||
children: [Text('muscles'), ..._data.map((e) => Text(e.name)).toList()],
|
||||
));
|
||||
color: Colors.brown,
|
||||
child: Column(children: [Text('muscles'), ..._data.map((e) => Text(e.name)).toList()]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/exercise.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/widgets/core/app_bar.dart';
|
||||
@@ -43,11 +43,7 @@ class _ExercisesScreenState extends State<ExercisesScreen> {
|
||||
Expanded(
|
||||
child: exercisesList.isEmpty
|
||||
? const Center(
|
||||
child: SizedBox(
|
||||
height: 100,
|
||||
width: 100,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
child: SizedBox(height: 100, width: 100, child: CircularProgressIndicator()),
|
||||
)
|
||||
: _ExercisesList(exerciseBaseList: exercisesList),
|
||||
),
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/platform.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/gallery.dart';
|
||||
import 'package:wger/widgets/core/app_bar.dart';
|
||||
import 'package:wger/widgets/gallery/forms.dart';
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:rive/rive.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/powersync.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/widgets/nutrition/meal.dart';
|
||||
@@ -59,10 +59,7 @@ class _LogMealScreenState extends State<LogMealScreen> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
meal.name,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
Text(meal.name, style: Theme.of(context).textTheme.headlineSmall),
|
||||
if (meal.mealItems.isEmpty)
|
||||
ListTile(title: Text(AppLocalizations.of(context).noIngredientsDefined))
|
||||
else
|
||||
@@ -114,9 +111,7 @@ class _LogMealScreenState extends State<LogMealScreen> {
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
MaterialLocalizations.of(context).cancelButtonLabel,
|
||||
),
|
||||
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/widgets/nutrition/meal.dart';
|
||||
|
||||
@@ -37,17 +37,11 @@ class _LogMealsScreenState extends State<LogMealsScreen> {
|
||||
final nutritionalPlan = ModalRoute.of(context)!.settings.arguments as NutritionalPlan;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context).selectMealToLog),
|
||||
),
|
||||
appBar: AppBar(title: Text(AppLocalizations.of(context).selectMealToLog)),
|
||||
body: ListView.builder(
|
||||
itemCount: nutritionalPlan.meals.length,
|
||||
itemBuilder: (context, index) => MealWidget(
|
||||
nutritionalPlan.meals[index],
|
||||
nutritionalPlan.dedupMealItems,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
itemBuilder: (context, index) =>
|
||||
MealWidget(nutritionalPlan.meals[index], nutritionalPlan.dedupMealItems, true, true),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/widgets/measurements/categories.dart';
|
||||
|
||||
@@ -17,17 +17,14 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/widgets/measurements/entries.dart';
|
||||
import 'package:wger/widgets/measurements/forms.dart';
|
||||
|
||||
enum MeasurementOptions {
|
||||
edit,
|
||||
delete,
|
||||
}
|
||||
enum MeasurementOptions { edit, delete }
|
||||
|
||||
class MeasurementEntriesScreen extends StatelessWidget {
|
||||
const MeasurementEntriesScreen();
|
||||
@@ -62,9 +59,7 @@ class MeasurementEntriesScreen extends StatelessWidget {
|
||||
context: context,
|
||||
builder: (BuildContext contextDialog) {
|
||||
return AlertDialog(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).confirmDelete(category.name),
|
||||
),
|
||||
content: Text(AppLocalizations.of(context).confirmDelete(category.name)),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
@@ -73,9 +68,7 @@ class MeasurementEntriesScreen extends StatelessWidget {
|
||||
TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).delete,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
onPressed: () {
|
||||
// Confirmed, delete the workout
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_svg_icons/flutter_svg_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
@@ -29,10 +29,7 @@ import 'package:wger/screens/log_meals_screen.dart';
|
||||
import 'package:wger/widgets/nutrition/forms.dart';
|
||||
import 'package:wger/widgets/nutrition/nutritional_plan_detail.dart';
|
||||
|
||||
enum NutritionalPlanOptions {
|
||||
edit,
|
||||
delete,
|
||||
}
|
||||
enum NutritionalPlanOptions { edit, delete }
|
||||
|
||||
class NutritionalPlanScreen extends StatefulWidget {
|
||||
const NutritionalPlanScreen();
|
||||
@@ -52,8 +49,10 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
|
||||
final id = ModalRoute.of(context)!.settings.arguments as String;
|
||||
//final id = 111;
|
||||
|
||||
final stream =
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false).watchNutritionPlan(id);
|
||||
final stream = Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).watchNutritionPlan(id);
|
||||
_subscription = stream.listen((plan) {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
@@ -105,10 +104,7 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
|
||||
heroTag: null,
|
||||
tooltip: AppLocalizations.of(context).logMeal,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
LogMealsScreen.routeName,
|
||||
arguments: _plan,
|
||||
);
|
||||
Navigator.of(context).pushNamed(LogMealsScreen.routeName, arguments: _plan);
|
||||
},
|
||||
child: const SvgIcon(
|
||||
icon: SvgIconData('assets/icons/meal-diary.svg'),
|
||||
@@ -128,9 +124,7 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
|
||||
actions: [
|
||||
if (!_plan!.onlyLogging)
|
||||
IconButton(
|
||||
icon: const SvgIcon(
|
||||
icon: SvgIconData('assets/icons/meal-add.svg'),
|
||||
),
|
||||
icon: const SvgIcon(icon: SvgIconData('assets/icons/meal-add.svg')),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
@@ -158,8 +152,10 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
|
||||
);
|
||||
break;
|
||||
case NutritionalPlanOptions.delete:
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.deletePlan(_plan!.id!);
|
||||
Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).deletePlan(_plan!.id!);
|
||||
Navigator.of(context).pop();
|
||||
break;
|
||||
}
|
||||
@@ -189,8 +185,9 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
|
||||
titlePadding: const EdgeInsets.fromLTRB(56, 0, 56, 16),
|
||||
title: Text(
|
||||
_plan!.getLabel(context),
|
||||
style:
|
||||
Theme.of(context).textTheme.titleLarge?.copyWith(color: appBarForeground),
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleLarge?.copyWith(color: appBarForeground),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -198,22 +195,17 @@ class _NutritionalPlanScreenState extends State<NutritionalPlanScreen> {
|
||||
future: NutritionalPlan.read(_plan!.id!),
|
||||
builder: (context, AsyncSnapshot<NutritionalPlan> snapshot) =>
|
||||
snapshot.connectionState == ConnectionState.waiting
|
||||
? SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
const SizedBox(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Consumer<NutritionPlansProvider>(
|
||||
builder: (context, value, child) =>
|
||||
NutritionalPlanDetailWidget(_plan!),
|
||||
? SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
const SizedBox(
|
||||
height: 200,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
]),
|
||||
)
|
||||
: Consumer<NutritionPlansProvider>(
|
||||
builder: (context, value, child) => NutritionalPlanDetailWidget(_plan!),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/widgets/core/app_bar.dart';
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
|
||||
class UpdateAppScreen extends StatelessWidget {
|
||||
const UpdateAppScreen();
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/widgets/core/app_bar.dart';
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/workout_plan.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
@@ -27,15 +27,9 @@ import 'package:wger/widgets/workouts/forms.dart';
|
||||
import 'package:wger/widgets/workouts/workout_logs.dart';
|
||||
import 'package:wger/widgets/workouts/workout_plan_detail.dart';
|
||||
|
||||
enum WorkoutScreenMode {
|
||||
workout,
|
||||
log,
|
||||
}
|
||||
enum WorkoutScreenMode { workout, log }
|
||||
|
||||
enum WorkoutOptions {
|
||||
edit,
|
||||
delete,
|
||||
}
|
||||
enum WorkoutOptions { edit, delete }
|
||||
|
||||
class WorkoutPlanScreen extends StatefulWidget {
|
||||
const WorkoutPlanScreen();
|
||||
@@ -55,8 +49,10 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
|
||||
}
|
||||
|
||||
Future<WorkoutPlan> _loadFullWorkout(BuildContext context, int planId) {
|
||||
return Provider.of<WorkoutPlansProvider>(context, listen: false)
|
||||
.fetchAndSetWorkoutPlanFull(planId);
|
||||
return Provider.of<WorkoutPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).fetchAndSetWorkoutPlanFull(planId);
|
||||
}
|
||||
|
||||
Widget getBody(WorkoutPlan plan) {
|
||||
@@ -105,8 +101,10 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
|
||||
|
||||
// Delete
|
||||
} else if (value == WorkoutOptions.delete) {
|
||||
Provider.of<WorkoutPlansProvider>(context, listen: false)
|
||||
.deleteWorkout(workoutPlan.id!);
|
||||
Provider.of<WorkoutPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).deleteWorkout(workoutPlan.id!);
|
||||
Navigator.of(context).pop();
|
||||
|
||||
// Toggle Mode
|
||||
@@ -131,19 +129,14 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
|
||||
FutureBuilder(
|
||||
future: _loadFullWorkout(context, workoutPlan.id!),
|
||||
builder: (context, AsyncSnapshot<WorkoutPlan> snapshot) => SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
if (snapshot.connectionState == ConnectionState.waiting)
|
||||
const SizedBox(
|
||||
height: 200,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
)
|
||||
else
|
||||
Consumer<WorkoutPlansProvider>(
|
||||
builder: (context, value, child) => getBody(workoutPlan),
|
||||
),
|
||||
],
|
||||
),
|
||||
delegate: SliverChildListDelegate([
|
||||
if (snapshot.connectionState == ConnectionState.waiting)
|
||||
const SizedBox(height: 200, child: Center(child: CircularProgressIndicator()))
|
||||
else
|
||||
Consumer<WorkoutPlansProvider>(
|
||||
builder: (context, value, child) => getBody(workoutPlan),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/workout_plan.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/exercises/forms.dart';
|
||||
import 'package:wger/helpers/i18n.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/category.dart';
|
||||
import 'package:wger/models/exercises/equipment.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/add_exercise.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
|
||||
@@ -40,9 +40,7 @@ class Step2Variations extends StatelessWidget {
|
||||
...exerciseProvider.exerciseBasesByVariation[key]!.map(
|
||||
(base) => Text(
|
||||
base
|
||||
.getExercise(
|
||||
Localizations.localeOf(context).languageCode,
|
||||
)
|
||||
.getExercise(Localizations.localeOf(context).languageCode)
|
||||
.name,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -61,7 +59,9 @@ class Step2Variations extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
// Exercise bases without variations
|
||||
...exerciseProvider.exercises.where((b) => b.variationId == null).map(
|
||||
...exerciseProvider.exercises
|
||||
.where((b) => b.variationId == null)
|
||||
.map(
|
||||
(base) => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
@@ -72,9 +72,7 @@ class Step2Variations extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
base
|
||||
.getExercise(
|
||||
Localizations.localeOf(context).languageCode,
|
||||
)
|
||||
.getExercise(Localizations.localeOf(context).languageCode)
|
||||
.name,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/exercises/forms.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/add_exercise.dart';
|
||||
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/exercises/forms.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/language.dart';
|
||||
import 'package:wger/providers/add_exercise.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
@@ -74,10 +74,9 @@ class _Step4TranslationState extends State<Step4Translation> {
|
||||
final names = alternateNames!.split('\n');
|
||||
for (final name in names) {
|
||||
if (name.length < MIN_CHARS_NAME || name.length > MAX_CHARS_NAME) {
|
||||
return AppLocalizations.of(context).enterCharacters(
|
||||
MIN_CHARS_NAME,
|
||||
MAX_CHARS_NAME,
|
||||
);
|
||||
return AppLocalizations.of(
|
||||
context,
|
||||
).enterCharacters(MIN_CHARS_NAME, MAX_CHARS_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/add_exercise.dart';
|
||||
import 'package:wger/widgets/add_exercise/mixins/image_picker_mixin.dart';
|
||||
import 'package:wger/widgets/add_exercise/preview_images.dart';
|
||||
@@ -26,9 +26,7 @@ class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin
|
||||
),
|
||||
Consumer<AddExerciseProvider>(
|
||||
builder: (ctx, provider, __) => provider.exerciseImages.isNotEmpty
|
||||
? PreviewExerciseImages(
|
||||
selectedImages: provider.exerciseImages,
|
||||
)
|
||||
? PreviewExerciseImages(selectedImages: provider.exerciseImages)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/misc.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
|
||||
class AboutEntry extends StatelessWidget {
|
||||
@@ -66,9 +66,7 @@ class AboutPage extends StatelessWidget {
|
||||
final today = DateTime.now();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context).aboutPageTitle),
|
||||
),
|
||||
appBar: AppBar(title: Text(AppLocalizations.of(context).aboutPageTitle)),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
@@ -89,13 +87,12 @@ class AboutPage extends StatelessWidget {
|
||||
children: [
|
||||
const Text(
|
||||
'Wger',
|
||||
style: TextStyle(
|
||||
fontSize: 23,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
style: TextStyle(fontSize: 23, fontWeight: FontWeight.w600),
|
||||
),
|
||||
Text(
|
||||
'App: ${authProvider.applicationVersion!.version}\n'
|
||||
'Server: ${authProvider.serverVersion}',
|
||||
),
|
||||
Text('App: ${authProvider.applicationVersion!.version}\n'
|
||||
'Server: ${authProvider.serverVersion}'),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -163,7 +160,8 @@ class AboutPage extends StatelessWidget {
|
||||
showLicensePage(
|
||||
context: context,
|
||||
applicationName: 'wger',
|
||||
applicationVersion: 'App: ${authProvider.applicationVersion!.version}\n'
|
||||
applicationVersion:
|
||||
'App: ${authProvider.applicationVersion!.version}\n'
|
||||
'Server: ${authProvider.serverVersion}',
|
||||
applicationLegalese: '\u{a9} 2020 - 2021 contributors',
|
||||
applicationIcon: Padding(
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/gallery.dart';
|
||||
@@ -50,9 +50,7 @@ class MainAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
title: Text(AppLocalizations.of(context).optionsLabel),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
MaterialLocalizations.of(context).closeButtonLabel,
|
||||
),
|
||||
child: Text(MaterialLocalizations.of(context).closeButtonLabel),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
@@ -69,9 +67,7 @@ class MainAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
FormScreen.routeName,
|
||||
arguments: FormScreenArguments(
|
||||
AppLocalizations.of(context).userProfile,
|
||||
UserProfileForm(
|
||||
context.read<UserProvider>().profile!,
|
||||
),
|
||||
UserProfileForm(context.read<UserProvider>().profile!),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
//import 'package:drift/drift.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
|
||||
@@ -34,9 +34,7 @@ class SettingsPage extends StatelessWidget {
|
||||
final nutritionProvider = Provider.of<NutritionPlansProvider>(context, listen: false);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context).settingsTitle),
|
||||
),
|
||||
appBar: AppBar(title: Text(AppLocalizations.of(context).settingsTitle)),
|
||||
body: ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
|
||||
class TextPrompt extends StatelessWidget {
|
||||
const TextPrompt();
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/helpers/misc.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/session.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
@@ -31,12 +31,7 @@ import 'package:wger/providers/workout_plans.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
|
||||
/// Types of events
|
||||
enum EventType {
|
||||
weight,
|
||||
measurement,
|
||||
session,
|
||||
caloriesDiary,
|
||||
}
|
||||
enum EventType { weight, measurement, session, caloriesDiary }
|
||||
|
||||
/// An event in the dashboard calendar
|
||||
class Event {
|
||||
@@ -84,8 +79,10 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
|
||||
|
||||
void loadEvents() async {
|
||||
// Process weight entries
|
||||
final BodyWeightProvider weightProvider =
|
||||
Provider.of<BodyWeightProvider>(context, listen: false);
|
||||
final BodyWeightProvider weightProvider = Provider.of<BodyWeightProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
for (final entry in weightProvider.items) {
|
||||
final date = DateFormatLists.format(entry.date);
|
||||
|
||||
@@ -98,8 +95,10 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
|
||||
}
|
||||
|
||||
// Process measurements
|
||||
final MeasurementProvider measurementProvider =
|
||||
Provider.of<MeasurementProvider>(context, listen: false);
|
||||
final MeasurementProvider measurementProvider = Provider.of<MeasurementProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
for (final category in measurementProvider.categories) {
|
||||
for (final entry in category.entries) {
|
||||
final date = DateFormatLists.format(entry.date);
|
||||
@@ -108,10 +107,9 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
|
||||
_events[date] = [];
|
||||
}
|
||||
|
||||
_events[date]!.add(Event(
|
||||
EventType.measurement,
|
||||
'${category.name}: ${entry.value} ${category.unit}',
|
||||
));
|
||||
_events[date]!.add(
|
||||
Event(EventType.measurement, '${category.name}: ${entry.value} ${category.unit}'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,16 +126,20 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
|
||||
time = '(${timeToString(session.timeStart)} - ${timeToString(session.timeEnd)})';
|
||||
|
||||
// Add events to lists
|
||||
_events[date]!.add(Event(
|
||||
EventType.session,
|
||||
'${AppLocalizations.of(context).impression}: ${session.impressionAsString} $time',
|
||||
));
|
||||
_events[date]!.add(
|
||||
Event(
|
||||
EventType.session,
|
||||
'${AppLocalizations.of(context).impression}: ${session.impressionAsString} $time',
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Process nutritional plans
|
||||
final NutritionPlansProvider nutritionProvider =
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false);
|
||||
final NutritionPlansProvider nutritionProvider = Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
for (final plan in nutritionProvider.items) {
|
||||
for (final entry in plan.logEntriesValues.entries) {
|
||||
final date = DateFormatLists.format(entry.key);
|
||||
@@ -146,10 +148,9 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
|
||||
}
|
||||
|
||||
// Add events to lists
|
||||
_events[date]!.add(Event(
|
||||
EventType.caloriesDiary,
|
||||
'${entry.value.energy.toStringAsFixed(0)} kcal',
|
||||
));
|
||||
_events[date]!.add(
|
||||
Event(EventType.caloriesDiary, '${entry.value.energy.toStringAsFixed(0)} kcal'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,8 +248,10 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
|
||||
valueListenable: _selectedEvents,
|
||||
builder: (context, value, _) => Column(
|
||||
children: [
|
||||
...value.map((event) => ListTile(
|
||||
title: Text((() {
|
||||
...value.map(
|
||||
(event) => ListTile(
|
||||
title: Text(
|
||||
(() {
|
||||
switch (event.type) {
|
||||
case EventType.caloriesDiary:
|
||||
return AppLocalizations.of(context).nutritionalDiary;
|
||||
@@ -262,10 +265,12 @@ class _DashboardCalendarWidgetState extends State<DashboardCalendarWidget>
|
||||
case EventType.measurement:
|
||||
return AppLocalizations.of(context).measurement;
|
||||
}
|
||||
})()),
|
||||
subtitle: Text(event.description),
|
||||
//onTap: () => print('$event tapped!'),
|
||||
)),
|
||||
})(),
|
||||
),
|
||||
subtitle: Text(event.description),
|
||||
//onTap: () => print('$event tapped!'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -20,11 +20,11 @@ import 'dart:async';
|
||||
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_svg_icons/flutter_svg_icons.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/models/workouts/workout_plan.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
@@ -66,8 +66,10 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final stream =
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false).watchNutritionPlanLast();
|
||||
final stream = Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).watchNutritionPlanLast();
|
||||
_subscription = stream.listen((plan) {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
@@ -97,8 +99,9 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
),
|
||||
subtitle: Text(
|
||||
_hasContent
|
||||
? DateFormat.yMd(Localizations.localeOf(context).languageCode)
|
||||
.format(_plan!.creationDate)
|
||||
? DateFormat.yMd(
|
||||
Localizations.localeOf(context).languageCode,
|
||||
).format(_plan!.creationDate)
|
||||
: '',
|
||||
),
|
||||
leading: Icon(
|
||||
@@ -127,17 +130,14 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
TextButton(
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
NutritionalPlanScreen.routeName,
|
||||
arguments: _plan!.id,
|
||||
);
|
||||
Navigator.of(
|
||||
context,
|
||||
).pushNamed(NutritionalPlanScreen.routeName, arguments: _plan!.id);
|
||||
},
|
||||
),
|
||||
Expanded(child: Container()),
|
||||
IconButton(
|
||||
icon: const SvgIcon(
|
||||
icon: SvgIconData('assets/icons/ingredient-diary.svg'),
|
||||
),
|
||||
icon: const SvgIcon(icon: SvgIconData('assets/icons/ingredient-diary.svg')),
|
||||
tooltip: AppLocalizations.of(context).logIngredient,
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
@@ -152,9 +152,7 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const SvgIcon(
|
||||
icon: SvgIconData('assets/icons/meal-diary.svg'),
|
||||
),
|
||||
icon: const SvgIcon(icon: SvgIconData('assets/icons/meal-diary.svg')),
|
||||
tooltip: AppLocalizations.of(context).logMeal,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(LogMealsScreen.routeName, arguments: _plan);
|
||||
@@ -223,9 +221,7 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).goToDetailPage,
|
||||
),
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(WeightScreen.routeName);
|
||||
},
|
||||
@@ -238,9 +234,12 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
|
||||
FormScreen.routeName,
|
||||
arguments: FormScreenArguments(
|
||||
AppLocalizations.of(context).newEntry,
|
||||
WeightForm(weightProvider
|
||||
.getNewestEntry()
|
||||
?.copyWith(id: null, date: DateTime.now())),
|
||||
WeightForm(
|
||||
weightProvider.getNewestEntry()?.copyWith(
|
||||
id: null,
|
||||
date: DateTime.now(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -279,8 +278,9 @@ class _DashboardMeasurementWidgetState extends State<DashboardMeasurementWidget>
|
||||
Widget build(BuildContext context) {
|
||||
final provider = Provider.of<MeasurementProvider>(context, listen: false);
|
||||
|
||||
final items =
|
||||
provider.categories.map<Widget>((item) => CategoriesCard(item, elevation: 0)).toList();
|
||||
final items = provider.categories
|
||||
.map<Widget>((item) => CategoriesCard(item, elevation: 0))
|
||||
.toList();
|
||||
if (items.isNotEmpty) {
|
||||
items.add(
|
||||
NothingFound(
|
||||
@@ -309,10 +309,8 @@ class _DashboardMeasurementWidgetState extends State<DashboardMeasurementWidget>
|
||||
// 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(
|
||||
context,
|
||||
MeasurementCategoriesScreen.routeName,
|
||||
),
|
||||
onPressed: () =>
|
||||
Navigator.pushNamed(context, MeasurementCategoriesScreen.routeName),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
@@ -346,16 +344,11 @@ class _DashboardMeasurementWidgetState extends State<DashboardMeasurementWidget>
|
||||
child: Container(
|
||||
width: 12.0,
|
||||
height: 12.0,
|
||||
margin: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
horizontal: 4.0,
|
||||
),
|
||||
margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color:
|
||||
Theme.of(context).textTheme.headlineSmall!.color!.withOpacity(
|
||||
_current == entry.key ? 0.9 : 0.4,
|
||||
),
|
||||
color: Theme.of(context).textTheme.headlineSmall!.color!
|
||||
.withOpacity(_current == entry.key ? 0.9 : 0.4),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -407,61 +400,63 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
}
|
||||
|
||||
for (final day in _workoutPlan!.days) {
|
||||
out.add(SizedBox(
|
||||
width: double.infinity,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
day.description,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: MutedText(day.getDaysText, textAlign: TextAlign.right),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
color: wgerPrimaryButtonColor,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(GymModeScreen.routeName, arguments: day);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
|
||||
for (final set in day.sets) {
|
||||
out.add(SizedBox(
|
||||
out.add(
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
child: Row(
|
||||
children: [
|
||||
...set.settingsFiltered.map((s) {
|
||||
return _showDetail
|
||||
? Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(s.exerciseObj
|
||||
.getExercise(Localizations.localeOf(context).languageCode)
|
||||
.name),
|
||||
const SizedBox(width: 10),
|
||||
MutedText(
|
||||
set.getSmartRepr(s.exerciseObj).join('\n'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
)
|
||||
: Container();
|
||||
}),
|
||||
Expanded(
|
||||
child: Text(
|
||||
day.description,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Expanded(child: MutedText(day.getDaysText, textAlign: TextAlign.right)),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
color: wgerPrimaryButtonColor,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(GymModeScreen.routeName, arguments: day);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
),
|
||||
);
|
||||
|
||||
for (final set in day.sets) {
|
||||
out.add(
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
...set.settingsFiltered.map((s) {
|
||||
return _showDetail
|
||||
? Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
s.exerciseObj
|
||||
.getExercise(Localizations.localeOf(context).languageCode)
|
||||
.name,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
MutedText(set.getSmartRepr(s.exerciseObj).join('\n')),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
)
|
||||
: Container();
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
out.add(const Divider());
|
||||
}
|
||||
@@ -481,8 +476,9 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
),
|
||||
subtitle: Text(
|
||||
_hasContent
|
||||
? DateFormat.yMd(Localizations.localeOf(context).languageCode)
|
||||
.format(_workoutPlan!.creationDate)
|
||||
? DateFormat.yMd(
|
||||
Localizations.localeOf(context).languageCode,
|
||||
).format(_workoutPlan!.creationDate)
|
||||
: '',
|
||||
),
|
||||
leading: Icon(
|
||||
@@ -519,10 +515,9 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
TextButton(
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
WorkoutPlanScreen.routeName,
|
||||
arguments: _workoutPlan,
|
||||
);
|
||||
Navigator.of(
|
||||
context,
|
||||
).pushNamed(WorkoutPlanScreen.routeName, arguments: _workoutPlan);
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -555,11 +550,7 @@ class NothingFound extends StatelessWidget {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
FormScreen.routeName,
|
||||
arguments: FormScreenArguments(
|
||||
_titleForm,
|
||||
hasListView: true,
|
||||
_form,
|
||||
),
|
||||
arguments: FormScreenArguments(_titleForm, hasListView: true, _form),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/i18n.dart';
|
||||
import 'package:wger/helpers/platform.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/exercise.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/models/exercises/translation.dart';
|
||||
@@ -83,18 +83,20 @@ class ExerciseDetail extends StatelessWidget {
|
||||
return out;
|
||||
}
|
||||
|
||||
out.add(Text(
|
||||
AppLocalizations.of(context).variations,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
));
|
||||
out.add(
|
||||
Text(
|
||||
AppLocalizations.of(context).variations,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
);
|
||||
Provider.of<ExercisesProvider>(context, listen: false)
|
||||
.findExercisesByVariationId(
|
||||
_exerciseBase.variationId!,
|
||||
exerciseBaseIdToExclude: _exerciseBase.id,
|
||||
)
|
||||
_exerciseBase.variationId!,
|
||||
exerciseBaseIdToExclude: _exerciseBase.id,
|
||||
)
|
||||
.forEach((element) {
|
||||
out.add(ExerciseListTile(exerciseBase: element));
|
||||
});
|
||||
out.add(ExerciseListTile(exerciseBase: element));
|
||||
});
|
||||
|
||||
out.add(const SizedBox(height: PADDING));
|
||||
return out;
|
||||
@@ -103,10 +105,9 @@ class ExerciseDetail extends StatelessWidget {
|
||||
List<Widget> getNotes(BuildContext context) {
|
||||
final List<Widget> out = [];
|
||||
if (_exercise.notes.isNotEmpty) {
|
||||
out.add(Text(
|
||||
AppLocalizations.of(context).notes,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
));
|
||||
out.add(
|
||||
Text(AppLocalizations.of(context).notes, style: Theme.of(context).textTheme.headlineSmall),
|
||||
);
|
||||
for (final e in _exercise.notes) {
|
||||
out.add(Text(e.comment));
|
||||
}
|
||||
@@ -118,36 +119,37 @@ class ExerciseDetail extends StatelessWidget {
|
||||
|
||||
List<Widget> getMuscles(BuildContext context) {
|
||||
final List<Widget> out = [];
|
||||
out.add(Text(
|
||||
AppLocalizations.of(context).muscles,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
));
|
||||
out.add(Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: PADDING),
|
||||
child: MuscleWidget(
|
||||
muscles: _exerciseBase.muscles,
|
||||
musclesSecondary: _exerciseBase.musclesSecondary,
|
||||
isFront: true,
|
||||
out.add(
|
||||
Text(AppLocalizations.of(context).muscles, style: Theme.of(context).textTheme.headlineSmall),
|
||||
);
|
||||
out.add(
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: PADDING),
|
||||
child: MuscleWidget(
|
||||
muscles: _exerciseBase.muscles,
|
||||
musclesSecondary: _exerciseBase.musclesSecondary,
|
||||
isFront: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: PADDING),
|
||||
child: MuscleWidget(
|
||||
muscles: _exerciseBase.muscles,
|
||||
musclesSecondary: _exerciseBase.musclesSecondary,
|
||||
isFront: false,
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: PADDING),
|
||||
child: MuscleWidget(
|
||||
muscles: _exerciseBase.muscles,
|
||||
musclesSecondary: _exerciseBase.musclesSecondary,
|
||||
isFront: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
));
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
out.add(
|
||||
Column(
|
||||
@@ -176,10 +178,12 @@ class ExerciseDetail extends StatelessWidget {
|
||||
|
||||
List<Widget> getDescription(BuildContext context) {
|
||||
final List<Widget> out = [];
|
||||
out.add(Text(
|
||||
AppLocalizations.of(context).description,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
));
|
||||
out.add(
|
||||
Text(
|
||||
AppLocalizations.of(context).description,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
);
|
||||
out.add(Html(data: _exercise.description));
|
||||
|
||||
return out;
|
||||
@@ -212,14 +216,16 @@ class ExerciseDetail extends StatelessWidget {
|
||||
);
|
||||
if (_exerciseBase.equipment.isNotEmpty) {
|
||||
_exerciseBase.equipment
|
||||
.map((e) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Chip(
|
||||
label: Text(getTranslation(e.name, context)),
|
||||
padding: EdgeInsets.zero,
|
||||
backgroundColor: theme.splashColor,
|
||||
),
|
||||
))
|
||||
.map(
|
||||
(e) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Chip(
|
||||
label: Text(getTranslation(e.name, context)),
|
||||
padding: EdgeInsets.zero,
|
||||
backgroundColor: theme.splashColor,
|
||||
),
|
||||
),
|
||||
)
|
||||
.forEach((element) => out.add(element));
|
||||
}
|
||||
out.add(const SizedBox(height: PADDING));
|
||||
@@ -242,11 +248,13 @@ class ExerciseDetail extends StatelessWidget {
|
||||
List<Widget> getAliases(BuildContext context) {
|
||||
final List<Widget> out = [];
|
||||
if (_exercise.aliases.isNotEmpty) {
|
||||
out.add(MutedText(
|
||||
AppLocalizations.of(context).alsoKnownAs(
|
||||
_exercise.aliases.map((e) => e.alias).toList().join(', '),
|
||||
out.add(
|
||||
MutedText(
|
||||
AppLocalizations.of(
|
||||
context,
|
||||
).alsoKnownAs(_exercise.aliases.map((e) => e.alias).toList().join(', ')),
|
||||
),
|
||||
));
|
||||
);
|
||||
out.add(const SizedBox(height: PADDING));
|
||||
}
|
||||
|
||||
@@ -284,10 +292,7 @@ class MuscleRowWidget extends StatelessWidget {
|
||||
final List<Muscle> muscles;
|
||||
final List<Muscle> musclesSecondary;
|
||||
|
||||
const MuscleRowWidget({
|
||||
required this.muscles,
|
||||
required this.musclesSecondary,
|
||||
});
|
||||
const MuscleRowWidget({required this.muscles, required this.musclesSecondary});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -342,9 +347,9 @@ class MuscleWidget extends StatelessWidget {
|
||||
children: [
|
||||
SvgPicture.asset('assets/images/muscles/$background.svg'),
|
||||
...muscles.map((m) => SvgPicture.asset('assets/images/muscles/main/muscle-${m.id}.svg')),
|
||||
...musclesSecondary.map((m) => SvgPicture.asset(
|
||||
'assets/images/muscles/secondary/muscle-${m.id}.svg',
|
||||
)),
|
||||
...musclesSecondary.map(
|
||||
(m) => SvgPicture.asset('assets/images/muscles/secondary/muscle-${m.id}.svg'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/screens/add_exercise_screen.dart';
|
||||
|
||||
@@ -59,9 +59,7 @@ class _FilterRowState extends State<FilterRow> {
|
||||
decoration: InputDecoration(
|
||||
hintText: '${AppLocalizations.of(context).exerciseName}...',
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
border: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.black),
|
||||
),
|
||||
border: const OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/gallery/image.dart' as gallery;
|
||||
import 'package:wger/providers/gallery.dart';
|
||||
|
||||
@@ -126,9 +126,7 @@ class _ImageFormState extends State<ImageForm> {
|
||||
_showPicker(ImageSource.gallery);
|
||||
},
|
||||
leading: const Icon(Icons.photo_library),
|
||||
title: Text(
|
||||
AppLocalizations.of(context).chooseFromLibrary,
|
||||
),
|
||||
title: Text(AppLocalizations.of(context).chooseFromLibrary),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -174,9 +172,7 @@ class _ImageFormState extends State<ImageForm> {
|
||||
),
|
||||
TextFormField(
|
||||
key: const Key('field-description'),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).description,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).description),
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
controller: descriptionController,
|
||||
@@ -196,12 +192,16 @@ class _ImageFormState extends State<ImageForm> {
|
||||
_form.currentState!.save();
|
||||
|
||||
if (widget._image.id == null) {
|
||||
Provider.of<GalleryProvider>(context, listen: false)
|
||||
.addImage(widget._image, _file!);
|
||||
Provider.of<GalleryProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).addImage(widget._image, _file!);
|
||||
Navigator.of(context).pop();
|
||||
} else {
|
||||
Provider.of<GalleryProvider>(context, listen: false)
|
||||
.editImage(widget._image, _file);
|
||||
Provider.of<GalleryProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).editImage(widget._image, _file);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/platform.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/gallery.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/widgets/core/text_prompt.dart';
|
||||
@@ -58,13 +58,12 @@ class Gallery extends StatelessWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
DateFormat.yMd(Localizations.localeOf(context).languageCode)
|
||||
.format(currentImage.date),
|
||||
DateFormat.yMd(
|
||||
Localizations.localeOf(context).languageCode,
|
||||
).format(currentImage.date),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
Expanded(
|
||||
child: Image.network(currentImage.url!),
|
||||
),
|
||||
Expanded(child: Image.network(currentImage.url!)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Text(currentImage.description),
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
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';
|
||||
|
||||
@@ -26,19 +26,12 @@ class CategoriesCard extends StatelessWidget {
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
currentCategory.name,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
child: Text(currentCategory.name, style: Theme.of(context).textTheme.titleLarge),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
height: 220,
|
||||
child: MeasurementChartWidgetFl(
|
||||
entriesAll,
|
||||
currentCategory.unit,
|
||||
avgs: entries7dAvg,
|
||||
),
|
||||
child: MeasurementChartWidgetFl(entriesAll, currentCategory.unit, avgs: entries7dAvg),
|
||||
),
|
||||
if (entries7dAvg.isNotEmpty)
|
||||
MeasurementOverallChangeWidget(
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:wger/helpers/charts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
|
||||
class MeasurementOverallChangeWidget extends StatelessWidget {
|
||||
final MeasurementChartEntry _first;
|
||||
@@ -34,8 +34,8 @@ class MeasurementOverallChangeWidget extends StatelessWidget {
|
||||
final prefix = delta > 0
|
||||
? '+'
|
||||
: delta < 0
|
||||
? '-'
|
||||
: '';
|
||||
? '-'
|
||||
: '';
|
||||
|
||||
return Text('overall change $prefix ${delta.abs().toStringAsFixed(1)} $_unit');
|
||||
}
|
||||
@@ -61,10 +61,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
|
||||
Widget build(BuildContext context) {
|
||||
return AspectRatio(
|
||||
aspectRatio: 1.70,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: LineChart(mainData()),
|
||||
),
|
||||
child: Padding(padding: const EdgeInsets.all(4), child: LineChart(mainData())),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,15 +72,13 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
|
||||
getTooltipItems: (touchedSpots) {
|
||||
return touchedSpots.map((touchedSpot) {
|
||||
final DateTime date = DateTime.fromMillisecondsSinceEpoch(touchedSpot.x.toInt());
|
||||
final dateStr =
|
||||
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date);
|
||||
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,
|
||||
),
|
||||
TextStyle(color: touchedSpot.bar.color, fontWeight: FontWeight.bold),
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
@@ -108,12 +103,8 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
|
||||
),
|
||||
titlesData: FlTitlesData(
|
||||
show: true,
|
||||
rightTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
topTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
@@ -132,15 +123,10 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
|
||||
DateFormat.yMd(Localizations.localeOf(context).languageCode).format(date),
|
||||
);
|
||||
}
|
||||
return Text(
|
||||
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date),
|
||||
);
|
||||
return Text(DateFormat.Md(Localizations.localeOf(context).languageCode).format(date));
|
||||
},
|
||||
interval: widget._entries.isNotEmpty
|
||||
? chartGetInterval(
|
||||
widget._entries.last.date,
|
||||
widget._entries.first.date,
|
||||
)
|
||||
? chartGetInterval(widget._entries.last.date, widget._entries.first.date)
|
||||
: 1000,
|
||||
),
|
||||
),
|
||||
@@ -168,10 +154,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
|
||||
lineBarsData: [
|
||||
LineChartBarData(
|
||||
spots: widget._entries
|
||||
.map((e) => FlSpot(
|
||||
e.date.millisecondsSinceEpoch.toDouble(),
|
||||
e.value.toDouble(),
|
||||
))
|
||||
.map((e) => FlSpot(e.date.millisecondsSinceEpoch.toDouble(), e.value.toDouble()))
|
||||
.toList(),
|
||||
isCurved: false,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
@@ -182,10 +165,7 @@ class _MeasurementChartWidgetFlState extends State<MeasurementChartWidgetFl> {
|
||||
if (widget.avgs != null)
|
||||
LineChartBarData(
|
||||
spots: widget.avgs!
|
||||
.map((e) => FlSpot(
|
||||
e.date.millisecondsSinceEpoch.toDouble(),
|
||||
e.value.toDouble(),
|
||||
))
|
||||
.map((e) => FlSpot(e.date.millisecondsSinceEpoch.toDouble(), e.value.toDouble()))
|
||||
.toList(),
|
||||
isCurved: false,
|
||||
color: Theme.of(context).colorScheme.tertiary,
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/measurements/measurement_category.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
@@ -38,82 +38,80 @@ class EntriesList extends StatelessWidget {
|
||||
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 entriesAll = _category.entries
|
||||
.map((e) => MeasurementChartEntry(e.value, e.date))
|
||||
.toList();
|
||||
final entries7dAvg = moving7dAverage(entriesAll);
|
||||
|
||||
return Column(children: [
|
||||
...getOverviewWidgetsSeries(
|
||||
_category.name,
|
||||
entriesAll,
|
||||
entries7dAvg,
|
||||
plan,
|
||||
_category.unit,
|
||||
context,
|
||||
),
|
||||
SizedBox(
|
||||
height: 300,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
itemCount: _category.entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
final currentEntry = _category.entries[index];
|
||||
final provider = Provider.of<MeasurementProvider>(context, listen: false);
|
||||
return Column(
|
||||
children: [
|
||||
...getOverviewWidgetsSeries(
|
||||
_category.name,
|
||||
entriesAll,
|
||||
entries7dAvg,
|
||||
plan,
|
||||
_category.unit,
|
||||
context,
|
||||
),
|
||||
SizedBox(
|
||||
height: 300,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
itemCount: _category.entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
final currentEntry = _category.entries[index];
|
||||
final provider = Provider.of<MeasurementProvider>(context, listen: false);
|
||||
|
||||
return Card(
|
||||
child: ListTile(
|
||||
title: Text('${currentEntry.value} ${_category.unit}'),
|
||||
subtitle: Text(
|
||||
DateFormat.yMd(Localizations.localeOf(context).languageCode)
|
||||
.format(currentEntry.date),
|
||||
),
|
||||
trailing: PopupMenuButton(
|
||||
itemBuilder: (BuildContext context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
child: Text(AppLocalizations.of(context).edit),
|
||||
onTap: () => Navigator.pushNamed(
|
||||
context,
|
||||
FormScreen.routeName,
|
||||
arguments: FormScreenArguments(
|
||||
AppLocalizations.of(context).edit,
|
||||
MeasurementEntryForm(
|
||||
currentEntry.category,
|
||||
currentEntry,
|
||||
return Card(
|
||||
child: ListTile(
|
||||
title: Text('${currentEntry.value} ${_category.unit}'),
|
||||
subtitle: Text(
|
||||
DateFormat.yMd(
|
||||
Localizations.localeOf(context).languageCode,
|
||||
).format(currentEntry.date),
|
||||
),
|
||||
trailing: PopupMenuButton(
|
||||
itemBuilder: (BuildContext context) {
|
||||
return [
|
||||
PopupMenuItem(
|
||||
child: Text(AppLocalizations.of(context).edit),
|
||||
onTap: () => Navigator.pushNamed(
|
||||
context,
|
||||
FormScreen.routeName,
|
||||
arguments: FormScreenArguments(
|
||||
AppLocalizations.of(context).edit,
|
||||
MeasurementEntryForm(currentEntry.category, currentEntry),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: Text(AppLocalizations.of(context).delete),
|
||||
onTap: () async {
|
||||
// Delete entry from DB
|
||||
await provider.deleteEntry(
|
||||
currentEntry.id!,
|
||||
currentEntry.category,
|
||||
);
|
||||
PopupMenuItem(
|
||||
child: Text(AppLocalizations.of(context).delete),
|
||||
onTap: () async {
|
||||
// Delete entry from DB
|
||||
await provider.deleteEntry(currentEntry.id!, currentEntry.category);
|
||||
|
||||
// and inform the user
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).successfullyDeleted,
|
||||
textAlign: TextAlign.center,
|
||||
// and inform the user
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).successfullyDeleted,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
];
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
];
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
]);
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/exceptions/http_exception.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/helpers/ui.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/measurements/measurement_category.dart';
|
||||
import 'package:wger/models/measurements/measurement_entry.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
@@ -31,11 +31,7 @@ class MeasurementCategoryForm extends StatelessWidget {
|
||||
final nameController = TextEditingController();
|
||||
final unitController = TextEditingController();
|
||||
|
||||
final Map<String, dynamic> categoryData = {
|
||||
'id': null,
|
||||
'name': '',
|
||||
'unit': '',
|
||||
};
|
||||
final Map<String, dynamic> categoryData = {'id': null, 'name': '', 'unit': ''};
|
||||
|
||||
MeasurementCategoryForm([MeasurementCategory? category]) {
|
||||
//this._category = category ?? MeasurementCategory();
|
||||
@@ -103,20 +99,14 @@ class MeasurementCategoryForm extends StatelessWidget {
|
||||
// Save the entry on the server
|
||||
try {
|
||||
categoryData['id'] == null
|
||||
? await Provider.of<MeasurementProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).addCategory(
|
||||
? await Provider.of<MeasurementProvider>(context, listen: false).addCategory(
|
||||
MeasurementCategory(
|
||||
id: categoryData['id'],
|
||||
name: categoryData['name'],
|
||||
unit: categoryData['unit'],
|
||||
),
|
||||
)
|
||||
: await Provider.of<MeasurementProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).editCategory(
|
||||
: await Provider.of<MeasurementProvider>(context, listen: false).editCategory(
|
||||
categoryData['id'],
|
||||
categoryData['name'],
|
||||
categoryData['unit'],
|
||||
@@ -274,20 +264,16 @@ class MeasurementEntryForm extends StatelessWidget {
|
||||
// Save the entry on the server
|
||||
try {
|
||||
_entryData['id'] == null
|
||||
? await Provider.of<MeasurementProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).addEntry(MeasurementEntry(
|
||||
id: _entryData['id'],
|
||||
category: _entryData['category'],
|
||||
date: _entryData['date'],
|
||||
value: _entryData['value'],
|
||||
notes: _entryData['notes'],
|
||||
))
|
||||
: await Provider.of<MeasurementProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).editEntry(
|
||||
? await Provider.of<MeasurementProvider>(context, listen: false).addEntry(
|
||||
MeasurementEntry(
|
||||
id: _entryData['id'],
|
||||
category: _entryData['category'],
|
||||
date: _entryData['date'],
|
||||
value: _entryData['value'],
|
||||
notes: _entryData['notes'],
|
||||
),
|
||||
)
|
||||
: await Provider.of<MeasurementProvider>(context, listen: false).editEntry(
|
||||
_entryData['id'],
|
||||
_entryData['category'],
|
||||
_entryData['value'],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/widgets/measurements/charts.dart';
|
||||
|
||||
@@ -11,11 +11,7 @@ List<Widget> getOverviewWidgets(
|
||||
BuildContext context,
|
||||
) {
|
||||
return [
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
Text(title, textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleLarge),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
height: 220,
|
||||
|
||||
@@ -20,8 +20,8 @@ import 'dart:math';
|
||||
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/helpers/colors.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
import 'package:wger/widgets/measurements/charts.dart';
|
||||
@@ -34,10 +34,8 @@ import 'package:wger/widgets/measurements/charts.dart';
|
||||
// * here we draw our own simple gauges that can go beyond 100%,
|
||||
// and support multiple segments
|
||||
class FlNutritionalPlanGoalWidget extends StatelessWidget {
|
||||
const FlNutritionalPlanGoalWidget({
|
||||
super.key,
|
||||
required NutritionalPlan nutritionalPlan,
|
||||
}) : _nutritionalPlan = nutritionalPlan;
|
||||
const FlNutritionalPlanGoalWidget({super.key, required NutritionalPlan nutritionalPlan})
|
||||
: _nutritionalPlan = nutritionalPlan;
|
||||
|
||||
final NutritionalPlan _nutritionalPlan;
|
||||
|
||||
@@ -47,20 +45,12 @@ class FlNutritionalPlanGoalWidget extends StatelessWidget {
|
||||
// why don't we just handle this inside this function? because it might be
|
||||
// *another* gauge that's in surplus and we want to have consistent widths
|
||||
// between all gauges
|
||||
Widget _diyGauge(
|
||||
BuildContext context,
|
||||
double normWidth,
|
||||
double? plan,
|
||||
double val,
|
||||
) {
|
||||
Widget _diyGauge(BuildContext context, double normWidth, double? plan, double val) {
|
||||
Container segment(double width, Color color) {
|
||||
return Container(
|
||||
height: 16,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(15.0),
|
||||
),
|
||||
decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(15.0)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,17 +61,21 @@ class FlNutritionalPlanGoalWidget extends StatelessWidget {
|
||||
|
||||
// paint a surplus
|
||||
if (val > plan) {
|
||||
return Stack(children: [
|
||||
segment(normWidth * val / plan, COLOR_SURPLUS),
|
||||
segment(normWidth, LIST_OF_COLORS8[0]),
|
||||
]);
|
||||
return Stack(
|
||||
children: [
|
||||
segment(normWidth * val / plan, COLOR_SURPLUS),
|
||||
segment(normWidth, LIST_OF_COLORS8[0]),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// paint a deficit
|
||||
return Stack(children: [
|
||||
segment(normWidth, Theme.of(context).colorScheme.surface),
|
||||
segment(normWidth * val / plan, LIST_OF_COLORS8[0]),
|
||||
]);
|
||||
return Stack(
|
||||
children: [
|
||||
segment(normWidth, Theme.of(context).colorScheme.surface),
|
||||
segment(normWidth * val / plan, LIST_OF_COLORS8[0]),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -90,87 +84,97 @@ class FlNutritionalPlanGoalWidget extends StatelessWidget {
|
||||
final goals = plan.nutritionalGoals;
|
||||
final today = plan.loggedNutritionalValuesToday;
|
||||
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
// if any of the bars goes over 100%, find the one that goes over the most
|
||||
// that one needs the most horizontal space to show how much it goes over,
|
||||
// and therefore reduces the width of "100%" the most, and this width we want
|
||||
// to be consistent for all other bars.
|
||||
// if none goes over, 100% means fill all available space
|
||||
final maxVal = [
|
||||
1.0,
|
||||
if (goals.energy != null && goals.energy! > 0) today.energy / goals.energy!,
|
||||
if (goals.protein != null && goals.protein! > 0) today.protein / goals.protein!,
|
||||
if (goals.carbohydrates != null && goals.carbohydrates! > 0)
|
||||
today.carbohydrates / goals.carbohydrates!,
|
||||
if (goals.fat != null && goals.fat! > 0) today.fat / goals.fat!,
|
||||
if (goals.fiber != null && goals.fiber! > 0) today.fiber / goals.fiber!,
|
||||
].reduce(max);
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
// if any of the bars goes over 100%, find the one that goes over the most
|
||||
// that one needs the most horizontal space to show how much it goes over,
|
||||
// and therefore reduces the width of "100%" the most, and this width we want
|
||||
// to be consistent for all other bars.
|
||||
// if none goes over, 100% means fill all available space
|
||||
final maxVal = [
|
||||
1.0,
|
||||
if (goals.energy != null && goals.energy! > 0) today.energy / goals.energy!,
|
||||
if (goals.protein != null && goals.protein! > 0) today.protein / goals.protein!,
|
||||
if (goals.carbohydrates != null && goals.carbohydrates! > 0)
|
||||
today.carbohydrates / goals.carbohydrates!,
|
||||
if (goals.fat != null && goals.fat! > 0) today.fat / goals.fat!,
|
||||
if (goals.fiber != null && goals.fiber! > 0) today.fiber / goals.fiber!,
|
||||
].reduce(max);
|
||||
|
||||
final normWidth = constraints.maxWidth / maxVal;
|
||||
final normWidth = constraints.maxWidth / maxVal;
|
||||
|
||||
String fmtMacro(String name, double today, double? goal, String unit) {
|
||||
return '$name: ${today.toStringAsFixed(0)}${goal == null ? '' : ' / ${goal.toStringAsFixed(0)}'} $unit';
|
||||
}
|
||||
String fmtMacro(String name, double today, double? goal, String unit) {
|
||||
return '$name: ${today.toStringAsFixed(0)}${goal == null ? '' : ' / ${goal.toStringAsFixed(0)}'} $unit';
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(fmtMacro(
|
||||
AppLocalizations.of(context).energy,
|
||||
today.energy,
|
||||
goals.energy,
|
||||
AppLocalizations.of(context).kcal,
|
||||
)),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.energy, today.energy),
|
||||
const SizedBox(height: 8),
|
||||
Text(fmtMacro(
|
||||
AppLocalizations.of(context).protein,
|
||||
today.protein,
|
||||
goals.protein,
|
||||
AppLocalizations.of(context).g,
|
||||
)),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.protein, today.protein),
|
||||
const SizedBox(height: 8),
|
||||
Text(fmtMacro(
|
||||
AppLocalizations.of(context).carbohydrates,
|
||||
today.carbohydrates,
|
||||
goals.carbohydrates,
|
||||
AppLocalizations.of(context).g,
|
||||
)),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(
|
||||
context,
|
||||
normWidth,
|
||||
goals.carbohydrates,
|
||||
today.carbohydrates,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(fmtMacro(
|
||||
AppLocalizations.of(context).fat,
|
||||
today.fat,
|
||||
goals.fat,
|
||||
AppLocalizations.of(context).g,
|
||||
)),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.fat, today.fat),
|
||||
// optionally display the advanced macro goals:
|
||||
if (goals.fiber != null)
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
const SizedBox(height: 8),
|
||||
Text(fmtMacro(
|
||||
AppLocalizations.of(context).fiber,
|
||||
today.fiber,
|
||||
goals.fiber,
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
fmtMacro(
|
||||
AppLocalizations.of(context).energy,
|
||||
today.energy,
|
||||
goals.energy,
|
||||
AppLocalizations.of(context).kcal,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.energy, today.energy),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
fmtMacro(
|
||||
AppLocalizations.of(context).protein,
|
||||
today.protein,
|
||||
goals.protein,
|
||||
AppLocalizations.of(context).g,
|
||||
)),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.fiber, today.fiber),
|
||||
]),
|
||||
],
|
||||
);
|
||||
});
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.protein, today.protein),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
fmtMacro(
|
||||
AppLocalizations.of(context).carbohydrates,
|
||||
today.carbohydrates,
|
||||
goals.carbohydrates,
|
||||
AppLocalizations.of(context).g,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.carbohydrates, today.carbohydrates),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
fmtMacro(
|
||||
AppLocalizations.of(context).fat,
|
||||
today.fat,
|
||||
goals.fat,
|
||||
AppLocalizations.of(context).g,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.fat, today.fat),
|
||||
// optionally display the advanced macro goals:
|
||||
if (goals.fiber != null)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
fmtMacro(
|
||||
AppLocalizations.of(context).fiber,
|
||||
today.fiber,
|
||||
goals.fiber,
|
||||
AppLocalizations.of(context).g,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
_diyGauge(context, normWidth, goals.fiber, today.fiber),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,16 +231,19 @@ class FlNutritionalPlanPieChartState extends State<FlNutritionalPlanPieChartWidg
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
(AppLocalizations.of(context).protein, LIST_OF_COLORS3[1]),
|
||||
(AppLocalizations.of(context).carbohydrates, LIST_OF_COLORS3[0]),
|
||||
(AppLocalizations.of(context).fat, LIST_OF_COLORS3[2]),
|
||||
]
|
||||
.map((e) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Indicator(color: e.$2, text: e.$1, isSquare: true),
|
||||
))
|
||||
.toList(),
|
||||
children:
|
||||
[
|
||||
(AppLocalizations.of(context).protein, LIST_OF_COLORS3[1]),
|
||||
(AppLocalizations.of(context).carbohydrates, LIST_OF_COLORS3[0]),
|
||||
(AppLocalizations.of(context).fat, LIST_OF_COLORS3[2]),
|
||||
]
|
||||
.map(
|
||||
(e) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: Indicator(color: e.$2, text: e.$1, isSquare: true),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
const SizedBox(width: 28),
|
||||
],
|
||||
@@ -265,10 +272,8 @@ class FlNutritionalPlanPieChartState extends State<FlNutritionalPlanPieChartWidg
|
||||
|
||||
/// Shows results vs plan of common macros, for today and last 7 days, as barchart
|
||||
class NutritionalDiaryChartWidgetFl extends StatefulWidget {
|
||||
const NutritionalDiaryChartWidgetFl({
|
||||
super.key,
|
||||
required NutritionalPlan nutritionalPlan,
|
||||
}) : _nutritionalPlan = nutritionalPlan;
|
||||
const NutritionalDiaryChartWidgetFl({super.key, required NutritionalPlan nutritionalPlan})
|
||||
: _nutritionalPlan = nutritionalPlan;
|
||||
|
||||
final NutritionalPlan _nutritionalPlan;
|
||||
|
||||
@@ -315,12 +320,7 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
|
||||
|
||||
final [colorPlanned, colorLoggedToday, colorLogged7Day] = LIST_OF_COLORS3;
|
||||
|
||||
BarChartGroupData barchartGroup(
|
||||
int x,
|
||||
double barsSpace,
|
||||
double barsWidth,
|
||||
String prop,
|
||||
) {
|
||||
BarChartGroupData barchartGroup(int x, double barsSpace, double barsWidth, String prop) {
|
||||
final plan = planned.prop(prop);
|
||||
|
||||
BarChartRodData barChartRodData(double? plan, double val, Color color) {
|
||||
@@ -391,20 +391,14 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
|
||||
getTitlesWidget: leftTitles,
|
||||
),
|
||||
),
|
||||
topTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
rightTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
),
|
||||
gridData: FlGridData(
|
||||
show: true,
|
||||
checkToShowHorizontalLine: (value) => value % 10 == 0,
|
||||
getDrawingHorizontalLine: (value) => const FlLine(
|
||||
color: Colors.black,
|
||||
strokeWidth: 1,
|
||||
),
|
||||
getDrawingHorizontalLine: (value) =>
|
||||
const FlLine(color: Colors.black, strokeWidth: 1),
|
||||
drawVerticalLine: false,
|
||||
),
|
||||
borderData: FlBorderData(show: false),
|
||||
@@ -412,12 +406,7 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
|
||||
barGroups: [
|
||||
barchartGroup(0, barsSpace, barsWidth, 'protein'),
|
||||
barchartGroup(1, barsSpace, barsWidth, 'carbohydrates'),
|
||||
barchartGroup(
|
||||
2,
|
||||
barsSpace,
|
||||
barsWidth,
|
||||
'carbohydratesSugar',
|
||||
),
|
||||
barchartGroup(2, barsSpace, barsWidth, 'carbohydratesSugar'),
|
||||
barchartGroup(3, barsSpace, barsWidth, 'fat'),
|
||||
barchartGroup(4, barsSpace, barsWidth, 'fatSaturated'),
|
||||
if (widget._nutritionalPlan.nutritionalGoals.fiber != null)
|
||||
@@ -430,21 +419,17 @@ class NutritionalDiaryChartWidgetFlState extends State<NutritionalDiaryChartWidg
|
||||
padding: const EdgeInsets.only(bottom: 40, left: 25, right: 25),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
(AppLocalizations.of(context).deficit, colorPlanned),
|
||||
(AppLocalizations.of(context).surplus, COLOR_SURPLUS),
|
||||
(AppLocalizations.of(context).today, colorLoggedToday),
|
||||
(AppLocalizations.of(context).weekAverage, colorLogged7Day),
|
||||
]
|
||||
.map(
|
||||
(e) => Indicator(
|
||||
color: e.$2,
|
||||
text: e.$1,
|
||||
isSquare: true,
|
||||
marginRight: 0,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
children:
|
||||
[
|
||||
(AppLocalizations.of(context).deficit, colorPlanned),
|
||||
(AppLocalizations.of(context).surplus, COLOR_SURPLUS),
|
||||
(AppLocalizations.of(context).today, colorLoggedToday),
|
||||
(AppLocalizations.of(context).weekAverage, colorLogged7Day),
|
||||
]
|
||||
.map(
|
||||
(e) => Indicator(color: e.$2, text: e.$1, isSquare: true, marginRight: 0),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -460,8 +445,8 @@ class MealDiaryBarChartWidget extends StatefulWidget {
|
||||
super.key,
|
||||
required NutritionalValues logged,
|
||||
required NutritionalValues planned,
|
||||
}) : _logged = logged,
|
||||
_planned = planned;
|
||||
}) : _logged = logged,
|
||||
_planned = planned;
|
||||
|
||||
final NutritionalValues _logged;
|
||||
final NutritionalValues _planned;
|
||||
@@ -486,12 +471,12 @@ class MealDiaryBarChartWidgetState extends State<MealDiaryBarChartWidget> {
|
||||
}
|
||||
|
||||
Widget leftTitles(double value, TitleMeta meta) => SideTitleWidget(
|
||||
axisSide: meta.axisSide,
|
||||
child: Text(
|
||||
AppLocalizations.of(context).percentValue(value.toStringAsFixed(0)),
|
||||
style: const TextStyle(fontSize: 10),
|
||||
),
|
||||
);
|
||||
axisSide: meta.axisSide,
|
||||
child: Text(
|
||||
AppLocalizations.of(context).percentValue(value.toStringAsFixed(0)),
|
||||
style: const TextStyle(fontSize: 10),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -523,19 +508,13 @@ class MealDiaryBarChartWidgetState extends State<MealDiaryBarChartWidget> {
|
||||
getTitlesWidget: leftTitles,
|
||||
),
|
||||
),
|
||||
topTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
rightTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
),
|
||||
gridData: FlGridData(
|
||||
show: true,
|
||||
getDrawingHorizontalLine: (value) => const FlLine(
|
||||
color: Colors.black,
|
||||
strokeWidth: 1,
|
||||
),
|
||||
getDrawingHorizontalLine: (value) =>
|
||||
const FlLine(color: Colors.black, strokeWidth: 1),
|
||||
drawVerticalLine: false,
|
||||
),
|
||||
borderData: FlBorderData(show: false),
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/exceptions/http_exception.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/helpers/ui.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/models/nutrition/log.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
@@ -65,10 +65,7 @@ class MealForm extends StatelessWidget {
|
||||
FocusScope.of(context).requestFocus(FocusNode());
|
||||
|
||||
// Open time picker
|
||||
final pickedTime = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: _meal.time!,
|
||||
);
|
||||
final pickedTime = await showTimePicker(context: context, initialTime: _meal.time!);
|
||||
if (pickedTime != null) {
|
||||
_timeController.text = timeToString(pickedTime)!;
|
||||
}
|
||||
@@ -101,10 +98,7 @@ class MealForm extends StatelessWidget {
|
||||
context,
|
||||
listen: false,
|
||||
).addMeal(_meal, _planId)
|
||||
: Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).editMeal(_meal);
|
||||
: Provider.of<NutritionPlansProvider>(context, listen: false).editMeal(_meal);
|
||||
} on WgerHttpException catch (error) {
|
||||
showHttpExceptionErrorDialog(error, context);
|
||||
} catch (error) {
|
||||
@@ -120,12 +114,7 @@ class MealForm extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Widget MealItemForm(
|
||||
Meal meal,
|
||||
List<MealItem> recent, [
|
||||
String? barcode,
|
||||
bool? test,
|
||||
]) {
|
||||
Widget MealItemForm(Meal meal, List<MealItem> recent, [String? barcode, bool? test]) {
|
||||
return IngredientForm(
|
||||
// TODO we use planId 0 here cause we don't have one and we don't need it I think?
|
||||
recent: recent.map((e) => Log.fromMealItem(e, "0", e.mealId)).toList(),
|
||||
@@ -143,14 +132,13 @@ Widget IngredientLogForm(NutritionalPlan plan) {
|
||||
return IngredientForm(
|
||||
recent: plan.dedupDiaryEntries,
|
||||
onSave: (BuildContext context, MealItem mealItem, DateTime? dt) {
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.logIngredientToDiary(mealItem, plan.id!, dt);
|
||||
Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).logIngredientToDiary(mealItem, plan.id!, dt);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).ingredientLogged,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
content: Text(AppLocalizations.of(context).ingredientLogged, textAlign: TextAlign.center),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -241,8 +229,9 @@ class IngredientFormState extends State<IngredientForm> {
|
||||
Widget build(BuildContext context) {
|
||||
final String unit = AppLocalizations.of(context).g;
|
||||
final queryLower = _searchQuery.toLowerCase();
|
||||
final suggestions =
|
||||
widget.recent.where((e) => e.ingredient.name.toLowerCase().contains(queryLower)).toList();
|
||||
final suggestions = widget.recent
|
||||
.where((e) => e.ingredient.name.toLowerCase().contains(queryLower))
|
||||
.toList();
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(20),
|
||||
child: Form(
|
||||
@@ -263,9 +252,7 @@ class IngredientFormState extends State<IngredientForm> {
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
key: const Key('field-weight'), // needed ?
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).weight,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).weight),
|
||||
controller: _amountController,
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: (value) {
|
||||
@@ -361,10 +348,7 @@ class IngredientFormState extends State<IngredientForm> {
|
||||
context,
|
||||
listen: false,
|
||||
).fetchIngredient(_mealItem.ingredientId),
|
||||
builder: (
|
||||
BuildContext context,
|
||||
AsyncSnapshot<Ingredient> snapshot,
|
||||
) {
|
||||
builder: (BuildContext context, AsyncSnapshot<Ingredient> snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
_mealItem.ingredient = snapshot.data!;
|
||||
return MealItemValuesTile(
|
||||
@@ -403,13 +387,7 @@ class IngredientFormState extends State<IngredientForm> {
|
||||
try {
|
||||
var date = DateTime.parse(_dateController.text);
|
||||
final tod = stringToTime(_timeController.text);
|
||||
date = DateTime(
|
||||
date.year,
|
||||
date.month,
|
||||
date.day,
|
||||
tod.hour,
|
||||
tod.minute,
|
||||
);
|
||||
date = DateTime(date.year, date.month, date.day, tod.hour, tod.minute);
|
||||
widget.onSave(context, _mealItem, date);
|
||||
} on WgerHttpException catch (error) {
|
||||
showHttpExceptionErrorDialog(error, context);
|
||||
@@ -431,11 +409,7 @@ class IngredientFormState extends State<IngredientForm> {
|
||||
itemBuilder: (context, index) {
|
||||
void select() {
|
||||
final ingredient = suggestions[index].ingredient;
|
||||
selectIngredient(
|
||||
ingredient.id,
|
||||
ingredient.name,
|
||||
suggestions[index].amount,
|
||||
);
|
||||
selectIngredient(ingredient.id, ingredient.name, suggestions[index].amount);
|
||||
}
|
||||
|
||||
return Card(
|
||||
@@ -444,10 +418,12 @@ class IngredientFormState extends State<IngredientForm> {
|
||||
title: Text(
|
||||
'${suggestions[index].ingredient.name} (${suggestions[index].amount.toStringAsFixed(0)}$unit)',
|
||||
),
|
||||
subtitle: Text(getShortNutritionValues(
|
||||
suggestions[index].ingredient.nutritionalValues,
|
||||
context,
|
||||
)),
|
||||
subtitle: Text(
|
||||
getShortNutritionValues(
|
||||
suggestions[index].ingredient.nutritionalValues,
|
||||
context,
|
||||
),
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@@ -539,9 +515,7 @@ class _PlanFormState extends State<PlanForm> {
|
||||
// Description
|
||||
TextFormField(
|
||||
key: const Key('field-description'),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).description,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).description),
|
||||
controller: _descriptionController,
|
||||
onSaved: (newValue) {
|
||||
widget._plan.description = newValue!;
|
||||
@@ -569,12 +543,7 @@ class _PlanFormState extends State<PlanForm> {
|
||||
child: DropdownButtonFormField<GoalType>(
|
||||
value: _goalType,
|
||||
items: GoalType.values
|
||||
.map(
|
||||
(e) => DropdownMenuItem<GoalType>(
|
||||
value: e,
|
||||
child: Text(e.label),
|
||||
),
|
||||
)
|
||||
.map((e) => DropdownMenuItem<GoalType>(value: e, child: Text(e.label)))
|
||||
.toList(),
|
||||
onChanged: (GoalType? g) {
|
||||
setState(() {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
@@ -27,18 +27,18 @@ import 'package:wger/widgets/core/core.dart';
|
||||
import 'package:wger/widgets/nutrition/ingredient_dialogs.dart';
|
||||
|
||||
List<String> getNutritionColumnNames(BuildContext context) => [
|
||||
AppLocalizations.of(context).energy,
|
||||
AppLocalizations.of(context).protein,
|
||||
AppLocalizations.of(context).carbohydrates,
|
||||
AppLocalizations.of(context).fat,
|
||||
];
|
||||
AppLocalizations.of(context).energy,
|
||||
AppLocalizations.of(context).protein,
|
||||
AppLocalizations.of(context).carbohydrates,
|
||||
AppLocalizations.of(context).fat,
|
||||
];
|
||||
|
||||
List<String> getNutritionalValues(NutritionalValues values, BuildContext context) => [
|
||||
AppLocalizations.of(context).kcalValue(values.energy.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.protein.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.carbohydrates.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.fat.toStringAsFixed(0)),
|
||||
];
|
||||
AppLocalizations.of(context).kcalValue(values.energy.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.protein.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.carbohydrates.toStringAsFixed(0)),
|
||||
AppLocalizations.of(context).gValue(values.fat.toStringAsFixed(0)),
|
||||
];
|
||||
|
||||
List<int> getNutritionColumnFlexes(BuildContext context) {
|
||||
return getNutritionColumnNames(context).map((e) {
|
||||
@@ -51,11 +51,7 @@ List<int> getNutritionColumnFlexes(BuildContext context) {
|
||||
}
|
||||
|
||||
List<Widget> muted(List<String> children) => children
|
||||
.map((e) => MutedText(
|
||||
e,
|
||||
textAlign: TextAlign.right,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
))
|
||||
.map((e) => MutedText(e, textAlign: TextAlign.right, overflow: TextOverflow.ellipsis))
|
||||
.toList();
|
||||
|
||||
// return a row of elements in the standard macros spacing
|
||||
@@ -85,15 +81,17 @@ String getShortNutritionValues(NutritionalValues values, BuildContext context) {
|
||||
}
|
||||
|
||||
String getKcalConsumed(Meal meal, BuildContext context) {
|
||||
final consumed =
|
||||
meal.diaryEntriesToday.map((e) => e.nutritionalValues.energy).fold(0.0, (a, b) => a + b);
|
||||
final consumed = meal.diaryEntriesToday
|
||||
.map((e) => e.nutritionalValues.energy)
|
||||
.fold(0.0, (a, b) => a + b);
|
||||
return AppLocalizations.of(context).kcalValue(consumed.toStringAsFixed(0));
|
||||
}
|
||||
|
||||
String getKcalConsumedVsPlanned(Meal meal, BuildContext context) {
|
||||
final planned = meal.plannedNutritionalValues.energy;
|
||||
final consumed =
|
||||
meal.diaryEntriesToday.map((e) => e.nutritionalValues.energy).fold(0.0, (a, b) => a + b);
|
||||
final consumed = meal.diaryEntriesToday
|
||||
.map((e) => e.nutritionalValues.energy)
|
||||
.fold(0.0, (a, b) => a + b);
|
||||
final loc = AppLocalizations.of(context);
|
||||
|
||||
return '${consumed.toStringAsFixed(0)} / ${planned.toStringAsFixed(0)} ${loc.kcal}';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/helpers/misc.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_goals.dart';
|
||||
import 'package:wger/widgets/nutrition/macro_nutrients_table.dart';
|
||||
@@ -143,15 +143,14 @@ class IngredientScanResultDialog extends StatelessWidget {
|
||||
if (snapshot.connectionState == ConnectionState.done && ingredient == null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
AppLocalizations.of(context).productNotFoundDescription(barcode),
|
||||
),
|
||||
child: Text(AppLocalizations.of(context).productNotFoundDescription(barcode)),
|
||||
),
|
||||
if (ingredient != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child:
|
||||
Text(AppLocalizations.of(context).productFoundDescription(ingredient.name)),
|
||||
child: Text(
|
||||
AppLocalizations.of(context).productFoundDescription(ingredient.name),
|
||||
),
|
||||
),
|
||||
if (ingredient?.image?.image != null)
|
||||
ingredientImage(ingredient!.image!.image, context),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_goals.dart';
|
||||
|
||||
class MacronutrientsTable extends StatelessWidget {
|
||||
@@ -22,13 +22,13 @@ class MacronutrientsTable extends StatelessWidget {
|
||||
final loc = AppLocalizations.of(context);
|
||||
|
||||
Widget columnHeader(bool left, String title) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: tablePadding),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
textAlign: left ? TextAlign.left : TextAlign.right,
|
||||
),
|
||||
);
|
||||
padding: const EdgeInsets.symmetric(vertical: tablePadding),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
textAlign: left ? TextAlign.left : TextAlign.right,
|
||||
),
|
||||
);
|
||||
|
||||
TableRow macroRow(int indent, bool g, String title, double? Function(NutritionalGoals ng) get) {
|
||||
final goal = get(nutritionalGoals);
|
||||
@@ -53,10 +53,7 @@ class MacronutrientsTable extends StatelessWidget {
|
||||
return Table(
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
border: TableBorder(
|
||||
horizontalInside: BorderSide(
|
||||
width: 1,
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
horizontalInside: BorderSide(width: 1, color: Theme.of(context).colorScheme.outline),
|
||||
),
|
||||
columnWidths: const {0: FractionColumnWidth(0.4)},
|
||||
children: [
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_svg_icons/flutter_svg_icons.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/models/nutrition/meal_item.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
@@ -36,7 +36,7 @@ import 'package:wger/widgets/nutrition/widgets.dart';
|
||||
enum viewMode {
|
||||
base, // just highlevel meal info (name, time)
|
||||
withIngredients, // + ingredients
|
||||
withAllDetails // + nutritional breakdown of ingredients, + logged today
|
||||
withAllDetails, // + nutritional breakdown of ingredients, + logged today
|
||||
}
|
||||
|
||||
class MealWidget extends StatefulWidget {
|
||||
@@ -45,12 +45,7 @@ class MealWidget extends StatefulWidget {
|
||||
final bool popTwice;
|
||||
final bool readOnly;
|
||||
|
||||
const MealWidget(
|
||||
this._meal,
|
||||
this._recentMealItems,
|
||||
this.popTwice,
|
||||
this.readOnly,
|
||||
);
|
||||
const MealWidget(this._meal, this._recentMealItems, this.popTwice, this.readOnly);
|
||||
|
||||
@override
|
||||
_MealWidgetState createState() => _MealWidgetState();
|
||||
@@ -173,8 +168,9 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
),
|
||||
)
|
||||
else
|
||||
...widget._meal.mealItems
|
||||
.map((item) => MealItemEditableFullTile(item, _viewMode, _editing)),
|
||||
...widget._meal.mealItems.map(
|
||||
(item) => MealItemEditableFullTile(item, _viewMode, _editing),
|
||||
),
|
||||
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
|
||||
const Divider(),
|
||||
if (_viewMode == viewMode.withIngredients || _viewMode == viewMode.withAllDetails)
|
||||
@@ -201,12 +197,12 @@ class _MealWidgetState extends State<MealWidget> {
|
||||
planned: widget._meal.plannedNutritionalValues,
|
||||
logged: widget._meal.loggedNutritionalValuesToday,
|
||||
),
|
||||
...widget._meal.diaryEntriesToday.map((item) => Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: [DiaryEntryTile(diaryEntry: item)],
|
||||
),
|
||||
)),
|
||||
...widget._meal.diaryEntriesToday.map(
|
||||
(item) => Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(children: [DiaryEntryTile(diaryEntry: item)]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -293,11 +289,11 @@ class MealHeader extends StatelessWidget {
|
||||
required viewMode viewMode,
|
||||
required Function() toggleEditing,
|
||||
required Function() toggleViewMode,
|
||||
}) : _meal = meal,
|
||||
_editing = editing,
|
||||
_viewMode = viewMode,
|
||||
_toggleViewMode = toggleViewMode,
|
||||
_toggleEditing = toggleEditing;
|
||||
}) : _meal = meal,
|
||||
_editing = editing,
|
||||
_viewMode = viewMode,
|
||||
_toggleViewMode = toggleViewMode,
|
||||
_toggleEditing = toggleEditing;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -306,35 +302,34 @@ class MealHeader extends StatelessWidget {
|
||||
children: [
|
||||
ListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
title: Row(children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
_meal.name,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
if (_meal.time != null)
|
||||
title: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(_meal.name, style: Theme.of(context).textTheme.titleLarge),
|
||||
Row(
|
||||
children: [
|
||||
if (_meal.time != null)
|
||||
Text(
|
||||
_meal.time!.format(context),
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
if (_meal.time != null) const SizedBox(width: 12),
|
||||
Text(
|
||||
_meal.time!.format(context),
|
||||
_meal.isRealMeal
|
||||
? getKcalConsumedVsPlanned(_meal, context)
|
||||
: getKcalConsumed(_meal, context),
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
if (_meal.time != null) const SizedBox(width: 12),
|
||||
Text(
|
||||
_meal.isRealMeal
|
||||
? getKcalConsumedVsPlanned(_meal, context)
|
||||
: getKcalConsumed(_meal, context),
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
],
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/models/nutrition/log.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
@@ -18,11 +18,7 @@ class MealItemValuesTile extends StatelessWidget {
|
||||
final Ingredient ingredient;
|
||||
final NutritionalValues nutritionalValues;
|
||||
|
||||
const MealItemValuesTile({
|
||||
super.key,
|
||||
required this.ingredient,
|
||||
required this.nutritionalValues,
|
||||
});
|
||||
const MealItemValuesTile({super.key, required this.ingredient, required this.nutritionalValues});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -53,11 +49,7 @@ class DiaryheaderTile extends StatelessWidget {
|
||||
|
||||
/// a NutritionTitle showing diary entries
|
||||
class DiaryEntryTile extends StatelessWidget {
|
||||
const DiaryEntryTile({
|
||||
super.key,
|
||||
required this.diaryEntry,
|
||||
this.nutritionalPlan,
|
||||
});
|
||||
const DiaryEntryTile({super.key, required this.diaryEntry, this.nutritionalPlan});
|
||||
|
||||
final Log diaryEntry;
|
||||
final NutritionalPlan? nutritionalPlan;
|
||||
@@ -82,8 +74,10 @@ class DiaryEntryTile extends StatelessWidget {
|
||||
: IconButton(
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
onPressed: () {
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.deleteLog(diaryEntry.id!, nutritionalPlan!.id!);
|
||||
Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).deleteLog(diaryEntry.id!, nutritionalPlan!.id!);
|
||||
},
|
||||
icon: const Icon(Icons.delete_outline),
|
||||
iconSize: ICON_SIZE_SMALL,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
import 'package:wger/widgets/nutrition/charts.dart';
|
||||
@@ -61,20 +61,14 @@ class NutritionalDiaryDetailWidget extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const DiaryheaderTile(),
|
||||
...logs.map(
|
||||
(e) => DiaryEntryTile(diaryEntry: e, nutritionalPlan: _nutritionalPlan),
|
||||
),
|
||||
...logs.map((e) => DiaryEntryTile(diaryEntry: e, nutritionalPlan: _nutritionalPlan)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NutritionDiaryTable extends StatelessWidget {
|
||||
const NutritionDiaryTable({
|
||||
super.key,
|
||||
required this.planned,
|
||||
required this.logged,
|
||||
});
|
||||
const NutritionDiaryTable({super.key, required this.planned, required this.logged});
|
||||
|
||||
static const double tablePadding = 7;
|
||||
final NutritionalValues planned;
|
||||
@@ -85,13 +79,13 @@ class NutritionDiaryTable extends StatelessWidget {
|
||||
final loc = AppLocalizations.of(context);
|
||||
|
||||
Widget columnHeader(bool left, String title) => Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: tablePadding),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
textAlign: left ? TextAlign.left : TextAlign.right,
|
||||
),
|
||||
);
|
||||
padding: const EdgeInsets.symmetric(vertical: tablePadding),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
textAlign: left ? TextAlign.left : TextAlign.right,
|
||||
),
|
||||
);
|
||||
|
||||
TableRow macroRow(int indent, bool g, String title, double Function(NutritionalValues nv) get) {
|
||||
final valFn = g ? loc.gValue : loc.kcalValue;
|
||||
@@ -115,12 +109,14 @@ class NutritionDiaryTable extends StatelessWidget {
|
||||
),
|
||||
columnWidths: const {0: FractionColumnWidth(0.4)},
|
||||
children: [
|
||||
TableRow(children: [
|
||||
columnHeader(true, loc.macronutrients),
|
||||
columnHeader(false, loc.planned),
|
||||
columnHeader(false, loc.logged),
|
||||
columnHeader(false, loc.difference),
|
||||
]),
|
||||
TableRow(
|
||||
children: [
|
||||
columnHeader(true, loc.macronutrients),
|
||||
columnHeader(false, loc.planned),
|
||||
columnHeader(false, loc.logged),
|
||||
columnHeader(false, loc.difference),
|
||||
],
|
||||
),
|
||||
macroRow(0, false, loc.energy, (NutritionalValues nv) => nv.energy),
|
||||
macroRow(0, true, loc.protein, (NutritionalValues nv) => nv.protein),
|
||||
macroRow(0, true, loc.carbohydrates, (NutritionalValues nv) => nv.carbohydrates),
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:wger/helpers/colors.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_goals.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_values.dart';
|
||||
import 'package:wger/screens/nutritional_diary_screen.dart';
|
||||
|
||||
class NutritionalDiaryTable extends StatelessWidget {
|
||||
const NutritionalDiaryTable({
|
||||
super.key,
|
||||
required NutritionalPlan nutritionalPlan,
|
||||
}) : plan = nutritionalPlan;
|
||||
const NutritionalDiaryTable({super.key, required NutritionalPlan nutritionalPlan})
|
||||
: plan = nutritionalPlan;
|
||||
|
||||
final NutritionalPlan plan;
|
||||
|
||||
@@ -82,46 +80,49 @@ class NutritionalDiaryTable extends StatelessWidget {
|
||||
decoration: BoxDecoration(
|
||||
border: Border(top: BorderSide(color: Colors.grey[300]!)),
|
||||
),
|
||||
children: [
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(color: LIST_OF_COLORS3.first),
|
||||
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.energy.toStringAsFixed(0),
|
||||
),
|
||||
if (goals.energy != null)
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
(values.energy - goals.energy!).toStringAsFixed(0),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.protein.toStringAsFixed(0),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.carbohydrates.toStringAsFixed(0),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.fat.toStringAsFixed(0),
|
||||
),
|
||||
].map((element) {
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
NutritionalDiaryScreen.routeName,
|
||||
arguments: NutritionalDiaryArguments(plan.id!, date),
|
||||
),
|
||||
child: element,
|
||||
);
|
||||
}).toList(),
|
||||
children:
|
||||
[
|
||||
Text(
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleMedium?.copyWith(color: LIST_OF_COLORS3.first),
|
||||
DateFormat.Md(Localizations.localeOf(context).languageCode).format(date),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.energy.toStringAsFixed(0),
|
||||
),
|
||||
if (goals.energy != null)
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
(values.energy - goals.energy!).toStringAsFixed(0),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.protein.toStringAsFixed(0),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.carbohydrates.toStringAsFixed(0),
|
||||
),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.end,
|
||||
values.fat.toStringAsFixed(0),
|
||||
),
|
||||
].map((element) {
|
||||
return GestureDetector(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
NutritionalDiaryScreen.routeName,
|
||||
arguments: NutritionalDiaryArguments(plan.id!, date),
|
||||
),
|
||||
child: element,
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/widgets/nutrition/charts.dart';
|
||||
@@ -34,86 +34,78 @@ class NutritionalPlanDetailWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final nutritionalGoals = _nutritionalPlan.nutritionalGoals;
|
||||
final lastWeightEntry =
|
||||
Provider.of<BodyWeightProvider>(context, listen: false).getNewestEntry();
|
||||
final nutritionalGoalsGperKg =
|
||||
lastWeightEntry != null ? nutritionalGoals / lastWeightEntry.weight.toDouble() : null;
|
||||
final lastWeightEntry = Provider.of<BodyWeightProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).getNewestEntry();
|
||||
final nutritionalGoalsGperKg = lastWeightEntry != null
|
||||
? nutritionalGoals / lastWeightEntry.weight.toDouble()
|
||||
: null;
|
||||
|
||||
return SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: FlNutritionalPlanGoalWidget(
|
||||
nutritionalPlan: _nutritionalPlan,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
..._nutritionalPlan.meals.map((meal) => MealWidget(
|
||||
meal,
|
||||
_nutritionalPlan.dedupMealItems,
|
||||
false,
|
||||
false,
|
||||
)),
|
||||
MealWidget(
|
||||
_nutritionalPlan.pseudoMealOthers('Other logs'),
|
||||
_nutritionalPlan.dedupMealItems,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
if (nutritionalGoals.isComplete())
|
||||
Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
height: 220,
|
||||
child: FlNutritionalPlanPieChartWidget(nutritionalGoals.toValues()),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: MacronutrientsTable(
|
||||
nutritionalGoals: nutritionalGoals,
|
||||
plannedValuesPercentage: nutritionalGoals.energyPercentage(),
|
||||
nutritionalGoalsGperKg: nutritionalGoalsGperKg,
|
||||
),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
Text(
|
||||
AppLocalizations.of(context).logged,
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
delegate: SliverChildListDelegate([
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: FlNutritionalPlanGoalWidget(nutritionalPlan: _nutritionalPlan),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
..._nutritionalPlan.meals.map(
|
||||
(meal) => MealWidget(meal, _nutritionalPlan.dedupMealItems, false, false),
|
||||
),
|
||||
MealWidget(
|
||||
_nutritionalPlan.pseudoMealOthers('Other logs'),
|
||||
_nutritionalPlan.dedupMealItems,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
if (nutritionalGoals.isComplete())
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 16, left: 8, right: 8),
|
||||
height: 300,
|
||||
child: NutritionalDiaryChartWidgetFl(
|
||||
nutritionalPlan: _nutritionalPlan,
|
||||
padding: const EdgeInsets.all(15),
|
||||
height: 220,
|
||||
child: FlNutritionalPlanPieChartWidget(nutritionalGoals.toValues()),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: MacronutrientsTable(
|
||||
nutritionalGoals: nutritionalGoals,
|
||||
plannedValuesPercentage: nutritionalGoals.energyPercentage(),
|
||||
nutritionalGoalsGperKg: nutritionalGoalsGperKg,
|
||||
),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(8.0)),
|
||||
Text(
|
||||
AppLocalizations.of(context).logged,
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 16, left: 8, right: 8),
|
||||
height: 300,
|
||||
child: NutritionalDiaryChartWidgetFl(nutritionalPlan: _nutritionalPlan),
|
||||
),
|
||||
if (_nutritionalPlan.logEntriesValues.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15, left: 15, right: 15),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
AppLocalizations.of(context).nutritionalDiary,
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
SizedBox(
|
||||
height: 200,
|
||||
child: SingleChildScrollView(
|
||||
child: NutritionalDiaryTable(nutritionalPlan: _nutritionalPlan),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_nutritionalPlan.logEntriesValues.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15, left: 15, right: 15),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
AppLocalizations.of(context).nutritionalDiary,
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
SizedBox(
|
||||
height: 200,
|
||||
child: SingleChildScrollView(
|
||||
child: NutritionalDiaryTable(
|
||||
nutritionalPlan: _nutritionalPlan,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/screens/nutritional_plan_screen.dart';
|
||||
@@ -39,8 +39,10 @@ class _NutritionalPlansListState extends State<NutritionalPlansList> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final stream =
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false).watchNutritionPlans();
|
||||
final stream = Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).watchNutritionPlans();
|
||||
_subscription = stream.listen((plans) {
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
@@ -71,10 +73,9 @@ class _NutritionalPlansListState extends State<NutritionalPlansList> {
|
||||
return Card(
|
||||
child: ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
NutritionalPlanScreen.routeName,
|
||||
arguments: currentPlan.id,
|
||||
);
|
||||
Navigator.of(
|
||||
context,
|
||||
).pushNamed(NutritionalPlanScreen.routeName, arguments: currentPlan.id);
|
||||
},
|
||||
title: Text(currentPlan.getLabel(context)),
|
||||
subtitle: Text(
|
||||
@@ -82,53 +83,56 @@ class _NutritionalPlansListState extends State<NutritionalPlansList> {
|
||||
Localizations.localeOf(context).languageCode,
|
||||
).format(currentPlan.creationDate),
|
||||
),
|
||||
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
const VerticalDivider(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
onPressed: () async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext contextDialog) {
|
||||
return AlertDialog(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).confirmDelete(currentPlan.description),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
MaterialLocalizations.of(context).cancelButtonLabel,
|
||||
),
|
||||
onPressed: () => Navigator.of(contextDialog).pop(),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const VerticalDivider(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
onPressed: () async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext contextDialog) {
|
||||
return AlertDialog(
|
||||
content: Text(
|
||||
AppLocalizations.of(
|
||||
context,
|
||||
).confirmDelete(currentPlan.description),
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).delete,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
MaterialLocalizations.of(context).cancelButtonLabel,
|
||||
),
|
||||
onPressed: () => Navigator.of(contextDialog).pop(),
|
||||
),
|
||||
onPressed: () {
|
||||
provider.deletePlan(currentPlan.id!);
|
||||
Navigator.of(contextDialog).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).successfullyDeleted,
|
||||
textAlign: TextAlign.center,
|
||||
TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).delete,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||
),
|
||||
onPressed: () {
|
||||
provider.deletePlan(currentPlan.id!);
|
||||
Navigator.of(contextDialog).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).successfullyDeleted,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
]),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart'; //import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:flutter_zxing/flutter_zxing.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
@@ -27,6 +26,7 @@ import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/misc.dart';
|
||||
import 'package:wger/helpers/platform.dart';
|
||||
import 'package:wger/helpers/ui.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/ingredient_api.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
@@ -38,19 +38,19 @@ class ScanReader extends StatelessWidget {
|
||||
const ScanReader();
|
||||
@override
|
||||
Widget build(BuildContext context) => Scaffold(
|
||||
body: ReaderWidget(
|
||||
onScan: (result) {
|
||||
// notes:
|
||||
// 1. even if result.isValid, result.error is always non-null (and set to "")
|
||||
// 2. i've never encountered scan errors to see when they occur, and
|
||||
// i wouldn't know what to do about them anyway, so we simply return
|
||||
// result.text in such case (which presumably will be null, or "")
|
||||
// 3. when user cancels (swipe left / back button) this code is no longer
|
||||
// run and the caller receives null
|
||||
Navigator.pop(context, result.text);
|
||||
},
|
||||
),
|
||||
);
|
||||
body: ReaderWidget(
|
||||
onScan: (result) {
|
||||
// notes:
|
||||
// 1. even if result.isValid, result.error is always non-null (and set to "")
|
||||
// 2. i've never encountered scan errors to see when they occur, and
|
||||
// i wouldn't know what to do about them anyway, so we simply return
|
||||
// result.text in such case (which presumably will be null, or "")
|
||||
// 3. when user cancels (swipe left / back button) this code is no longer
|
||||
// run and the caller receives null
|
||||
Navigator.pop(context, result.text);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class IngredientTypeahead extends StatefulWidget {
|
||||
@@ -92,8 +92,9 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
|
||||
|
||||
Future<String> readerscan(BuildContext context) async {
|
||||
try {
|
||||
final code = await Navigator.of(context)
|
||||
.push<String?>(MaterialPageRoute(builder: (context) => const ScanReader()));
|
||||
final code = await Navigator.of(
|
||||
context,
|
||||
).push<String?>(MaterialPageRoute(builder: (context) => const ScanReader()));
|
||||
if (code == null) {
|
||||
return '';
|
||||
}
|
||||
@@ -152,12 +153,8 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
|
||||
final url = context.read<NutritionPlansProvider>().baseProvider.auth.serverUrl;
|
||||
return ListTile(
|
||||
leading: suggestion.data.image != null
|
||||
? CircleAvatar(
|
||||
backgroundImage: NetworkImage(url! + suggestion.data.image!),
|
||||
)
|
||||
: const CircleIconAvatar(
|
||||
Icon(Icons.image, color: Colors.grey),
|
||||
),
|
||||
? CircleAvatar(backgroundImage: NetworkImage(url! + suggestion.data.image!))
|
||||
: const CircleIconAvatar(Icon(Icons.image, color: Colors.grey)),
|
||||
title: Text(suggestion.value),
|
||||
// subtitle: Text(suggestion.data.id.toString()),
|
||||
trailing: IconButton(
|
||||
@@ -217,8 +214,10 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => FutureBuilder<Ingredient?>(
|
||||
future: Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.searchIngredientWithCode(barcode),
|
||||
future: Provider.of<NutritionPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).searchIngredientWithCode(barcode),
|
||||
builder: (BuildContext context, AsyncSnapshot<Ingredient?> snapshot) {
|
||||
return IngredientScanResultDialog(snapshot, barcode, widget.selectIngredient);
|
||||
},
|
||||
@@ -238,9 +237,7 @@ class IngredientAvatar extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return ingredient.image != null
|
||||
? GestureDetector(
|
||||
child: CircleAvatar(
|
||||
backgroundImage: NetworkImage(ingredient.image!.image),
|
||||
),
|
||||
child: CircleAvatar(backgroundImage: NetworkImage(ingredient.image!.image)),
|
||||
onTap: () async {
|
||||
if (ingredient.image!.objectUrl != '') {
|
||||
return launchURL(ingredient.image!.objectUrl, context);
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/user/profile.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
@@ -132,9 +132,7 @@ class _UserProfileFormState extends State<UserProfileForm> {
|
||||
context.read<UserProvider>().saveProfile();
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context).successfullySaved),
|
||||
),
|
||||
SnackBar(content: Text(AppLocalizations.of(context).successfullySaved)),
|
||||
);
|
||||
},
|
||||
child: Text(AppLocalizations.of(context).save),
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/exceptions/http_exception.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/helpers/ui.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/body_weight/weight_entry.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
|
||||
@@ -52,10 +52,7 @@ class WeightForm extends StatelessWidget {
|
||||
// Stop keyboard from appearing
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).date,
|
||||
suffixIcon: const Icon(
|
||||
Icons.calendar_today,
|
||||
key: Key('calendarIcon'),
|
||||
),
|
||||
suffixIcon: const Icon(Icons.calendar_today, key: Key('calendarIcon')),
|
||||
),
|
||||
enableInteractiveSelection: false,
|
||||
controller: dateController,
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
@@ -38,8 +38,9 @@ class WeightOverview extends StatelessWidget {
|
||||
final weightProvider = Provider.of<BodyWeightProvider>(context, listen: false);
|
||||
final plan = Provider.of<NutritionPlansProvider>(context, listen: false).currentPlan;
|
||||
|
||||
final entriesAll =
|
||||
weightProvider.items.map((e) => MeasurementChartEntry(e.weight, e.date)).toList();
|
||||
final entriesAll = weightProvider.items
|
||||
.map((e) => MeasurementChartEntry(e.weight, e.date))
|
||||
.toList();
|
||||
final entries7dAvg = moving7dAverage(entriesAll);
|
||||
|
||||
final unit = weightUnit(profile!.isMetric, context);
|
||||
@@ -55,10 +56,7 @@ class WeightOverview extends StatelessWidget {
|
||||
context,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pushNamed(
|
||||
context,
|
||||
MeasurementCategoriesScreen.routeName,
|
||||
),
|
||||
onPressed: () => Navigator.pushNamed(context, MeasurementCategoriesScreen.routeName),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
|
||||
@@ -17,14 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/screens/add_exercise_screen.dart';
|
||||
import 'package:wger/screens/exercises_screen.dart';
|
||||
|
||||
enum _WorkoutAppBarOptions {
|
||||
list,
|
||||
contribute,
|
||||
}
|
||||
enum _WorkoutAppBarOptions { list, contribute }
|
||||
|
||||
class WorkoutOverviewAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
const WorkoutOverviewAppBar();
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:wger/helpers/charts.dart';
|
||||
import 'package:wger/helpers/colors.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
|
||||
class LogChartWidgetFl extends StatefulWidget {
|
||||
final Map _data;
|
||||
@@ -79,12 +79,8 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
|
||||
),
|
||||
titlesData: FlTitlesData(
|
||||
show: true,
|
||||
rightTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
topTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
@@ -116,10 +112,7 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
|
||||
),
|
||||
),
|
||||
),
|
||||
borderData: FlBorderData(
|
||||
show: true,
|
||||
border: Border.all(color: const Color(0xff37434d)),
|
||||
),
|
||||
borderData: FlBorderData(show: true, border: Border.all(color: const Color(0xff37434d))),
|
||||
lineBarsData: [
|
||||
...widget._data['chart_data'].map((e) {
|
||||
colors.moveNext();
|
||||
@@ -138,11 +131,8 @@ class _LogChartWidgetFlState extends State<LogChartWidgetFl> {
|
||||
isStrokeCapRound: true,
|
||||
dotData: FlDotData(
|
||||
show: true,
|
||||
getDotPainter: (p0, p1, p2, p3) => FlDotCirclePainter(
|
||||
radius: 2,
|
||||
color: Colors.black,
|
||||
strokeWidth: 0,
|
||||
),
|
||||
getDotPainter: (p0, p1, p2, p3) =>
|
||||
FlDotCirclePainter(radius: 2, color: Colors.black, strokeWidth: 0),
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/day.dart';
|
||||
import 'package:wger/models/workouts/set.dart';
|
||||
import 'package:wger/models/workouts/setting.dart';
|
||||
@@ -57,15 +57,15 @@ class SettingWidget extends StatelessWidget {
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(setting.exerciseObj
|
||||
.getExercise(Localizations.localeOf(context).languageCode)
|
||||
.name),
|
||||
title: Text(
|
||||
setting.exerciseObj
|
||||
.getExercise(Localizations.localeOf(context).languageCode)
|
||||
.name,
|
||||
),
|
||||
content: ExerciseDetail(setting.exerciseObj),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
MaterialLocalizations.of(context).closeButtonLabel,
|
||||
),
|
||||
child: Text(MaterialLocalizations.of(context).closeButtonLabel),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
@@ -81,9 +81,7 @@ class SettingWidget extends StatelessWidget {
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
...set.getSmartRepr(setting.exerciseObj).map((e) => Text(e)),
|
||||
],
|
||||
children: [...set.getSmartRepr(setting.exerciseObj).map((e) => Text(e))],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -149,10 +147,7 @@ class _WorkoutDayWidgetState extends State<WorkoutDayWidget> {
|
||||
if (_editing)
|
||||
ReorderableDragStartListener(
|
||||
index: index,
|
||||
child: const IconButton(
|
||||
icon: Icon(Icons.drag_handle),
|
||||
onPressed: null,
|
||||
),
|
||||
child: const IconButton(icon: Icon(Icons.drag_handle), onPressed: null),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -167,11 +162,7 @@ class _WorkoutDayWidgetState extends State<WorkoutDayWidget> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DayHeader(
|
||||
day: widget._day,
|
||||
expanded: _editing,
|
||||
toggle: _toggleExpanded,
|
||||
),
|
||||
DayHeader(day: widget._day, expanded: _editing, toggle: _toggleExpanded),
|
||||
if (_editing)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
@@ -265,13 +256,10 @@ class DayHeader extends StatelessWidget {
|
||||
final bool _editing;
|
||||
final Function _toggle;
|
||||
|
||||
const DayHeader({
|
||||
required Day day,
|
||||
required bool expanded,
|
||||
required Function toggle,
|
||||
}) : _day = day,
|
||||
_editing = expanded,
|
||||
_toggle = toggle;
|
||||
const DayHeader({required Day day, required bool expanded, required Function toggle})
|
||||
: _day = day,
|
||||
_editing = expanded,
|
||||
_toggle = toggle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -285,22 +273,24 @@ class DayHeader extends StatelessWidget {
|
||||
subtitle: Text(_day.getDaysTextTranslated(Localizations.localeOf(context).languageCode)),
|
||||
leading: const Icon(Icons.play_arrow),
|
||||
minLeadingWidth: 8,
|
||||
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
const SizedBox(height: 40, width: 1, child: VerticalDivider()),
|
||||
const SizedBox(width: 10),
|
||||
IconButton(
|
||||
icon: _editing ? const Icon(Icons.done) : const Icon(Icons.edit),
|
||||
tooltip: _editing ? AppLocalizations.of(context).done : AppLocalizations.of(context).edit,
|
||||
onPressed: () {
|
||||
_toggle();
|
||||
},
|
||||
),
|
||||
]),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(height: 40, width: 1, child: VerticalDivider()),
|
||||
const SizedBox(width: 10),
|
||||
IconButton(
|
||||
icon: _editing ? const Icon(Icons.done) : const Icon(Icons.edit),
|
||||
tooltip: _editing
|
||||
? AppLocalizations.of(context).done
|
||||
: AppLocalizations.of(context).edit,
|
||||
onPressed: () {
|
||||
_toggle();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
GymModeScreen.routeName,
|
||||
arguments: _day,
|
||||
);
|
||||
Navigator.of(context).pushNamed(GymModeScreen.routeName, arguments: _day);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/exercise.dart';
|
||||
import 'package:wger/models/workouts/day.dart';
|
||||
import 'package:wger/models/workouts/repetition_unit.dart';
|
||||
@@ -72,9 +72,7 @@ class WorkoutForm extends StatelessWidget {
|
||||
),
|
||||
TextFormField(
|
||||
key: const Key('field-description'),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).description,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).description),
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
controller: workoutDescriptionController,
|
||||
@@ -113,10 +111,9 @@ class WorkoutForm extends StatelessWidget {
|
||||
listen: false,
|
||||
).addWorkout(_plan);
|
||||
if (context.mounted) {
|
||||
Navigator.of(context).pushReplacementNamed(
|
||||
WorkoutPlanScreen.routeName,
|
||||
arguments: newPlan,
|
||||
);
|
||||
Navigator.of(
|
||||
context,
|
||||
).pushReplacementNamed(WorkoutPlanScreen.routeName, arguments: newPlan);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -142,10 +139,9 @@ class _DayCheckboxState extends State<DayCheckbox> {
|
||||
Widget build(BuildContext context) {
|
||||
return CheckboxListTile(
|
||||
key: Key('field-checkbox-${widget._dayNr}'),
|
||||
title: Text(widget._day.getDayTranslated(
|
||||
widget._dayNr,
|
||||
Localizations.localeOf(context).languageCode,
|
||||
)),
|
||||
title: Text(
|
||||
widget._day.getDayTranslated(widget._dayNr, Localizations.localeOf(context).languageCode),
|
||||
),
|
||||
value: widget._day.daysOfWeek.contains(widget._dayNr),
|
||||
onChanged: (bool? newValue) {
|
||||
setState(() {
|
||||
@@ -223,14 +219,12 @@ class _DayFormWidgetState extends State<DayFormWidget> {
|
||||
|
||||
try {
|
||||
if (widget._day.id == null) {
|
||||
Provider.of<WorkoutPlansProvider>(context, listen: false).addDay(
|
||||
widget._day,
|
||||
widget.workout,
|
||||
);
|
||||
Provider.of<WorkoutPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).addDay(widget._day, widget.workout);
|
||||
} else {
|
||||
Provider.of<WorkoutPlansProvider>(context, listen: false).editDay(
|
||||
widget._day,
|
||||
);
|
||||
Provider.of<WorkoutPlansProvider>(context, listen: false).editDay(widget._day);
|
||||
}
|
||||
|
||||
widget.dayController.clear();
|
||||
@@ -442,22 +436,16 @@ class _SetFormWidgetState extends State<SetFormWidget> {
|
||||
return null;
|
||||
}
|
||||
return context.read<ExercisesProvider>().searchExercise(
|
||||
pattern,
|
||||
languageCode: Localizations.localeOf(context).languageCode,
|
||||
searchEnglish: _searchEnglish,
|
||||
);
|
||||
pattern,
|
||||
languageCode: Localizations.localeOf(context).languageCode,
|
||||
searchEnglish: _searchEnglish,
|
||||
);
|
||||
},
|
||||
itemBuilder: (
|
||||
BuildContext context,
|
||||
Exercise exerciseSuggestion,
|
||||
) =>
|
||||
ListTile(
|
||||
itemBuilder: (BuildContext context, Exercise exerciseSuggestion) => ListTile(
|
||||
key: Key('exercise-${exerciseSuggestion.id}'),
|
||||
leading: SizedBox(
|
||||
width: 45,
|
||||
child: ExerciseImageWidget(
|
||||
image: exerciseSuggestion.getMainImage,
|
||||
),
|
||||
child: ExerciseImageWidget(image: exerciseSuggestion.getMainImage),
|
||||
),
|
||||
title: Text(
|
||||
exerciseSuggestion
|
||||
@@ -487,10 +475,7 @@ class _SetFormWidgetState extends State<SetFormWidget> {
|
||||
);
|
||||
},
|
||||
transitionBuilder: (context, animation, child) => FadeTransition(
|
||||
opacity: CurvedAnimation(
|
||||
parent: animation,
|
||||
curve: Curves.fastOutSlowIn,
|
||||
),
|
||||
opacity: CurvedAnimation(parent: animation, curve: Curves.fastOutSlowIn),
|
||||
child: child,
|
||||
),
|
||||
onSelected: (Exercise exerciseSuggestion) {
|
||||
@@ -538,8 +523,9 @@ class _SetFormWidgetState extends State<SetFormWidget> {
|
||||
final index = entry.key;
|
||||
final exercise = entry.value;
|
||||
final showSupersetInfo = (index + 1) < widget._set.exerciseBasesObj.length;
|
||||
final settings =
|
||||
widget._set.settings.where((e) => e.exerciseObj.id == exercise.id).toList();
|
||||
final settings = widget._set.settings
|
||||
.where((e) => e.exerciseObj.id == exercise.id)
|
||||
.toList();
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
@@ -551,16 +537,10 @@ class _SetFormWidgetState extends State<SetFormWidget> {
|
||||
removeExerciseBase,
|
||||
),
|
||||
if (showSupersetInfo)
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(3.0),
|
||||
child: Text('+'),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(3.0), child: Text('+')),
|
||||
if (showSupersetInfo) Text(AppLocalizations.of(context).supersetWith),
|
||||
if (showSupersetInfo)
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(3.0),
|
||||
child: Text('+'),
|
||||
),
|
||||
const Padding(padding: EdgeInsets.all(3.0), child: Text('+')),
|
||||
],
|
||||
);
|
||||
}),
|
||||
@@ -648,29 +628,17 @@ class ExerciseSetting extends StatelessWidget {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: RepsInputWidget(setting, _detailed),
|
||||
),
|
||||
Flexible(flex: 2, child: RepsInputWidget(setting, _detailed)),
|
||||
const SizedBox(width: 4),
|
||||
Flexible(
|
||||
flex: 3,
|
||||
child: RepetitionUnitInputWidget(setting),
|
||||
),
|
||||
Flexible(flex: 3, child: RepetitionUnitInputWidget(setting)),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: WeightInputWidget(setting, _detailed),
|
||||
),
|
||||
Flexible(flex: 2, child: WeightInputWidget(setting, _detailed)),
|
||||
const SizedBox(width: 4),
|
||||
Flexible(
|
||||
flex: 3,
|
||||
child: WeightUnitInputWidget(setting, key: Key(i.toString())),
|
||||
),
|
||||
Flexible(flex: 3, child: WeightUnitInputWidget(setting, key: Key(i.toString()))),
|
||||
],
|
||||
),
|
||||
Flexible(flex: 2, child: RiRInputWidget(setting)),
|
||||
@@ -919,15 +887,15 @@ class _WeightUnitInputWidgetState extends State<WeightUnitInputWidget> {
|
||||
widget._setting.weightUnit = newValue;
|
||||
});
|
||||
},
|
||||
items: Provider.of<WorkoutPlansProvider>(context, listen: false)
|
||||
.weightUnits
|
||||
items: Provider.of<WorkoutPlansProvider>(context, listen: false).weightUnits
|
||||
.map<DropdownMenuItem<WeightUnit>>((WeightUnit value) {
|
||||
return DropdownMenuItem<WeightUnit>(
|
||||
key: Key(value.id.toString()),
|
||||
value: value,
|
||||
child: Text(value.name),
|
||||
);
|
||||
}).toList(),
|
||||
return DropdownMenuItem<WeightUnit>(
|
||||
key: Key(value.id.toString()),
|
||||
value: value,
|
||||
child: Text(value.name),
|
||||
);
|
||||
})
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -951,9 +919,7 @@ class _RepetitionUnitInputWidgetState extends State<RepetitionUnitInputWidget> {
|
||||
|
||||
return DropdownButtonFormField(
|
||||
value: selectedWeightUnit,
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).repetitionUnit,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).repetitionUnit),
|
||||
isDense: true,
|
||||
onChanged: (RepetitionUnit? newValue) {
|
||||
setState(() {
|
||||
@@ -961,15 +927,15 @@ class _RepetitionUnitInputWidgetState extends State<RepetitionUnitInputWidget> {
|
||||
widget._setting.repetitionUnit = newValue;
|
||||
});
|
||||
},
|
||||
items: Provider.of<WorkoutPlansProvider>(context, listen: false)
|
||||
.repetitionUnits
|
||||
items: Provider.of<WorkoutPlansProvider>(context, listen: false).repetitionUnits
|
||||
.map<DropdownMenuItem<RepetitionUnit>>((RepetitionUnit value) {
|
||||
return DropdownMenuItem<RepetitionUnit>(
|
||||
key: Key(value.id.toString()),
|
||||
value: value,
|
||||
child: Text(value.name),
|
||||
);
|
||||
}).toList(),
|
||||
return DropdownMenuItem<RepetitionUnit>(
|
||||
key: Key(value.id.toString()),
|
||||
value: value,
|
||||
child: Text(value.name),
|
||||
);
|
||||
})
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -27,8 +26,8 @@ import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/gym_mode.dart';
|
||||
import 'package:wger/helpers/i18n.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/helpers/misc.dart';
|
||||
import 'package:wger/helpers/ui.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/exercise.dart';
|
||||
import 'package:wger/models/workouts/day.dart';
|
||||
import 'package:wger/models/workouts/log.dart';
|
||||
@@ -83,8 +82,10 @@ class _GymModeState extends State<GymMode> {
|
||||
for (final set in widget._workoutDay.sets) {
|
||||
var firstPage = true;
|
||||
for (final setting in set.settingsComputed) {
|
||||
final exerciseBase = Provider.of<ExercisesProvider>(context, listen: false)
|
||||
.findExerciseById(setting.exerciseId);
|
||||
final exerciseBase = Provider.of<ExercisesProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).findExerciseById(setting.exerciseId);
|
||||
|
||||
if (firstPage) {
|
||||
_exercisePages[exerciseBase] = currentPage;
|
||||
@@ -116,23 +117,20 @@ class _GymModeState extends State<GymMode> {
|
||||
currentElement++;
|
||||
|
||||
if (firstPage) {
|
||||
out.add(ExerciseOverview(
|
||||
_controller,
|
||||
exerciseBase,
|
||||
ratioCompleted,
|
||||
_exercisePages,
|
||||
));
|
||||
out.add(ExerciseOverview(_controller, exerciseBase, ratioCompleted, _exercisePages));
|
||||
}
|
||||
|
||||
out.add(LogPage(
|
||||
_controller,
|
||||
setting,
|
||||
set,
|
||||
exerciseBase,
|
||||
workoutProvider.findById(widget._workoutDay.workoutId),
|
||||
ratioCompleted,
|
||||
_exercisePages,
|
||||
));
|
||||
out.add(
|
||||
LogPage(
|
||||
_controller,
|
||||
setting,
|
||||
set,
|
||||
exerciseBase,
|
||||
workoutProvider.findById(widget._workoutDay.workoutId),
|
||||
ratioCompleted,
|
||||
_exercisePages,
|
||||
),
|
||||
);
|
||||
out.add(TimerWidget(_controller, ratioCompleted, _exercisePages));
|
||||
firstPage = false;
|
||||
}
|
||||
@@ -149,8 +147,10 @@ class _GymModeState extends State<GymMode> {
|
||||
StartPage(_controller, widget._workoutDay, _exercisePages),
|
||||
...getContent(),
|
||||
SessionPage(
|
||||
Provider.of<WorkoutPlansProvider>(context, listen: false)
|
||||
.findById(widget._workoutDay.workoutId),
|
||||
Provider.of<WorkoutPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).findById(widget._workoutDay.workoutId),
|
||||
_controller,
|
||||
widget._start,
|
||||
_exercisePages,
|
||||
@@ -298,9 +298,7 @@ class _LogPageState extends State<LogPage> {
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).repetitions,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).repetitions),
|
||||
enabled: true,
|
||||
controller: _repsController,
|
||||
keyboardType: TextInputType.number,
|
||||
@@ -353,9 +351,7 @@ class _LogPageState extends State<LogPage> {
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).weight,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).weight),
|
||||
controller: _weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
onFieldSubmitted: (_) {},
|
||||
@@ -512,9 +508,9 @@ class _LogPageState extends State<LogPage> {
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
...widget._workoutPlan
|
||||
.filterLogsByExerciseBase(widget._exerciseBase, unique: true)
|
||||
.map((log) {
|
||||
...widget._workoutPlan.filterLogsByExerciseBase(widget._exerciseBase, unique: true).map((
|
||||
log,
|
||||
) {
|
||||
return ListTile(
|
||||
title: Text(log.singleLogRepTextNoNl),
|
||||
subtitle: Text(
|
||||
@@ -533,9 +529,9 @@ class _LogPageState extends State<LogPage> {
|
||||
widget._log.weightUnit = log.weightUnitObj;
|
||||
|
||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text(AppLocalizations.of(context).dataCopied),
|
||||
));
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text(AppLocalizations.of(context).dataCopied)));
|
||||
});
|
||||
},
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
@@ -584,9 +580,7 @@ class _LogPageState extends State<LogPage> {
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
key.toString(),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -598,9 +592,7 @@ class _LogPageState extends State<LogPage> {
|
||||
),
|
||||
],
|
||||
)
|
||||
: MutedText(
|
||||
AppLocalizations.of(context).plateCalculatorNotDivisible,
|
||||
),
|
||||
: MutedText(AppLocalizations.of(context).plateCalculatorNotDivisible),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
],
|
||||
@@ -676,20 +668,20 @@ class ExerciseOverview extends StatelessWidget {
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
..._exerciseBase.equipment.map((e) => Text(
|
||||
getTranslation(e.name, context),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
textAlign: TextAlign.center,
|
||||
)),
|
||||
..._exerciseBase.equipment.map(
|
||||
(e) => Text(
|
||||
getTranslation(e.name, context),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
if (_exerciseBase.images.isNotEmpty)
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 200,
|
||||
child: ListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: [
|
||||
..._exerciseBase.images.map((e) => ExerciseImageWidget(image: e)),
|
||||
],
|
||||
children: [..._exerciseBase.images.map((e) => ExerciseImageWidget(image: e))],
|
||||
),
|
||||
),
|
||||
Html(
|
||||
@@ -712,12 +704,7 @@ class SessionPage extends StatefulWidget {
|
||||
final TimeOfDay _start;
|
||||
final Map<Exercise, int> _exercisePages;
|
||||
|
||||
const SessionPage(
|
||||
this._workoutPlan,
|
||||
this._controller,
|
||||
this._start,
|
||||
this._exercisePages,
|
||||
);
|
||||
const SessionPage(this._workoutPlan, this._controller, this._start, this._exercisePages);
|
||||
|
||||
@override
|
||||
_SessionPageState createState() => _SessionPageState();
|
||||
@@ -777,9 +764,11 @@ class _SessionPageState extends State<SessionPage> {
|
||||
renderBorder: false,
|
||||
onPressed: (int index) {
|
||||
setState(() {
|
||||
for (int buttonIndex = 0;
|
||||
buttonIndex < selectedImpression.length;
|
||||
buttonIndex++) {
|
||||
for (
|
||||
int buttonIndex = 0;
|
||||
buttonIndex < selectedImpression.length;
|
||||
buttonIndex++
|
||||
) {
|
||||
_session.impression = index + 1;
|
||||
|
||||
if (buttonIndex == index) {
|
||||
@@ -798,9 +787,7 @@ class _SessionPageState extends State<SessionPage> {
|
||||
],
|
||||
),
|
||||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context).notes,
|
||||
),
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(context).notes),
|
||||
maxLines: 3,
|
||||
controller: notesController,
|
||||
keyboardType: TextInputType.multiline,
|
||||
@@ -922,11 +909,7 @@ class TimerWidget extends StatefulWidget {
|
||||
final double _ratioCompleted;
|
||||
final Map<Exercise, int> _exercisePages;
|
||||
|
||||
const TimerWidget(
|
||||
this._controller,
|
||||
this._ratioCompleted,
|
||||
this._exercisePages,
|
||||
);
|
||||
const TimerWidget(this._controller, this._ratioCompleted, this._exercisePages);
|
||||
|
||||
@override
|
||||
_TimerWidgetState createState() => _TimerWidgetState();
|
||||
@@ -1054,18 +1037,11 @@ class NavigationHeader extends StatelessWidget {
|
||||
final String _title;
|
||||
final Map<Exercise, int> exercisePages;
|
||||
|
||||
const NavigationHeader(
|
||||
this._title,
|
||||
this._controller, {
|
||||
required this.exercisePages,
|
||||
});
|
||||
const NavigationHeader(this._title, this._controller, {required this.exercisePages});
|
||||
|
||||
Widget getDialog(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).jumpTo,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
title: Text(AppLocalizations.of(context).jumpTo, textAlign: TextAlign.center),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
@@ -1121,10 +1097,7 @@ class NavigationHeader extends StatelessWidget {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.toc),
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => getDialog(context),
|
||||
);
|
||||
showDialog(context: context, builder: (ctx) => getDialog(context));
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:table_calendar/table_calendar.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/exercise.dart';
|
||||
import 'package:wger/models/workouts/log.dart';
|
||||
import 'package:wger/models/workouts/session.dart';
|
||||
@@ -70,10 +70,7 @@ class _WorkoutLogsState extends State<WorkoutLogs> {
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
AppLocalizations.of(context).logHelpEntries,
|
||||
textAlign: TextAlign.justify,
|
||||
),
|
||||
child: Text(AppLocalizations.of(context).logHelpEntries, textAlign: TextAlign.justify),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
@@ -82,10 +79,7 @@ class _WorkoutLogsState extends State<WorkoutLogs> {
|
||||
textAlign: TextAlign.justify,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: WorkoutLogCalendar(widget._workoutPlan),
|
||||
),
|
||||
SizedBox(width: double.infinity, child: WorkoutLogCalendar(widget._workoutPlan)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/workout_plan.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/screens/workout_plan_screen.dart';
|
||||
@@ -50,17 +50,11 @@ class _WorkoutPlanDetailState extends State<WorkoutPlanDetail> {
|
||||
}
|
||||
},
|
||||
isSelected: const [true, false],
|
||||
children: const [
|
||||
Icon(Icons.table_chart),
|
||||
Icon(Icons.show_chart),
|
||||
],
|
||||
children: const [Icon(Icons.table_chart), Icon(Icons.show_chart)],
|
||||
),
|
||||
),
|
||||
if (widget._workoutPlan.description != '')
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(15),
|
||||
child: Text(widget._workoutPlan.description),
|
||||
),
|
||||
Padding(padding: const EdgeInsets.all(15), child: Text(widget._workoutPlan.description)),
|
||||
...widget._workoutPlan.days.map((workoutDay) => WorkoutDayWidget(workoutDay)),
|
||||
Column(
|
||||
children: [
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
import 'package:wger/screens/workout_plan_screen.dart';
|
||||
import 'package:wger/widgets/core/text_prompt.dart';
|
||||
@@ -46,10 +46,9 @@ class WorkoutPlansList extends StatelessWidget {
|
||||
onTap: () {
|
||||
_workoutProvider.setCurrentPlan(currentWorkout.id!);
|
||||
|
||||
Navigator.of(context).pushNamed(
|
||||
WorkoutPlanScreen.routeName,
|
||||
arguments: currentWorkout,
|
||||
);
|
||||
Navigator.of(
|
||||
context,
|
||||
).pushNamed(WorkoutPlanScreen.routeName, arguments: currentWorkout);
|
||||
},
|
||||
title: Text(currentWorkout.name),
|
||||
subtitle: Text(
|
||||
@@ -57,62 +56,65 @@ class WorkoutPlansList extends StatelessWidget {
|
||||
Localizations.localeOf(context).languageCode,
|
||||
).format(currentWorkout.creationDate),
|
||||
),
|
||||
trailing: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
const VerticalDivider(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
onPressed: () async {
|
||||
// Delete workout from DB
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext contextDialog) {
|
||||
return AlertDialog(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).confirmDelete(currentWorkout.name),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
MaterialLocalizations.of(context).cancelButtonLabel,
|
||||
),
|
||||
onPressed: () => Navigator.of(contextDialog).pop(),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const VerticalDivider(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
tooltip: AppLocalizations.of(context).delete,
|
||||
onPressed: () async {
|
||||
// Delete workout from DB
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext contextDialog) {
|
||||
return AlertDialog(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).confirmDelete(currentWorkout.name),
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).delete,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text(
|
||||
MaterialLocalizations.of(context).cancelButtonLabel,
|
||||
),
|
||||
onPressed: () => Navigator.of(contextDialog).pop(),
|
||||
),
|
||||
onPressed: () {
|
||||
// Confirmed, delete the workout
|
||||
Provider.of<WorkoutPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).deleteWorkout(currentWorkout.id!);
|
||||
|
||||
// Close the popup
|
||||
Navigator.of(contextDialog).pop();
|
||||
|
||||
// and inform the user
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).successfullyDeleted,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
TextButton(
|
||||
child: Text(
|
||||
AppLocalizations.of(context).delete,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
]),
|
||||
),
|
||||
onPressed: () {
|
||||
// Confirmed, delete the workout
|
||||
Provider.of<WorkoutPlansProvider>(
|
||||
context,
|
||||
listen: false,
|
||||
).deleteWorkout(currentWorkout.id!);
|
||||
|
||||
// Close the popup
|
||||
Navigator.of(contextDialog).pop();
|
||||
|
||||
// and inform the user
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
AppLocalizations.of(context).successfullyDeleted,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/http.dart';
|
||||
@@ -28,6 +27,7 @@ import 'package:mockito/mockito.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
import 'package:wger/screens/auth_screen.dart';
|
||||
|
||||
@@ -38,17 +38,9 @@ void main() {
|
||||
late AuthProvider authProvider;
|
||||
late MockClient mockClient;
|
||||
|
||||
final Uri tRegistration = Uri(
|
||||
scheme: 'https',
|
||||
host: 'wger.de',
|
||||
path: 'api/v2/register/',
|
||||
);
|
||||
final Uri tRegistration = Uri(scheme: 'https', host: 'wger.de', path: 'api/v2/register/');
|
||||
|
||||
final Uri tLogin = Uri(
|
||||
scheme: 'https',
|
||||
host: 'wger.de',
|
||||
path: 'api/v2/login/',
|
||||
);
|
||||
final Uri tLogin = Uri(scheme: 'https', host: 'wger.de', path: 'api/v2/login/');
|
||||
|
||||
final responseLoginOk = {'token': 'b01c44d3e3e016a615d2f82b16d31f8b924fb936'};
|
||||
|
||||
@@ -85,19 +77,15 @@ void main() {
|
||||
buildSignature: 'buildSignature',
|
||||
);
|
||||
|
||||
when(mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) => Future(() => Response(json.encode(responseLoginOk), 200)));
|
||||
when(
|
||||
mockClient.post(tLogin, headers: anyNamed('headers'), body: anyNamed('body')),
|
||||
).thenAnswer((_) => Future(() => Response(json.encode(responseLoginOk), 200)));
|
||||
|
||||
when(mockClient.get(any)).thenAnswer((_) => Future(() => Response('"1.2.3.4"', 200)));
|
||||
|
||||
when(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) => Future(() => Response(json.encode(responseRegistrationOk), 201)));
|
||||
when(
|
||||
mockClient.post(tRegistration, headers: anyNamed('headers'), body: anyNamed('body')),
|
||||
).thenAnswer((_) => Future(() => Response(json.encode(responseRegistrationOk), 201)));
|
||||
});
|
||||
|
||||
group('Login mode', () {
|
||||
@@ -134,11 +122,13 @@ void main() {
|
||||
// Assert
|
||||
expect(find.textContaining('An Error Occurred'), findsNothing);
|
||||
verify(mockClient.get(any));
|
||||
verify(mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
));
|
||||
verify(
|
||||
mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Login - wront username & password', (WidgetTester tester) async {
|
||||
@@ -149,11 +139,9 @@ void main() {
|
||||
'non_field_errors': ['Username or password unknown'],
|
||||
};
|
||||
|
||||
when(mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
|
||||
when(
|
||||
mockClient.post(tLogin, headers: anyNamed('headers'), body: anyNamed('body')),
|
||||
).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
|
||||
await tester.pumpWidget(getWidget());
|
||||
|
||||
// Act
|
||||
@@ -166,11 +154,13 @@ void main() {
|
||||
expect(find.textContaining('An Error Occurred'), findsOne);
|
||||
expect(find.textContaining('Non field errors'), findsOne);
|
||||
expect(find.textContaining('Username or password unknown'), findsOne);
|
||||
verify(mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
));
|
||||
verify(
|
||||
mockClient.post(
|
||||
tLogin,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -219,11 +209,13 @@ void main() {
|
||||
|
||||
// Assert
|
||||
expect(find.textContaining('An Error Occurred'), findsNothing);
|
||||
verify(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
));
|
||||
verify(
|
||||
mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Registration - password problems', (WidgetTester tester) async {
|
||||
@@ -232,17 +224,12 @@ void main() {
|
||||
tester.view.devicePixelRatio = 1.0;
|
||||
final response = {
|
||||
'username': ['This field must be unique.'],
|
||||
'password': [
|
||||
'This password is too common.',
|
||||
'This password is entirely numeric.',
|
||||
],
|
||||
'password': ['This password is too common.', 'This password is entirely numeric.'],
|
||||
};
|
||||
|
||||
when(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: anyNamed('body'),
|
||||
)).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
|
||||
when(
|
||||
mockClient.post(tRegistration, headers: anyNamed('headers'), body: anyNamed('body')),
|
||||
).thenAnswer((_) => Future(() => Response(json.encode(response), 400)));
|
||||
await tester.pumpWidget(getWidget());
|
||||
|
||||
// Act
|
||||
@@ -259,11 +246,13 @@ void main() {
|
||||
expect(find.textContaining('This password is entirely numeric'), findsOne);
|
||||
expect(find.textContaining('This field must be unique'), findsOne);
|
||||
|
||||
verify(mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
));
|
||||
verify(
|
||||
mockClient.post(
|
||||
tRegistration,
|
||||
headers: anyNamed('headers'),
|
||||
body: json.encode({'username': 'testuser', 'password': '123456789'}),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/widgets/core/settings.dart';
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/add_exercise.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/widgets/exercises/exercises.dart';
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/models/gallery/image.dart' as gallery;
|
||||
import 'package:wger/providers/gallery.dart';
|
||||
import 'package:wger/widgets/gallery/forms.dart';
|
||||
|
||||
import '../../test_data/gallery.dart';
|
||||
import 'gallery_form_test.mocks.dart';
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:network_image_mock/network_image_mock.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/gallery.dart';
|
||||
import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/widgets/gallery/overview.dart';
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/measurements/measurement_category.dart';
|
||||
import 'package:wger/models/measurements/measurement_entry.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
@@ -37,14 +37,24 @@ void main() {
|
||||
setUp(() {
|
||||
mockMeasurementProvider = MockMeasurementProvider();
|
||||
when(mockMeasurementProvider.categories).thenReturn([
|
||||
MeasurementCategory(id: 1, name: 'body fat', unit: '%', entries: [
|
||||
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 9, 1), value: 10, notes: ''),
|
||||
MeasurementEntry(id: 2, category: 1, date: DateTime(2021, 9, 5), value: 11, notes: ''),
|
||||
]),
|
||||
MeasurementCategory(id: 2, name: 'biceps', unit: 'cm', entries: [
|
||||
MeasurementEntry(id: 3, category: 2, date: DateTime(2021, 9, 1), value: 30, notes: ''),
|
||||
MeasurementEntry(id: 4, category: 2, date: DateTime(2021, 9, 5), value: 40, notes: ''),
|
||||
]),
|
||||
MeasurementCategory(
|
||||
id: 1,
|
||||
name: 'body fat',
|
||||
unit: '%',
|
||||
entries: [
|
||||
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 9, 1), value: 10, notes: ''),
|
||||
MeasurementEntry(id: 2, category: 1, date: DateTime(2021, 9, 5), value: 11, notes: ''),
|
||||
],
|
||||
),
|
||||
MeasurementCategory(
|
||||
id: 2,
|
||||
name: 'biceps',
|
||||
unit: 'cm',
|
||||
entries: [
|
||||
MeasurementEntry(id: 3, category: 2, date: DateTime(2021, 9, 1), value: 30, notes: ''),
|
||||
MeasurementEntry(id: 4, category: 2, date: DateTime(2021, 9, 5), value: 40, notes: ''),
|
||||
],
|
||||
),
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/measurements/measurement_category.dart';
|
||||
import 'package:wger/models/measurements/measurement_entry.dart';
|
||||
import 'package:wger/providers/measurement.dart';
|
||||
@@ -37,10 +37,21 @@ void main() {
|
||||
setUp(() {
|
||||
mockMeasurementProvider = MockMeasurementProvider();
|
||||
when(mockMeasurementProvider.findCategoryById(any)).thenReturn(
|
||||
MeasurementCategory(id: 1, name: 'body fat', unit: '%', entries: [
|
||||
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 8, 1), value: 10.2, notes: ''),
|
||||
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 8, 10), value: 18.1, notes: 'a'),
|
||||
]),
|
||||
MeasurementCategory(
|
||||
id: 1,
|
||||
name: 'body fat',
|
||||
unit: '%',
|
||||
entries: [
|
||||
MeasurementEntry(id: 1, category: 1, date: DateTime(2021, 8, 1), value: 10.2, notes: ''),
|
||||
MeasurementEntry(
|
||||
id: 1,
|
||||
category: 1,
|
||||
date: DateTime(2021, 8, 10),
|
||||
value: 18.1,
|
||||
notes: 'a',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
mockNutritionPlansProvider = MockNutritionPlansProvider();
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/widgets/nutrition/charts.dart';
|
||||
import 'package:wger/widgets/nutrition/nutritional_diary_detail.dart';
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
import 'package:clock/clock.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/helpers/json.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
@@ -61,9 +61,7 @@ void main() {
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
navigatorKey: key,
|
||||
home: Scaffold(body: MealForm("1", meal)),
|
||||
routes: {
|
||||
NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
|
||||
},
|
||||
routes: {NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen()},
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -81,11 +79,7 @@ void main() {
|
||||
await tester.pumpWidget(createFormScreen(meal1));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.text('17:00'),
|
||||
findsOneWidget,
|
||||
reason: 'Time of existing meal is filled in',
|
||||
);
|
||||
expect(find.text('17:00'), findsOneWidget, reason: 'Time of existing meal is filled in');
|
||||
|
||||
expect(
|
||||
find.text('Initial Name 1'),
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@@ -10,6 +9,7 @@ import 'package:mockito/mockito.dart';
|
||||
import 'package:network_image_mock/network_image_mock.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/exercises/ingredient_api.dart';
|
||||
import 'package:wger/models/nutrition/ingredient.dart';
|
||||
import 'package:wger/models/nutrition/meal.dart';
|
||||
@@ -74,14 +74,17 @@ void main() {
|
||||
when(mockNutrition.searchIngredientWithCode('123')).thenAnswer((_) => Future.value(ingredient));
|
||||
when(mockNutrition.searchIngredientWithCode('')).thenAnswer((_) => Future.value(null));
|
||||
when(mockNutrition.searchIngredientWithCode('222')).thenAnswer((_) => Future.value(null));
|
||||
when(mockNutrition.searchIngredient(
|
||||
any,
|
||||
languageCode: anyNamed('languageCode'),
|
||||
searchEnglish: anyNamed('searchEnglish'),
|
||||
)).thenAnswer(
|
||||
when(
|
||||
mockNutrition.searchIngredient(
|
||||
any,
|
||||
languageCode: anyNamed('languageCode'),
|
||||
searchEnglish: anyNamed('searchEnglish'),
|
||||
),
|
||||
).thenAnswer(
|
||||
(_) => Future.value(
|
||||
IngredientApiSearch.fromJson(json.decode(fixture('nutrition/ingredient_suggestions')))
|
||||
.suggestions,
|
||||
IngredientApiSearch.fromJson(
|
||||
json.decode(fixture('nutrition/ingredient_suggestions')),
|
||||
).suggestions,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -104,9 +107,7 @@ void main() {
|
||||
MealItemForm(meal, const [], code, test),
|
||||
),
|
||||
),
|
||||
routes: {
|
||||
NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
|
||||
},
|
||||
routes: {NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen()},
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -294,40 +295,41 @@ void main() {
|
||||
expect(find.text('Please enter a valid number'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'save complete ingredient with correct weight input type',
|
||||
(WidgetTester tester) async {
|
||||
await tester.pumpWidget(createMealItemFormScreen(meal1, '123', true));
|
||||
testWidgets('save complete ingredient with correct weight input type', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(createMealItemFormScreen(meal1, '123', true));
|
||||
|
||||
final IngredientFormState formState = tester.state(find.byType(IngredientForm));
|
||||
final IngredientFormState formState = tester.state(find.byType(IngredientForm));
|
||||
|
||||
await tester.tap(find.byKey(const Key('scan-button')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('scan-button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsOneWidget);
|
||||
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsOneWidget);
|
||||
|
||||
await tester.tap(find.byKey(const Key('ingredient-scan-result-dialog-confirm-button')));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key('ingredient-scan-result-dialog-confirm-button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(formState.ingredientIdController.text, '1');
|
||||
expect(formState.ingredientIdController.text, '1');
|
||||
|
||||
await tester.enterText(find.byKey(const Key('field-weight')), '2');
|
||||
await tester.enterText(find.byKey(const Key('field-weight')), '2');
|
||||
|
||||
// once ID and weight are set, it'll fetchIngredient and show macros preview and ingredient image
|
||||
when(mockNutrition.fetchIngredient(1)).thenAnswer((_) => Future.value(
|
||||
Ingredient.fromJson(jsonDecode(fixture('nutrition/ingredientinfo_59887.json'))),
|
||||
));
|
||||
await mockNetworkImagesFor(() => tester.pumpAndSettle());
|
||||
// once ID and weight are set, it'll fetchIngredient and show macros preview and ingredient image
|
||||
when(mockNutrition.fetchIngredient(1)).thenAnswer(
|
||||
(_) => Future.value(
|
||||
Ingredient.fromJson(jsonDecode(fixture('nutrition/ingredientinfo_59887.json'))),
|
||||
),
|
||||
);
|
||||
await mockNetworkImagesFor(() => tester.pumpAndSettle());
|
||||
|
||||
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsNothing);
|
||||
expect(find.byKey(const Key('ingredient-scan-result-dialog')), findsNothing);
|
||||
|
||||
await tester.tap(find.byKey(const Key(SUBMIT_BUTTON_KEY_NAME)));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.byKey(const Key(SUBMIT_BUTTON_KEY_NAME)));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(formState.mealItem.amount, 2);
|
||||
expect(formState.mealItem.amount, 2);
|
||||
|
||||
verify(mockNutrition.addMealItem(any, meal1));
|
||||
},
|
||||
);
|
||||
verify(mockNutrition.addMealItem(any, meal1));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/screens/nutritional_plan_screen.dart';
|
||||
@@ -59,9 +59,7 @@ void main() {
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
navigatorKey: key,
|
||||
home: Scaffold(body: PlanForm(plan)),
|
||||
routes: {
|
||||
NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen(),
|
||||
},
|
||||
routes: {NutritionalPlanScreen.routeName: (ctx) => const NutritionalPlanScreen()},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:golden_toolkit/golden_toolkit.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/database/ingredients/ingredients_database.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
@@ -54,11 +54,7 @@ void main() {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider<NutritionPlansProvider>(
|
||||
create: (context) => NutritionPlansProvider(
|
||||
mockBaseProvider,
|
||||
[],
|
||||
database: database,
|
||||
),
|
||||
create: (context) => NutritionPlansProvider(mockBaseProvider, [], database: database),
|
||||
),
|
||||
ChangeNotifierProvider<BodyWeightProvider>(
|
||||
create: (context) => BodyWeightProvider(mockBaseProvider),
|
||||
@@ -82,64 +78,59 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
testGoldens(
|
||||
'Test the widgets on the nutritional plan screen',
|
||||
(tester) async {
|
||||
await loadAppFonts();
|
||||
final globalKey = GlobalKey();
|
||||
await tester.pumpWidgetBuilder(
|
||||
Material(key: globalKey),
|
||||
wrapper: materialAppWrapper(
|
||||
localizations: [AppLocalizations.delegate],
|
||||
),
|
||||
surfaceSize: const Size(500, 1000),
|
||||
);
|
||||
await tester.pumpWidget(createNutritionalPlan());
|
||||
await tester.tap(find.byType(TextButton));
|
||||
await tester.pumpAndSettle();
|
||||
testGoldens('Test the widgets on the nutritional plan screen', (tester) async {
|
||||
await loadAppFonts();
|
||||
final globalKey = GlobalKey();
|
||||
await tester.pumpWidgetBuilder(
|
||||
Material(key: globalKey),
|
||||
wrapper: materialAppWrapper(localizations: [AppLocalizations.delegate]),
|
||||
surfaceSize: const Size(500, 1000),
|
||||
);
|
||||
await tester.pumpWidget(createNutritionalPlan());
|
||||
await tester.tap(find.byType(TextButton));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await screenMatchesGolden(tester, 'nutritional_plan_1_default_view');
|
||||
await screenMatchesGolden(tester, 'nutritional_plan_1_default_view');
|
||||
|
||||
// Default view shows plan description, info button, and no ingredients
|
||||
expect(find.text('Less fat, more protein'), findsOneWidget);
|
||||
expect(find.byIcon(Icons.info_outline), findsNWidgets(3)); // 2 meals, 1 "other logs"
|
||||
expect(find.byIcon(Icons.info), findsNothing);
|
||||
expect(find.text('100g Water'), findsNothing);
|
||||
expect(find.text('75g Burger soup'), findsNothing);
|
||||
// Default view shows plan description, info button, and no ingredients
|
||||
expect(find.text('Less fat, more protein'), findsOneWidget);
|
||||
expect(find.byIcon(Icons.info_outline), findsNWidgets(3)); // 2 meals, 1 "other logs"
|
||||
expect(find.byIcon(Icons.info), findsNothing);
|
||||
expect(find.text('100g Water'), findsNothing);
|
||||
expect(find.text('75g Burger soup'), findsNothing);
|
||||
|
||||
// tap the first info button changes it and reveals ingredients for the first meal
|
||||
var infoOutlineButtons = find.byIcon(Icons.info_outline);
|
||||
await tester.tap(infoOutlineButtons.first); // 2nd button shows up also, but is off-screen
|
||||
await tester.pumpAndSettle();
|
||||
await screenMatchesGolden(tester, 'nutritional_plan_2_one_meal_with_ingredients');
|
||||
// tap the first info button changes it and reveals ingredients for the first meal
|
||||
var infoOutlineButtons = find.byIcon(Icons.info_outline);
|
||||
await tester.tap(infoOutlineButtons.first); // 2nd button shows up also, but is off-screen
|
||||
await tester.pumpAndSettle();
|
||||
await screenMatchesGolden(tester, 'nutritional_plan_2_one_meal_with_ingredients');
|
||||
|
||||
// Ingredients show up now
|
||||
expect(find.text('100g Water'), findsOneWidget);
|
||||
expect(find.text('75g Burger soup'), findsOneWidget);
|
||||
// Ingredients show up now
|
||||
expect(find.text('100g Water'), findsOneWidget);
|
||||
expect(find.text('75g Burger soup'), findsOneWidget);
|
||||
|
||||
// .. and the button icon has changed
|
||||
expect(find.byIcon(Icons.info_outline), findsNWidgets(2));
|
||||
expect(find.byIcon(Icons.info), findsOneWidget);
|
||||
// .. and the button icon has changed
|
||||
expect(find.byIcon(Icons.info_outline), findsNWidgets(2));
|
||||
expect(find.byIcon(Icons.info), findsOneWidget);
|
||||
|
||||
// the goals widget pushes this content down a bit.
|
||||
// let's first find our icon (note: the previous icon no longer matches)
|
||||
infoOutlineButtons = find.byIcon(Icons.info_outline);
|
||||
// the goals widget pushes this content down a bit.
|
||||
// let's first find our icon (note: the previous icon no longer matches)
|
||||
infoOutlineButtons = find.byIcon(Icons.info_outline);
|
||||
|
||||
await tester.scrollUntilVisible(infoOutlineButtons.first, 30);
|
||||
expect(find.text('300g Broccoli cake'), findsNothing);
|
||||
await tester.scrollUntilVisible(infoOutlineButtons.first, 30);
|
||||
expect(find.text('300g Broccoli cake'), findsNothing);
|
||||
|
||||
await tester.tap(infoOutlineButtons.first);
|
||||
await tester.pumpAndSettle();
|
||||
await screenMatchesGolden(tester, 'nutritional_plan_3_both_meals_with_ingredients');
|
||||
expect(find.byIcon(Icons.info_outline), findsOneWidget);
|
||||
expect(find.byIcon(Icons.info), findsNWidgets(2));
|
||||
await tester.tap(infoOutlineButtons.first);
|
||||
await tester.pumpAndSettle();
|
||||
await screenMatchesGolden(tester, 'nutritional_plan_3_both_meals_with_ingredients');
|
||||
expect(find.byIcon(Icons.info_outline), findsOneWidget);
|
||||
expect(find.byIcon(Icons.info), findsNWidgets(2));
|
||||
|
||||
await tester.scrollUntilVisible(find.text('300g Broccoli cake'), 30);
|
||||
expect(find.text('300g Broccoli cake'), findsOneWidget);
|
||||
await tester.scrollUntilVisible(find.text('300g Broccoli cake'), 30);
|
||||
expect(find.text('300g Broccoli cake'), findsOneWidget);
|
||||
|
||||
expect(find.byType(Card), findsNWidgets(3));
|
||||
},
|
||||
);
|
||||
expect(find.byType(Card), findsNWidgets(3));
|
||||
});
|
||||
|
||||
testWidgets('Tests the localization of times - EN', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(createNutritionalPlan());
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/database/ingredients/ingredients_database.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/nutrition/nutritional_plan.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
@@ -51,34 +51,29 @@ void main() {
|
||||
});
|
||||
|
||||
Widget createHomeScreen({locale = 'en'}) {
|
||||
when(client.delete(any, headers: anyNamed('headers')))
|
||||
.thenAnswer((_) async => http.Response('', 200));
|
||||
when(
|
||||
client.delete(any, headers: anyNamed('headers')),
|
||||
).thenAnswer((_) async => http.Response('', 200));
|
||||
|
||||
when(mockBaseProvider.deleteRequest(any, any)).thenAnswer(
|
||||
(_) async => http.Response('', 200),
|
||||
);
|
||||
when(mockBaseProvider.deleteRequest(any, any)).thenAnswer((_) async => http.Response('', 200));
|
||||
|
||||
when(mockAuthProvider.token).thenReturn('1234');
|
||||
when(mockAuthProvider.serverUrl).thenReturn('http://localhost');
|
||||
when(mockAuthProvider.getAppNameHeader()).thenReturn('wger app');
|
||||
|
||||
return ChangeNotifierProvider<NutritionPlansProvider>(
|
||||
create: (context) => NutritionPlansProvider(
|
||||
mockBaseProvider,
|
||||
[
|
||||
NutritionalPlan(
|
||||
id: 'deadbeefa',
|
||||
description: 'test plan 1',
|
||||
creationDate: DateTime(2021, 01, 01),
|
||||
),
|
||||
NutritionalPlan(
|
||||
id: 'deadbeefb',
|
||||
description: 'test plan 2',
|
||||
creationDate: DateTime(2021, 01, 10),
|
||||
),
|
||||
],
|
||||
database: database,
|
||||
),
|
||||
create: (context) => NutritionPlansProvider(mockBaseProvider, [
|
||||
NutritionalPlan(
|
||||
id: 'deadbeefa',
|
||||
description: 'test plan 1',
|
||||
creationDate: DateTime(2021, 01, 01),
|
||||
),
|
||||
NutritionalPlan(
|
||||
id: 'deadbeefb',
|
||||
description: 'test plan 2',
|
||||
creationDate: DateTime(2021, 01, 10),
|
||||
),
|
||||
], database: database),
|
||||
child: MaterialApp(
|
||||
locale: Locale(locale),
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/body_weight/weight_entry.dart';
|
||||
import 'package:wger/widgets/weight/forms.dart';
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/nutrition.dart';
|
||||
import 'package:wger/providers/user.dart';
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
@@ -45,11 +45,8 @@ void main() {
|
||||
|
||||
Widget createHomeScreen({locale = 'en'}) {
|
||||
return ChangeNotifierProvider<WorkoutPlansProvider>(
|
||||
create: (context) => WorkoutPlansProvider(
|
||||
mockBaseProvider,
|
||||
mockExerciseProvider,
|
||||
[workoutPlan],
|
||||
),
|
||||
create: (context) =>
|
||||
WorkoutPlansProvider(mockBaseProvider, mockExerciseProvider, [workoutPlan]),
|
||||
child: ChangeNotifierProvider<ExercisesProvider>(
|
||||
create: (context) => mockExerciseProvider,
|
||||
child: MaterialApp(
|
||||
@@ -66,9 +63,7 @@ void main() {
|
||||
),
|
||||
child: const SizedBox(),
|
||||
),
|
||||
routes: {
|
||||
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
|
||||
},
|
||||
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/repetition_unit.dart';
|
||||
import 'package:wger/models/workouts/setting.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
@@ -65,9 +65,7 @@ void main() {
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
navigatorKey: key,
|
||||
home: Scaffold(body: RepetitionUnitInputWidget(setting1)),
|
||||
routes: {
|
||||
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
|
||||
},
|
||||
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/setting.dart';
|
||||
import 'package:wger/models/workouts/weight_unit.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
@@ -66,9 +66,7 @@ void main() {
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
navigatorKey: key,
|
||||
home: Scaffold(body: WeightUnitInputWidget(setting1)),
|
||||
routes: {
|
||||
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
|
||||
},
|
||||
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/day.dart';
|
||||
import 'package:wger/models/workouts/workout_plan.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/workout_plan.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
import 'package:wger/screens/workout_plan_screen.dart';
|
||||
@@ -45,8 +45,9 @@ void main() {
|
||||
setUp(() {
|
||||
mockWorkoutPlans = MockWorkoutPlansProvider();
|
||||
when(mockWorkoutPlans.editWorkout(any)).thenAnswer((_) => Future.value(existingPlan));
|
||||
when(mockWorkoutPlans.fetchAndSetWorkoutPlanFull(any))
|
||||
.thenAnswer((_) => Future.value(existingPlan));
|
||||
when(
|
||||
mockWorkoutPlans.fetchAndSetWorkoutPlanFull(any),
|
||||
).thenAnswer((_) => Future.value(existingPlan));
|
||||
});
|
||||
|
||||
Widget createHomeScreen(WorkoutPlan workoutPlan, {locale = 'en'}) {
|
||||
@@ -60,9 +61,7 @@ void main() {
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
navigatorKey: key,
|
||||
home: Scaffold(body: WorkoutForm(workoutPlan)),
|
||||
routes: {
|
||||
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
|
||||
},
|
||||
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -79,11 +78,7 @@ void main() {
|
||||
await tester.pumpWidget(createHomeScreen(existingPlan));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(
|
||||
find.text('test 1'),
|
||||
findsOneWidget,
|
||||
reason: 'Name of existing workout plan',
|
||||
);
|
||||
expect(find.text('test 1'), findsOneWidget, reason: 'Name of existing workout plan');
|
||||
expect(
|
||||
find.text('description 1'),
|
||||
findsOneWidget,
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/database/exercises/exercise_database.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/providers/workout_plans.dart';
|
||||
@@ -57,9 +57,7 @@ void main() {
|
||||
),
|
||||
child: const SizedBox(),
|
||||
),
|
||||
routes: {
|
||||
WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen(),
|
||||
},
|
||||
routes: {WorkoutPlanScreen.routeName: (ctx) => const WorkoutPlanScreen()},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/database/exercises/exercise_database.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/workout_plan.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
@@ -49,23 +49,15 @@ void main() {
|
||||
});
|
||||
|
||||
Widget createHomeScreen({locale = 'en'}) {
|
||||
final uri = Uri(
|
||||
scheme: 'https',
|
||||
host: 'localhost',
|
||||
path: 'api/v2/workout/',
|
||||
);
|
||||
final uri = Uri(scheme: 'https', host: 'localhost', path: 'api/v2/workout/');
|
||||
when(mockBaseProvider.makeUrl('workout', query: anyNamed('query'))).thenReturn(uri);
|
||||
when(mockBaseProvider.deleteRequest(any, any)).thenAnswer((_) async => http.Response('', 204));
|
||||
|
||||
return ChangeNotifierProvider<WorkoutPlansProvider>(
|
||||
create: (context) => WorkoutPlansProvider(
|
||||
mockBaseProvider,
|
||||
testExercisesProvider,
|
||||
[
|
||||
WorkoutPlan(id: 1, creationDate: DateTime(2021, 01, 01), name: 'test 1'),
|
||||
WorkoutPlan(id: 2, creationDate: DateTime(2021, 02, 12), name: 'test 2'),
|
||||
],
|
||||
),
|
||||
create: (context) => WorkoutPlansProvider(mockBaseProvider, testExercisesProvider, [
|
||||
WorkoutPlan(id: 1, creationDate: DateTime(2021, 01, 01), name: 'test 1'),
|
||||
WorkoutPlan(id: 2, creationDate: DateTime(2021, 02, 12), name: 'test 2'),
|
||||
]),
|
||||
child: MaterialApp(
|
||||
locale: Locale(locale),
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
*/
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||
import 'package:wger/models/workouts/day.dart';
|
||||
import 'package:wger/models/workouts/set.dart';
|
||||
import 'package:wger/models/workouts/setting.dart';
|
||||
@@ -51,11 +51,8 @@ void main() {
|
||||
|
||||
Widget createHomeScreen({locale = 'en'}) {
|
||||
return ChangeNotifierProvider<WorkoutPlansProvider>(
|
||||
create: (context) => WorkoutPlansProvider(
|
||||
mockBaseProvider,
|
||||
mockExerciseProvider,
|
||||
[workoutPlan],
|
||||
),
|
||||
create: (context) =>
|
||||
WorkoutPlansProvider(mockBaseProvider, mockExerciseProvider, [workoutPlan]),
|
||||
child: ChangeNotifierProvider<ExercisesProvider>(
|
||||
create: (context) => mockExerciseProvider,
|
||||
child: MaterialApp(
|
||||
@@ -84,11 +81,13 @@ void main() {
|
||||
when(mockWorkoutPlans.addSet(any)).thenAnswer((_) => Future.value(Set.empty()));
|
||||
when(mockWorkoutPlans.addSetting(any)).thenAnswer((_) => Future.value(Setting.empty()));
|
||||
when(mockWorkoutPlans.fetchSmartText(any, any)).thenAnswer((_) => Future.value('2 x 10'));
|
||||
when(mockExerciseProvider.searchExercise(
|
||||
any,
|
||||
languageCode: anyNamed('languageCode'),
|
||||
searchEnglish: anyNamed('searchEnglish'),
|
||||
)).thenAnswer((_) => Future.value([getTestExercises().first]));
|
||||
when(
|
||||
mockExerciseProvider.searchExercise(
|
||||
any,
|
||||
languageCode: anyNamed('languageCode'),
|
||||
searchEnglish: anyNamed('searchEnglish'),
|
||||
),
|
||||
).thenAnswer((_) => Future.value([getTestExercises().first]));
|
||||
|
||||
await tester.pumpWidget(createHomeScreen());
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
Reference in New Issue
Block a user