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