forked from eatvio/eatvio_app
my diets have been update
This commit is contained in:
3
assets/icons/play_icon.svg
Normal file
3
assets/icons/play_icon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.92 11L10.82 8.5C11.0067 8.38 11.1 8.21333 11.1 8C11.1 7.78667 11.0067 7.62 10.82 7.5L6.92 5C6.72 4.86667 6.51667 4.85667 6.31 4.97C6.10333 5.08333 6 5.26 6 5.5V10.5C6 10.74 6.10333 10.9167 6.31 11.03C6.51667 11.1433 6.72 11.1333 6.92 11ZM8 16C6.89333 16 5.85333 15.79 4.88 15.37C3.90667 14.95 3.06 14.38 2.34 13.66C1.62 12.94 1.05 12.0933 0.63 11.12C0.21 10.1467 0 9.10667 0 8C0 6.89333 0.21 5.85333 0.63 4.88C1.05 3.90667 1.62 3.06 2.34 2.34C3.06 1.62 3.90667 1.05 4.88 0.63C5.85333 0.21 6.89333 0 8 0C9.10667 0 10.1467 0.21 11.12 0.63C12.0933 1.05 12.94 1.62 13.66 2.34C14.38 3.06 14.95 3.90667 15.37 4.88C15.79 5.85333 16 6.89333 16 8C16 9.10667 15.79 10.1467 15.37 11.12C14.95 12.0933 14.38 12.94 13.66 13.66C12.94 14.38 12.0933 14.95 11.12 15.37C10.1467 15.79 9.10667 16 8 16ZM8 14.4C9.78667 14.4 11.3 13.78 12.54 12.54C13.78 11.3 14.4 9.78667 14.4 8C14.4 6.21333 13.78 4.7 12.54 3.46C11.3 2.22 9.78667 1.6 8 1.6C6.21333 1.6 4.7 2.22 3.46 3.46C2.22 4.7 1.6 6.21333 1.6 8C1.6 9.78667 2.22 11.3 3.46 12.54C4.7 13.78 6.21333 14.4 8 14.4Z" fill="#2F80ED"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -30,8 +30,8 @@ import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/plans/presentation/pages/about_plan_screen.dart';
|
||||
import 'package:eatvio_app/features/profile/presentation/pages/profile_screen.dart';
|
||||
import 'package:eatvio_app/features/profile/presentation/pages/subs_screen.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/pages/about_recipes_screen.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/pages/recipe_create_screen.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/about_recipe_screen.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/pages/recipe_create_screen.dart';
|
||||
import 'package:eatvio_app/features/registration/presentation/pages/registration_screen.dart';
|
||||
import 'package:eatvio_app/features/settings/entities/settings_entity.dart';
|
||||
import 'package:eatvio_app/features/settings/presentation/pages/change_email_screen.dart';
|
||||
@@ -58,6 +58,8 @@ class AppRouter {
|
||||
path: '/auth-screen',
|
||||
name: 'authScreen',
|
||||
redirect: (context, state) async {
|
||||
// TokenStorage.removeTokenInStorage();
|
||||
// await TokenStorage.saveTokenInStorage('1|laravel_sanctum_zaU2133RQ0wbxDYdH7IQxTpThmilWtKhzxbSt5X1065fcae3');
|
||||
if (await TokenStorage.haveTokenInStorage()) {
|
||||
return '/my-profile-screen';
|
||||
}
|
||||
@@ -128,9 +130,14 @@ class AppRouter {
|
||||
GoRoute(
|
||||
path: '/about-recipes-screen',
|
||||
name: 'aboutRecipesScreen',
|
||||
builder: (context, state) => AboutRecipesScreen(
|
||||
recipes: state.extra as Recipes,
|
||||
),
|
||||
builder: (context, state) {
|
||||
final data = state.extra as Map<String, dynamic>;
|
||||
return AboutRecipeScreen(
|
||||
recipe: data['recipe'] as Recipe,
|
||||
index: data['index'] as int?,
|
||||
navigateToComments: data['navigateToComments'] as bool,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: RecipeCreateScreen.path,
|
||||
|
||||
@@ -54,9 +54,12 @@ import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/prof
|
||||
import 'package:eatvio_app/features/profile/presentation/bloc/sub_cubit/sub_cubit.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:eatvio_app/features/profile/services/profile_service.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipes/reporitories/recipe_repository.dart';
|
||||
import 'package:eatvio_app/features/recipes/services/recipe_service.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/reporitories/recipe_repository.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/services/recipe_service.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipe/repositories/about_recipe_repository.dart';
|
||||
import 'package:eatvio_app/features/recipe/services/about_recipe_service.dart';
|
||||
import 'package:eatvio_app/features/registration/presentation/bloc/registration_cubit/registration_cubit.dart';
|
||||
import 'package:eatvio_app/features/registration/repositories/registration_repository.dart';
|
||||
import 'package:eatvio_app/features/registration/services/registration_service.dart';
|
||||
@@ -80,7 +83,7 @@ Future<void> init() async {
|
||||
// Cubit factories
|
||||
sl.registerFactory<RegistrationCubit>(() => RegistrationCubit(registrationRepository: sl()));
|
||||
sl.registerFactory<ChatRoomCubit>(() => ChatRoomCubit(chatRepository: sl(), wsManager: sl()));
|
||||
sl.registerFactory<RecipesCubit>(() => RecipesCubit(feedRepository: sl(), recipeRepository: sl()));
|
||||
sl.registerFactory<RecipesCubit>(() => RecipesCubit(feedRepository: sl(), recipeRepository: sl(), aboutRecipeRepository: sl()));
|
||||
sl.registerFactory<CalendarCubit>(() => CalendarCubit(calendarRepository: sl()));
|
||||
sl.registerFactory<ProfileCubit>(() => ProfileCubit(profileRepository: sl(), chatRepository: sl()));
|
||||
sl.registerFactory<profilePlans.PlansCubit>(() => profilePlans.PlansCubit(plansRepository: sl()));
|
||||
@@ -99,10 +102,11 @@ Future<void> init() async {
|
||||
sl.registerFactory<FeedProfileCubit>(() => FeedProfileCubit(profileRepository: sl()));
|
||||
sl.registerFactory<AboutPlanCubit>(() => AboutPlanCubit(planRepository: sl()));
|
||||
sl.registerFactory<CreateRecipeCubit>(() => CreateRecipeCubit(recipeRepository: sl()));
|
||||
sl.registerFactory<MyDietsCubit>(() => MyDietsCubit(myDietsRepository: sl()));
|
||||
sl.registerFactory<MyDietsCubit>(() => MyDietsCubit(myDietsRepository: sl(), createDietRepository: sl()));
|
||||
sl.registerFactory<MyPlansCubit>(() => MyPlansCubit(myPlansRepository: sl()));
|
||||
sl.registerFactory<UserDetailsCubit>(() => UserDetailsCubit(profileRepository: sl()));
|
||||
sl.registerFactory<ConsultantsCubit>(() => ConsultantsCubit(feedRepository: sl()));
|
||||
sl.registerFactory<AboutRecipeCubit>(() => AboutRecipeCubit(recipeRepository: sl(), profileRepository: sl()));
|
||||
|
||||
// Repository
|
||||
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
||||
@@ -122,6 +126,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<PlanRepository>(() => PlanRepository(planService: sl()));
|
||||
sl.registerLazySingleton<MyDietsRepository>(() => MyDietsRepository(myDietsService: sl()));
|
||||
sl.registerLazySingleton<MyPlansRepository>(() => MyPlansRepository(myPlansService: sl()));
|
||||
sl.registerLazySingleton<AboutRecipeRepository>(() => AboutRecipeRepository(recipeService: sl()));
|
||||
|
||||
// Services
|
||||
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
|
||||
@@ -129,7 +134,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<RegistrationService>(() => RegistrationService(sl()));
|
||||
sl.registerLazySingleton<CalendarService>(() => CalendarService(sl()));
|
||||
sl.registerLazySingleton<ProfileService>(() => ProfileService(sl()));
|
||||
sl.registerLazySingleton<RecipeService>(() => RecipeService(sl()));
|
||||
sl.registerLazySingleton<CreateRecipeService>(() => CreateRecipeService(sl()));
|
||||
sl.registerLazySingleton<SettingsService>(() => SettingsService(sl()));
|
||||
sl.registerLazySingleton<ConsultantService>(() => ConsultantService(sl()));
|
||||
sl.registerLazySingleton<DiaryService>(() => DiaryService(sl()));
|
||||
@@ -142,6 +147,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<MyDietsService>(() => MyDietsService(sl()));
|
||||
sl.registerLazySingleton<MyPlansService>(() => MyPlansService(sl()));
|
||||
sl.registerLazySingleton<WsService>(() => WsService(sl()));
|
||||
sl.registerLazySingleton<AboutRecipeService>(() => AboutRecipeService(sl()));
|
||||
|
||||
// External
|
||||
sl.registerLazySingleton(
|
||||
|
||||
5
lib/core/utils/enums.dart
Normal file
5
lib/core/utils/enums.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
enum ProductType {
|
||||
diet,
|
||||
plan,
|
||||
recipe
|
||||
}
|
||||
@@ -41,3 +41,33 @@ String getCommentForm(int number, S s) {
|
||||
return s.comments_plural;
|
||||
}
|
||||
}
|
||||
|
||||
String getMinuteForm(int number) {
|
||||
if (number % 10 == 1 && number % 100 != 11) {
|
||||
return S.current.minute;
|
||||
} else if ([2, 3, 4].contains(number % 10) && ![12, 13, 14].contains(number % 100)) {
|
||||
return S.current.minutes;
|
||||
} else {
|
||||
return S.current.another_form_of_minute;
|
||||
}
|
||||
}
|
||||
|
||||
String getHourForm(int number) {
|
||||
if (number % 10 == 1 && number % 100 != 11) {
|
||||
return S.current.hour;
|
||||
} else if ([2, 3, 4].contains(number % 10) && ![12, 13, 14].contains(number % 100)) {
|
||||
return S.current.another_form_of_hour;
|
||||
} else {
|
||||
return S.current.hours;
|
||||
}
|
||||
}
|
||||
|
||||
String getStepForm(int number) {
|
||||
if (number % 10 == 1 && number % 100 != 11) {
|
||||
return S.current.stage;
|
||||
} else if ([2, 3, 4].contains(number % 10) && ![12, 13, 14].contains(number % 100)) {
|
||||
return S.current.another_form_of_stage;
|
||||
} else {
|
||||
return S.current.stages;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/type_badges.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -11,21 +13,35 @@ import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class InfoRow extends StatelessWidget {
|
||||
const InfoRow({
|
||||
required this.type,
|
||||
super.key,
|
||||
this.diet,
|
||||
this.itemsBackgroundColor,
|
||||
this.disableDescriptionOfTypes = false,
|
||||
this.plan,
|
||||
this.recipe,
|
||||
});
|
||||
final ProductType type;
|
||||
final Color? itemsBackgroundColor;
|
||||
final Diet? diet;
|
||||
final PlanModel? plan;
|
||||
final Recipe? recipe;
|
||||
|
||||
final bool disableDescriptionOfTypes;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
|
||||
String? timeTitle;
|
||||
if (recipe != null) {
|
||||
final hours = recipe!.cookingTime ~/ 60;
|
||||
final minutes = recipe!.cookingTime % 60;
|
||||
if (hours > 0) {
|
||||
timeTitle = '$hours ${getHourForm(hours)} $minutes ${getMinuteForm(minutes)}';
|
||||
} else {
|
||||
timeTitle = '$minutes ${getMinuteForm(minutes)}';
|
||||
}
|
||||
}
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
scrollDirection: Axis.horizontal,
|
||||
@@ -41,7 +57,11 @@ class InfoRow extends StatelessWidget {
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
diet == null ? '${plan?.duration} ${getDayForm(plan?.duration ?? 7, s)}' : '${diet?.duration} ${getDayForm(diet?.duration ?? 7, s)}',
|
||||
switch (type) {
|
||||
ProductType.diet => '${diet?.duration} ${getDayForm(diet?.duration ?? 7, s)}',
|
||||
ProductType.plan => '${plan?.duration} ${getDayForm(plan?.duration ?? 7, s)}',
|
||||
ProductType.recipe => '${timeTitle ?? ''}',
|
||||
},
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
@@ -51,18 +71,42 @@ class InfoRow extends StatelessWidget {
|
||||
backgroundColor: itemsBackgroundColor,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/people.svg',
|
||||
switch (type) {
|
||||
ProductType.diet => 'assets/icons/people.svg',
|
||||
ProductType.plan => 'assets/icons/people.svg',
|
||||
ProductType.recipe => 'assets/icons/calories.svg',
|
||||
},
|
||||
width: 13.3,
|
||||
height: 13.3,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'80 человек прошли',
|
||||
switch (type) {
|
||||
ProductType.diet => '80 человек прошли',
|
||||
ProductType.plan => '80 человек прошли',
|
||||
ProductType.recipe => (recipe?.calories.toStringAsFixed(0) ?? '0') + ' ккал',
|
||||
},
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
if (type == ProductType.recipe)
|
||||
InfoBouble(
|
||||
backgroundColor: itemsBackgroundColor,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/steps.svg',
|
||||
width: 13.3,
|
||||
height: 13.3,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'${recipe?.steps?.length ?? 0} ${getStepForm(recipe?.steps?.length ?? 0)}',
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (plan?.type.hasAtLeastOneType() == true || diet?.type.hasAtLeastOneType() == true)
|
||||
InfoBouble(
|
||||
backgroundColor: itemsBackgroundColor,
|
||||
|
||||
@@ -19,5 +19,3 @@ class CreateDietModel with _$CreateDietModel {
|
||||
List<List<List<DailySchedule>>>? dailySchedule,
|
||||
}) = _CreateDietModel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -233,7 +233,13 @@ class _CreateDietScreenContentState extends State<CreateDietScreenContent> {
|
||||
else
|
||||
CustomOutlinedButton(
|
||||
onPressed: () {
|
||||
context.read<CreateDietCubit>().publishDiet();
|
||||
if (widget.diet != null) {
|
||||
context.read<CreateDietCubit>().updateDiet(
|
||||
widget.diet!.id,
|
||||
);
|
||||
} else {
|
||||
context.read<CreateDietCubit>().createDiet();
|
||||
}
|
||||
},
|
||||
text: widget.diet != null ? s.save : s.publish,
|
||||
height: 52,
|
||||
|
||||
@@ -18,6 +18,7 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
final ProfileRepository profileRepository;
|
||||
final GlossaryRepository glossaryRepository;
|
||||
String? tempImagePath;
|
||||
int? dietId;
|
||||
static const _dietStateValues = DietState.values;
|
||||
|
||||
CreateDietCubit({required this.profileRepository, required this.createDietRepository, required this.glossaryRepository}) : super(CreateDietState.initial());
|
||||
@@ -25,10 +26,12 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
Future<void> setInitialData(Diet? diet) async {
|
||||
if (diet == null) return;
|
||||
emit(state.copyWith(isLoading: true, isDietBeingEdited: true));
|
||||
final countOfDays = diet.dailySchedule.length;
|
||||
dietId = diet.id;
|
||||
final dailyScheduleWithNutrition = await createDietRepository.getDietPortionsNutrition(diet.id);
|
||||
final countOfDays = dailyScheduleWithNutrition.length;
|
||||
final List<List<List<DailySchedule>>> dailySchedule = List.generate(countOfDays, (index) => [[], [], [], [], []]);
|
||||
|
||||
for (final dayEntry in diet.dailySchedule.entries) {
|
||||
for (final dayEntry in dailyScheduleWithNutrition.entries) {
|
||||
for (final mealEntry in dayEntry.value.entries) {
|
||||
for (final product in mealEntry.value.values) {
|
||||
dailySchedule[dayEntry.key - 1][mealEntry.key - 1].add(product);
|
||||
@@ -318,7 +321,7 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
return diet;
|
||||
}
|
||||
|
||||
Future<String?> publishDiet() async {
|
||||
Future<String?> createDiet() async {
|
||||
emit(state.copyWith(isDietPublishing: true));
|
||||
if (!_isFromValid()) return null;
|
||||
try {
|
||||
@@ -347,6 +350,33 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<String?> updateDiet(int dietId) async {
|
||||
if (!_isFromValid()) return null;
|
||||
try {
|
||||
File? image;
|
||||
if (state.dietData.image != null) {
|
||||
image = await ImageCompressUtility.compressFile(File(state.dietData.image!.path));
|
||||
}
|
||||
await createDietRepository.updateDiet(
|
||||
dietId: dietId,
|
||||
name: state.dietData.name,
|
||||
duration: state.dietData.duration,
|
||||
state: state.dietData.state ?? DietState.active,
|
||||
image: image,
|
||||
meatType: state.dietData.type['meat'] == true ? '1' : '0',
|
||||
carbType: state.dietData.type['carb'] == true ? '1' : '0',
|
||||
vegType: state.dietData.type['veg'] == true ? '1' : '0',
|
||||
lightType: state.dietData.type['light'] == true ? '1' : '0',
|
||||
details: state.dietData.details,
|
||||
dailySchedule: state.dietData.dailySchedule,
|
||||
);
|
||||
return null;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
return 'Произошла непредвиденная ошибка';
|
||||
}
|
||||
}
|
||||
|
||||
bool _isFromValid() {
|
||||
bool result = true;
|
||||
if ((state.dietData.name?.length ?? 0) < 3) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
@@ -300,7 +301,7 @@ class _DietPreviewScreenState extends State<DietPreviewScreen> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
InfoRow(diet: widget.diet),
|
||||
InfoRow(diet: widget.diet, type: ProductType.diet,),
|
||||
ExpandableText(
|
||||
text: widget.diet.details,
|
||||
),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
||||
@@ -33,6 +35,7 @@ class _AddMealWidgetState extends State<AddMealWidget> {
|
||||
GlossaryModel? selectedGlossary;
|
||||
final productNameController = TextEditingController();
|
||||
final quantityController = TextEditingController();
|
||||
List<GlossaryModel> glossariesList = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -66,47 +69,27 @@ class _AddMealWidgetState extends State<AddMealWidget> {
|
||||
children: [
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width * 0.8 - 32,
|
||||
child: TypeAheadField<GlossaryModel>(
|
||||
child: CustomTextFormField(
|
||||
controller: productNameController,
|
||||
itemBuilder: (context, glossary) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
glossary.name,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
autofocus: true,
|
||||
hintText: 'Введите название продукта/блюда',
|
||||
onChanged: (query) {
|
||||
EasyDebounce.debounce(
|
||||
'glossary-search',
|
||||
Duration(milliseconds: 250),
|
||||
() async {
|
||||
selectedGlossary = null;
|
||||
if (query.isEmpty) {
|
||||
glossariesList = [];
|
||||
selectedGlossary = null;
|
||||
setState(() {});
|
||||
return;
|
||||
}
|
||||
glossariesList = await widget.createDietCubit.getGlossaryListByQuery(query);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
itemSeparatorBuilder: (context, index) => _divider(context),
|
||||
onSelected: (newSelectedGlossary) async {
|
||||
setState(() {
|
||||
selectedGlossary = newSelectedGlossary;
|
||||
productNameController.text = selectedGlossary!.name;
|
||||
});
|
||||
},
|
||||
suggestionsCallback: (query) async {
|
||||
if (query.length < 1) return [];
|
||||
final suggestionsList = await widget.createDietCubit.getGlossaryListByQuery(query);
|
||||
return suggestionsList;
|
||||
},
|
||||
builder: (context, controller, focusNode) {
|
||||
return CustomTextFormField(
|
||||
controller: controller,
|
||||
autofocus: true,
|
||||
focusNode: focusNode,
|
||||
hintText: 'Введите название продукта/блюда',
|
||||
);
|
||||
},
|
||||
emptyBuilder: (context) {
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
errorBuilder: (context, object) => Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text('Нет подходящих вариантов'),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
@@ -129,7 +112,56 @@ class _AddMealWidgetState extends State<AddMealWidget> {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
glossariesList.isEmpty ? const SizedBox(height: 16) : const SizedBox.shrink(),
|
||||
Container(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: 256,
|
||||
),
|
||||
child: ListView.separated(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, i) {
|
||||
return ListTile(
|
||||
onTap: () async {
|
||||
setState(() {
|
||||
selectedGlossary = glossariesList[i];
|
||||
productNameController.text = selectedGlossary!.name;
|
||||
});
|
||||
glossariesList = [];
|
||||
setState(() {});
|
||||
FocusManager.instance.primaryFocus?.nextFocus();
|
||||
},
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
title: Text(
|
||||
glossariesList[i].name,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
subtitle: glossariesList[i].grInPortion == 0
|
||||
? null
|
||||
: Text(
|
||||
'${glossariesList[i].grInPortion} г',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
trailing: Icon(
|
||||
Icons.add_rounded,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
contentPadding: EdgeInsets.only(left: 12),
|
||||
);
|
||||
},
|
||||
itemCount: glossariesList.length,
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return CustomDivider();
|
||||
},
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
if (widget.portionIndex != null)
|
||||
@@ -188,7 +220,7 @@ class _AddMealWidgetState extends State<AddMealWidget> {
|
||||
|
||||
Future<void> addPortion() async {
|
||||
final portionIndex = widget.portionIndex;
|
||||
final measurementUnits = selectedGlossary?.grInPortion == null
|
||||
var measurementUnits = selectedGlossary?.grInPortion == null
|
||||
? Portion.PCS
|
||||
: selectedGlossary?.grInPortion == 0
|
||||
? Portion.GRAMS
|
||||
@@ -199,7 +231,7 @@ class _AddMealWidgetState extends State<AddMealWidget> {
|
||||
final portion = DailySchedule(
|
||||
dailyNutrition: DailyNutrition(energy: calories, proteins: proteins, fats: fats, carbohydrates: carbohydrates),
|
||||
quantity: int.parse(quantityController.text),
|
||||
name: glossary.name,
|
||||
name: glossary.name,
|
||||
productNutritionalValueId: glossary.id.toString(),
|
||||
portion: measurementUnits,
|
||||
);
|
||||
@@ -234,7 +266,8 @@ class _AddMealWidgetState extends State<AddMealWidget> {
|
||||
),
|
||||
);
|
||||
if (newGlossary != null) {
|
||||
final [calories, carbohydrates, proteins, fats] = _getCPFC(newGlossary, Portion.GRAMS);
|
||||
measurementUnits = Portion.GRAMS;
|
||||
final [calories, carbohydrates, proteins, fats] = _getCPFC(newGlossary, measurementUnits);
|
||||
final portion = DailySchedule(
|
||||
dailyNutrition: DailyNutrition(energy: calories, proteins: proteins, fats: fats, carbohydrates: carbohydrates),
|
||||
quantity: int.parse(quantityController.text),
|
||||
|
||||
@@ -58,4 +58,97 @@ class CreateDietRepository {
|
||||
return createDietService.createPersonalDiet(formData: formData);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<int, Map<int, Map<int, DailySchedule>>>> getDietPortionsNutrition(int dietId) async {
|
||||
try {
|
||||
final response = await createDietService.getDietPortionsNutrition(diet: dietId);
|
||||
final data = response.data;
|
||||
final dailySchedule = (data as Map<String, dynamic>).map((key, value) {
|
||||
return MapEntry(
|
||||
int.parse(key),
|
||||
(value as Map<String, dynamic>).map((key, value) {
|
||||
return MapEntry(
|
||||
int.parse(key),
|
||||
(value as Map<String, dynamic>).map((key, value) {
|
||||
return MapEntry(int.parse(key), DailySchedule.fromJson(value as Map<String, dynamic>));
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
});
|
||||
return dailySchedule;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateDiet({
|
||||
required int dietId,
|
||||
required DietState state,
|
||||
String? name,
|
||||
int? duration,
|
||||
String? meatType,
|
||||
String? carbType,
|
||||
String? vegType,
|
||||
String? lightType,
|
||||
String? details,
|
||||
File? image,
|
||||
List<List<List<DailySchedule>>>? dailySchedule,
|
||||
}) {
|
||||
final dietMap = <String, dynamic>{};
|
||||
if (dailySchedule != null) {
|
||||
for (final (dayIndex, day) in dailySchedule.indexed) {
|
||||
for (final (mealIndex, meal) in day.indexed) {
|
||||
for (final (productIndex, product) in meal.indexed) {
|
||||
final jsonProduct = product.toJson();
|
||||
dietMap.addAll({
|
||||
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][name]': jsonProduct['name'],
|
||||
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][portion]': jsonProduct['portion'],
|
||||
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][quantity]': jsonProduct['quantity'],
|
||||
'daily_schedule[${dayIndex + 1}][${mealIndex + 1}][${productIndex}][product_nutritional_value_id]': jsonProduct['product_nutritional_value_id'],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name != null) {
|
||||
dietMap.addAll({'name': name});
|
||||
}
|
||||
if (details != null) {
|
||||
dietMap.addAll({'details': details});
|
||||
}
|
||||
if (duration != null) {
|
||||
dietMap.addAll({'duration': duration});
|
||||
}
|
||||
if (meatType != null) {
|
||||
dietMap.addAll({'type[meat]': meatType});
|
||||
}
|
||||
if (carbType != null) {
|
||||
dietMap.addAll({'type[carb]': carbType});
|
||||
}
|
||||
if (vegType != null) {
|
||||
dietMap.addAll({'type[veg]': vegType});
|
||||
}
|
||||
if (lightType != null) {
|
||||
dietMap.addAll({'type[light]': lightType});
|
||||
}
|
||||
if (image != null) {
|
||||
dietMap.addAll({
|
||||
'image': MultipartFile.fromFileSync(
|
||||
image.path,
|
||||
filename: image.path.split(Platform.pathSeparator).last,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
final formData = FormData.fromMap(dietMap);
|
||||
switch (state) {
|
||||
case DietState.active:
|
||||
return createDietService.updatePublished(diet: dietId, formData: formData);
|
||||
case DietState.draft:
|
||||
return createDietService.updateDrafted(diet: dietId, formData: formData);
|
||||
case DietState.personal:
|
||||
return createDietService.updatePersonal(diet: dietId, formData: formData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,30 @@ abstract class CreateDietService {
|
||||
Future<CreatedDiet> createPersonalDiet({
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@PUT('/api/diets/update/published/{diet}')
|
||||
@MultiPart()
|
||||
Future<void> updatePublished({
|
||||
@Path() required int diet,
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@PUT('/api/diets/update/drafted/{diet}')
|
||||
@MultiPart()
|
||||
Future<void> updateDrafted({
|
||||
@Path() required int diet,
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@PUT('/api/diets/update/personalized/{diet}')
|
||||
@MultiPart()
|
||||
Future<void> updatePersonal({
|
||||
@Path() required int diet,
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@GET('/api/diets/show/{diet}/per_portion_nutritions')
|
||||
Future<HttpResponse> getDietPortionsNutrition({
|
||||
@Path() required int diet,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -113,6 +113,111 @@ class _CreateDietService implements CreateDietService {
|
||||
return _value;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePublished({
|
||||
required int diet,
|
||||
required FormData formData,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = formData;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(
|
||||
method: 'PUT',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
contentType: 'multipart/form-data',
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/diets/update/published/${diet}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateDrafted({
|
||||
required int diet,
|
||||
required FormData formData,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = formData;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(
|
||||
method: 'PUT',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
contentType: 'multipart/form-data',
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/diets/update/drafted/${diet}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updatePersonal({
|
||||
required int diet,
|
||||
required FormData formData,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = formData;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(
|
||||
method: 'PUT',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
contentType: 'multipart/form-data',
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/diets/update/personalized/${diet}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<HttpResponse<dynamic>> getDietPortionsNutrition({
|
||||
required int diet,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<HttpResponse<dynamic>>(
|
||||
Options(method: 'GET', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/diets/show/${diet}/per_portion_nutritions',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
final _result = await _dio.fetch(_options);
|
||||
final _value = _result.data;
|
||||
final httpResponse = HttpResponse(_value, _result);
|
||||
return httpResponse;
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:eatvio_app/features/recipes/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_model.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/step.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_model.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/step.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'recipe_create_entity.freezed.dart';
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:eatvio_app/features/recipes/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/step.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/step.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'recipe_create_model.freezed.dart';
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:eatvio_app/features/recipes/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/step.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/step.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'recipe_model.freezed.dart';
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:eatvio_app/features/recipes/entities/recipe_create_entity.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/recipes/reporitories/recipe_repository.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/entities/recipe_create_entity.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/reporitories/recipe_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class CreateRecipeCubit extends Cubit<CreateRecipeState> {
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:eatvio_app/features/recipes/entities/recipe_create_entity.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/entities/recipe_create_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'create_recipe_state.freezed.dart';
|
||||
@@ -1,11 +1,11 @@
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/info_about_recipe_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/ingredients_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/steps_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/info_about_recipe_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/ingredients_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/steps_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -3,13 +3,13 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_drop_down.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/entities/recipe_create_entity.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/image_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/portion_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/tags_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/time_of_cook_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/entities/recipe_create_entity.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/image_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/portion_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/tags_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/time_of_cook_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/ingredient.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/widgets/step_image_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/step_image_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_model.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_tag_model.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/step.dart';
|
||||
import 'package:eatvio_app/features/recipes/services/recipe_service.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/product.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_model.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_tag_model.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/step.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/services/recipe_service.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/product.dart';
|
||||
|
||||
class RecipeRepository {
|
||||
final RecipeService recipeService;
|
||||
final CreateRecipeService recipeService;
|
||||
|
||||
|
||||
RecipeRepository({required this.recipeService});
|
||||
|
||||
@@ -99,5 +100,5 @@ class RecipeRepository {
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
lib/features/create_recipe/services/recipe_service.dart
Normal file
47
lib/features/create_recipe/services/recipe_service.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_model.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_tag_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/product.dart';
|
||||
|
||||
part 'recipe_service.g.dart';
|
||||
|
||||
@RestApi()
|
||||
abstract class CreateRecipeService {
|
||||
factory CreateRecipeService(Dio dio, {String baseUrl}) = _CreateRecipeService;
|
||||
|
||||
@POST('/api/recipes/{slug}/like')
|
||||
Future<void> likeRecipe({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/{slug}/add_to_favorite')
|
||||
Future<void> addToFavorite({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/{slug}/remove_from_favorite')
|
||||
Future<void> removeFromFavorite({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@GET('/api/recipes/show/{id}')
|
||||
Future<RecipeModel> getRecipe(@Path() String id);
|
||||
|
||||
@GET('/api/diary/product_nutritional_values/filter')
|
||||
Future<Map<String, List<Product>>> getInputProduct(@Query('name') String name);
|
||||
|
||||
@POST('/api/recipes/create')
|
||||
@MultiPart()
|
||||
Future<void> publishRecipe({
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/update/{id}')
|
||||
Future<RecipeModel> editRecipe(@Part() Map<String, Object?> recipe, String id);
|
||||
|
||||
@GET('/api/recipes/tags')
|
||||
Future<RecipeTagModel> getTags();
|
||||
|
||||
|
||||
}
|
||||
@@ -8,8 +8,8 @@ part of 'recipe_service.dart';
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
|
||||
|
||||
class _RecipeService implements RecipeService {
|
||||
_RecipeService(this._dio, {this.baseUrl, this.errorLogger});
|
||||
class _CreateRecipeService implements CreateRecipeService {
|
||||
_CreateRecipeService(this._dio, {this.baseUrl, this.errorLogger});
|
||||
|
||||
final Dio _dio;
|
||||
|
||||
@@ -17,6 +17,63 @@ class _RecipeService implements RecipeService {
|
||||
|
||||
final ParseErrorLogger? errorLogger;
|
||||
|
||||
@override
|
||||
Future<void> likeRecipe({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/like',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addToFavorite({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/add_to_favorite',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeFromFavorite({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/remove_from_favorite',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<RecipeModel> getRecipe(String id) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
@@ -8,7 +8,7 @@ import 'package:eatvio_app/features/chat/services/chat_service.dart';
|
||||
import 'package:eatvio_app/features/diets/services/diet_service.dart';
|
||||
import 'package:eatvio_app/features/feed/services/feed_service.dart';
|
||||
import 'package:eatvio_app/features/profile/services/profile_service.dart';
|
||||
import 'package:eatvio_app/features/recipes/services/recipe_service.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/services/recipe_service.dart';
|
||||
|
||||
sealed class TestCases {
|
||||
String get name => throw UnimplementedError();
|
||||
@@ -247,7 +247,7 @@ class GetRecipes implements TestCases {
|
||||
try {
|
||||
final dio = sl<Dio>();
|
||||
final feedService = FeedService(dio, baseUrl: baseUrl);
|
||||
final recipeService = RecipeService(dio, baseUrl: baseUrl);
|
||||
final recipeService = CreateRecipeService(dio, baseUrl: baseUrl);
|
||||
final tagsModel = await recipeService.getTags();
|
||||
final tags = tagsModel.data;
|
||||
final tagsIds = tags.map((e) => e.id).toList();
|
||||
@@ -431,7 +431,7 @@ class GetRecipesComments implements TestCases {
|
||||
try {
|
||||
final dio = sl<Dio>();
|
||||
final feedService = FeedService(dio, baseUrl: baseUrl);
|
||||
final recipeService = RecipeService(dio, baseUrl: baseUrl);
|
||||
final recipeService = CreateRecipeService(dio, baseUrl: baseUrl);
|
||||
final tagsModel = await recipeService.getTags();
|
||||
final tags = tagsModel.data;
|
||||
final tagsIds = tags.map((e) => e.id).toList();
|
||||
|
||||
@@ -89,6 +89,12 @@ class _AddProductModalState extends State<AddProductModal> {
|
||||
'glossary-search',
|
||||
Duration(milliseconds: 250),
|
||||
() async {
|
||||
selectedGlossary = null;
|
||||
if (query.isEmpty) {
|
||||
glossariesList = [];
|
||||
setState(() {});
|
||||
return;
|
||||
}
|
||||
glossariesList = await widget.diaryCubit.getGlossaryListByQuery(query);
|
||||
setState(() {});
|
||||
},
|
||||
@@ -131,7 +137,7 @@ class _AddProductModalState extends State<AddProductModal> {
|
||||
selectedGlossary = glossariesList[i];
|
||||
productNameController.text = selectedGlossary!.name;
|
||||
});
|
||||
glossariesList = await widget.diaryCubit.getGlossaryListByQuery(glossariesList[i].name);
|
||||
glossariesList = [];
|
||||
setState(() {});
|
||||
FocusManager.instance.primaryFocus?.nextFocus();
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/glossary/models/glossary_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
class GlossaryModerationRequestModalWidget extends StatefulWidget {
|
||||
@@ -31,13 +32,13 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
||||
GlossaryModel? glossary;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (glossaryState == GlossaryState.alert) {
|
||||
return _alert();
|
||||
} else if (glossaryState == GlossaryState.success) {
|
||||
return _success();
|
||||
} else {
|
||||
return _addNewGlossaryProduct();
|
||||
}
|
||||
return PopScope(
|
||||
child: switch (glossaryState) {
|
||||
GlossaryState.alert => _alert(),
|
||||
GlossaryState.addNewProduct => _addNewGlossaryProduct(),
|
||||
GlossaryState.success => _success(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
@@ -419,7 +420,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
InfoRow(diet: widget.diet),
|
||||
InfoRow(diet: widget.diet, type: ProductType.diet,),
|
||||
ExpandableText(
|
||||
text: widget.diet.details,
|
||||
),
|
||||
@@ -466,7 +467,7 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
dietState.diet.totalComments.toString() + ' ' + getCommentForm(widget.diet.totalComments, s),
|
||||
dietState.diet.totalComments.toString() + ' ' + getCommentForm(dietState.diet.totalComments, s),
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.gray500,
|
||||
),
|
||||
|
||||
@@ -40,6 +40,7 @@ class _ExpandableTextState extends State<ExpandableText> {
|
||||
data: widget.text,
|
||||
style: {
|
||||
"*": Style(
|
||||
margin: Margins.all(0),
|
||||
color: Colors.black87,
|
||||
maxLines: isExpanded ? null : widget.maxLines,
|
||||
textOverflow: TextOverflow.clip,
|
||||
|
||||
@@ -96,7 +96,7 @@ class DailySchedule with _$DailySchedule {
|
||||
@JsonKey(name: "name") required String name,
|
||||
@JsonKey(name: "portion") required Portion portion,
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity) required int quantity,
|
||||
@JsonKey(includeToJson: false, includeFromJson: false) DailyNutrition? dailyNutrition,
|
||||
@JsonKey(name: 'nutrition', includeToJson: false) DailyNutrition? dailyNutrition,
|
||||
@JsonKey(name: 'product_nutritional_value_id', includeToJson: true, includeFromJson: false, includeIfNull: false) String? productNutritionalValueId,
|
||||
}) = _DailySchedule;
|
||||
|
||||
@@ -117,10 +117,21 @@ enum Portion {
|
||||
@JsonValue("milliliters")
|
||||
MILLILITERS,
|
||||
@JsonValue("pcs")
|
||||
PCS
|
||||
}
|
||||
PCS;
|
||||
|
||||
final portionValues = EnumValues({"grams": Portion.GRAMS, "milliliters": Portion.MILLILITERS, "pcs": Portion.PCS});
|
||||
static Portion? getPortionFromValue(String value) {
|
||||
switch (value) {
|
||||
case 'gr':
|
||||
return Portion.GRAMS;
|
||||
case 'milliliters':
|
||||
return Portion.MILLILITERS;
|
||||
case 'pcs':
|
||||
return Portion.PCS;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DietType with _$DietType {
|
||||
|
||||
@@ -1246,7 +1246,7 @@ mixin _$DailySchedule {
|
||||
Portion get portion => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity)
|
||||
int get quantity => throw _privateConstructorUsedError;
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
@JsonKey(name: 'nutrition', includeToJson: false)
|
||||
DailyNutrition? get dailyNutrition => throw _privateConstructorUsedError;
|
||||
@JsonKey(
|
||||
name: 'product_nutritional_value_id',
|
||||
@@ -1275,7 +1275,7 @@ abstract class $DailyScheduleCopyWith<$Res> {
|
||||
{@JsonKey(name: "name") String name,
|
||||
@JsonKey(name: "portion") Portion portion,
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity) int quantity,
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
@JsonKey(name: 'nutrition', includeToJson: false)
|
||||
DailyNutrition? dailyNutrition,
|
||||
@JsonKey(
|
||||
name: 'product_nutritional_value_id',
|
||||
@@ -1359,7 +1359,7 @@ abstract class _$$DailyScheduleImplCopyWith<$Res>
|
||||
{@JsonKey(name: "name") String name,
|
||||
@JsonKey(name: "portion") Portion portion,
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity) int quantity,
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
@JsonKey(name: 'nutrition', includeToJson: false)
|
||||
DailyNutrition? dailyNutrition,
|
||||
@JsonKey(
|
||||
name: 'product_nutritional_value_id',
|
||||
@@ -1424,8 +1424,7 @@ class _$DailyScheduleImpl implements _DailySchedule {
|
||||
@JsonKey(name: "portion") required this.portion,
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity)
|
||||
required this.quantity,
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
this.dailyNutrition,
|
||||
@JsonKey(name: 'nutrition', includeToJson: false) this.dailyNutrition,
|
||||
@JsonKey(
|
||||
name: 'product_nutritional_value_id',
|
||||
includeToJson: true,
|
||||
@@ -1446,7 +1445,7 @@ class _$DailyScheduleImpl implements _DailySchedule {
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity)
|
||||
final int quantity;
|
||||
@override
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
@JsonKey(name: 'nutrition', includeToJson: false)
|
||||
final DailyNutrition? dailyNutrition;
|
||||
@override
|
||||
@JsonKey(
|
||||
@@ -1504,7 +1503,7 @@ abstract class _DailySchedule implements DailySchedule {
|
||||
@JsonKey(name: "portion") required final Portion portion,
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity)
|
||||
required final int quantity,
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
@JsonKey(name: 'nutrition', includeToJson: false)
|
||||
final DailyNutrition? dailyNutrition,
|
||||
@JsonKey(
|
||||
name: 'product_nutritional_value_id',
|
||||
@@ -1526,7 +1525,7 @@ abstract class _DailySchedule implements DailySchedule {
|
||||
@JsonKey(name: "quantity", fromJson: _parseQuantity)
|
||||
int get quantity;
|
||||
@override
|
||||
@JsonKey(includeToJson: false, includeFromJson: false)
|
||||
@JsonKey(name: 'nutrition', includeToJson: false)
|
||||
DailyNutrition? get dailyNutrition;
|
||||
@override
|
||||
@JsonKey(
|
||||
|
||||
@@ -117,6 +117,9 @@ _$DailyScheduleImpl _$$DailyScheduleImplFromJson(Map<String, dynamic> json) =>
|
||||
name: json['name'] as String,
|
||||
portion: $enumDecode(_$PortionEnumMap, json['portion']),
|
||||
quantity: _parseQuantity(json['quantity']),
|
||||
dailyNutrition: json['nutrition'] == null
|
||||
? null
|
||||
: DailyNutrition.fromJson(json['nutrition'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DailyScheduleImplToJson(_$DailyScheduleImpl instance) =>
|
||||
|
||||
@@ -5,12 +5,13 @@ part 'recipes_model.freezed.dart';
|
||||
part 'recipes_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class Recipes with _$Recipes {
|
||||
const factory Recipes({
|
||||
class Recipe with _$Recipe {
|
||||
const factory Recipe({
|
||||
required int id,
|
||||
required String image,
|
||||
required String state,
|
||||
@JsonKey(name: 'cooking_time') required int cookingTime,
|
||||
@JsonKey(name: 'active_time') required int activeCookingTime,
|
||||
required List<Ingredient>? ingredients,
|
||||
required String description,
|
||||
required List<Step>? steps,
|
||||
@@ -22,13 +23,14 @@ class Recipes with _$Recipes {
|
||||
required String slug,
|
||||
@JsonKey(name: 'total_comments') required int commentsCount,
|
||||
@JsonKey(name: 'was_liked_by_me') required bool wasLikedByMe,
|
||||
@JsonKey(name: 'is_favorite') required bool isFavorite,
|
||||
@JsonKey(name: 'energy_per_serving') required double calories,
|
||||
@JsonKey(name: 'total_likes') required int likesCount,
|
||||
@JsonKey(name: 'total_views') required int viewsCount,
|
||||
required Author author,
|
||||
}) = _Recipes;
|
||||
|
||||
factory Recipes.fromJson(Map<String, Object?> json) => _$RecipesFromJson(json);
|
||||
factory Recipe.fromJson(Map<String, Object?> json) => _$RecipeFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
||||
@@ -14,17 +14,19 @@ T _$identity<T>(T value) => value;
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
Recipes _$RecipesFromJson(Map<String, dynamic> json) {
|
||||
Recipe _$RecipeFromJson(Map<String, dynamic> json) {
|
||||
return _Recipes.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Recipes {
|
||||
mixin _$Recipe {
|
||||
int get id => throw _privateConstructorUsedError;
|
||||
String get image => throw _privateConstructorUsedError;
|
||||
String get state => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'cooking_time')
|
||||
int get cookingTime => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'active_time')
|
||||
int get activeCookingTime => throw _privateConstructorUsedError;
|
||||
List<Ingredient>? get ingredients => throw _privateConstructorUsedError;
|
||||
String get description => throw _privateConstructorUsedError;
|
||||
List<Step>? get steps => throw _privateConstructorUsedError;
|
||||
@@ -41,6 +43,8 @@ mixin _$Recipes {
|
||||
int get commentsCount => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'was_liked_by_me')
|
||||
bool get wasLikedByMe => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'is_favorite')
|
||||
bool get isFavorite => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'energy_per_serving')
|
||||
double get calories => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: 'total_likes')
|
||||
@@ -49,25 +53,26 @@ mixin _$Recipes {
|
||||
int get viewsCount => throw _privateConstructorUsedError;
|
||||
Author get author => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this Recipes to a JSON map.
|
||||
/// Serializes this Recipe to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of Recipes
|
||||
/// Create a copy of Recipe
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$RecipesCopyWith<Recipes> get copyWith => throw _privateConstructorUsedError;
|
||||
$RecipeCopyWith<Recipe> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $RecipesCopyWith<$Res> {
|
||||
factory $RecipesCopyWith(Recipes value, $Res Function(Recipes) then) =
|
||||
_$RecipesCopyWithImpl<$Res, Recipes>;
|
||||
abstract class $RecipeCopyWith<$Res> {
|
||||
factory $RecipeCopyWith(Recipe value, $Res Function(Recipe) then) =
|
||||
_$RecipeCopyWithImpl<$Res, Recipe>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{int id,
|
||||
String image,
|
||||
String state,
|
||||
@JsonKey(name: 'cooking_time') int cookingTime,
|
||||
@JsonKey(name: 'active_time') int activeCookingTime,
|
||||
List<Ingredient>? ingredients,
|
||||
String description,
|
||||
List<Step>? steps,
|
||||
@@ -79,6 +84,7 @@ abstract class $RecipesCopyWith<$Res> {
|
||||
String slug,
|
||||
@JsonKey(name: 'total_comments') int commentsCount,
|
||||
@JsonKey(name: 'was_liked_by_me') bool wasLikedByMe,
|
||||
@JsonKey(name: 'is_favorite') bool isFavorite,
|
||||
@JsonKey(name: 'energy_per_serving') double calories,
|
||||
@JsonKey(name: 'total_likes') int likesCount,
|
||||
@JsonKey(name: 'total_views') int viewsCount,
|
||||
@@ -88,16 +94,16 @@ abstract class $RecipesCopyWith<$Res> {
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$RecipesCopyWithImpl<$Res, $Val extends Recipes>
|
||||
implements $RecipesCopyWith<$Res> {
|
||||
_$RecipesCopyWithImpl(this._value, this._then);
|
||||
class _$RecipeCopyWithImpl<$Res, $Val extends Recipe>
|
||||
implements $RecipeCopyWith<$Res> {
|
||||
_$RecipeCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of Recipes
|
||||
/// Create a copy of Recipe
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
@@ -106,6 +112,7 @@ class _$RecipesCopyWithImpl<$Res, $Val extends Recipes>
|
||||
Object? image = null,
|
||||
Object? state = null,
|
||||
Object? cookingTime = null,
|
||||
Object? activeCookingTime = null,
|
||||
Object? ingredients = freezed,
|
||||
Object? description = null,
|
||||
Object? steps = freezed,
|
||||
@@ -117,6 +124,7 @@ class _$RecipesCopyWithImpl<$Res, $Val extends Recipes>
|
||||
Object? slug = null,
|
||||
Object? commentsCount = null,
|
||||
Object? wasLikedByMe = null,
|
||||
Object? isFavorite = null,
|
||||
Object? calories = null,
|
||||
Object? likesCount = null,
|
||||
Object? viewsCount = null,
|
||||
@@ -139,6 +147,10 @@ class _$RecipesCopyWithImpl<$Res, $Val extends Recipes>
|
||||
? _value.cookingTime
|
||||
: cookingTime // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
activeCookingTime: null == activeCookingTime
|
||||
? _value.activeCookingTime
|
||||
: activeCookingTime // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
ingredients: freezed == ingredients
|
||||
? _value.ingredients
|
||||
: ingredients // ignore: cast_nullable_to_non_nullable
|
||||
@@ -183,6 +195,10 @@ class _$RecipesCopyWithImpl<$Res, $Val extends Recipes>
|
||||
? _value.wasLikedByMe
|
||||
: wasLikedByMe // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isFavorite: null == isFavorite
|
||||
? _value.isFavorite
|
||||
: isFavorite // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
calories: null == calories
|
||||
? _value.calories
|
||||
: calories // ignore: cast_nullable_to_non_nullable
|
||||
@@ -202,7 +218,7 @@ class _$RecipesCopyWithImpl<$Res, $Val extends Recipes>
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
/// Create a copy of Recipes
|
||||
/// Create a copy of Recipe
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
@@ -214,7 +230,7 @@ class _$RecipesCopyWithImpl<$Res, $Val extends Recipes>
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$RecipesImplCopyWith<$Res> implements $RecipesCopyWith<$Res> {
|
||||
abstract class _$$RecipesImplCopyWith<$Res> implements $RecipeCopyWith<$Res> {
|
||||
factory _$$RecipesImplCopyWith(
|
||||
_$RecipesImpl value, $Res Function(_$RecipesImpl) then) =
|
||||
__$$RecipesImplCopyWithImpl<$Res>;
|
||||
@@ -225,6 +241,7 @@ abstract class _$$RecipesImplCopyWith<$Res> implements $RecipesCopyWith<$Res> {
|
||||
String image,
|
||||
String state,
|
||||
@JsonKey(name: 'cooking_time') int cookingTime,
|
||||
@JsonKey(name: 'active_time') int activeCookingTime,
|
||||
List<Ingredient>? ingredients,
|
||||
String description,
|
||||
List<Step>? steps,
|
||||
@@ -236,6 +253,7 @@ abstract class _$$RecipesImplCopyWith<$Res> implements $RecipesCopyWith<$Res> {
|
||||
String slug,
|
||||
@JsonKey(name: 'total_comments') int commentsCount,
|
||||
@JsonKey(name: 'was_liked_by_me') bool wasLikedByMe,
|
||||
@JsonKey(name: 'is_favorite') bool isFavorite,
|
||||
@JsonKey(name: 'energy_per_serving') double calories,
|
||||
@JsonKey(name: 'total_likes') int likesCount,
|
||||
@JsonKey(name: 'total_views') int viewsCount,
|
||||
@@ -247,13 +265,13 @@ abstract class _$$RecipesImplCopyWith<$Res> implements $RecipesCopyWith<$Res> {
|
||||
|
||||
/// @nodoc
|
||||
class __$$RecipesImplCopyWithImpl<$Res>
|
||||
extends _$RecipesCopyWithImpl<$Res, _$RecipesImpl>
|
||||
extends _$RecipeCopyWithImpl<$Res, _$RecipesImpl>
|
||||
implements _$$RecipesImplCopyWith<$Res> {
|
||||
__$$RecipesImplCopyWithImpl(
|
||||
_$RecipesImpl _value, $Res Function(_$RecipesImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of Recipes
|
||||
/// Create a copy of Recipe
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
@@ -262,6 +280,7 @@ class __$$RecipesImplCopyWithImpl<$Res>
|
||||
Object? image = null,
|
||||
Object? state = null,
|
||||
Object? cookingTime = null,
|
||||
Object? activeCookingTime = null,
|
||||
Object? ingredients = freezed,
|
||||
Object? description = null,
|
||||
Object? steps = freezed,
|
||||
@@ -273,6 +292,7 @@ class __$$RecipesImplCopyWithImpl<$Res>
|
||||
Object? slug = null,
|
||||
Object? commentsCount = null,
|
||||
Object? wasLikedByMe = null,
|
||||
Object? isFavorite = null,
|
||||
Object? calories = null,
|
||||
Object? likesCount = null,
|
||||
Object? viewsCount = null,
|
||||
@@ -295,6 +315,10 @@ class __$$RecipesImplCopyWithImpl<$Res>
|
||||
? _value.cookingTime
|
||||
: cookingTime // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
activeCookingTime: null == activeCookingTime
|
||||
? _value.activeCookingTime
|
||||
: activeCookingTime // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
ingredients: freezed == ingredients
|
||||
? _value._ingredients
|
||||
: ingredients // ignore: cast_nullable_to_non_nullable
|
||||
@@ -339,6 +363,10 @@ class __$$RecipesImplCopyWithImpl<$Res>
|
||||
? _value.wasLikedByMe
|
||||
: wasLikedByMe // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isFavorite: null == isFavorite
|
||||
? _value.isFavorite
|
||||
: isFavorite // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
calories: null == calories
|
||||
? _value.calories
|
||||
: calories // ignore: cast_nullable_to_non_nullable
|
||||
@@ -367,6 +395,7 @@ class _$RecipesImpl implements _Recipes {
|
||||
required this.image,
|
||||
required this.state,
|
||||
@JsonKey(name: 'cooking_time') required this.cookingTime,
|
||||
@JsonKey(name: 'active_time') required this.activeCookingTime,
|
||||
required final List<Ingredient>? ingredients,
|
||||
required this.description,
|
||||
required final List<Step>? steps,
|
||||
@@ -378,6 +407,7 @@ class _$RecipesImpl implements _Recipes {
|
||||
required this.slug,
|
||||
@JsonKey(name: 'total_comments') required this.commentsCount,
|
||||
@JsonKey(name: 'was_liked_by_me') required this.wasLikedByMe,
|
||||
@JsonKey(name: 'is_favorite') required this.isFavorite,
|
||||
@JsonKey(name: 'energy_per_serving') required this.calories,
|
||||
@JsonKey(name: 'total_likes') required this.likesCount,
|
||||
@JsonKey(name: 'total_views') required this.viewsCount,
|
||||
@@ -397,6 +427,9 @@ class _$RecipesImpl implements _Recipes {
|
||||
@override
|
||||
@JsonKey(name: 'cooking_time')
|
||||
final int cookingTime;
|
||||
@override
|
||||
@JsonKey(name: 'active_time')
|
||||
final int activeCookingTime;
|
||||
final List<Ingredient>? _ingredients;
|
||||
@override
|
||||
List<Ingredient>? get ingredients {
|
||||
@@ -441,6 +474,9 @@ class _$RecipesImpl implements _Recipes {
|
||||
@JsonKey(name: 'was_liked_by_me')
|
||||
final bool wasLikedByMe;
|
||||
@override
|
||||
@JsonKey(name: 'is_favorite')
|
||||
final bool isFavorite;
|
||||
@override
|
||||
@JsonKey(name: 'energy_per_serving')
|
||||
final double calories;
|
||||
@override
|
||||
@@ -454,7 +490,7 @@ class _$RecipesImpl implements _Recipes {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Recipes(id: $id, image: $image, state: $state, cookingTime: $cookingTime, ingredients: $ingredients, description: $description, steps: $steps, videoUrl: $videoUrl, createdAt: $createdAt, updatedAt: $updatedAt, title: $title, type: $type, slug: $slug, commentsCount: $commentsCount, wasLikedByMe: $wasLikedByMe, calories: $calories, likesCount: $likesCount, viewsCount: $viewsCount, author: $author)';
|
||||
return 'Recipe(id: $id, image: $image, state: $state, cookingTime: $cookingTime, activeCookingTime: $activeCookingTime, ingredients: $ingredients, description: $description, steps: $steps, videoUrl: $videoUrl, createdAt: $createdAt, updatedAt: $updatedAt, title: $title, type: $type, slug: $slug, commentsCount: $commentsCount, wasLikedByMe: $wasLikedByMe, isFavorite: $isFavorite, calories: $calories, likesCount: $likesCount, viewsCount: $viewsCount, author: $author)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -467,6 +503,8 @@ class _$RecipesImpl implements _Recipes {
|
||||
(identical(other.state, state) || other.state == state) &&
|
||||
(identical(other.cookingTime, cookingTime) ||
|
||||
other.cookingTime == cookingTime) &&
|
||||
(identical(other.activeCookingTime, activeCookingTime) ||
|
||||
other.activeCookingTime == activeCookingTime) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._ingredients, _ingredients) &&
|
||||
(identical(other.description, description) ||
|
||||
@@ -485,6 +523,8 @@ class _$RecipesImpl implements _Recipes {
|
||||
other.commentsCount == commentsCount) &&
|
||||
(identical(other.wasLikedByMe, wasLikedByMe) ||
|
||||
other.wasLikedByMe == wasLikedByMe) &&
|
||||
(identical(other.isFavorite, isFavorite) ||
|
||||
other.isFavorite == isFavorite) &&
|
||||
(identical(other.calories, calories) ||
|
||||
other.calories == calories) &&
|
||||
(identical(other.likesCount, likesCount) ||
|
||||
@@ -502,6 +542,7 @@ class _$RecipesImpl implements _Recipes {
|
||||
image,
|
||||
state,
|
||||
cookingTime,
|
||||
activeCookingTime,
|
||||
const DeepCollectionEquality().hash(_ingredients),
|
||||
description,
|
||||
const DeepCollectionEquality().hash(_steps),
|
||||
@@ -513,13 +554,14 @@ class _$RecipesImpl implements _Recipes {
|
||||
slug,
|
||||
commentsCount,
|
||||
wasLikedByMe,
|
||||
isFavorite,
|
||||
calories,
|
||||
likesCount,
|
||||
viewsCount,
|
||||
author
|
||||
]);
|
||||
|
||||
/// Create a copy of Recipes
|
||||
/// Create a copy of Recipe
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@@ -535,12 +577,13 @@ class _$RecipesImpl implements _Recipes {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Recipes implements Recipes {
|
||||
abstract class _Recipes implements Recipe {
|
||||
const factory _Recipes(
|
||||
{required final int id,
|
||||
required final String image,
|
||||
required final String state,
|
||||
@JsonKey(name: 'cooking_time') required final int cookingTime,
|
||||
@JsonKey(name: 'active_time') required final int activeCookingTime,
|
||||
required final List<Ingredient>? ingredients,
|
||||
required final String description,
|
||||
required final List<Step>? steps,
|
||||
@@ -552,6 +595,7 @@ abstract class _Recipes implements Recipes {
|
||||
required final String slug,
|
||||
@JsonKey(name: 'total_comments') required final int commentsCount,
|
||||
@JsonKey(name: 'was_liked_by_me') required final bool wasLikedByMe,
|
||||
@JsonKey(name: 'is_favorite') required final bool isFavorite,
|
||||
@JsonKey(name: 'energy_per_serving') required final double calories,
|
||||
@JsonKey(name: 'total_likes') required final int likesCount,
|
||||
@JsonKey(name: 'total_views') required final int viewsCount,
|
||||
@@ -569,6 +613,9 @@ abstract class _Recipes implements Recipes {
|
||||
@JsonKey(name: 'cooking_time')
|
||||
int get cookingTime;
|
||||
@override
|
||||
@JsonKey(name: 'active_time')
|
||||
int get activeCookingTime;
|
||||
@override
|
||||
List<Ingredient>? get ingredients;
|
||||
@override
|
||||
String get description;
|
||||
@@ -596,6 +643,9 @@ abstract class _Recipes implements Recipes {
|
||||
@JsonKey(name: 'was_liked_by_me')
|
||||
bool get wasLikedByMe;
|
||||
@override
|
||||
@JsonKey(name: 'is_favorite')
|
||||
bool get isFavorite;
|
||||
@override
|
||||
@JsonKey(name: 'energy_per_serving')
|
||||
double get calories;
|
||||
@override
|
||||
@@ -607,7 +657,7 @@ abstract class _Recipes implements Recipes {
|
||||
@override
|
||||
Author get author;
|
||||
|
||||
/// Create a copy of Recipes
|
||||
/// Create a copy of Recipe
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
|
||||
@@ -12,6 +12,7 @@ _$RecipesImpl _$$RecipesImplFromJson(Map<String, dynamic> json) =>
|
||||
image: json['image'] as String,
|
||||
state: json['state'] as String,
|
||||
cookingTime: (json['cooking_time'] as num).toInt(),
|
||||
activeCookingTime: (json['active_time'] as num).toInt(),
|
||||
ingredients: (json['ingredients'] as List<dynamic>?)
|
||||
?.map((e) => Ingredient.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
@@ -27,6 +28,7 @@ _$RecipesImpl _$$RecipesImplFromJson(Map<String, dynamic> json) =>
|
||||
slug: json['slug'] as String,
|
||||
commentsCount: (json['total_comments'] as num).toInt(),
|
||||
wasLikedByMe: json['was_liked_by_me'] as bool,
|
||||
isFavorite: json['is_favorite'] as bool,
|
||||
calories: (json['energy_per_serving'] as num).toDouble(),
|
||||
likesCount: (json['total_likes'] as num).toInt(),
|
||||
viewsCount: (json['total_views'] as num).toInt(),
|
||||
@@ -39,6 +41,7 @@ Map<String, dynamic> _$$RecipesImplToJson(_$RecipesImpl instance) =>
|
||||
'image': instance.image,
|
||||
'state': instance.state,
|
||||
'cooking_time': instance.cookingTime,
|
||||
'active_time': instance.activeCookingTime,
|
||||
'ingredients': instance.ingredients,
|
||||
'description': instance.description,
|
||||
'steps': instance.steps,
|
||||
@@ -50,6 +53,7 @@ Map<String, dynamic> _$$RecipesImplToJson(_$RecipesImpl instance) =>
|
||||
'slug': instance.slug,
|
||||
'total_comments': instance.commentsCount,
|
||||
'was_liked_by_me': instance.wasLikedByMe,
|
||||
'is_favorite': instance.isFavorite,
|
||||
'energy_per_serving': instance.calories,
|
||||
'total_likes': instance.likesCount,
|
||||
'total_views': instance.viewsCount,
|
||||
|
||||
@@ -8,7 +8,7 @@ part 'recipes_pagination_model.g.dart';
|
||||
@freezed
|
||||
class RecipesPagination with _$RecipesPagination {
|
||||
const factory RecipesPagination({
|
||||
@JsonKey(name: 'data') required List<Recipes> recipesList,
|
||||
@JsonKey(name: 'data') required List<Recipe> recipesList,
|
||||
// @JsonKey(name: "current_page") required int currentPage,
|
||||
// @JsonKey(name: "first_page_url") required String firstPageUrl,
|
||||
// required int from,
|
||||
|
||||
@@ -21,7 +21,7 @@ RecipesPagination _$RecipesPaginationFromJson(Map<String, dynamic> json) {
|
||||
/// @nodoc
|
||||
mixin _$RecipesPagination {
|
||||
@JsonKey(name: 'data')
|
||||
List<Recipes> get recipesList => throw _privateConstructorUsedError;
|
||||
List<Recipe> get recipesList => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this RecipesPagination to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@@ -39,7 +39,7 @@ abstract class $RecipesPaginationCopyWith<$Res> {
|
||||
RecipesPagination value, $Res Function(RecipesPagination) then) =
|
||||
_$RecipesPaginationCopyWithImpl<$Res, RecipesPagination>;
|
||||
@useResult
|
||||
$Res call({@JsonKey(name: 'data') List<Recipes> recipesList});
|
||||
$Res call({@JsonKey(name: 'data') List<Recipe> recipesList});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -63,7 +63,7 @@ class _$RecipesPaginationCopyWithImpl<$Res, $Val extends RecipesPagination>
|
||||
recipesList: null == recipesList
|
||||
? _value.recipesList
|
||||
: recipesList // ignore: cast_nullable_to_non_nullable
|
||||
as List<Recipes>,
|
||||
as List<Recipe>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ abstract class _$$RecipesPaginationImplCopyWith<$Res>
|
||||
__$$RecipesPaginationImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({@JsonKey(name: 'data') List<Recipes> recipesList});
|
||||
$Res call({@JsonKey(name: 'data') List<Recipe> recipesList});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -98,7 +98,7 @@ class __$$RecipesPaginationImplCopyWithImpl<$Res>
|
||||
recipesList: null == recipesList
|
||||
? _value._recipesList
|
||||
: recipesList // ignore: cast_nullable_to_non_nullable
|
||||
as List<Recipes>,
|
||||
as List<Recipe>,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -107,16 +107,16 @@ class __$$RecipesPaginationImplCopyWithImpl<$Res>
|
||||
@JsonSerializable()
|
||||
class _$RecipesPaginationImpl implements _RecipesPagination {
|
||||
const _$RecipesPaginationImpl(
|
||||
{@JsonKey(name: 'data') required final List<Recipes> recipesList})
|
||||
{@JsonKey(name: 'data') required final List<Recipe> recipesList})
|
||||
: _recipesList = recipesList;
|
||||
|
||||
factory _$RecipesPaginationImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$RecipesPaginationImplFromJson(json);
|
||||
|
||||
final List<Recipes> _recipesList;
|
||||
final List<Recipe> _recipesList;
|
||||
@override
|
||||
@JsonKey(name: 'data')
|
||||
List<Recipes> get recipesList {
|
||||
List<Recipe> get recipesList {
|
||||
if (_recipesList is EqualUnmodifiableListView) return _recipesList;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_recipesList);
|
||||
@@ -160,7 +160,7 @@ class _$RecipesPaginationImpl implements _RecipesPagination {
|
||||
|
||||
abstract class _RecipesPagination implements RecipesPagination {
|
||||
const factory _RecipesPagination(
|
||||
{@JsonKey(name: 'data') required final List<Recipes> recipesList}) =
|
||||
{@JsonKey(name: 'data') required final List<Recipe> recipesList}) =
|
||||
_$RecipesPaginationImpl;
|
||||
|
||||
factory _RecipesPagination.fromJson(Map<String, dynamic> json) =
|
||||
@@ -168,7 +168,7 @@ abstract class _RecipesPagination implements RecipesPagination {
|
||||
|
||||
@override
|
||||
@JsonKey(name: 'data')
|
||||
List<Recipes> get recipesList;
|
||||
List<Recipe> get recipesList;
|
||||
|
||||
/// Create a copy of RecipesPagination
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
|
||||
@@ -10,7 +10,7 @@ _$RecipesPaginationImpl _$$RecipesPaginationImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$RecipesPaginationImpl(
|
||||
recipesList: (json['data'] as List<dynamic>)
|
||||
.map((e) => Recipes.fromJson(e as Map<String, dynamic>))
|
||||
.map((e) => Recipe.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,23 +1,46 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_state.dart';
|
||||
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_tag_model.dart';
|
||||
import 'package:eatvio_app/features/recipes/reporitories/recipe_repository.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_tag_model.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/reporitories/recipe_repository.dart';
|
||||
import 'package:eatvio_app/features/recipe/repositories/about_recipe_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class RecipesCubit extends Cubit<RecipesState> {
|
||||
final FeedRepository feedRepository;
|
||||
final RecipeRepository recipeRepository;
|
||||
final AboutRecipeRepository aboutRecipeRepository;
|
||||
Set<int> _selectedTags = {};
|
||||
int currentPage = 1;
|
||||
late int lastPage;
|
||||
bool isLoading = false;
|
||||
String? _query;
|
||||
late final StreamSubscription likesStateSubscription;
|
||||
late final StreamSubscription favoriteStateSubscription;
|
||||
late final StreamSubscription commentsStateSubscription;
|
||||
|
||||
RecipesCubit({
|
||||
required this.feedRepository,
|
||||
required this.recipeRepository,
|
||||
}) : super(const RecipesState.loading());
|
||||
required this.aboutRecipeRepository,
|
||||
}) : super(RecipesState.initial()) {
|
||||
likesStateSubscription = aboutRecipeRepository.recipeLikeState.listen((likesState) {
|
||||
_changeRecipeLikeState(likesState);
|
||||
});
|
||||
favoriteStateSubscription = aboutRecipeRepository.recipeFavoriteState.listen((favoriteState) {
|
||||
_changeRecipeFavoriteState(favoriteState);
|
||||
});
|
||||
commentsStateSubscription = aboutRecipeRepository.recipeCommentsState.listen((commentsState) {
|
||||
_changeRecipeCommentsState(commentsState);
|
||||
});
|
||||
}
|
||||
|
||||
loadRecipesList({
|
||||
String? query,
|
||||
@@ -28,9 +51,10 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
tags: _selectedTags.toList(),
|
||||
query: query,
|
||||
);
|
||||
|
||||
final recipesTags = (await recipeRepository.getRecipesTags());
|
||||
emit(
|
||||
RecipesState.loaded(
|
||||
state.copyWith(
|
||||
recipesList: recipesList,
|
||||
recipesTags: recipesTags,
|
||||
selectedTags: _selectedTags,
|
||||
@@ -41,7 +65,7 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
lastPage = currentPage;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
emit(RecipesState.error(errorMessage: e.toString()));
|
||||
emit(state.copyWith(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +73,7 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
if (currentPage < lastPage && !isLoading) {
|
||||
isLoading = true;
|
||||
|
||||
emit((state as RecipesStateLoaded).copyWith(isLoading: isLoading));
|
||||
emit(state.copyWith(isLoading: isLoading));
|
||||
|
||||
try {
|
||||
if (currentPage < lastPage) {
|
||||
@@ -61,9 +85,9 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
);
|
||||
isLoading = false;
|
||||
emit(
|
||||
(state as RecipesStateLoaded).copyWith(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...(state as RecipesStateLoaded).recipesList,
|
||||
...state.recipesList,
|
||||
...recipesList,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
@@ -72,7 +96,7 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
}
|
||||
lastPage = currentPage;
|
||||
} catch (e) {
|
||||
emit(RecipesState.error(errorMessage: e.toString()));
|
||||
emit(state.copyWith(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,14 +104,202 @@ class RecipesCubit extends Cubit<RecipesState> {
|
||||
updateTags(RecipeTag tag) {
|
||||
_selectedTags.contains(tag.id) ? _selectedTags.remove(tag.id) : _selectedTags.add(tag.id);
|
||||
emit(
|
||||
(state as RecipesStateLoaded).copyWith(
|
||||
state.copyWith(
|
||||
selectedTags: _selectedTags,
|
||||
selectedTagsCounter: _selectedTags.length,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
likeRecipe(String slug) async => await feedRepository.likeRecipe(slug: slug);
|
||||
Future<void> addRecipeToFavorite(String slug, int index) async {
|
||||
final currentRecipes = state.recipesList;
|
||||
final recipesForModification = [...currentRecipes];
|
||||
final currentRecipe = currentRecipes[index];
|
||||
|
||||
unlikeRecipe(String slug) async => await feedRepository.unlikeRecipe(slug: slug);
|
||||
recipesForModification[index] = currentRecipe.copyWith(
|
||||
isFavorite: true,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...recipesForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
EasyDebounce.debounce(
|
||||
'add_or_remove_plan_from_favorite',
|
||||
Duration(milliseconds: 200),
|
||||
() async {
|
||||
try {
|
||||
await aboutRecipeRepository.addToFavorite(slug);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время');
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...currentRecipes,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removeRecipeFromFavorite(String slug, int index) async {
|
||||
final currentRecipes = state.recipesList;
|
||||
final recipesForModification = [...currentRecipes];
|
||||
final currentRecipe = currentRecipes[index];
|
||||
|
||||
recipesForModification[index] = currentRecipe.copyWith(
|
||||
isFavorite: false,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...recipesForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
EasyDebounce.debounce(
|
||||
'add_or_remove_plan_from_favorite',
|
||||
Duration(milliseconds: 200),
|
||||
() async {
|
||||
try {
|
||||
await aboutRecipeRepository.removeFromFavorite(slug);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время');
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...currentRecipes,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> likeRecipe(String slug, int index) async {
|
||||
final currentRecipes = state.recipesList;
|
||||
final recipesForModification = [...currentRecipes];
|
||||
final currentRecipe = currentRecipes[index];
|
||||
if (currentRecipe.wasLikedByMe) {
|
||||
recipesForModification[index] = currentRecipe.copyWith(
|
||||
likesCount: currentRecipe.likesCount - 1,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...recipesForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
recipesForModification[index] = currentRecipe.copyWith(
|
||||
likesCount: currentRecipe.likesCount + 1,
|
||||
wasLikedByMe: true,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...recipesForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
EasyDebounce.debounce(
|
||||
'like_plan',
|
||||
Duration(milliseconds: 200),
|
||||
() async {
|
||||
try {
|
||||
await aboutRecipeRepository.likeRecipe(slug);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...currentRecipes,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _changeRecipeLikeState(LikesState likesState) {
|
||||
final currentRecipes = state.recipesList;
|
||||
final recipesForModification = [...currentRecipes];
|
||||
final currentRecipe = currentRecipes[likesState.index];
|
||||
|
||||
recipesForModification[likesState.index] = currentRecipe.copyWith(
|
||||
likesCount: likesState.totalLikes,
|
||||
wasLikedByMe: likesState.wasLikedByMe,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...recipesForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _changeRecipeFavoriteState(FavoriteState favoriteState) {
|
||||
final currentRecipes = state.recipesList;
|
||||
final recipesForModification = [...currentRecipes];
|
||||
final currentRecipe = currentRecipes[favoriteState.index];
|
||||
|
||||
recipesForModification[favoriteState.index] = currentRecipe.copyWith(
|
||||
isFavorite: favoriteState.isFavorite,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...recipesForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _changeRecipeCommentsState(CommentsState commentsState) {
|
||||
final currentRecipes = state.recipesList;
|
||||
final recipesForModification = [...currentRecipes];
|
||||
final currentRecipe = currentRecipes[commentsState.index];
|
||||
|
||||
recipesForModification[commentsState.index] = currentRecipe.copyWith(
|
||||
commentsCount: commentsState.totalComments,
|
||||
);
|
||||
emit(
|
||||
state.copyWith(
|
||||
recipesList: [
|
||||
...recipesForModification,
|
||||
],
|
||||
isLoading: isLoading,
|
||||
errorMessage: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_tag_model.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_tag_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'recipes_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class RecipesState with _$RecipesState {
|
||||
const factory RecipesState() = _RecipesState;
|
||||
|
||||
const factory RecipesState.loading() = RecipesStateLoading;
|
||||
|
||||
const factory RecipesState.loaded({
|
||||
required List<Recipes> recipesList,
|
||||
const factory RecipesState({
|
||||
required List<Recipe> recipesList,
|
||||
required List<RecipeTag> recipesTags,
|
||||
required Set<int> selectedTags,
|
||||
required int selectedTagsCounter,
|
||||
required bool isLoading,
|
||||
}) = RecipesStateLoaded;
|
||||
String? errorMessage,
|
||||
}) = _RecipesState;
|
||||
|
||||
const factory RecipesState.error({
|
||||
required String errorMessage,
|
||||
}) = RecipesStateError;
|
||||
factory RecipesState.initial() => RecipesState(
|
||||
recipesList: [],
|
||||
recipesTags: [],
|
||||
selectedTags: {},
|
||||
selectedTagsCounter: 0,
|
||||
isLoading: true,
|
||||
errorMessage: null,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,65 +16,17 @@ final _privateConstructorUsedError = UnsupportedError(
|
||||
|
||||
/// @nodoc
|
||||
mixin _$RecipesState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(
|
||||
List<Recipes> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading)
|
||||
loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value) $default, {
|
||||
required TResult Function(RecipesStateLoading value) loading,
|
||||
required TResult Function(RecipesStateLoaded value) loaded,
|
||||
required TResult Function(RecipesStateError value) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_RecipesState value)? $default, {
|
||||
TResult? Function(RecipesStateLoading value)? loading,
|
||||
TResult? Function(RecipesStateLoaded value)? loaded,
|
||||
TResult? Function(RecipesStateError value)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value)? $default, {
|
||||
TResult Function(RecipesStateLoading value)? loading,
|
||||
TResult Function(RecipesStateLoaded value)? loaded,
|
||||
TResult Function(RecipesStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
List<Recipe> get recipesList => throw _privateConstructorUsedError;
|
||||
List<RecipeTag> get recipesTags => throw _privateConstructorUsedError;
|
||||
Set<int> get selectedTags => throw _privateConstructorUsedError;
|
||||
int get selectedTagsCounter => throw _privateConstructorUsedError;
|
||||
bool get isLoading => throw _privateConstructorUsedError;
|
||||
String? get errorMessage => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$RecipesStateCopyWith<RecipesState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -83,6 +35,14 @@ abstract class $RecipesStateCopyWith<$Res> {
|
||||
factory $RecipesStateCopyWith(
|
||||
RecipesState value, $Res Function(RecipesState) then) =
|
||||
_$RecipesStateCopyWithImpl<$Res, RecipesState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{List<Recipe> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading,
|
||||
String? errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -97,13 +57,60 @@ class _$RecipesStateCopyWithImpl<$Res, $Val extends RecipesState>
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? recipesList = null,
|
||||
Object? recipesTags = null,
|
||||
Object? selectedTags = null,
|
||||
Object? selectedTagsCounter = null,
|
||||
Object? isLoading = null,
|
||||
Object? errorMessage = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
recipesList: null == recipesList
|
||||
? _value.recipesList
|
||||
: recipesList // ignore: cast_nullable_to_non_nullable
|
||||
as List<Recipe>,
|
||||
recipesTags: null == recipesTags
|
||||
? _value.recipesTags
|
||||
: recipesTags // ignore: cast_nullable_to_non_nullable
|
||||
as List<RecipeTag>,
|
||||
selectedTags: null == selectedTags
|
||||
? _value.selectedTags
|
||||
: selectedTags // ignore: cast_nullable_to_non_nullable
|
||||
as Set<int>,
|
||||
selectedTagsCounter: null == selectedTagsCounter
|
||||
? _value.selectedTagsCounter
|
||||
: selectedTagsCounter // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
errorMessage: freezed == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$RecipesStateImplCopyWith<$Res> {
|
||||
abstract class _$$RecipesStateImplCopyWith<$Res>
|
||||
implements $RecipesStateCopyWith<$Res> {
|
||||
factory _$$RecipesStateImplCopyWith(
|
||||
_$RecipesStateImpl value, $Res Function(_$RecipesStateImpl) then) =
|
||||
__$$RecipesStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{List<Recipe> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading,
|
||||
String? errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -116,268 +123,6 @@ class __$$RecipesStateImplCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$RecipesStateImpl implements _RecipesState {
|
||||
const _$RecipesStateImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecipesState()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$RecipesStateImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(
|
||||
List<Recipes> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading)
|
||||
loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return $default();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return $default?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value) $default, {
|
||||
required TResult Function(RecipesStateLoading value) loading,
|
||||
required TResult Function(RecipesStateLoaded value) loaded,
|
||||
required TResult Function(RecipesStateError value) error,
|
||||
}) {
|
||||
return $default(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_RecipesState value)? $default, {
|
||||
TResult? Function(RecipesStateLoading value)? loading,
|
||||
TResult? Function(RecipesStateLoaded value)? loaded,
|
||||
TResult? Function(RecipesStateError value)? error,
|
||||
}) {
|
||||
return $default?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value)? $default, {
|
||||
TResult Function(RecipesStateLoading value)? loading,
|
||||
TResult Function(RecipesStateLoaded value)? loaded,
|
||||
TResult Function(RecipesStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _RecipesState implements RecipesState {
|
||||
const factory _RecipesState() = _$RecipesStateImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$RecipesStateLoadingImplCopyWith<$Res> {
|
||||
factory _$$RecipesStateLoadingImplCopyWith(_$RecipesStateLoadingImpl value,
|
||||
$Res Function(_$RecipesStateLoadingImpl) then) =
|
||||
__$$RecipesStateLoadingImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$RecipesStateLoadingImplCopyWithImpl<$Res>
|
||||
extends _$RecipesStateCopyWithImpl<$Res, _$RecipesStateLoadingImpl>
|
||||
implements _$$RecipesStateLoadingImplCopyWith<$Res> {
|
||||
__$$RecipesStateLoadingImplCopyWithImpl(_$RecipesStateLoadingImpl _value,
|
||||
$Res Function(_$RecipesStateLoadingImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$RecipesStateLoadingImpl implements RecipesStateLoading {
|
||||
const _$RecipesStateLoadingImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecipesState.loading()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$RecipesStateLoadingImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(
|
||||
List<Recipes> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading)
|
||||
loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loading();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loading?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value) $default, {
|
||||
required TResult Function(RecipesStateLoading value) loading,
|
||||
required TResult Function(RecipesStateLoaded value) loaded,
|
||||
required TResult Function(RecipesStateError value) error,
|
||||
}) {
|
||||
return loading(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_RecipesState value)? $default, {
|
||||
TResult? Function(RecipesStateLoading value)? loading,
|
||||
TResult? Function(RecipesStateLoaded value)? loaded,
|
||||
TResult? Function(RecipesStateError value)? error,
|
||||
}) {
|
||||
return loading?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value)? $default, {
|
||||
TResult Function(RecipesStateLoading value)? loading,
|
||||
TResult Function(RecipesStateLoaded value)? loaded,
|
||||
TResult Function(RecipesStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class RecipesStateLoading implements RecipesState {
|
||||
const factory RecipesStateLoading() = _$RecipesStateLoadingImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$RecipesStateLoadedImplCopyWith<$Res> {
|
||||
factory _$$RecipesStateLoadedImplCopyWith(_$RecipesStateLoadedImpl value,
|
||||
$Res Function(_$RecipesStateLoadedImpl) then) =
|
||||
__$$RecipesStateLoadedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{List<Recipes> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$RecipesStateLoadedImplCopyWithImpl<$Res>
|
||||
extends _$RecipesStateCopyWithImpl<$Res, _$RecipesStateLoadedImpl>
|
||||
implements _$$RecipesStateLoadedImplCopyWith<$Res> {
|
||||
__$$RecipesStateLoadedImplCopyWithImpl(_$RecipesStateLoadedImpl _value,
|
||||
$Res Function(_$RecipesStateLoadedImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
@@ -386,12 +131,13 @@ class __$$RecipesStateLoadedImplCopyWithImpl<$Res>
|
||||
Object? selectedTags = null,
|
||||
Object? selectedTagsCounter = null,
|
||||
Object? isLoading = null,
|
||||
Object? errorMessage = freezed,
|
||||
}) {
|
||||
return _then(_$RecipesStateLoadedImpl(
|
||||
return _then(_$RecipesStateImpl(
|
||||
recipesList: null == recipesList
|
||||
? _value._recipesList
|
||||
: recipesList // ignore: cast_nullable_to_non_nullable
|
||||
as List<Recipes>,
|
||||
as List<Recipe>,
|
||||
recipesTags: null == recipesTags
|
||||
? _value._recipesTags
|
||||
: recipesTags // ignore: cast_nullable_to_non_nullable
|
||||
@@ -408,26 +154,31 @@ class __$$RecipesStateLoadedImplCopyWithImpl<$Res>
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
errorMessage: freezed == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$RecipesStateLoadedImpl implements RecipesStateLoaded {
|
||||
const _$RecipesStateLoadedImpl(
|
||||
{required final List<Recipes> recipesList,
|
||||
class _$RecipesStateImpl implements _RecipesState {
|
||||
const _$RecipesStateImpl(
|
||||
{required final List<Recipe> recipesList,
|
||||
required final List<RecipeTag> recipesTags,
|
||||
required final Set<int> selectedTags,
|
||||
required this.selectedTagsCounter,
|
||||
required this.isLoading})
|
||||
required this.isLoading,
|
||||
this.errorMessage})
|
||||
: _recipesList = recipesList,
|
||||
_recipesTags = recipesTags,
|
||||
_selectedTags = selectedTags;
|
||||
|
||||
final List<Recipes> _recipesList;
|
||||
final List<Recipe> _recipesList;
|
||||
@override
|
||||
List<Recipes> get recipesList {
|
||||
List<Recipe> get recipesList {
|
||||
if (_recipesList is EqualUnmodifiableListView) return _recipesList;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_recipesList);
|
||||
@@ -453,17 +204,19 @@ class _$RecipesStateLoadedImpl implements RecipesStateLoaded {
|
||||
final int selectedTagsCounter;
|
||||
@override
|
||||
final bool isLoading;
|
||||
@override
|
||||
final String? errorMessage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecipesState.loaded(recipesList: $recipesList, recipesTags: $recipesTags, selectedTags: $selectedTags, selectedTagsCounter: $selectedTagsCounter, isLoading: $isLoading)';
|
||||
return 'RecipesState(recipesList: $recipesList, recipesTags: $recipesTags, selectedTags: $selectedTags, selectedTagsCounter: $selectedTagsCounter, isLoading: $isLoading, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$RecipesStateLoadedImpl &&
|
||||
other is _$RecipesStateImpl &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._recipesList, _recipesList) &&
|
||||
const DeepCollectionEquality()
|
||||
@@ -473,7 +226,9 @@ class _$RecipesStateLoadedImpl implements RecipesStateLoaded {
|
||||
(identical(other.selectedTagsCounter, selectedTagsCounter) ||
|
||||
other.selectedTagsCounter == selectedTagsCounter) &&
|
||||
(identical(other.isLoading, isLoading) ||
|
||||
other.isLoading == isLoading));
|
||||
other.isLoading == isLoading) &&
|
||||
(identical(other.errorMessage, errorMessage) ||
|
||||
other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -483,287 +238,44 @@ class _$RecipesStateLoadedImpl implements RecipesStateLoaded {
|
||||
const DeepCollectionEquality().hash(_recipesTags),
|
||||
const DeepCollectionEquality().hash(_selectedTags),
|
||||
selectedTagsCounter,
|
||||
isLoading);
|
||||
isLoading,
|
||||
errorMessage);
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$RecipesStateLoadedImplCopyWith<_$RecipesStateLoadedImpl> get copyWith =>
|
||||
__$$RecipesStateLoadedImplCopyWithImpl<_$RecipesStateLoadedImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(
|
||||
List<Recipes> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading)
|
||||
loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return loaded(
|
||||
recipesList, recipesTags, selectedTags, selectedTagsCounter, isLoading);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return loaded?.call(
|
||||
recipesList, recipesTags, selectedTags, selectedTagsCounter, isLoading);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(recipesList, recipesTags, selectedTags, selectedTagsCounter,
|
||||
isLoading);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value) $default, {
|
||||
required TResult Function(RecipesStateLoading value) loading,
|
||||
required TResult Function(RecipesStateLoaded value) loaded,
|
||||
required TResult Function(RecipesStateError value) error,
|
||||
}) {
|
||||
return loaded(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_RecipesState value)? $default, {
|
||||
TResult? Function(RecipesStateLoading value)? loading,
|
||||
TResult? Function(RecipesStateLoaded value)? loaded,
|
||||
TResult? Function(RecipesStateError value)? error,
|
||||
}) {
|
||||
return loaded?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value)? $default, {
|
||||
TResult Function(RecipesStateLoading value)? loading,
|
||||
TResult Function(RecipesStateLoaded value)? loaded,
|
||||
TResult Function(RecipesStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
_$$RecipesStateImplCopyWith<_$RecipesStateImpl> get copyWith =>
|
||||
__$$RecipesStateImplCopyWithImpl<_$RecipesStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class RecipesStateLoaded implements RecipesState {
|
||||
const factory RecipesStateLoaded(
|
||||
{required final List<Recipes> recipesList,
|
||||
abstract class _RecipesState implements RecipesState {
|
||||
const factory _RecipesState(
|
||||
{required final List<Recipe> recipesList,
|
||||
required final List<RecipeTag> recipesTags,
|
||||
required final Set<int> selectedTags,
|
||||
required final int selectedTagsCounter,
|
||||
required final bool isLoading}) = _$RecipesStateLoadedImpl;
|
||||
required final bool isLoading,
|
||||
final String? errorMessage}) = _$RecipesStateImpl;
|
||||
|
||||
List<Recipes> get recipesList;
|
||||
@override
|
||||
List<Recipe> get recipesList;
|
||||
@override
|
||||
List<RecipeTag> get recipesTags;
|
||||
@override
|
||||
Set<int> get selectedTags;
|
||||
@override
|
||||
int get selectedTagsCounter;
|
||||
@override
|
||||
bool get isLoading;
|
||||
@override
|
||||
String? get errorMessage;
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$RecipesStateLoadedImplCopyWith<_$RecipesStateLoadedImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$RecipesStateErrorImplCopyWith<$Res> {
|
||||
factory _$$RecipesStateErrorImplCopyWith(_$RecipesStateErrorImpl value,
|
||||
$Res Function(_$RecipesStateErrorImpl) then) =
|
||||
__$$RecipesStateErrorImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String errorMessage});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$RecipesStateErrorImplCopyWithImpl<$Res>
|
||||
extends _$RecipesStateCopyWithImpl<$Res, _$RecipesStateErrorImpl>
|
||||
implements _$$RecipesStateErrorImplCopyWith<$Res> {
|
||||
__$$RecipesStateErrorImplCopyWithImpl(_$RecipesStateErrorImpl _value,
|
||||
$Res Function(_$RecipesStateErrorImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? errorMessage = null,
|
||||
}) {
|
||||
return _then(_$RecipesStateErrorImpl(
|
||||
errorMessage: null == errorMessage
|
||||
? _value.errorMessage
|
||||
: errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$RecipesStateErrorImpl implements RecipesStateError {
|
||||
const _$RecipesStateErrorImpl({required this.errorMessage});
|
||||
|
||||
@override
|
||||
final String errorMessage;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RecipesState.error(errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$RecipesStateErrorImpl &&
|
||||
(identical(other.errorMessage, errorMessage) ||
|
||||
other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, errorMessage);
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$RecipesStateErrorImplCopyWith<_$RecipesStateErrorImpl> get copyWith =>
|
||||
__$$RecipesStateErrorImplCopyWithImpl<_$RecipesStateErrorImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() loading,
|
||||
required TResult Function(
|
||||
List<Recipes> recipesList,
|
||||
List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags,
|
||||
int selectedTagsCounter,
|
||||
bool isLoading)
|
||||
loaded,
|
||||
required TResult Function(String errorMessage) error,
|
||||
}) {
|
||||
return error(errorMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult? Function(String errorMessage)? error,
|
||||
}) {
|
||||
return error?.call(errorMessage);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? loading,
|
||||
TResult Function(List<Recipes> recipesList, List<RecipeTag> recipesTags,
|
||||
Set<int> selectedTags, int selectedTagsCounter, bool isLoading)?
|
||||
loaded,
|
||||
TResult Function(String errorMessage)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(errorMessage);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value) $default, {
|
||||
required TResult Function(RecipesStateLoading value) loading,
|
||||
required TResult Function(RecipesStateLoaded value) loaded,
|
||||
required TResult Function(RecipesStateError value) error,
|
||||
}) {
|
||||
return error(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_RecipesState value)? $default, {
|
||||
TResult? Function(RecipesStateLoading value)? loading,
|
||||
TResult? Function(RecipesStateLoaded value)? loaded,
|
||||
TResult? Function(RecipesStateError value)? error,
|
||||
}) {
|
||||
return error?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_RecipesState value)? $default, {
|
||||
TResult Function(RecipesStateLoading value)? loading,
|
||||
TResult Function(RecipesStateLoaded value)? loaded,
|
||||
TResult Function(RecipesStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class RecipesStateError implements RecipesState {
|
||||
const factory RecipesStateError({required final String errorMessage}) =
|
||||
_$RecipesStateErrorImpl;
|
||||
|
||||
String get errorMessage;
|
||||
|
||||
/// Create a copy of RecipesState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$RecipesStateErrorImplCopyWith<_$RecipesStateErrorImpl> get copyWith =>
|
||||
_$$RecipesStateImplCopyWith<_$RecipesStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import 'package:eatvio_app/features/feed/presentation/widgets/tags_modal_widget.
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/recipes/presentation/pages/recipe_create_screen.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/pages/recipe_create_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
@@ -30,21 +31,27 @@ class DietsWidget extends StatefulWidget {
|
||||
class _DietsWidgetState extends State<DietsWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
return InkWell(
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'aboutDietScreen',
|
||||
extra: {
|
||||
'diet': widget.diet,
|
||||
'index': widget.index,
|
||||
'navigateToComments': false,
|
||||
},
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutDietScreen', extra: {'diet': widget.diet, 'index': widget.index, 'navigateToComments': false}),
|
||||
child: ClipRRect(
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.diet.image,
|
||||
@@ -52,123 +59,124 @@ class _DietsWidgetState extends State<DietsWidget> {
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 14,
|
||||
child: BookmarkButton(
|
||||
onTap: () async {
|
||||
if (widget.diet.isFavorite) {
|
||||
await context.read<DietsCubit>().removeDietFromFavorite(widget.diet.id, widget.index);
|
||||
} else {
|
||||
await context.read<DietsCubit>().addDietToFavorite(widget.diet.id, widget.index);
|
||||
}
|
||||
},
|
||||
color: appTheme.whiteA700,
|
||||
isFavorite: widget.diet.isFavorite,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
width: 40,
|
||||
height: 44,
|
||||
size: 19,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: InfoRow(
|
||||
diet: widget.diet,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
widget.diet.name,
|
||||
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
if (widget.diet.details.isNotEmpty) ...[
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Html(
|
||||
data: widget.diet.details.length > 200 ? widget.diet.details.substring(0, 200) + '...' : widget.diet.details,
|
||||
style: {
|
||||
"*": Style(
|
||||
margin: Margins.zero,
|
||||
color: appTheme.black,
|
||||
fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14),
|
||||
fontWeight: TextStyles.textSMedium.fontWeight ?? FontWeight.w400,
|
||||
),
|
||||
Positioned(
|
||||
right: 14,
|
||||
child: BookmarkButton(
|
||||
onTap: () async {
|
||||
if (widget.diet.isFavorite) {
|
||||
await context.read<DietsCubit>().removeDietFromFavorite(widget.diet.id, widget.index);
|
||||
} else {
|
||||
await context.read<DietsCubit>().addDietToFavorite(widget.diet.id, widget.index);
|
||||
}
|
||||
},
|
||||
color: appTheme.whiteA700,
|
||||
isFavorite: widget.diet.isFavorite,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
width: 40,
|
||||
height: 44,
|
||||
size: 19,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, top: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
FeedIconButton(
|
||||
icon: widget.diet.wasLikedByMe ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: widget.diet.totalLikes.toString(),
|
||||
iconColor: widget.diet.wasLikedByMe ? appTheme.blueA400 : null,
|
||||
backgroundColor: widget.diet.wasLikedByMe ? appTheme.transparentBlue : null,
|
||||
onTap: () async {
|
||||
await context.read<DietsCubit>().likeDiet(widget.diet.id, widget.index);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
text: widget.diet.totalComments.toString(),
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutDietScreen', extra: {'diet': widget.diet, 'index': widget.index, 'navigateToComments': true}),
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/repost.svg'),
|
||||
onTap: () async {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
final result = await Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/diet/' + widget.diet.id.toString(),
|
||||
),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
switch (result.status) {
|
||||
case ShareResultStatus.success:
|
||||
case ShareResultStatus.dismissed:
|
||||
case ShareResultStatus.unavailable:
|
||||
}
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/eye2.svg'),
|
||||
text: widget.diet.totalViews.toString(),
|
||||
backgroundColor: Colors.transparent,
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: InfoRow(
|
||||
diet: widget.diet,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
type: ProductType.diet
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
SizedBox(height: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
widget.diet.name,
|
||||
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
if (widget.diet.details.isNotEmpty) ...[
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Html(
|
||||
data: widget.diet.details.length > 200 ? widget.diet.details.substring(0, 200) + '...' : widget.diet.details,
|
||||
style: {
|
||||
"*": Style(
|
||||
margin: Margins.zero,
|
||||
color: appTheme.black,
|
||||
fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14),
|
||||
fontWeight: TextStyles.textSMedium.fontWeight ?? FontWeight.w400,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, top: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
FeedIconButton(
|
||||
icon: widget.diet.wasLikedByMe ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: widget.diet.totalLikes.toString(),
|
||||
iconColor: widget.diet.wasLikedByMe ? appTheme.blueA400 : null,
|
||||
backgroundColor: widget.diet.wasLikedByMe ? appTheme.transparentBlue : null,
|
||||
onTap: () async {
|
||||
await context.read<DietsCubit>().likeDiet(widget.diet.id, widget.index);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
text: widget.diet.totalComments.toString(),
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutDietScreen', extra: {'diet': widget.diet, 'index': widget.index, 'navigateToComments': true}),
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/repost.svg'),
|
||||
onTap: () async {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
final result = await Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/diet/' + widget.diet.id.toString(),
|
||||
),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
switch (result.status) {
|
||||
case ShareResultStatus.success:
|
||||
case ShareResultStatus.dismissed:
|
||||
case ShareResultStatus.unavailable:
|
||||
}
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/eye2.svg'),
|
||||
text: widget.diet.totalViews.toString(),
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
@@ -33,21 +34,27 @@ class _PlanWidgetState extends State<PlanWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
return InkWell(
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'aboutPlanScreen',
|
||||
extra: {
|
||||
'plan': widget.plan,
|
||||
'index': widget.index,
|
||||
'navigateToComments': false,
|
||||
},
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutPlanScreen', extra: {'plan': widget.plan, 'index': widget.index, 'navigateToComments': false}),
|
||||
child: ClipRRect(
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.plan.image,
|
||||
@@ -55,176 +62,177 @@ class _PlanWidgetState extends State<PlanWidget> {
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 14,
|
||||
child: BookmarkButton(
|
||||
onTap: () async {
|
||||
if (widget.plan.isFavorite) {
|
||||
await context.read<PlansCubit>().removePlanFromFavorite(widget.plan.slug, widget.index);
|
||||
} else {
|
||||
await context.read<PlansCubit>().addPlanToFavorite(widget.plan.slug, widget.index);
|
||||
}
|
||||
},
|
||||
color: appTheme.whiteA700,
|
||||
isFavorite: widget.plan.isFavorite,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
width: 40,
|
||||
height: 44,
|
||||
size: 19,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: InfoRow(
|
||||
plan: widget.plan,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
Positioned(
|
||||
right: 14,
|
||||
child: BookmarkButton(
|
||||
onTap: () async {
|
||||
if (widget.plan.isFavorite) {
|
||||
await context.read<PlansCubit>().removePlanFromFavorite(widget.plan.slug, widget.index);
|
||||
} else {
|
||||
await context.read<PlansCubit>().addPlanToFavorite(widget.plan.slug, widget.index);
|
||||
}
|
||||
},
|
||||
color: appTheme.whiteA700,
|
||||
isFavorite: widget.plan.isFavorite,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
width: 40,
|
||||
height: 44,
|
||||
size: 19,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
widget.plan.name,
|
||||
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
if (widget.plan.details.isNotEmpty) ...[
|
||||
SizedBox(
|
||||
height: 12,
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: InfoRow(
|
||||
plan: widget.plan,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
type: ProductType.plan
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Html(
|
||||
data: widget.plan.details.length > 200 ? widget.plan.details.substring(0, 200) + '...' : widget.plan.details,
|
||||
style: {
|
||||
"*": Style(
|
||||
margin: Margins.zero,
|
||||
color: appTheme.black,
|
||||
fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14),
|
||||
fontWeight: TextStyles.textSMedium.fontWeight ?? FontWeight.w400,
|
||||
),
|
||||
child: Text(
|
||||
widget.plan.name,
|
||||
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
if (widget.plan.details.isNotEmpty) ...[
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Html(
|
||||
data: widget.plan.details.length > 200 ? widget.plan.details.substring(0, 200) + '...' : widget.plan.details,
|
||||
style: {
|
||||
"*": Style(
|
||||
margin: Margins.zero,
|
||||
color: appTheme.black,
|
||||
fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14),
|
||||
fontWeight: TextStyles.textSMedium.fontWeight ?? FontWeight.w400,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: Container(
|
||||
width: 46,
|
||||
height: 46,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
image: DecorationImage(
|
||||
image: NetworkImage(widget.plan.author.authorProfileIcon),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
InfoBouble(
|
||||
radius: 12,
|
||||
backgroundColor: appTheme.gray50,
|
||||
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 10),
|
||||
children: [
|
||||
Text(
|
||||
'${widget.plan.author.authorPlaceInRating}-й в рейтинге',
|
||||
style: TextStyles.textXSSemibold.copyWith(
|
||||
color: appTheme.blueA400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'${widget.plan.packetsCount == 1 ? widget.plan.packet1Options?.price : '${s.from} ${widget.plan.minPriceOfOptions.toStringAsFixed(0)}'}₽',
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.greenA700),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
],
|
||||
),
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
widget.plan.author.authorName,
|
||||
style: TextStyles.textSSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
FeedIconButton(
|
||||
icon: widget.plan.wasLikedByMe ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: widget.plan.totalLikes.toString(),
|
||||
iconColor: widget.plan.wasLikedByMe ? appTheme.blueA400 : null,
|
||||
backgroundColor: widget.plan.wasLikedByMe ? appTheme.transparentBlue : null,
|
||||
onTap: () async {
|
||||
await context.read<PlansCubit>().likePlan(widget.plan.slug, widget.index);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: Container(
|
||||
width: 46,
|
||||
height: 46,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
image: DecorationImage(
|
||||
image: NetworkImage(widget.plan.author.authorProfileIcon),
|
||||
fit: BoxFit.cover,
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
InfoBouble(
|
||||
radius: 12,
|
||||
backgroundColor: appTheme.gray50,
|
||||
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 10),
|
||||
children: [
|
||||
Text(
|
||||
'${widget.plan.author.authorPlaceInRating}-й в рейтинге',
|
||||
style: TextStyles.textXSSemibold.copyWith(
|
||||
color: appTheme.blueA400,
|
||||
FeedIconButton(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
text: widget.plan.totalComments.toString(),
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutPlanScreen', extra: {'plan': widget.plan, 'index': widget.index, 'navigateToComments': true}),
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/repost.svg'),
|
||||
onTap: () async {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
final result = await Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/diet/' + widget.plan.id.toString(),
|
||||
),
|
||||
),
|
||||
],
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
switch (result.status) {
|
||||
case ShareResultStatus.success:
|
||||
case ShareResultStatus.dismissed:
|
||||
case ShareResultStatus.unavailable:
|
||||
}
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
'${widget.plan.packetsCount == 1 ? widget.plan.packet1Options?.price : '${s.from} ${widget.plan.minPriceOfOptions.toStringAsFixed(0)}'}₽',
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.greenA700),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/eye2.svg'),
|
||||
text: widget.plan.totalViews.toString(),
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
],
|
||||
),
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
widget.plan.author.authorName,
|
||||
style: TextStyles.textSSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
FeedIconButton(
|
||||
icon: widget.plan.wasLikedByMe ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: widget.plan.totalLikes.toString(),
|
||||
iconColor: widget.plan.wasLikedByMe ? appTheme.blueA400 : null,
|
||||
backgroundColor: widget.plan.wasLikedByMe ? appTheme.transparentBlue : null,
|
||||
onTap: () async {
|
||||
await context.read<PlansCubit>().likePlan(widget.plan.slug, widget.index);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
text: widget.plan.totalComments.toString(),
|
||||
onTap: () =>
|
||||
GoRouter.of(context).pushNamed('aboutPlanScreen', extra: {'plan': widget.plan, 'index': widget.index, 'navigateToComments': true}),
|
||||
),
|
||||
SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/repost.svg'),
|
||||
onTap: () async {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
final result = await Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/diet/' + widget.plan.id.toString(),
|
||||
),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
switch (result.status) {
|
||||
case ShareResultStatus.success:
|
||||
case ShareResultStatus.dismissed:
|
||||
case ShareResultStatus.unavailable:
|
||||
}
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset('assets/icons/eye2.svg'),
|
||||
text: widget.plan.totalViews.toString(),
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,38 +14,39 @@ class Recipes extends StatelessWidget {
|
||||
onRefresh: () => context.read<RecipesCubit>().loadRecipesList(),
|
||||
child: BlocBuilder<RecipesCubit, RecipesState>(
|
||||
builder: (BuildContext context, RecipesState state) {
|
||||
if (state is RecipesStateLoaded) {
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return RecipesWidget(
|
||||
recipes: state.recipesList[index],
|
||||
index: index,
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
},
|
||||
itemCount: state.recipesList.length,
|
||||
);
|
||||
} else if (state is RecipesStateError) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.errorMessage),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if (state.isLoading) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: const Loader(),
|
||||
);
|
||||
}
|
||||
if (state.errorMessage != null) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.errorMessage ?? ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
shrinkWrap: true,
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return RecipesWidget(
|
||||
recipe: state.recipesList[index],
|
||||
index: index,
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
},
|
||||
itemCount: state.recipesList.length,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_state.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
@@ -16,11 +20,11 @@ import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class RecipesWidget extends StatefulWidget {
|
||||
final int index;
|
||||
final Recipes recipes;
|
||||
final Recipe recipe;
|
||||
|
||||
const RecipesWidget({
|
||||
super.key,
|
||||
required this.recipes,
|
||||
required this.recipe,
|
||||
required this.index,
|
||||
});
|
||||
|
||||
@@ -29,177 +33,207 @@ class RecipesWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RecipesWidgetState extends State<RecipesWidget> {
|
||||
late bool isLiked;
|
||||
late int totalLikes;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
isLiked = false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return BlocBuilder<RecipesCubit, RecipesState>(
|
||||
builder: (BuildContext context, RecipesState state) {
|
||||
if (state is RecipesStateLoaded) {
|
||||
isLiked = state.recipesList[widget.index].wasLikedByMe;
|
||||
totalLikes = state.recipesList[widget.index].likesCount;
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () => GoRouter.of(context).pushNamed('aboutRecipesScreen', extra: widget.recipes),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.recipes.image,
|
||||
fit: BoxFit.fitWidth,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 8,
|
||||
bottom: 8,
|
||||
child: Wrap(
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
_iconButton('assets/icons/clock.svg', widget.recipes.cookingTime.toString() + ' минут'),
|
||||
SizedBox(width: 8),
|
||||
_iconButton('assets/icons/steps.svg', '${widget.recipes.steps?.length.toString()}' + ' этапов'),
|
||||
SizedBox(width: 8),
|
||||
_iconButton('assets/icons/calories.svg', widget.recipes.calories.toStringAsFixed(0) + ' ккал'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(
|
||||
widget.recipes.title ?? '',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
final isLiked = widget.recipe.wasLikedByMe;
|
||||
final totalLikes = widget.recipe.likesCount;
|
||||
final isFavorite = widget.recipe.isFavorite;
|
||||
final hours = widget.recipe.cookingTime ~/ 60;
|
||||
final minutes = widget.recipe.cookingTime % 60;
|
||||
final String timeTitle;
|
||||
if (hours > 0) {
|
||||
timeTitle = '$hours ${getHourForm(hours)} $minutes ${getMinuteForm(minutes)}';
|
||||
} else {
|
||||
timeTitle = '$minutes ${getMinuteForm(minutes)}';
|
||||
}
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'aboutRecipesScreen',
|
||||
extra: {
|
||||
'recipe': widget.recipe,
|
||||
'index': widget.index,
|
||||
'navigateToComments': false,
|
||||
},
|
||||
),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.recipe.image,
|
||||
fit: BoxFit.fitWidth,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.recipes.description.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Html(
|
||||
data: widget.recipes.description.length > 200 ? widget.recipes.description.substring(0, 200) : widget.recipes.description,
|
||||
style: {
|
||||
"*": Style(
|
||||
color: Colors.black87,
|
||||
),
|
||||
Positioned(
|
||||
left: 8,
|
||||
bottom: 8,
|
||||
child: Wrap(
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
_iconButton('assets/icons/clock.svg', timeTitle),
|
||||
SizedBox(width: 8),
|
||||
_iconButton('assets/icons/steps.svg', '${widget.recipe.steps?.length ?? 0} ${getStepForm(widget.recipe.steps?.length ?? 0)}'),
|
||||
SizedBox(width: 8),
|
||||
_iconButton('assets/icons/calories.svg', widget.recipe.calories.toStringAsFixed(0) + ' ккал'),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 14,
|
||||
child: BookmarkButton(
|
||||
onTap: () async {
|
||||
if (isFavorite) {
|
||||
await context.read<RecipesCubit>().removeRecipeFromFavorite(widget.recipe.slug, widget.index);
|
||||
} else {
|
||||
await context.read<RecipesCubit>().addRecipeToFavorite(widget.recipe.slug, widget.index);
|
||||
}
|
||||
},
|
||||
color: appTheme.whiteA700,
|
||||
isFavorite: isFavorite,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
width: 40,
|
||||
height: 44,
|
||||
size: 19,
|
||||
),
|
||||
),
|
||||
if (widget.recipes.description.length > 200)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
'Читать полностью...',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: appTheme.blueA400,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
widget.recipe.title ?? '',
|
||||
style: TextStyles.textMSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
if (widget.recipe.videoUrl != null && widget.recipe.videoUrl!.isNotEmpty) ...[
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: Row(
|
||||
children: [
|
||||
FeedIconButton(
|
||||
icon: isLiked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: widget.recipes.likesCount.toString(),
|
||||
iconColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
|
||||
backgroundColor: isLiked ? Colors.red.withValues(alpha: 0.1) : null,
|
||||
textColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
|
||||
onTap: () async {
|
||||
setState(() {
|
||||
isLiked = !isLiked;
|
||||
isLiked ? totalLikes++ : totalLikes--;
|
||||
});
|
||||
isLiked
|
||||
? await context.read<RecipesCubit>().likeRecipe(state.recipesList[widget.index].slug)
|
||||
: await context.read<RecipesCubit>().unlikeRecipe(state.recipesList[widget.index].slug);
|
||||
await context.read<RecipesCubit>().loadRecipesList();
|
||||
},
|
||||
),
|
||||
SvgPicture.asset('assets/icons/play_icon.svg', width: 16, height: 16),
|
||||
SizedBox(width: 8),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset(
|
||||
'assets/icons/comment.svg',
|
||||
height: 20,
|
||||
width: 20,
|
||||
colorFilter: ColorFilter.mode(
|
||||
appTheme.gray600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
text: widget.recipes.commentsCount.toString(),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'aboutRecipesScreen',
|
||||
extra: widget.recipes,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset(
|
||||
height: 20,
|
||||
width: 20,
|
||||
'assets/icons/share.svg',
|
||||
colorFilter: ColorFilter.mode(appTheme.gray600, BlendMode.srcIn),
|
||||
),
|
||||
onTap: () {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/blog_post/' + widget.recipes.id.toString(),
|
||||
),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.visibility_rounded,
|
||||
size: 16,
|
||||
color: appTheme.gray500,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
widget.recipes.viewsCount.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: appTheme.gray500,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
s.there_is_a_video,
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
if (widget.recipe.description.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Html(
|
||||
data: widget.recipe.description.length > 200 ? widget.recipe.description.substring(0, 200) : widget.recipe.description,
|
||||
style: {
|
||||
"*": Style(
|
||||
color: appTheme.black,
|
||||
margin: Margins.all(0),
|
||||
fontFamily: TextStyles.textSMedium.fontFamily,
|
||||
fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14),
|
||||
fontWeight: TextStyles.textSMedium.fontWeight,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
if (widget.recipe.description.length > 200)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
'Читать полностью...',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: appTheme.blueA400,
|
||||
decoration: TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
FeedIconButton(
|
||||
icon: isLiked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: totalLikes.toString(),
|
||||
iconColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
|
||||
backgroundColor: isLiked ? Colors.red.withValues(alpha: 0.1) : null,
|
||||
textColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
|
||||
onTap: () async {
|
||||
await context.read<RecipesCubit>().likeRecipe(widget.recipe.slug, widget.index);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
FeedIconButton(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
text: widget.recipe.commentsCount.toString(),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'aboutRecipesScreen',
|
||||
extra: {
|
||||
'recipe': widget.recipe,
|
||||
'index': widget.index,
|
||||
'navigateToComments': true,
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
FeedIconButton(
|
||||
svgIcon: SvgPicture.asset(
|
||||
height: 15,
|
||||
width: 12,
|
||||
'assets/icons/repost.svg',
|
||||
colorFilter: ColorFilter.mode(appTheme.gray600, BlendMode.srcIn),
|
||||
),
|
||||
onTap: () {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/blog_post/' + widget.recipe.id.toString(),
|
||||
),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
},
|
||||
),
|
||||
Spacer(),
|
||||
Icon(
|
||||
Icons.visibility_rounded,
|
||||
size: 16,
|
||||
color: appTheme.gray500,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
widget.recipe.viewsCount.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: appTheme.gray500,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -208,7 +242,7 @@ class _RecipesWidgetState extends State<RecipesWidget> {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.8),
|
||||
color: appTheme.whiteA700,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
height: 32,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/recipes_cubit/recipes_state.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_tag_model.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/models/recipe_tag_model.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -23,25 +23,21 @@ class _TagsModalWidgetState extends State<TagsModalWidget> {
|
||||
return BlocBuilder<RecipesCubit, RecipesState>(
|
||||
bloc: widget.recipesCubit,
|
||||
builder: (BuildContext context, RecipesState state) {
|
||||
if (state is RecipesStateLoaded) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: -8,
|
||||
children: [
|
||||
for (int i = 0; i < state.recipesTags.length; i++)
|
||||
_tagChip(
|
||||
tag: state.recipesTags[i],
|
||||
isSelected: state.selectedTags.contains(state.recipesTags[i].id),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: -8,
|
||||
children: [
|
||||
for (int i = 0; i < state.recipesTags.length; i++)
|
||||
_tagChip(
|
||||
tag: state.recipesTags[i],
|
||||
isSelected: state.selectedTags.contains(state.recipesTags[i].id),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class FeedRepository {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Recipes>> getRecipes({
|
||||
Future<List<Recipe>> getRecipes({
|
||||
String? query,
|
||||
List<int>? tags,
|
||||
int page = 1,
|
||||
@@ -64,7 +64,7 @@ class FeedRepository {
|
||||
}
|
||||
}
|
||||
|
||||
Future<PlanPaginationModel> getPlans({
|
||||
Future<PlanPaginationModel> getPlans({
|
||||
int page = 1,
|
||||
String? query,
|
||||
String? types,
|
||||
@@ -85,7 +85,7 @@ class FeedRepository {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<CommentModel> getBlogPostComments({
|
||||
required String id,
|
||||
}) async {
|
||||
@@ -217,24 +217,4 @@ class FeedRepository {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> likeRecipe({
|
||||
required String slug,
|
||||
}) async {
|
||||
try {
|
||||
await feedService.likeRecipe(slug: slug);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> unlikeRecipe({
|
||||
required String slug,
|
||||
}) async {
|
||||
try {
|
||||
await feedService.unlikeRecipe(slug: slug);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,16 +103,6 @@ abstract class FeedService {
|
||||
@Path() required int id,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/{slug}/like')
|
||||
Future<void> likeRecipe({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/{slug}/unliked')
|
||||
Future<void> unlikeRecipe({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@GET('/api/consultants/index')
|
||||
Future<FeedConsultantPaginationModel> getConsultants();
|
||||
}
|
||||
|
||||
@@ -427,44 +427,6 @@ class _FeedService implements FeedService {
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> likeRecipe({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/like',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> unlikeRecipe({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/unliked',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<FeedConsultantPaginationModel> getConsultants() async {
|
||||
final _extra = <String, dynamic>{};
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:developer';
|
||||
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/features/create_diet/repositories/create_diet_repository.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
|
||||
import 'package:eatvio_app/features/my_diets/repositories/my_diets_repository.dart';
|
||||
@@ -9,6 +10,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class MyDietsCubit extends Cubit<MyDietsState> {
|
||||
final MyDietsRepository myDietsRepository;
|
||||
final CreateDietRepository createDietRepository;
|
||||
|
||||
int currentDraftPage = 1;
|
||||
int currentPersonalPage = 1;
|
||||
@@ -35,7 +37,10 @@ class MyDietsCubit extends Cubit<MyDietsState> {
|
||||
static const List<int?> _durationValues = [null, ...durationValues];
|
||||
static const List<String?> _types = [null, ...dietTypeValues];
|
||||
|
||||
MyDietsCubit({required this.myDietsRepository}) : super(MyDietsState());
|
||||
MyDietsCubit({
|
||||
required this.myDietsRepository,
|
||||
required this.createDietRepository,
|
||||
}) : super(MyDietsState());
|
||||
|
||||
void changeTypeFilter(int index) {
|
||||
if (state.selectedStateIndex == 0) {
|
||||
@@ -283,4 +288,17 @@ class MyDietsCubit extends Cubit<MyDietsState> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> publishDiet(int dietId) async {
|
||||
try {
|
||||
await createDietRepository.updateDiet(
|
||||
dietId: dietId,
|
||||
state: DietState.active,
|
||||
);
|
||||
return null;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
return 'Произошла непредвиденная ошибка';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
@@ -63,6 +64,7 @@ class _MyDietWidgetState extends State<MyDietWidget> {
|
||||
diet: widget.diet,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
type: ProductType.diet
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -113,6 +115,7 @@ class _MyDietWidgetState extends State<MyDietWidget> {
|
||||
child: CustomOutlinedButton(
|
||||
onPressed: () {
|
||||
if (state.selectedStateIndex == 1) {
|
||||
context.read<MyDietsCubit>().publishDiet(widget.diet.id);
|
||||
} else if (state.selectedStateIndex == 2) {
|
||||
} else {
|
||||
GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: widget.diet);
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
@@ -62,6 +63,7 @@ class _MyPlanWidgetState extends State<MyPlanWidget> {
|
||||
plan: widget.plan,
|
||||
itemsBackgroundColor: appTheme.whiteA700,
|
||||
disableDescriptionOfTypes: true,
|
||||
type: ProductType.plan,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
@@ -400,9 +401,7 @@ class _AboutPlanScreenState extends State<AboutPlanScreen> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
|
||||
/// TODO глянуть как заменить
|
||||
InfoRow(plan: state.planModel),
|
||||
InfoRow(plan: state.planModel, type: ProductType.plan),
|
||||
ExpandableText(
|
||||
text: widget.plan.details,
|
||||
),
|
||||
|
||||
@@ -10,11 +10,12 @@ class ItemWidget extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
text,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
Expanded(
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset(
|
||||
'assets/icons/ok.svg',
|
||||
width: 20,
|
||||
|
||||
@@ -567,6 +567,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
Uri.parse(
|
||||
state.profile.educationResource?.vkLink ?? '',
|
||||
),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
'assets/icons/vk.svg',
|
||||
@@ -577,8 +578,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
() {
|
||||
launchUrl(
|
||||
Uri.parse(
|
||||
state.profile.educationResource?.vkLink ?? '',
|
||||
state.profile.educationResource?.vkLink ?? '',
|
||||
),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
'assets/icons/telegram.svg',
|
||||
@@ -591,6 +593,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
Uri.parse(
|
||||
state.profile.educationResource?.personalSiteLink ?? '',
|
||||
),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
'assets/icons/web.svg',
|
||||
|
||||
473
lib/features/recipe/presentation/about_recipe_screen.dart
Normal file
473
lib/features/recipe/presentation/about_recipe_screen.dart
Normal file
@@ -0,0 +1,473 @@
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/more_options.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/widgets/ingredients_widget.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/widgets/steps_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_portal/flutter_portal.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class AboutRecipeScreen extends StatefulWidget {
|
||||
final Recipe recipe;
|
||||
final int? index;
|
||||
final bool navigateToComments;
|
||||
|
||||
AboutRecipeScreen({super.key, required this.recipe, required this.index, required this.navigateToComments});
|
||||
|
||||
@override
|
||||
State<AboutRecipeScreen> createState() => _AboutRecipeScreenState();
|
||||
}
|
||||
|
||||
class _AboutRecipeScreenState extends State<AboutRecipeScreen> {
|
||||
final CommentsCubit commentsCubit = sl<CommentsCubit>();
|
||||
final AboutRecipeCubit recipeCubit = sl<AboutRecipeCubit>();
|
||||
int? replyId;
|
||||
final ScrollController scrollController = ScrollController();
|
||||
final textEditingController = TextEditingController();
|
||||
bool isMoreOptionsVisible = false;
|
||||
bool _jumped = false;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
scrollController.addListener(() {
|
||||
if (isMoreOptionsVisible) {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _scrollToBottom() {
|
||||
_jumped = true;
|
||||
scrollController.jumpTo(
|
||||
scrollController.position.maxScrollExtent,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return BlocProvider(
|
||||
create: (context) => recipeCubit..getRecipe(widget.recipe.slug),
|
||||
child: BlocProvider<CommentsCubit>(
|
||||
create: (BuildContext context) => commentsCubit
|
||||
..getComments(
|
||||
widget.recipe.slug.toString(),
|
||||
CommentSourceType.recipe,
|
||||
true,
|
||||
),
|
||||
child: BlocConsumer<CommentsCubit, CommentsState>(
|
||||
listener: (BuildContext context, CommentsState commentsState) {
|
||||
if (commentsState is CommentsStateLoaded) {
|
||||
setState(() {
|
||||
replyId = commentsState.replyId;
|
||||
});
|
||||
}
|
||||
},
|
||||
builder: (BuildContext context, CommentsState state) {
|
||||
return BlocBuilder<AboutRecipeCubit, AboutRecipeState>(
|
||||
builder: (context, recipeState) {
|
||||
if (recipeState is AboutRecipeStateLoaded) {
|
||||
Future.delayed(Duration(milliseconds: 500), () {
|
||||
if (widget.navigateToComments && !_jumped) {
|
||||
_scrollToBottom();
|
||||
}
|
||||
});
|
||||
return Scaffold(
|
||||
backgroundColor: appTheme.gray100,
|
||||
resizeToAvoidBottomInset: true,
|
||||
bottomSheet: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 12) + (Platform.isIOS ? const EdgeInsets.only(bottom: 16) : EdgeInsets.zero),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Colors.black.withValues(alpha: 0.1),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (replyId != null)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
replyId = null;
|
||||
textEditingController.clear();
|
||||
});
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.close_rounded,
|
||||
size: 18,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (replyId != null) SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
child: TextFormField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: textEditingController,
|
||||
maxLines: 5,
|
||||
minLines: 1,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
hintText: s.comment.capitalize(),
|
||||
hintStyle: TextStyles.textMMedium.copyWith(color: appTheme.lightGray600),
|
||||
filled: true,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (textEditingController.text.length > 2) {
|
||||
commentsCubit.sendComment(
|
||||
id: widget.recipe.slug,
|
||||
commentText: textEditingController.text,
|
||||
parentCommentId: replyId,
|
||||
commentSourceType: CommentSourceType.recipe,
|
||||
);
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
textEditingController.clear();
|
||||
replyId = null;
|
||||
});
|
||||
Future.delayed(Duration(milliseconds: 500), () {
|
||||
recipeCubit.getRecipe(widget.recipe.slug, index: widget.index);
|
||||
});
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: textEditingController.text.length > 2 ? appTheme.blueA400 : appTheme.gray50,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.send_rounded,
|
||||
size: 18,
|
||||
color: textEditingController.text.length > 2 ? appTheme.whiteA700 : appTheme.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.recipe.title ?? '',
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
path: 'recipe/${widget.recipe.slug}',
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
padding: EdgeInsets.only(bottom: 160),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 8),
|
||||
MainBackgroundBouble(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.recipe.image,
|
||||
height: 300,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset('assets/icons/eye.svg', width: 18, height: 12),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
widget.recipe.viewsCount.toString(),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
recipeCubit.likeRecipe(widget.recipe.slug, widget.index);
|
||||
},
|
||||
child: InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
'assets/icons/heart.svg',
|
||||
width: 14,
|
||||
height: 12,
|
||||
colorFilter: recipeState.recipe.wasLikedByMe ? ColorFilter.mode(appTheme.blueA400, BlendMode.srcIn) : null,
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
recipeState.recipe.likesCount.toString(),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
InfoBouble(
|
||||
children: [
|
||||
SvgPicture.asset('assets/icons/comment2.svg', width: 13, height: 12),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
recipeState.recipe.commentsCount.toString(),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
backgroundColor: appTheme.whiteA700,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 14,
|
||||
child: BookmarkButton(
|
||||
onTap: () async {
|
||||
if (recipeState.recipe.isFavorite) {
|
||||
await context.read<AboutRecipeCubit>().removeFromFavorite(widget.recipe.slug, widget.index);
|
||||
} else {
|
||||
await context.read<AboutRecipeCubit>().addToFavorite(widget.recipe.slug, widget.index);
|
||||
}
|
||||
},
|
||||
color: appTheme.whiteA700,
|
||||
isFavorite: recipeState.recipe.isFavorite,
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
||||
width: 40,
|
||||
height: 44,
|
||||
size: 19,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
s.about_recipe,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
InfoRow(
|
||||
recipe: widget.recipe,
|
||||
type: ProductType.recipe,
|
||||
),
|
||||
if (widget.recipe.videoUrl != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, bottom: 12, top: 12),
|
||||
child: GestureDetector(
|
||||
onTap: () async {
|
||||
try {
|
||||
final uri = Uri.parse(widget.recipe.videoUrl!);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
showErrorToast(s.could_not_launch_video);
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
s.check_out_video_recipe,
|
||||
style: TextStyles.textMSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
SvgPicture.asset('assets/icons/play_icon.svg', width: 16, height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
ExpandableText(
|
||||
text: widget.recipe.description,
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: AuthorCard(
|
||||
author: widget.recipe.author,
|
||||
title: s.recipe_author,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
if (widget.recipe.ingredients?.isNotEmpty == true)
|
||||
IngredientsWidget(
|
||||
recipe: widget.recipe,
|
||||
),
|
||||
if (widget.recipe.steps?.isNotEmpty == true) ...[
|
||||
SizedBox(height: 12),
|
||||
StepsWidget(
|
||||
recipe: widget.recipe,
|
||||
),
|
||||
],
|
||||
SizedBox(height: 8),
|
||||
MainBackgroundBouble(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
recipeState.recipe.commentsCount.toString() + ' ' + getCommentForm(widget.recipe.commentsCount, s),
|
||||
style: TextStyles.textMMedium.copyWith(
|
||||
color: appTheme.gray500,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
if (state is CommentsStateLoading) const Loader(),
|
||||
if (state is CommentsStateLoaded)
|
||||
CommentsWidget(
|
||||
id: widget.recipe.slug,
|
||||
commentSourceType: CommentSourceType.recipe,
|
||||
comment: state.comment,
|
||||
replyId: replyId,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
body: const Loader(),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
149
lib/features/recipe/presentation/cubit/about_recipe_cubit.dart
Normal file
149
lib/features/recipe/presentation/cubit/about_recipe_cubit.dart
Normal file
@@ -0,0 +1,149 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/features/recipe/repositories/about_recipe_repository.dart';
|
||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||
import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_state.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class AboutRecipeCubit extends Cubit<AboutRecipeState> {
|
||||
AboutRecipeCubit({required this.recipeRepository, required this.profileRepository })
|
||||
: super(AboutRecipeState.initial());
|
||||
final AboutRecipeRepository recipeRepository;
|
||||
final ProfileRepository profileRepository;
|
||||
bool isCurrentDietStarted = false;
|
||||
bool hasStartedDiet = false;
|
||||
String? userStartedDietName;
|
||||
|
||||
Future<void> getRecipe(String id, {int? index}) async {
|
||||
try {
|
||||
final recipe = await recipeRepository.getRecipe(id);
|
||||
if (index != null) {
|
||||
recipeRepository.emitCommentsStateToFeed(CommentsState(index: index, totalComments: recipe.commentsCount));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: recipe));
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> initRecipe(String id, {int? index}) async {
|
||||
try {
|
||||
emit(AboutRecipeState.loading());
|
||||
final recipe = await recipeRepository.getRecipe(id);
|
||||
if (index != null) {
|
||||
recipeRepository.emitCommentsStateToFeed(CommentsState(index: index, totalComments: recipe.commentsCount));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: recipe));
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> likeRecipe(String id, int? recipeIndexInFeed) async {
|
||||
if (state is! AboutRecipeStateLoaded) return;
|
||||
|
||||
final currentRecipe = (state as AboutRecipeStateLoaded).recipe;
|
||||
|
||||
if (currentRecipe.wasLikedByMe) {
|
||||
final updatedRecipe = currentRecipe.copyWith(
|
||||
likesCount: currentRecipe.likesCount - 1,
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
if (recipeIndexInFeed != null) {
|
||||
recipeRepository.emitLikesStateToFeed(LikesState(wasLikedByMe: updatedRecipe.wasLikedByMe, totalLikes: updatedRecipe.likesCount, index: recipeIndexInFeed));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: updatedRecipe));
|
||||
} else {
|
||||
final updatedRecipe = currentRecipe.copyWith(
|
||||
likesCount: currentRecipe.likesCount + 1,
|
||||
wasLikedByMe: true,
|
||||
);
|
||||
if (recipeIndexInFeed != null) {
|
||||
recipeRepository.emitLikesStateToFeed(LikesState(wasLikedByMe: updatedRecipe.wasLikedByMe, totalLikes: updatedRecipe.likesCount, index: recipeIndexInFeed));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: updatedRecipe));
|
||||
}
|
||||
|
||||
EasyDebounce.debounce(
|
||||
'like_recipe',
|
||||
Duration(seconds: 1),
|
||||
() async {
|
||||
try {
|
||||
await recipeRepository.likeRecipe(id);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
if (recipeIndexInFeed != null) {
|
||||
recipeRepository
|
||||
.emitLikesStateToFeed(LikesState(wasLikedByMe: currentRecipe.wasLikedByMe, totalLikes: currentRecipe.likesCount, index: recipeIndexInFeed));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: currentRecipe));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addToFavorite(String id, int? recipeIndex) async {
|
||||
if (state is! AboutRecipeStateLoaded) return;
|
||||
|
||||
final currentRecipe = (state as AboutRecipeStateLoaded).recipe;
|
||||
|
||||
final updatedRecipe = currentRecipe.copyWith(
|
||||
isFavorite: true,
|
||||
);
|
||||
if (recipeIndex != null) {
|
||||
recipeRepository.emitFavoriteStateToFeed(FavoriteState(isFavorite: updatedRecipe.isFavorite, index: recipeIndex));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: updatedRecipe));
|
||||
|
||||
EasyDebounce.debounce(
|
||||
'add_or_remove_diet_to_favorites',
|
||||
Duration(seconds: 1),
|
||||
() async {
|
||||
try {
|
||||
await recipeRepository.addToFavorite(id);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время');
|
||||
if (recipeIndex != null) {
|
||||
recipeRepository.emitFavoriteStateToFeed(FavoriteState(isFavorite: currentRecipe.isFavorite, index: recipeIndex));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: currentRecipe));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> removeFromFavorite(String id, int? recipeIndex) async {
|
||||
if (state is! AboutRecipeStateLoaded) return;
|
||||
|
||||
final currentRecipe = (state as AboutRecipeStateLoaded).recipe;
|
||||
|
||||
final updatedRecipe = currentRecipe.copyWith(
|
||||
isFavorite: false,
|
||||
);
|
||||
if (recipeIndex != null) {
|
||||
recipeRepository.emitFavoriteStateToFeed(FavoriteState(isFavorite: updatedRecipe.isFavorite, index: recipeIndex));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: updatedRecipe));
|
||||
|
||||
EasyDebounce.debounce(
|
||||
'add_or_remove_diet_to_favorites',
|
||||
Duration(seconds: 1),
|
||||
() async {
|
||||
try {
|
||||
await recipeRepository.removeFromFavorite(id);
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время');
|
||||
if (recipeIndex != null) {
|
||||
recipeRepository.emitFavoriteStateToFeed(FavoriteState(isFavorite: currentRecipe.isFavorite, index: recipeIndex));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: currentRecipe));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'about_recipe_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class AboutRecipeState with _$AboutRecipeState {
|
||||
const factory AboutRecipeState() = _AboutRecipeState;
|
||||
|
||||
const factory AboutRecipeState.initial() = AboutRecipeStateInitial;
|
||||
const factory AboutRecipeState.loading() = AboutRecipeStateLoading;
|
||||
const factory AboutRecipeState.loaded({
|
||||
required Recipe recipe,
|
||||
}) = AboutRecipeStateLoaded;
|
||||
const factory AboutRecipeState.error({required String message}) = RecipeStateError;
|
||||
}
|
||||
@@ -0,0 +1,805 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'about_recipe_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AboutRecipeState {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Recipe recipe) loaded,
|
||||
required TResult Function(String message) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? initial,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Recipe recipe)? loaded,
|
||||
TResult? Function(String message)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Recipe recipe)? loaded,
|
||||
TResult Function(String message)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value) $default, {
|
||||
required TResult Function(AboutRecipeStateInitial value) initial,
|
||||
required TResult Function(AboutRecipeStateLoading value) loading,
|
||||
required TResult Function(AboutRecipeStateLoaded value) loaded,
|
||||
required TResult Function(RecipeStateError value) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AboutRecipeState value)? $default, {
|
||||
TResult? Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult? Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult? Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult? Function(RecipeStateError value)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value)? $default, {
|
||||
TResult Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult Function(RecipeStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $AboutRecipeStateCopyWith<$Res> {
|
||||
factory $AboutRecipeStateCopyWith(
|
||||
AboutRecipeState value, $Res Function(AboutRecipeState) then) =
|
||||
_$AboutRecipeStateCopyWithImpl<$Res, AboutRecipeState>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$AboutRecipeStateCopyWithImpl<$Res, $Val extends AboutRecipeState>
|
||||
implements $AboutRecipeStateCopyWith<$Res> {
|
||||
_$AboutRecipeStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AboutRecipeStateImplCopyWith<$Res> {
|
||||
factory _$$AboutRecipeStateImplCopyWith(_$AboutRecipeStateImpl value,
|
||||
$Res Function(_$AboutRecipeStateImpl) then) =
|
||||
__$$AboutRecipeStateImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AboutRecipeStateImplCopyWithImpl<$Res>
|
||||
extends _$AboutRecipeStateCopyWithImpl<$Res, _$AboutRecipeStateImpl>
|
||||
implements _$$AboutRecipeStateImplCopyWith<$Res> {
|
||||
__$$AboutRecipeStateImplCopyWithImpl(_$AboutRecipeStateImpl _value,
|
||||
$Res Function(_$AboutRecipeStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AboutRecipeStateImpl implements _AboutRecipeState {
|
||||
const _$AboutRecipeStateImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AboutRecipeState()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$AboutRecipeStateImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Recipe recipe) loaded,
|
||||
required TResult Function(String message) error,
|
||||
}) {
|
||||
return $default();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? initial,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Recipe recipe)? loaded,
|
||||
TResult? Function(String message)? error,
|
||||
}) {
|
||||
return $default?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Recipe recipe)? loaded,
|
||||
TResult Function(String message)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value) $default, {
|
||||
required TResult Function(AboutRecipeStateInitial value) initial,
|
||||
required TResult Function(AboutRecipeStateLoading value) loading,
|
||||
required TResult Function(AboutRecipeStateLoaded value) loaded,
|
||||
required TResult Function(RecipeStateError value) error,
|
||||
}) {
|
||||
return $default(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AboutRecipeState value)? $default, {
|
||||
TResult? Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult? Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult? Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult? Function(RecipeStateError value)? error,
|
||||
}) {
|
||||
return $default?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value)? $default, {
|
||||
TResult Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult Function(RecipeStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if ($default != null) {
|
||||
return $default(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _AboutRecipeState implements AboutRecipeState {
|
||||
const factory _AboutRecipeState() = _$AboutRecipeStateImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AboutRecipeStateInitialImplCopyWith<$Res> {
|
||||
factory _$$AboutRecipeStateInitialImplCopyWith(
|
||||
_$AboutRecipeStateInitialImpl value,
|
||||
$Res Function(_$AboutRecipeStateInitialImpl) then) =
|
||||
__$$AboutRecipeStateInitialImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AboutRecipeStateInitialImplCopyWithImpl<$Res>
|
||||
extends _$AboutRecipeStateCopyWithImpl<$Res, _$AboutRecipeStateInitialImpl>
|
||||
implements _$$AboutRecipeStateInitialImplCopyWith<$Res> {
|
||||
__$$AboutRecipeStateInitialImplCopyWithImpl(
|
||||
_$AboutRecipeStateInitialImpl _value,
|
||||
$Res Function(_$AboutRecipeStateInitialImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AboutRecipeStateInitialImpl implements AboutRecipeStateInitial {
|
||||
const _$AboutRecipeStateInitialImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AboutRecipeState.initial()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AboutRecipeStateInitialImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Recipe recipe) loaded,
|
||||
required TResult Function(String message) error,
|
||||
}) {
|
||||
return initial();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? initial,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Recipe recipe)? loaded,
|
||||
TResult? Function(String message)? error,
|
||||
}) {
|
||||
return initial?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Recipe recipe)? loaded,
|
||||
TResult Function(String message)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value) $default, {
|
||||
required TResult Function(AboutRecipeStateInitial value) initial,
|
||||
required TResult Function(AboutRecipeStateLoading value) loading,
|
||||
required TResult Function(AboutRecipeStateLoaded value) loaded,
|
||||
required TResult Function(RecipeStateError value) error,
|
||||
}) {
|
||||
return initial(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AboutRecipeState value)? $default, {
|
||||
TResult? Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult? Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult? Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult? Function(RecipeStateError value)? error,
|
||||
}) {
|
||||
return initial?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value)? $default, {
|
||||
TResult Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult Function(RecipeStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AboutRecipeStateInitial implements AboutRecipeState {
|
||||
const factory AboutRecipeStateInitial() = _$AboutRecipeStateInitialImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AboutRecipeStateLoadingImplCopyWith<$Res> {
|
||||
factory _$$AboutRecipeStateLoadingImplCopyWith(
|
||||
_$AboutRecipeStateLoadingImpl value,
|
||||
$Res Function(_$AboutRecipeStateLoadingImpl) then) =
|
||||
__$$AboutRecipeStateLoadingImplCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AboutRecipeStateLoadingImplCopyWithImpl<$Res>
|
||||
extends _$AboutRecipeStateCopyWithImpl<$Res, _$AboutRecipeStateLoadingImpl>
|
||||
implements _$$AboutRecipeStateLoadingImplCopyWith<$Res> {
|
||||
__$$AboutRecipeStateLoadingImplCopyWithImpl(
|
||||
_$AboutRecipeStateLoadingImpl _value,
|
||||
$Res Function(_$AboutRecipeStateLoadingImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AboutRecipeStateLoadingImpl implements AboutRecipeStateLoading {
|
||||
const _$AboutRecipeStateLoadingImpl();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AboutRecipeState.loading()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AboutRecipeStateLoadingImpl);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Recipe recipe) loaded,
|
||||
required TResult Function(String message) error,
|
||||
}) {
|
||||
return loading();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? initial,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Recipe recipe)? loaded,
|
||||
TResult? Function(String message)? error,
|
||||
}) {
|
||||
return loading?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Recipe recipe)? loaded,
|
||||
TResult Function(String message)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value) $default, {
|
||||
required TResult Function(AboutRecipeStateInitial value) initial,
|
||||
required TResult Function(AboutRecipeStateLoading value) loading,
|
||||
required TResult Function(AboutRecipeStateLoaded value) loaded,
|
||||
required TResult Function(RecipeStateError value) error,
|
||||
}) {
|
||||
return loading(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AboutRecipeState value)? $default, {
|
||||
TResult? Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult? Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult? Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult? Function(RecipeStateError value)? error,
|
||||
}) {
|
||||
return loading?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value)? $default, {
|
||||
TResult Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult Function(RecipeStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AboutRecipeStateLoading implements AboutRecipeState {
|
||||
const factory AboutRecipeStateLoading() = _$AboutRecipeStateLoadingImpl;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AboutRecipeStateLoadedImplCopyWith<$Res> {
|
||||
factory _$$AboutRecipeStateLoadedImplCopyWith(
|
||||
_$AboutRecipeStateLoadedImpl value,
|
||||
$Res Function(_$AboutRecipeStateLoadedImpl) then) =
|
||||
__$$AboutRecipeStateLoadedImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({Recipe recipe});
|
||||
|
||||
$RecipeCopyWith<$Res> get recipe;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AboutRecipeStateLoadedImplCopyWithImpl<$Res>
|
||||
extends _$AboutRecipeStateCopyWithImpl<$Res, _$AboutRecipeStateLoadedImpl>
|
||||
implements _$$AboutRecipeStateLoadedImplCopyWith<$Res> {
|
||||
__$$AboutRecipeStateLoadedImplCopyWithImpl(
|
||||
_$AboutRecipeStateLoadedImpl _value,
|
||||
$Res Function(_$AboutRecipeStateLoadedImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? recipe = null,
|
||||
}) {
|
||||
return _then(_$AboutRecipeStateLoadedImpl(
|
||||
recipe: null == recipe
|
||||
? _value.recipe
|
||||
: recipe // ignore: cast_nullable_to_non_nullable
|
||||
as Recipe,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$RecipeCopyWith<$Res> get recipe {
|
||||
return $RecipeCopyWith<$Res>(_value.recipe, (value) {
|
||||
return _then(_value.copyWith(recipe: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AboutRecipeStateLoadedImpl implements AboutRecipeStateLoaded {
|
||||
const _$AboutRecipeStateLoadedImpl({required this.recipe});
|
||||
|
||||
@override
|
||||
final Recipe recipe;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AboutRecipeState.loaded(recipe: $recipe)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AboutRecipeStateLoadedImpl &&
|
||||
(identical(other.recipe, recipe) || other.recipe == recipe));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, recipe);
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$AboutRecipeStateLoadedImplCopyWith<_$AboutRecipeStateLoadedImpl>
|
||||
get copyWith => __$$AboutRecipeStateLoadedImplCopyWithImpl<
|
||||
_$AboutRecipeStateLoadedImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Recipe recipe) loaded,
|
||||
required TResult Function(String message) error,
|
||||
}) {
|
||||
return loaded(recipe);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? initial,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Recipe recipe)? loaded,
|
||||
TResult? Function(String message)? error,
|
||||
}) {
|
||||
return loaded?.call(recipe);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Recipe recipe)? loaded,
|
||||
TResult Function(String message)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(recipe);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value) $default, {
|
||||
required TResult Function(AboutRecipeStateInitial value) initial,
|
||||
required TResult Function(AboutRecipeStateLoading value) loading,
|
||||
required TResult Function(AboutRecipeStateLoaded value) loaded,
|
||||
required TResult Function(RecipeStateError value) error,
|
||||
}) {
|
||||
return loaded(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AboutRecipeState value)? $default, {
|
||||
TResult? Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult? Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult? Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult? Function(RecipeStateError value)? error,
|
||||
}) {
|
||||
return loaded?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value)? $default, {
|
||||
TResult Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult Function(RecipeStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loaded != null) {
|
||||
return loaded(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AboutRecipeStateLoaded implements AboutRecipeState {
|
||||
const factory AboutRecipeStateLoaded({required final Recipe recipe}) =
|
||||
_$AboutRecipeStateLoadedImpl;
|
||||
|
||||
Recipe get recipe;
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$AboutRecipeStateLoadedImplCopyWith<_$AboutRecipeStateLoadedImpl>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$RecipeStateErrorImplCopyWith<$Res> {
|
||||
factory _$$RecipeStateErrorImplCopyWith(_$RecipeStateErrorImpl value,
|
||||
$Res Function(_$RecipeStateErrorImpl) then) =
|
||||
__$$RecipeStateErrorImplCopyWithImpl<$Res>;
|
||||
@useResult
|
||||
$Res call({String message});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$RecipeStateErrorImplCopyWithImpl<$Res>
|
||||
extends _$AboutRecipeStateCopyWithImpl<$Res, _$RecipeStateErrorImpl>
|
||||
implements _$$RecipeStateErrorImplCopyWith<$Res> {
|
||||
__$$RecipeStateErrorImplCopyWithImpl(_$RecipeStateErrorImpl _value,
|
||||
$Res Function(_$RecipeStateErrorImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? message = null,
|
||||
}) {
|
||||
return _then(_$RecipeStateErrorImpl(
|
||||
message: null == message
|
||||
? _value.message
|
||||
: message // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$RecipeStateErrorImpl implements RecipeStateError {
|
||||
const _$RecipeStateErrorImpl({required this.message});
|
||||
|
||||
@override
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AboutRecipeState.error(message: $message)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$RecipeStateErrorImpl &&
|
||||
(identical(other.message, message) || other.message == message));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, message);
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$RecipeStateErrorImplCopyWith<_$RecipeStateErrorImpl> get copyWith =>
|
||||
__$$RecipeStateErrorImplCopyWithImpl<_$RecipeStateErrorImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>(
|
||||
TResult Function() $default, {
|
||||
required TResult Function() initial,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Recipe recipe) loaded,
|
||||
required TResult Function(String message) error,
|
||||
}) {
|
||||
return error(message);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>(
|
||||
TResult? Function()? $default, {
|
||||
TResult? Function()? initial,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Recipe recipe)? loaded,
|
||||
TResult? Function(String message)? error,
|
||||
}) {
|
||||
return error?.call(message);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>(
|
||||
TResult Function()? $default, {
|
||||
TResult Function()? initial,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Recipe recipe)? loaded,
|
||||
TResult Function(String message)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(message);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value) $default, {
|
||||
required TResult Function(AboutRecipeStateInitial value) initial,
|
||||
required TResult Function(AboutRecipeStateLoading value) loading,
|
||||
required TResult Function(AboutRecipeStateLoaded value) loaded,
|
||||
required TResult Function(RecipeStateError value) error,
|
||||
}) {
|
||||
return error(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>(
|
||||
TResult? Function(_AboutRecipeState value)? $default, {
|
||||
TResult? Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult? Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult? Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult? Function(RecipeStateError value)? error,
|
||||
}) {
|
||||
return error?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>(
|
||||
TResult Function(_AboutRecipeState value)? $default, {
|
||||
TResult Function(AboutRecipeStateInitial value)? initial,
|
||||
TResult Function(AboutRecipeStateLoading value)? loading,
|
||||
TResult Function(AboutRecipeStateLoaded value)? loaded,
|
||||
TResult Function(RecipeStateError value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class RecipeStateError implements AboutRecipeState {
|
||||
const factory RecipeStateError({required final String message}) =
|
||||
_$RecipeStateErrorImpl;
|
||||
|
||||
String get message;
|
||||
|
||||
/// Create a copy of AboutRecipeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$RecipeStateErrorImplCopyWith<_$RecipeStateErrorImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class IngredientsWidget extends StatelessWidget {
|
||||
const IngredientsWidget({super.key, required this.recipe});
|
||||
final Recipe recipe;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return MainBackgroundBouble(
|
||||
child: ExpansionTile(
|
||||
initiallyExpanded: true,
|
||||
shape: Border(),
|
||||
title: Text(
|
||||
s.ingredients,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
children: List.generate(recipe.ingredients!.length, (index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 16, bottom: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 4,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.black,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final portion = Portion.getPortionFromValue(recipe.ingredients![index].unit ?? '');
|
||||
|
||||
String? portionName;
|
||||
if (portion != null) {
|
||||
portionName = getLocalizedMeasurementUnits(s, portion);
|
||||
}
|
||||
return Text(
|
||||
'${recipe.ingredients![index].name} - ${recipe.ingredients![index].portion} ${portionName}',
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
63
lib/features/recipe/presentation/widgets/steps_widget.dart
Normal file
63
lib/features/recipe/presentation/widgets/steps_widget.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class StepsWidget extends StatelessWidget {
|
||||
const StepsWidget({super.key, required this.recipe});
|
||||
final Recipe recipe;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return MainBackgroundBouble(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
s.step_by_step_photo_recipe,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
...List.generate(recipe.steps?.length ?? 0, (index) {
|
||||
return Column(
|
||||
spacing: 8,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
child: Text(
|
||||
'${s.step} ${index + 1}',
|
||||
style: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700),
|
||||
),
|
||||
),
|
||||
if (recipe.steps?[index].image != null && recipe.steps![index].image.isNotEmpty)
|
||||
AspectRatio(
|
||||
aspectRatio: 16 / 12,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Image.network(
|
||||
baseUrl + '/storage/' + recipe.steps![index].image,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
recipe.steps![index].description,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:async';
|
||||
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/features/recipe/services/about_recipe_service.dart';
|
||||
|
||||
class AboutRecipeRepository {
|
||||
final AboutRecipeService recipeService;
|
||||
final _recipeLikeStateStreamController = StreamController<LikesState>.broadcast();
|
||||
final _recipeFavoriteStateStreamController = StreamController<FavoriteState>.broadcast();
|
||||
final _recipeCommentsStateStreamController = StreamController<CommentsState>.broadcast();
|
||||
Stream get recipeLikeState => _recipeLikeStateStreamController.stream;
|
||||
Stream get recipeFavoriteState => _recipeFavoriteStateStreamController.stream;
|
||||
Stream get recipeCommentsState => _recipeCommentsStateStreamController.stream;
|
||||
|
||||
AboutRecipeRepository({required this.recipeService});
|
||||
|
||||
Future<Recipe> getRecipe(String recipeID) async {
|
||||
try {
|
||||
return await recipeService.getRecipe(recipeID);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> likeRecipe(String slug) async {
|
||||
try {
|
||||
await recipeService.likeRecipe(slug: slug);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addToFavorite(String slug) async {
|
||||
try {
|
||||
await recipeService.addToFavorite(slug: slug);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> removeFromFavorite(String slug) async {
|
||||
try {
|
||||
await recipeService.removeFromFavorite(slug: slug);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
void emitLikesStateToFeed(LikesState state) => _recipeLikeStateStreamController.add(state);
|
||||
void emitFavoriteStateToFeed(FavoriteState state) => _recipeFavoriteStateStreamController.add(state);
|
||||
void emitCommentsStateToFeed(CommentsState state) => _recipeCommentsStateStreamController.add(state);
|
||||
}
|
||||
28
lib/features/recipe/services/about_recipe_service.dart
Normal file
28
lib/features/recipe/services/about_recipe_service.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
|
||||
part 'about_recipe_service.g.dart';
|
||||
|
||||
@RestApi()
|
||||
abstract class AboutRecipeService {
|
||||
factory AboutRecipeService(Dio dio, {String baseUrl}) = _AboutRecipeService;
|
||||
|
||||
@POST('/api/recipes/{slug}/like')
|
||||
Future<void> likeRecipe({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/{slug}/add_to_favorite')
|
||||
Future<void> addToFavorite({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/{slug}/remove_from_favorite')
|
||||
Future<void> removeFromFavorite({
|
||||
@Path() required String slug,
|
||||
});
|
||||
|
||||
@GET('/api/recipes/show/{id}')
|
||||
Future<Recipe> getRecipe(@Path() String id);
|
||||
}
|
||||
130
lib/features/recipe/services/about_recipe_service.g.dart
Normal file
130
lib/features/recipe/services/about_recipe_service.g.dart
Normal file
@@ -0,0 +1,130 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'about_recipe_service.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RetrofitGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
|
||||
|
||||
class _AboutRecipeService implements AboutRecipeService {
|
||||
_AboutRecipeService(this._dio, {this.baseUrl, this.errorLogger});
|
||||
|
||||
final Dio _dio;
|
||||
|
||||
String? baseUrl;
|
||||
|
||||
final ParseErrorLogger? errorLogger;
|
||||
|
||||
@override
|
||||
Future<void> likeRecipe({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/like',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addToFavorite({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/add_to_favorite',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> removeFromFavorite({required String slug}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/remove_from_favorite',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Recipe> getRecipe(String id) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<Recipe>(
|
||||
Options(method: 'GET', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/show/${id}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
final _result = await _dio.fetch<Map<String, dynamic>>(_options);
|
||||
late Recipe _value;
|
||||
try {
|
||||
_value = Recipe.fromJson(_result.data!);
|
||||
} on Object catch (e, s) {
|
||||
errorLogger?.logError(e, s, _options);
|
||||
rethrow;
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
requestOptions.responseType == ResponseType.stream)) {
|
||||
if (T == String) {
|
||||
requestOptions.responseType = ResponseType.plain;
|
||||
} else {
|
||||
requestOptions.responseType = ResponseType.json;
|
||||
}
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
|
||||
if (baseUrl == null || baseUrl.trim().isEmpty) {
|
||||
return dioBaseUrl;
|
||||
}
|
||||
|
||||
final url = Uri.parse(baseUrl);
|
||||
|
||||
if (url.isAbsolute) {
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
|
||||
}
|
||||
}
|
||||
@@ -1,430 +0,0 @@
|
||||
import 'dart:io';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart' as step;
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class AboutRecipesScreen extends StatefulWidget {
|
||||
final Recipes recipes;
|
||||
|
||||
const AboutRecipesScreen({super.key, required this.recipes});
|
||||
|
||||
@override
|
||||
State<AboutRecipesScreen> createState() => _AboutRecipesScreenState();
|
||||
}
|
||||
|
||||
class _AboutRecipesScreenState extends State<AboutRecipesScreen> {
|
||||
final CommentsCubit commentsCubit = sl<CommentsCubit>();
|
||||
final textEditingController = TextEditingController();
|
||||
int? replyId;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<CommentsCubit>(
|
||||
create: (BuildContext context) => commentsCubit
|
||||
..getComments(
|
||||
widget.recipes.slug,
|
||||
CommentSourceType.recipe,
|
||||
true,
|
||||
),
|
||||
child: BlocConsumer<CommentsCubit, CommentsState>(
|
||||
listener: (BuildContext context, CommentsState state) {
|
||||
if (state is CommentsStateLoaded) {
|
||||
setState(() {
|
||||
replyId = state.replyId;
|
||||
});
|
||||
}
|
||||
},
|
||||
builder: (BuildContext context, CommentsState state) {
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
bottomSheet: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 12) + (Platform.isIOS ? const EdgeInsets.only(bottom: 16) : EdgeInsets.zero),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: Colors.black.withValues(alpha: 0.1),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (replyId != null)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
replyId = null;
|
||||
textEditingController.clear();
|
||||
});
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.close_rounded,
|
||||
size: 18,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (replyId != null) SizedBox(width: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width - (replyId == null ? 64 : 104),
|
||||
child: TextFormField(
|
||||
onChanged: (_) {
|
||||
setState(() {});
|
||||
},
|
||||
controller: textEditingController,
|
||||
maxLines: 5,
|
||||
minLines: 1,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
height: 1,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
hintText: 'Комментарий',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1,
|
||||
color: Color(0xFFAEAEB2),
|
||||
),
|
||||
filled: true,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderSide: BorderSide(
|
||||
color: Color(0xFFD1D1D6),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (textEditingController.text.length > 2) {
|
||||
commentsCubit.sendComment(
|
||||
id: widget.recipes.slug,
|
||||
commentText: textEditingController.text,
|
||||
parentCommentId: replyId,
|
||||
commentSourceType: CommentSourceType.recipe,
|
||||
);
|
||||
context.read<CommentsCubit>().setReplyId(null);
|
||||
setState(() {
|
||||
textEditingController.clear();
|
||||
replyId = null;
|
||||
});
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: textEditingController.text.length > 2 ? appTheme.blueA400 : Colors.grey,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
height: 32,
|
||||
width: 32,
|
||||
child: Icon(
|
||||
Icons.send_rounded,
|
||||
size: 18,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
appBar: AppBar(
|
||||
actions: [
|
||||
InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: () => GoRouter.of(context).pushNamed('profileScreen', extra: widget.recipes.author),
|
||||
child: Ink(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
maxRadius: 16,
|
||||
minRadius: 16,
|
||||
backgroundImage: NetworkImage(widget.recipes.author.authorProfileIcon),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
widget.recipes.author.authorName,
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.only(bottom: 80),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
widget.recipes.title ?? '',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.timer_outlined),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
widget.recipes.cookingTime.toString() + ' минут',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
Icon(Icons.fast_forward_outlined),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'${widget.recipes.steps?.length ?? 0}' + ' этапов',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (widget.recipes.description.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Html(
|
||||
data: widget.recipes.description,
|
||||
style: {
|
||||
"*": Style(
|
||||
color: Colors.black87,
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
CachedNetworkImage(
|
||||
imageUrl: baseUrl + '/storage/' + widget.recipes.image,
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
'Ингредиенты',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
ListView.separated(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
if (widget.recipes.ingredients != null) {
|
||||
return _ingredient(widget.recipes.ingredients![index]);
|
||||
}
|
||||
return SizedBox.shrink();
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(height: 4),
|
||||
itemCount: widget.recipes.ingredients?.length ?? 0,
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
'Пошаговый рецепт',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
if (widget.recipes.steps == null) return SizedBox.shrink();
|
||||
return _step(widget.recipes.steps![index], index + 1);
|
||||
},
|
||||
separatorBuilder: (context, index) => Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Container(
|
||||
height: 0.4,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
),
|
||||
itemCount: widget.recipes.steps?.length ?? 0,
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Container(
|
||||
height: 0.4,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
widget.recipes.commentsCount.toString() + ' КОММЕНТАРИЕВ',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: appTheme.gray500,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
if (state is CommentsStateLoading)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: const Loader(),
|
||||
),
|
||||
if (state is CommentsStateLoaded)
|
||||
CommentsWidget(
|
||||
id: widget.recipes.slug,
|
||||
commentSourceType: CommentSourceType.recipe,
|
||||
comment: state.comment,
|
||||
replyId: replyId,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_ingredient(Ingredient ingredient) {
|
||||
return Text(
|
||||
'• ' + ingredient.name + ' ' + ingredient.portion + ' ' + (ingredient.unit ?? ''),
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_step(step.Step step, int stepNumber) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
'Шаг ' + stepNumber.toString(),
|
||||
style: TextStyle(
|
||||
color: Colors.black54,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
step.description,
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
if (step.image.length > 1)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: CachedNetworkImage(imageUrl: baseUrl + '/storage/' + step.image),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_model.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/recipe_tag_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
import 'package:eatvio_app/features/recipes/models/product.dart';
|
||||
|
||||
part 'recipe_service.g.dart';
|
||||
|
||||
@RestApi()
|
||||
abstract class RecipeService {
|
||||
factory RecipeService(Dio dio, {String baseUrl}) = _RecipeService;
|
||||
|
||||
@GET('/api/recipes/show/{id}')
|
||||
Future<RecipeModel> getRecipe(@Path() String id);
|
||||
|
||||
@GET('/api/diary/product_nutritional_values/filter')
|
||||
Future<Map<String, List<Product>>> getInputProduct(@Query('name') String name);
|
||||
|
||||
@POST('/api/recipes/create')
|
||||
@MultiPart()
|
||||
Future<void> publishRecipe({
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/update/{id}')
|
||||
Future<RecipeModel> editRecipe(@Part() Map<String, Object?> recipe, String id);
|
||||
|
||||
@GET('/api/recipes/tags')
|
||||
Future<RecipeTagModel> getTags();
|
||||
}
|
||||
@@ -24,7 +24,10 @@ class SupportScreen extends StatelessWidget {
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse('https://t.me/eatvio'));
|
||||
launchUrl(
|
||||
Uri.parse('https://t.me/eatvio'),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Ink(
|
||||
@@ -53,7 +56,10 @@ class SupportScreen extends StatelessWidget {
|
||||
const SizedBox(height: 8),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse('mailto:help@eatv.io'));
|
||||
launchUrl(
|
||||
Uri.parse('mailto:help@eatv.io'),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Ink(
|
||||
|
||||
@@ -39,10 +39,8 @@ MessageLookupByLibrary? _findExact(String localeName) {
|
||||
/// User programs should call this before using [localeName] for messages.
|
||||
Future<bool> initializeMessages(String localeName) {
|
||||
var availableLocale = Intl.verifiedLocale(
|
||||
localeName,
|
||||
(locale) => _deferredLibraries[locale] != null,
|
||||
onFailure: (_) => null,
|
||||
);
|
||||
localeName, (locale) => _deferredLibraries[locale] != null,
|
||||
onFailure: (_) => null);
|
||||
if (availableLocale == null) {
|
||||
return new SynchronousFuture(false);
|
||||
}
|
||||
@@ -62,11 +60,8 @@ bool _messagesExistFor(String locale) {
|
||||
}
|
||||
|
||||
MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) {
|
||||
var actualLocale = Intl.verifiedLocale(
|
||||
locale,
|
||||
_messagesExistFor,
|
||||
onFailure: (_) => null,
|
||||
);
|
||||
var actualLocale =
|
||||
Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null);
|
||||
if (actualLocale == null) return null;
|
||||
return _findExact(actualLocale);
|
||||
}
|
||||
|
||||
@@ -22,375 +22,350 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
"Moscow": MessageLookupByLibrary.simpleMessage("Москва"),
|
||||
"Russia": MessageLookupByLibrary.simpleMessage("Россия"),
|
||||
"about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"),
|
||||
"about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"),
|
||||
"active": MessageLookupByLibrary.simpleMessage("Активен"),
|
||||
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
|
||||
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
|
||||
"add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"),
|
||||
"adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"),
|
||||
"additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Дополнительная информация",
|
||||
),
|
||||
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"all": MessageLookupByLibrary.simpleMessage("Все"),
|
||||
"allergies_presence": MessageLookupByLibrary.simpleMessage(
|
||||
"Наличие аллергии",
|
||||
),
|
||||
"another_form_of_comment": MessageLookupByLibrary.simpleMessage(
|
||||
"комментария",
|
||||
),
|
||||
"another_form_of_day": MessageLookupByLibrary.simpleMessage("дня"),
|
||||
"answer": MessageLookupByLibrary.simpleMessage("Ответить"),
|
||||
"archived": MessageLookupByLibrary.simpleMessage("В архиве"),
|
||||
"authentificate": MessageLookupByLibrary.simpleMessage("Войти"),
|
||||
"average_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Средние показатели давления:",
|
||||
),
|
||||
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"),
|
||||
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"carb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"carb_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
||||
),
|
||||
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||
"chat": MessageLookupByLibrary.simpleMessage("Чат"),
|
||||
"chest": MessageLookupByLibrary.simpleMessage("Грудь"),
|
||||
"chest_circumference": MessageLookupByLibrary.simpleMessage("Обхват груди"),
|
||||
"choose_diet_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите срок диеты",
|
||||
),
|
||||
"choose_plan_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите срок плана",
|
||||
),
|
||||
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике",
|
||||
),
|
||||
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры обязательны к заполнению",
|
||||
),
|
||||
"circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры должны быть числами",
|
||||
),
|
||||
"circumferences_chart": MessageLookupByLibrary.simpleMessage(
|
||||
"График обхватов",
|
||||
),
|
||||
"city": MessageLookupByLibrary.simpleMessage("Город"),
|
||||
"city_of_living": MessageLookupByLibrary.simpleMessage("Город проживания"),
|
||||
"comfort": MessageLookupByLibrary.simpleMessage("Комфорт"),
|
||||
"comment": MessageLookupByLibrary.simpleMessage("комментарий"),
|
||||
"comments": MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
"complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"),
|
||||
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Цена для покупателя",
|
||||
),
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
||||
"diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"),
|
||||
"diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"),
|
||||
"diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"),
|
||||
"do_you_have_hypertension_tendency": MessageLookupByLibrary.simpleMessage(
|
||||
"Есть ли у вас гипертония?",
|
||||
),
|
||||
"do_you_have_hypotension_tendency": MessageLookupByLibrary.simpleMessage(
|
||||
"Есть ли у вас гипотония?",
|
||||
),
|
||||
"do_you_take_pills": MessageLookupByLibrary.simpleMessage(
|
||||
"Принимаете ли вы лекарства или бады?",
|
||||
),
|
||||
"down_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Нижние показатели давления:",
|
||||
),
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"drafted": MessageLookupByLibrary.simpleMessage("Черновики"),
|
||||
"eating_behavior": MessageLookupByLibrary.simpleMessage(
|
||||
"Пищевое поведение",
|
||||
),
|
||||
"eating_behavior_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование пищевого поведения",
|
||||
),
|
||||
"eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;",
|
||||
),
|
||||
"economy": MessageLookupByLibrary.simpleMessage("Эконом"),
|
||||
"edit": MessageLookupByLibrary.simpleMessage("Редактировать"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("Электронная почта"),
|
||||
"email_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Необходимо ввести адрес электронной почты",
|
||||
),
|
||||
"email_invalid": MessageLookupByLibrary.simpleMessage(
|
||||
"Некорректный адрес электронной почты",
|
||||
),
|
||||
"enter_additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите любую дополнительную информацию на своё усмотрение:",
|
||||
),
|
||||
"enter_diet_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите описание диеты",
|
||||
),
|
||||
"enter_diet_name": MessageLookupByLibrary.simpleMessage(
|
||||
"Выведите название диеты",
|
||||
),
|
||||
"enter_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите информацию...",
|
||||
),
|
||||
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
"expand": MessageLookupByLibrary.simpleMessage("Показать полностью"),
|
||||
"fats": MessageLookupByLibrary.simpleMessage("Жиры"),
|
||||
"favorite_foods": MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши любимые/нелюбимые продукты питания?",
|
||||
),
|
||||
"female": MessageLookupByLibrary.simpleMessage("Женский"),
|
||||
"fill_in_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Заполните информацию:",
|
||||
),
|
||||
"finish": MessageLookupByLibrary.simpleMessage("Завершить"),
|
||||
"first_name": MessageLookupByLibrary.simpleMessage("Имя"),
|
||||
"first_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя обязательно для заполнения",
|
||||
),
|
||||
"first_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени должен быть минимум 1 символ",
|
||||
),
|
||||
"fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"),
|
||||
"fit_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;",
|
||||
),
|
||||
"fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"),
|
||||
"from": MessageLookupByLibrary.simpleMessage("от"),
|
||||
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
|
||||
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
|
||||
"general_info": MessageLookupByLibrary.simpleMessage("Общая информация"),
|
||||
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"has_alergy": MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
|
||||
"has_hyper": MessageLookupByLibrary.simpleMessage(
|
||||
"Склонность к гипертонии",
|
||||
),
|
||||
"has_hypo": MessageLookupByLibrary.simpleMessage("Склонность к гипотонии"),
|
||||
"height": MessageLookupByLibrary.simpleMessage("Рост"),
|
||||
"height_measurements": MessageLookupByLibrary.simpleMessage("Замер роста"),
|
||||
"hide": MessageLookupByLibrary.simpleMessage("Свернуть"),
|
||||
"hip_circumference": MessageLookupByLibrary.simpleMessage("Обхват бедер"),
|
||||
"hips": MessageLookupByLibrary.simpleMessage("Бедра"),
|
||||
"in_progress": MessageLookupByLibrary.simpleMessage("В процессе"),
|
||||
"inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"initial_measurements": MessageLookupByLibrary.simpleMessage(
|
||||
"Первичные замеры",
|
||||
),
|
||||
"label": MessageLookupByLibrary.simpleMessage("Название"),
|
||||
"language": MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name": MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
"last_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Фамилия обязательна для заполнения",
|
||||
),
|
||||
"last_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В фамилии должен быть минимум 6 символов",
|
||||
),
|
||||
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
|
||||
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
|
||||
"light_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.",
|
||||
),
|
||||
"liked_groceries": MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"link_was_copied": MessageLookupByLibrary.simpleMessage(
|
||||
"Ссылка успешно скопирована",
|
||||
),
|
||||
"loading": MessageLookupByLibrary.simpleMessage("Загрузка..."),
|
||||
"lower": MessageLookupByLibrary.simpleMessage("Нижнее"),
|
||||
"male": MessageLookupByLibrary.simpleMessage("Мужской"),
|
||||
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
|
||||
"meat": MessageLookupByLibrary.simpleMessage("Мясо"),
|
||||
"meat_type": MessageLookupByLibrary.simpleMessage("С мясом"),
|
||||
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму.",
|
||||
),
|
||||
"milliliter": MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"minimal_customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Минимальная цена для покупателя: 1200₽",
|
||||
),
|
||||
"most_new": MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old": MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err": MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"),
|
||||
"msg_something_went_wrong": MessageLookupByLibrary.simpleMessage(
|
||||
"Что то пошло не так!",
|
||||
),
|
||||
"my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"),
|
||||
"my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"),
|
||||
"my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"),
|
||||
"my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"),
|
||||
"name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя пользователя обязательно для заполнения",
|
||||
),
|
||||
"name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени пользователя должно быть минимум 6 символов",
|
||||
),
|
||||
"no": MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account": MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"not_liked_groceries": MessageLookupByLibrary.simpleMessage(
|
||||
"Не любимые продукты",
|
||||
),
|
||||
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option": MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content": MessageLookupByLibrary.simpleMessage("Содержание опции"),
|
||||
"option_content_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"На связи 7 дней в неделю",
|
||||
),
|
||||
"option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"),
|
||||
"option_desc_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"Этот план питания для похудения на 7 дней сбалансированный и разнообразный",
|
||||
),
|
||||
"option_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Продолжительность опции",
|
||||
),
|
||||
"option_personal_diet_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Опция подразумевает создание индивидуальной диеты",
|
||||
),
|
||||
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"other_info": MessageLookupByLibrary.simpleMessage("Прочая информация"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation": MessageLookupByLibrary.simpleMessage(
|
||||
"Подтвердите пароль",
|
||||
),
|
||||
"password_confirmation_mismatch": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароли не совпадают",
|
||||
),
|
||||
"password_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароль обязателен для заполнения",
|
||||
),
|
||||
"password_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В пароле должно быть минимум 6 символов",
|
||||
),
|
||||
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
||||
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
|
||||
"personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"),
|
||||
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
|
||||
"physical_fitness": MessageLookupByLibrary.simpleMessage(
|
||||
"Физическая форма",
|
||||
),
|
||||
"place_of_living": MessageLookupByLibrary.simpleMessage("Место проживания"),
|
||||
"plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"),
|
||||
"plan_desc": MessageLookupByLibrary.simpleMessage("Описание плана"),
|
||||
"plan_desc_example": MessageLookupByLibrary.simpleMessage(
|
||||
"Большое подробное, привлекательное описание плана",
|
||||
),
|
||||
"plan_duration": MessageLookupByLibrary.simpleMessage("Срок плана"),
|
||||
"plan_label_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План для поддержания формы",
|
||||
),
|
||||
"plan_type": MessageLookupByLibrary.simpleMessage("Тип плана"),
|
||||
"plans_complete": MessageLookupByLibrary.simpleMessage("Пройденные планы"),
|
||||
"popular": MessageLookupByLibrary.simpleMessage("Популярные"),
|
||||
"preferred_language": MessageLookupByLibrary.simpleMessage(
|
||||
"Предпочитаемый язык общения",
|
||||
),
|
||||
"pressure": MessageLookupByLibrary.simpleMessage("Давление"),
|
||||
"pressure_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления обязательны к заполнению",
|
||||
),
|
||||
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления должны быть числами",
|
||||
),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("Превью"),
|
||||
"price": MessageLookupByLibrary.simpleMessage("Цена"),
|
||||
"price_explanation": MessageLookupByLibrary.simpleMessage(
|
||||
"Разница в ценах, это комиссия Итвио",
|
||||
),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"published": MessageLookupByLibrary.simpleMessage("Опубликованные"),
|
||||
"removeFromActive": MessageLookupByLibrary.simpleMessage(
|
||||
"Снять с публикации",
|
||||
),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"sex": MessageLookupByLibrary.simpleMessage("Пол"),
|
||||
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),
|
||||
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"slim": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;",
|
||||
),
|
||||
"sport_hobbies": MessageLookupByLibrary.simpleMessage(
|
||||
"Спортивные увлечения",
|
||||
),
|
||||
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"takes_pills": MessageLookupByLibrary.simpleMessage("Принимает лекарства"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:",
|
||||
),
|
||||
"three_options": MessageLookupByLibrary.simpleMessage("3 опции"),
|
||||
"time": MessageLookupByLibrary.simpleMessage("Время прохождения"),
|
||||
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
|
||||
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
|
||||
"unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Нелюбимые продукты",
|
||||
),
|
||||
"up_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Верхние показатели давления:",
|
||||
),
|
||||
"upper": MessageLookupByLibrary.simpleMessage("Верхнее"),
|
||||
"user_authorization": MessageLookupByLibrary.simpleMessage(
|
||||
"Аутентификация",
|
||||
),
|
||||
"user_data": MessageLookupByLibrary.simpleMessage("Данные пользователя"),
|
||||
"user_registration": MessageLookupByLibrary.simpleMessage(
|
||||
"Регистрация пользователя",
|
||||
),
|
||||
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),
|
||||
"vegan": MessageLookupByLibrary.simpleMessage("Веган."),
|
||||
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья.",
|
||||
),
|
||||
"waist": MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference": MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
"weight": MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
"weight_chart": MessageLookupByLibrary.simpleMessage("График веса"),
|
||||
"weight_measurements": MessageLookupByLibrary.simpleMessage("Замер веса"),
|
||||
"wellness": MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Улучшение самочувствия",
|
||||
),
|
||||
"wellness_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
||||
),
|
||||
"what_is_your_name": MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
"Неверные данные пользователя",
|
||||
),
|
||||
"you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"),
|
||||
"your_blood_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваше артериальное давление?",
|
||||
),
|
||||
"your_favorite_sports": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши спортивные увлечения?",
|
||||
),
|
||||
"your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:"),
|
||||
};
|
||||
"Moscow": MessageLookupByLibrary.simpleMessage("Москва"),
|
||||
"Russia": MessageLookupByLibrary.simpleMessage("Россия"),
|
||||
"about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"),
|
||||
"about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"),
|
||||
"about_recipe": MessageLookupByLibrary.simpleMessage("Об этом рецепте"),
|
||||
"active": MessageLookupByLibrary.simpleMessage("Активен"),
|
||||
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
|
||||
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
|
||||
"add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"),
|
||||
"adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"),
|
||||
"additional_information":
|
||||
MessageLookupByLibrary.simpleMessage("Дополнительная информация"),
|
||||
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"all": MessageLookupByLibrary.simpleMessage("Все"),
|
||||
"allergies_presence":
|
||||
MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
|
||||
"another_form_of_comment":
|
||||
MessageLookupByLibrary.simpleMessage("комментария"),
|
||||
"another_form_of_day": MessageLookupByLibrary.simpleMessage("дня"),
|
||||
"another_form_of_hour": MessageLookupByLibrary.simpleMessage("часа"),
|
||||
"another_form_of_minute": MessageLookupByLibrary.simpleMessage("минут"),
|
||||
"another_form_of_stage": MessageLookupByLibrary.simpleMessage("этапа"),
|
||||
"answer": MessageLookupByLibrary.simpleMessage("Ответить"),
|
||||
"archived": MessageLookupByLibrary.simpleMessage("В архиве"),
|
||||
"authentificate": MessageLookupByLibrary.simpleMessage("Войти"),
|
||||
"average_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Средние показатели давления:"),
|
||||
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"),
|
||||
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"cancel_diet": MessageLookupByLibrary.simpleMessage("Отменить диету?"),
|
||||
"carb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"carb_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||
"chat": MessageLookupByLibrary.simpleMessage("Чат"),
|
||||
"check_out_video_recipe":
|
||||
MessageLookupByLibrary.simpleMessage("Посмотреть видео рецепт"),
|
||||
"chest": MessageLookupByLibrary.simpleMessage("Грудь"),
|
||||
"chest_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват груди"),
|
||||
"choose_diet_duration":
|
||||
MessageLookupByLibrary.simpleMessage("Выберите срок диеты"),
|
||||
"choose_plan_duration":
|
||||
MessageLookupByLibrary.simpleMessage("Выберите срок плана"),
|
||||
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике"),
|
||||
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры обязательны к заполнению"),
|
||||
"circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры должны быть числами"),
|
||||
"circumferences_chart":
|
||||
MessageLookupByLibrary.simpleMessage("График обхватов"),
|
||||
"city": MessageLookupByLibrary.simpleMessage("Город"),
|
||||
"city_of_living":
|
||||
MessageLookupByLibrary.simpleMessage("Город проживания"),
|
||||
"comfort": MessageLookupByLibrary.simpleMessage("Комфорт"),
|
||||
"comment": MessageLookupByLibrary.simpleMessage("комментарий"),
|
||||
"comments": MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
"complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"),
|
||||
"confirm": MessageLookupByLibrary.simpleMessage("Подтвердить"),
|
||||
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"could_not_cancel_diet":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось отменить диету"),
|
||||
"could_not_launch_video":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось запустить видео"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price":
|
||||
MessageLookupByLibrary.simpleMessage("Цена для покупателя"),
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
||||
"diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"),
|
||||
"diet_started":
|
||||
MessageLookupByLibrary.simpleMessage("Диета уже начата"),
|
||||
"diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"),
|
||||
"diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"),
|
||||
"do_you_have_hypertension_tendency":
|
||||
MessageLookupByLibrary.simpleMessage("Есть ли у вас гипертония?"),
|
||||
"do_you_have_hypotension_tendency":
|
||||
MessageLookupByLibrary.simpleMessage("Есть ли у вас гипотония?"),
|
||||
"do_you_take_pills": MessageLookupByLibrary.simpleMessage(
|
||||
"Принимаете ли вы лекарства или бады?"),
|
||||
"down_pressure":
|
||||
MessageLookupByLibrary.simpleMessage("Нижние показатели давления:"),
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"drafted": MessageLookupByLibrary.simpleMessage("Черновики"),
|
||||
"eating_behavior":
|
||||
MessageLookupByLibrary.simpleMessage("Пищевое поведение"),
|
||||
"eating_behavior_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование пищевого поведения"),
|
||||
"eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;"),
|
||||
"economy": MessageLookupByLibrary.simpleMessage("Эконом"),
|
||||
"edit": MessageLookupByLibrary.simpleMessage("Редактировать"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("Электронная почта"),
|
||||
"email_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Необходимо ввести адрес электронной почты"),
|
||||
"email_invalid": MessageLookupByLibrary.simpleMessage(
|
||||
"Некорректный адрес электронной почты"),
|
||||
"enter_additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите любую дополнительную информацию на своё усмотрение:"),
|
||||
"enter_diet_description":
|
||||
MessageLookupByLibrary.simpleMessage("Введите описание диеты"),
|
||||
"enter_diet_name":
|
||||
MessageLookupByLibrary.simpleMessage("Выведите название диеты"),
|
||||
"enter_information":
|
||||
MessageLookupByLibrary.simpleMessage("Введите информацию..."),
|
||||
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
"expand": MessageLookupByLibrary.simpleMessage("Показать полностью"),
|
||||
"fats": MessageLookupByLibrary.simpleMessage("Жиры"),
|
||||
"favorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши любимые/нелюбимые продукты питания?"),
|
||||
"female": MessageLookupByLibrary.simpleMessage("Женский"),
|
||||
"fill_in_information":
|
||||
MessageLookupByLibrary.simpleMessage("Заполните информацию:"),
|
||||
"finish": MessageLookupByLibrary.simpleMessage("Завершить"),
|
||||
"first_name": MessageLookupByLibrary.simpleMessage("Имя"),
|
||||
"first_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя обязательно для заполнения"),
|
||||
"first_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени должен быть минимум 1 символ"),
|
||||
"fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"),
|
||||
"fit_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"),
|
||||
"from": MessageLookupByLibrary.simpleMessage("от"),
|
||||
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
|
||||
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
|
||||
"general_info":
|
||||
MessageLookupByLibrary.simpleMessage("Общая информация"),
|
||||
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"has_alergy": MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
|
||||
"has_hyper":
|
||||
MessageLookupByLibrary.simpleMessage("Склонность к гипертонии"),
|
||||
"has_hypo":
|
||||
MessageLookupByLibrary.simpleMessage("Склонность к гипотонии"),
|
||||
"height": MessageLookupByLibrary.simpleMessage("Рост"),
|
||||
"height_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Замер роста"),
|
||||
"hide": MessageLookupByLibrary.simpleMessage("Свернуть"),
|
||||
"hip_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват бедер"),
|
||||
"hips": MessageLookupByLibrary.simpleMessage("Бедра"),
|
||||
"hour": MessageLookupByLibrary.simpleMessage("час"),
|
||||
"hours": MessageLookupByLibrary.simpleMessage("часов"),
|
||||
"in_progress": MessageLookupByLibrary.simpleMessage("В процессе"),
|
||||
"inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"ingredients": MessageLookupByLibrary.simpleMessage("Ингредиенты"),
|
||||
"initial_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Первичные замеры"),
|
||||
"label": MessageLookupByLibrary.simpleMessage("Название"),
|
||||
"language": MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name": MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
"last_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Фамилия обязательна для заполнения"),
|
||||
"last_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В фамилии должен быть минимум 6 символов"),
|
||||
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
|
||||
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
|
||||
"light_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."),
|
||||
"liked_groceries":
|
||||
MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"link_was_copied":
|
||||
MessageLookupByLibrary.simpleMessage("Ссылка успешно скопирована"),
|
||||
"loading": MessageLookupByLibrary.simpleMessage("Загрузка..."),
|
||||
"lower": MessageLookupByLibrary.simpleMessage("Нижнее"),
|
||||
"male": MessageLookupByLibrary.simpleMessage("Мужской"),
|
||||
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
|
||||
"meat": MessageLookupByLibrary.simpleMessage("Мясо"),
|
||||
"meat_type": MessageLookupByLibrary.simpleMessage("С мясом"),
|
||||
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму."),
|
||||
"milliliter": MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"minimal_customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Минимальная цена для покупателя: 1200₽"),
|
||||
"minute": MessageLookupByLibrary.simpleMessage("минута"),
|
||||
"minutes": MessageLookupByLibrary.simpleMessage("минуты"),
|
||||
"most_new": MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old": MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err":
|
||||
MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"),
|
||||
"msg_something_went_wrong":
|
||||
MessageLookupByLibrary.simpleMessage("Что то пошло не так!"),
|
||||
"my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"),
|
||||
"my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"),
|
||||
"my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"),
|
||||
"my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"),
|
||||
"name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя пользователя обязательно для заполнения"),
|
||||
"name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени пользователя должно быть минимум 6 символов"),
|
||||
"no": MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account":
|
||||
MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"not_liked_groceries":
|
||||
MessageLookupByLibrary.simpleMessage("Не любимые продукты"),
|
||||
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option": MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content":
|
||||
MessageLookupByLibrary.simpleMessage("Содержание опции"),
|
||||
"option_content_hint_text":
|
||||
MessageLookupByLibrary.simpleMessage("На связи 7 дней в неделю"),
|
||||
"option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"),
|
||||
"option_desc_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"Этот план питания для похудения на 7 дней сбалансированный и разнообразный"),
|
||||
"option_duration":
|
||||
MessageLookupByLibrary.simpleMessage("Продолжительность опции"),
|
||||
"option_personal_diet_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Опция подразумевает создание индивидуальной диеты"),
|
||||
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"other_info": MessageLookupByLibrary.simpleMessage("Прочая информация"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation":
|
||||
MessageLookupByLibrary.simpleMessage("Подтвердите пароль"),
|
||||
"password_confirmation_mismatch":
|
||||
MessageLookupByLibrary.simpleMessage("Пароли не совпадают"),
|
||||
"password_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароль обязателен для заполнения"),
|
||||
"password_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В пароле должно быть минимум 6 символов"),
|
||||
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
||||
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
|
||||
"personal_diet_state":
|
||||
MessageLookupByLibrary.simpleMessage("Персональная"),
|
||||
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
|
||||
"physical_fitness":
|
||||
MessageLookupByLibrary.simpleMessage("Физическая форма"),
|
||||
"place_of_living":
|
||||
MessageLookupByLibrary.simpleMessage("Место проживания"),
|
||||
"plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"),
|
||||
"plan_desc": MessageLookupByLibrary.simpleMessage("Описание плана"),
|
||||
"plan_desc_example": MessageLookupByLibrary.simpleMessage(
|
||||
"Большое подробное, привлекательное описание плана"),
|
||||
"plan_duration": MessageLookupByLibrary.simpleMessage("Срок плана"),
|
||||
"plan_label_desc":
|
||||
MessageLookupByLibrary.simpleMessage("План для поддержания формы"),
|
||||
"plan_type": MessageLookupByLibrary.simpleMessage("Тип плана"),
|
||||
"plans_complete":
|
||||
MessageLookupByLibrary.simpleMessage("Пройденные планы"),
|
||||
"popular": MessageLookupByLibrary.simpleMessage("Популярные"),
|
||||
"preferred_language":
|
||||
MessageLookupByLibrary.simpleMessage("Предпочитаемый язык общения"),
|
||||
"pressure": MessageLookupByLibrary.simpleMessage("Давление"),
|
||||
"pressure_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления обязательны к заполнению"),
|
||||
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления должны быть числами"),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("Превью"),
|
||||
"price": MessageLookupByLibrary.simpleMessage("Цена"),
|
||||
"price_explanation": MessageLookupByLibrary.simpleMessage(
|
||||
"Разница в ценах, это комиссия Итвио"),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"published": MessageLookupByLibrary.simpleMessage("Опубликованные"),
|
||||
"recipe_author": MessageLookupByLibrary.simpleMessage("Автор рецепта"),
|
||||
"removeFromActive":
|
||||
MessageLookupByLibrary.simpleMessage("Снять с публикации"),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"sex": MessageLookupByLibrary.simpleMessage("Пол"),
|
||||
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),
|
||||
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"slim": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"sport_hobbies":
|
||||
MessageLookupByLibrary.simpleMessage("Спортивные увлечения"),
|
||||
"stage": MessageLookupByLibrary.simpleMessage("этап"),
|
||||
"stages": MessageLookupByLibrary.simpleMessage("этапов"),
|
||||
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"step": MessageLookupByLibrary.simpleMessage("Шаг"),
|
||||
"step_by_step_photo_recipe":
|
||||
MessageLookupByLibrary.simpleMessage("Пошаговый фоторецепт"),
|
||||
"takes_pills":
|
||||
MessageLookupByLibrary.simpleMessage("Принимает лекарства"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"),
|
||||
"there_is_a_video": MessageLookupByLibrary.simpleMessage("Есть видео"),
|
||||
"three_options": MessageLookupByLibrary.simpleMessage("3 опции"),
|
||||
"time": MessageLookupByLibrary.simpleMessage("Время прохождения"),
|
||||
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
|
||||
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
|
||||
"unfavorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"),
|
||||
"up_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Верхние показатели давления:"),
|
||||
"upper": MessageLookupByLibrary.simpleMessage("Верхнее"),
|
||||
"user_authorization":
|
||||
MessageLookupByLibrary.simpleMessage("Аутентификация"),
|
||||
"user_data":
|
||||
MessageLookupByLibrary.simpleMessage("Данные пользователя"),
|
||||
"user_registration":
|
||||
MessageLookupByLibrary.simpleMessage("Регистрация пользователя"),
|
||||
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),
|
||||
"vegan": MessageLookupByLibrary.simpleMessage("Веган."),
|
||||
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья."),
|
||||
"waist": MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
"weight": MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
"weight_chart": MessageLookupByLibrary.simpleMessage("График веса"),
|
||||
"weight_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Замер веса"),
|
||||
"wellness":
|
||||
MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type":
|
||||
MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"what_is_your_name":
|
||||
MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
"Неверные данные пользователя"),
|
||||
"you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"),
|
||||
"your_blood_pressure":
|
||||
MessageLookupByLibrary.simpleMessage("Ваше артериальное давление?"),
|
||||
"your_favorite_sports":
|
||||
MessageLookupByLibrary.simpleMessage("Ваши спортивные увлечения?"),
|
||||
"your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,350 +22,299 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
"Moscow": MessageLookupByLibrary.simpleMessage("Москва"),
|
||||
"Russia": MessageLookupByLibrary.simpleMessage("Россия"),
|
||||
"about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"),
|
||||
"about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"),
|
||||
"active": MessageLookupByLibrary.simpleMessage("Активен"),
|
||||
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
|
||||
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
|
||||
"add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"),
|
||||
"adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"),
|
||||
"additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Дополнительная информация",
|
||||
),
|
||||
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"all": MessageLookupByLibrary.simpleMessage("Все"),
|
||||
"allergies_presence": MessageLookupByLibrary.simpleMessage(
|
||||
"Наличие аллергии",
|
||||
),
|
||||
"another_form_of_comment": MessageLookupByLibrary.simpleMessage(
|
||||
"комментария",
|
||||
),
|
||||
"another_form_of_day": MessageLookupByLibrary.simpleMessage("дня"),
|
||||
"answer": MessageLookupByLibrary.simpleMessage("Ответить"),
|
||||
"archived": MessageLookupByLibrary.simpleMessage("В архиве"),
|
||||
"authentificate": MessageLookupByLibrary.simpleMessage("Войти"),
|
||||
"average_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Средние показатели давления:",
|
||||
),
|
||||
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"),
|
||||
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"carb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"carb_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
||||
),
|
||||
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||
"chat": MessageLookupByLibrary.simpleMessage("Чат"),
|
||||
"chest": MessageLookupByLibrary.simpleMessage("Грудь"),
|
||||
"chest_circumference": MessageLookupByLibrary.simpleMessage("Обхват груди"),
|
||||
"choose_diet_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите срок диеты",
|
||||
),
|
||||
"choose_plan_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите срок плана",
|
||||
),
|
||||
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике",
|
||||
),
|
||||
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры обязательны к заполнению",
|
||||
),
|
||||
"circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры должны быть числами",
|
||||
),
|
||||
"circumferences_chart": MessageLookupByLibrary.simpleMessage(
|
||||
"График обхватов",
|
||||
),
|
||||
"city": MessageLookupByLibrary.simpleMessage("Город"),
|
||||
"city_of_living": MessageLookupByLibrary.simpleMessage("Город проживания"),
|
||||
"comfort": MessageLookupByLibrary.simpleMessage("Комфорт"),
|
||||
"comment": MessageLookupByLibrary.simpleMessage("комментарий"),
|
||||
"comments": MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
"complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"),
|
||||
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Цена для покупателя",
|
||||
),
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
||||
"diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"),
|
||||
"diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"),
|
||||
"diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"),
|
||||
"do_you_have_hypertension_tendency": MessageLookupByLibrary.simpleMessage(
|
||||
"Есть ли у вас гипертония?",
|
||||
),
|
||||
"do_you_have_hypotension_tendency": MessageLookupByLibrary.simpleMessage(
|
||||
"Есть ли у вас гипотония?",
|
||||
),
|
||||
"do_you_take_pills": MessageLookupByLibrary.simpleMessage(
|
||||
"Принимаете ли вы лекарства или бады?",
|
||||
),
|
||||
"down_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Нижние показатели давления:",
|
||||
),
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"drafted": MessageLookupByLibrary.simpleMessage("Черновики"),
|
||||
"eating_behavior": MessageLookupByLibrary.simpleMessage(
|
||||
"Пищевое поведение",
|
||||
),
|
||||
"eating_behavior_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование пищевого поведения",
|
||||
),
|
||||
"eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;",
|
||||
),
|
||||
"economy": MessageLookupByLibrary.simpleMessage("Эконом"),
|
||||
"edit": MessageLookupByLibrary.simpleMessage("Редактировать"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("Электронная почта"),
|
||||
"email_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Необходимо ввести адрес электронной почты",
|
||||
),
|
||||
"email_invalid": MessageLookupByLibrary.simpleMessage(
|
||||
"Некорректный адрес электронной почты",
|
||||
),
|
||||
"enter_additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите любую дополнительную информацию на своё усмотрение:",
|
||||
),
|
||||
"enter_diet_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите описание диеты",
|
||||
),
|
||||
"enter_diet_name": MessageLookupByLibrary.simpleMessage(
|
||||
"Выведите название диеты",
|
||||
),
|
||||
"enter_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите информацию...",
|
||||
),
|
||||
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
"expand": MessageLookupByLibrary.simpleMessage("Показать полностью"),
|
||||
"fats": MessageLookupByLibrary.simpleMessage("Жиры"),
|
||||
"favorite_foods": MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши любимые/нелюбимые продукты питания?",
|
||||
),
|
||||
"female": MessageLookupByLibrary.simpleMessage("Женский"),
|
||||
"fill_in_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Заполните информацию:",
|
||||
),
|
||||
"finish": MessageLookupByLibrary.simpleMessage("Завершить"),
|
||||
"first_name": MessageLookupByLibrary.simpleMessage("Имя"),
|
||||
"first_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя обязательно для заполнения",
|
||||
),
|
||||
"first_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени должен быть минимум 1 символ",
|
||||
),
|
||||
"fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"),
|
||||
"fit_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;",
|
||||
),
|
||||
"fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"),
|
||||
"from": MessageLookupByLibrary.simpleMessage("от"),
|
||||
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
|
||||
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
|
||||
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"height_measurements": MessageLookupByLibrary.simpleMessage("Замер роста"),
|
||||
"hide": MessageLookupByLibrary.simpleMessage("Свернуть"),
|
||||
"hip_circumference": MessageLookupByLibrary.simpleMessage("Обхват бедер"),
|
||||
"hips": MessageLookupByLibrary.simpleMessage("Бедра"),
|
||||
"in_progress": MessageLookupByLibrary.simpleMessage("В процессе"),
|
||||
"inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"initial_measurements": MessageLookupByLibrary.simpleMessage(
|
||||
"Первичные замеры",
|
||||
),
|
||||
"label": MessageLookupByLibrary.simpleMessage("Название"),
|
||||
"language": MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name": MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
"last_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Фамилия обязательна для заполнения",
|
||||
),
|
||||
"last_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В фамилии должен быть минимум 6 символов",
|
||||
),
|
||||
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
|
||||
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
|
||||
"light_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками.",
|
||||
),
|
||||
"link_was_copied": MessageLookupByLibrary.simpleMessage(
|
||||
"Ссылка успешно скопирована",
|
||||
),
|
||||
"loading": MessageLookupByLibrary.simpleMessage("Загрузка..."),
|
||||
"male": MessageLookupByLibrary.simpleMessage("Мужской"),
|
||||
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
|
||||
"meat": MessageLookupByLibrary.simpleMessage("Мясо"),
|
||||
"meat_type": MessageLookupByLibrary.simpleMessage("С мясом"),
|
||||
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму.",
|
||||
),
|
||||
"milliliter": MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"minimal_customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Минимальная цена для покупателя: 1200₽",
|
||||
),
|
||||
"most_new": MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old": MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err": MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"),
|
||||
"msg_something_went_wrong": MessageLookupByLibrary.simpleMessage(
|
||||
"Что то пошло не так!",
|
||||
),
|
||||
"my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"),
|
||||
"my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"),
|
||||
"my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"),
|
||||
"my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"),
|
||||
"name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя пользователя обязательно для заполнения",
|
||||
),
|
||||
"name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени пользователя должно быть минимум 6 символов",
|
||||
),
|
||||
"no": MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account": MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option": MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content": MessageLookupByLibrary.simpleMessage("Содержание опции"),
|
||||
"option_content_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"На связи 7 дней в неделю",
|
||||
),
|
||||
"option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"),
|
||||
"option_desc_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"Этот план питания для похудения на 7 дней сбалансированный и разнообразный",
|
||||
),
|
||||
"option_duration": MessageLookupByLibrary.simpleMessage(
|
||||
"Продолжительность опции",
|
||||
),
|
||||
"option_personal_diet_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Опция подразумевает создание индивидуальной диеты",
|
||||
),
|
||||
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation": MessageLookupByLibrary.simpleMessage(
|
||||
"Подтвердите пароль",
|
||||
),
|
||||
"password_confirmation_mismatch": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароли не совпадают",
|
||||
),
|
||||
"password_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароль обязателен для заполнения",
|
||||
),
|
||||
"password_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В пароле должно быть минимум 6 символов",
|
||||
),
|
||||
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
||||
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
|
||||
"personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"),
|
||||
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
|
||||
"place_of_living": MessageLookupByLibrary.simpleMessage("Место проживания"),
|
||||
"plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"),
|
||||
"plan_desc": MessageLookupByLibrary.simpleMessage("Описание плана"),
|
||||
"plan_desc_example": MessageLookupByLibrary.simpleMessage(
|
||||
"Большое подробное, привлекательное описание плана",
|
||||
),
|
||||
"plan_duration": MessageLookupByLibrary.simpleMessage("Срок плана"),
|
||||
"plan_label_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План для поддержания формы",
|
||||
),
|
||||
"plans_complete": MessageLookupByLibrary.simpleMessage("Пройденные планы"),
|
||||
"popular": MessageLookupByLibrary.simpleMessage("Популярные"),
|
||||
"preferred_language": MessageLookupByLibrary.simpleMessage(
|
||||
"Предпочитаемый язык общения",
|
||||
),
|
||||
"pressure_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления обязательны к заполнению",
|
||||
),
|
||||
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления должны быть числами",
|
||||
),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("Превью"),
|
||||
"price": MessageLookupByLibrary.simpleMessage("Цена"),
|
||||
"price_explanation": MessageLookupByLibrary.simpleMessage(
|
||||
"Разница в ценах, это комиссия Итвио",
|
||||
),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"published": MessageLookupByLibrary.simpleMessage("Опубликованные"),
|
||||
"removeFromActive": MessageLookupByLibrary.simpleMessage(
|
||||
"Снять с публикации",
|
||||
),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),
|
||||
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"slim": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;",
|
||||
),
|
||||
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:",
|
||||
),
|
||||
"three_options": MessageLookupByLibrary.simpleMessage("3 опции"),
|
||||
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
|
||||
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
|
||||
"unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Нелюбимые продукты",
|
||||
),
|
||||
"up_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Верхние показатели давления:",
|
||||
),
|
||||
"user_authorization": MessageLookupByLibrary.simpleMessage(
|
||||
"Аутентификация",
|
||||
),
|
||||
"user_data": MessageLookupByLibrary.simpleMessage("Данные пользователя"),
|
||||
"user_registration": MessageLookupByLibrary.simpleMessage(
|
||||
"Регистрация пользователя",
|
||||
),
|
||||
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),
|
||||
"vegan": MessageLookupByLibrary.simpleMessage("Веган."),
|
||||
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья.",
|
||||
),
|
||||
"waist": MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference": MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
"weight": MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
"weight_chart": MessageLookupByLibrary.simpleMessage("График веса"),
|
||||
"weight_measurements": MessageLookupByLibrary.simpleMessage("Замер веса"),
|
||||
"wellness": MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Улучшение самочувствия",
|
||||
),
|
||||
"wellness_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
||||
),
|
||||
"what_is_your_name": MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
"Неверные данные пользователя",
|
||||
),
|
||||
"you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"),
|
||||
"your_blood_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваше артериальное давление?",
|
||||
),
|
||||
"your_favorite_sports": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши спортивные увлечения?",
|
||||
),
|
||||
"your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:"),
|
||||
};
|
||||
"Moscow": MessageLookupByLibrary.simpleMessage("Москва"),
|
||||
"Russia": MessageLookupByLibrary.simpleMessage("Россия"),
|
||||
"about_diet": MessageLookupByLibrary.simpleMessage("Об этой диете"),
|
||||
"about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"),
|
||||
"active": MessageLookupByLibrary.simpleMessage("Активен"),
|
||||
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
|
||||
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
|
||||
"add_measure": MessageLookupByLibrary.simpleMessage("Добавить замер"),
|
||||
"adding_plan": MessageLookupByLibrary.simpleMessage("Добавление плана"),
|
||||
"additional_information":
|
||||
MessageLookupByLibrary.simpleMessage("Дополнительная информация"),
|
||||
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"all": MessageLookupByLibrary.simpleMessage("Все"),
|
||||
"allergies_presence":
|
||||
MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
|
||||
"another_form_of_comment":
|
||||
MessageLookupByLibrary.simpleMessage("комментария"),
|
||||
"another_form_of_day": MessageLookupByLibrary.simpleMessage("дня"),
|
||||
"answer": MessageLookupByLibrary.simpleMessage("Ответить"),
|
||||
"archived": MessageLookupByLibrary.simpleMessage("В архиве"),
|
||||
"authentificate": MessageLookupByLibrary.simpleMessage("Войти"),
|
||||
"average_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Средние показатели давления:"),
|
||||
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"),
|
||||
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"carb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"carb_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||
"chat": MessageLookupByLibrary.simpleMessage("Чат"),
|
||||
"chest": MessageLookupByLibrary.simpleMessage("Грудь"),
|
||||
"chest_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват груди"),
|
||||
"choose_diet_duration":
|
||||
MessageLookupByLibrary.simpleMessage("Выберите срок диеты"),
|
||||
"choose_plan_duration":
|
||||
MessageLookupByLibrary.simpleMessage("Выберите срок плана"),
|
||||
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике"),
|
||||
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры обязательны к заполнению"),
|
||||
"circumference_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все замеры должны быть числами"),
|
||||
"circumferences_chart":
|
||||
MessageLookupByLibrary.simpleMessage("График обхватов"),
|
||||
"city": MessageLookupByLibrary.simpleMessage("Город"),
|
||||
"city_of_living":
|
||||
MessageLookupByLibrary.simpleMessage("Город проживания"),
|
||||
"comfort": MessageLookupByLibrary.simpleMessage("Комфорт"),
|
||||
"comment": MessageLookupByLibrary.simpleMessage("комментарий"),
|
||||
"comments": MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
"complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"),
|
||||
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price":
|
||||
MessageLookupByLibrary.simpleMessage("Цена для покупателя"),
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
||||
"diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"),
|
||||
"diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"),
|
||||
"diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"),
|
||||
"do_you_have_hypertension_tendency":
|
||||
MessageLookupByLibrary.simpleMessage("Есть ли у вас гипертония?"),
|
||||
"do_you_have_hypotension_tendency":
|
||||
MessageLookupByLibrary.simpleMessage("Есть ли у вас гипотония?"),
|
||||
"do_you_take_pills": MessageLookupByLibrary.simpleMessage(
|
||||
"Принимаете ли вы лекарства или бады?"),
|
||||
"down_pressure":
|
||||
MessageLookupByLibrary.simpleMessage("Нижние показатели давления:"),
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"drafted": MessageLookupByLibrary.simpleMessage("Черновики"),
|
||||
"eating_behavior":
|
||||
MessageLookupByLibrary.simpleMessage("Пищевое поведение"),
|
||||
"eating_behavior_type": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование пищевого поведения"),
|
||||
"eating_behavior_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Формирование здорового пищевого поведения — это процесс, который включает в себя изменение привычек и отношения к еде. Он направлен на то, чтобы помочь людям научиться правильно питаться и поддерживать здоровый образ жизни.Основные принципы формирования здорового пищевого поведения: \n● Разнообразие продуктов; \n● Сбалансированный рацион; \n● Питьевой режим; \n● Ограничение вредных продуктов; \n● Регулярные приёмы пищи; \n● Умеренность;Осознанное питание; \n● Физическая активность;"),
|
||||
"economy": MessageLookupByLibrary.simpleMessage("Эконом"),
|
||||
"edit": MessageLookupByLibrary.simpleMessage("Редактировать"),
|
||||
"email": MessageLookupByLibrary.simpleMessage("Электронная почта"),
|
||||
"email_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Необходимо ввести адрес электронной почты"),
|
||||
"email_invalid": MessageLookupByLibrary.simpleMessage(
|
||||
"Некорректный адрес электронной почты"),
|
||||
"enter_additional_information": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите любую дополнительную информацию на своё усмотрение:"),
|
||||
"enter_diet_description":
|
||||
MessageLookupByLibrary.simpleMessage("Введите описание диеты"),
|
||||
"enter_diet_name":
|
||||
MessageLookupByLibrary.simpleMessage("Выведите название диеты"),
|
||||
"enter_information":
|
||||
MessageLookupByLibrary.simpleMessage("Введите информацию..."),
|
||||
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
"expand": MessageLookupByLibrary.simpleMessage("Показать полностью"),
|
||||
"fats": MessageLookupByLibrary.simpleMessage("Жиры"),
|
||||
"favorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
"favorite_unfavorite_foods": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваши любимые/нелюбимые продукты питания?"),
|
||||
"female": MessageLookupByLibrary.simpleMessage("Женский"),
|
||||
"fill_in_information":
|
||||
MessageLookupByLibrary.simpleMessage("Заполните информацию:"),
|
||||
"finish": MessageLookupByLibrary.simpleMessage("Завершить"),
|
||||
"first_name": MessageLookupByLibrary.simpleMessage("Имя"),
|
||||
"first_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя обязательно для заполнения"),
|
||||
"first_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени должен быть минимум 1 символ"),
|
||||
"fit_type": MessageLookupByLibrary.simpleMessage("Поддержание формы"),
|
||||
"fit_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"),
|
||||
"from": MessageLookupByLibrary.simpleMessage("от"),
|
||||
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
|
||||
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
|
||||
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
||||
"height_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Замер роста"),
|
||||
"hide": MessageLookupByLibrary.simpleMessage("Свернуть"),
|
||||
"hip_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват бедер"),
|
||||
"hips": MessageLookupByLibrary.simpleMessage("Бедра"),
|
||||
"in_progress": MessageLookupByLibrary.simpleMessage("В процессе"),
|
||||
"inactive_diet_state": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"initial_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Первичные замеры"),
|
||||
"label": MessageLookupByLibrary.simpleMessage("Название"),
|
||||
"language": MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name": MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
"last_name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Фамилия обязательна для заполнения"),
|
||||
"last_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В фамилии должен быть минимум 6 символов"),
|
||||
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
|
||||
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
|
||||
"light_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"С некоторыми видами диет можно употреблять алкоголь в умеренных количествах. Рекомендуется совмещать вместе с низкокалорийными закусками."),
|
||||
"link_was_copied":
|
||||
MessageLookupByLibrary.simpleMessage("Ссылка успешно скопирована"),
|
||||
"loading": MessageLookupByLibrary.simpleMessage("Загрузка..."),
|
||||
"male": MessageLookupByLibrary.simpleMessage("Мужской"),
|
||||
"meal": MessageLookupByLibrary.simpleMessage("Приём пищи"),
|
||||
"meat": MessageLookupByLibrary.simpleMessage("Мясо"),
|
||||
"meat_type": MessageLookupByLibrary.simpleMessage("С мясом"),
|
||||
"meat_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета с мясом полезная и сбалансированная. Включает в себя нежирное мясо: курицу, индейку, кролика или говядину. В сочетании с овощами получаете все необходимые витамины и минералы. Не забывайте о порциях и старайтесь есть медленно, прислушиваясь к своему организму."),
|
||||
"milliliter": MessageLookupByLibrary.simpleMessage("мл"),
|
||||
"minimal_customer_price": MessageLookupByLibrary.simpleMessage(
|
||||
"Минимальная цена для покупателя: 1200₽"),
|
||||
"most_new": MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old": MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err":
|
||||
MessageLookupByLibrary.simpleMessage("Сетевая ошибка!"),
|
||||
"msg_something_went_wrong":
|
||||
MessageLookupByLibrary.simpleMessage("Что то пошло не так!"),
|
||||
"my_blog": MessageLookupByLibrary.simpleMessage("Мой блог"),
|
||||
"my_diets": MessageLookupByLibrary.simpleMessage("Мои диеты"),
|
||||
"my_plans": MessageLookupByLibrary.simpleMessage("Мои планы"),
|
||||
"my_settings": MessageLookupByLibrary.simpleMessage("Мои настройки"),
|
||||
"name_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Имя пользователя обязательно для заполнения"),
|
||||
"name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени пользователя должно быть минимум 6 символов"),
|
||||
"no": MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account":
|
||||
MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option": MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content":
|
||||
MessageLookupByLibrary.simpleMessage("Содержание опции"),
|
||||
"option_content_hint_text":
|
||||
MessageLookupByLibrary.simpleMessage("На связи 7 дней в неделю"),
|
||||
"option_desc": MessageLookupByLibrary.simpleMessage("Описание опции"),
|
||||
"option_desc_hint_text": MessageLookupByLibrary.simpleMessage(
|
||||
"Этот план питания для похудения на 7 дней сбалансированный и разнообразный"),
|
||||
"option_duration":
|
||||
MessageLookupByLibrary.simpleMessage("Продолжительность опции"),
|
||||
"option_personal_diet_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Опция подразумевает создание индивидуальной диеты"),
|
||||
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation":
|
||||
MessageLookupByLibrary.simpleMessage("Подтвердите пароль"),
|
||||
"password_confirmation_mismatch":
|
||||
MessageLookupByLibrary.simpleMessage("Пароли не совпадают"),
|
||||
"password_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Пароль обязателен для заполнения"),
|
||||
"password_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В пароле должно быть минимум 6 символов"),
|
||||
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
||||
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
|
||||
"personal_diet_state":
|
||||
MessageLookupByLibrary.simpleMessage("Персональная"),
|
||||
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
|
||||
"place_of_living":
|
||||
MessageLookupByLibrary.simpleMessage("Место проживания"),
|
||||
"plan_author": MessageLookupByLibrary.simpleMessage("Автор плана"),
|
||||
"plan_desc": MessageLookupByLibrary.simpleMessage("Описание плана"),
|
||||
"plan_desc_example": MessageLookupByLibrary.simpleMessage(
|
||||
"Большое подробное, привлекательное описание плана"),
|
||||
"plan_duration": MessageLookupByLibrary.simpleMessage("Срок плана"),
|
||||
"plan_label_desc":
|
||||
MessageLookupByLibrary.simpleMessage("План для поддержания формы"),
|
||||
"plans_complete":
|
||||
MessageLookupByLibrary.simpleMessage("Пройденные планы"),
|
||||
"popular": MessageLookupByLibrary.simpleMessage("Популярные"),
|
||||
"preferred_language":
|
||||
MessageLookupByLibrary.simpleMessage("Предпочитаемый язык общения"),
|
||||
"pressure_empty": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления обязательны к заполнению"),
|
||||
"pressure_is_not_a_number": MessageLookupByLibrary.simpleMessage(
|
||||
"Все показатели давления должны быть числами"),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("Превью"),
|
||||
"price": MessageLookupByLibrary.simpleMessage("Цена"),
|
||||
"price_explanation": MessageLookupByLibrary.simpleMessage(
|
||||
"Разница в ценах, это комиссия Итвио"),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"published": MessageLookupByLibrary.simpleMessage("Опубликованные"),
|
||||
"removeFromActive":
|
||||
MessageLookupByLibrary.simpleMessage("Снять с публикации"),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"share": MessageLookupByLibrary.simpleMessage("Поделиться"),
|
||||
"skip": MessageLookupByLibrary.simpleMessage("Пропустить"),
|
||||
"slim": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
"Расскажите в свободной форме о том как просыпаетесь, когда едите, когда ложитесь спать:"),
|
||||
"three_options": MessageLookupByLibrary.simpleMessage("3 опции"),
|
||||
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
|
||||
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
|
||||
"unfavorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"),
|
||||
"up_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
"Верхние показатели давления:"),
|
||||
"user_authorization":
|
||||
MessageLookupByLibrary.simpleMessage("Аутентификация"),
|
||||
"user_data":
|
||||
MessageLookupByLibrary.simpleMessage("Данные пользователя"),
|
||||
"user_registration":
|
||||
MessageLookupByLibrary.simpleMessage("Регистрация пользователя"),
|
||||
"username": MessageLookupByLibrary.simpleMessage("Имя пользователя"),
|
||||
"vegan": MessageLookupByLibrary.simpleMessage("Веган."),
|
||||
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья."),
|
||||
"waist": MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
"weight": MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
"weight_chart": MessageLookupByLibrary.simpleMessage("График веса"),
|
||||
"weight_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Замер веса"),
|
||||
"wellness":
|
||||
MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type":
|
||||
MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"what_is_your_name":
|
||||
MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
"Неверные данные пользователя"),
|
||||
"you_will_get": MessageLookupByLibrary.simpleMessage("Вы получите"),
|
||||
"your_blood_pressure":
|
||||
MessageLookupByLibrary.simpleMessage("Ваше артериальное давление?"),
|
||||
"your_favorite_sports":
|
||||
MessageLookupByLibrary.simpleMessage("Ваши спортивные увлечения?"),
|
||||
"your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:")
|
||||
};
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -230,5 +230,22 @@
|
||||
"diet_started": "Диета уже начата",
|
||||
"cancel_diet": "Отменить диету?",
|
||||
"confirm": "Подтвердить",
|
||||
"could_not_cancel_diet": "Не удалось отменить диету"
|
||||
"could_not_cancel_diet": "Не удалось отменить диету",
|
||||
"hours": "часов",
|
||||
"hour": "час",
|
||||
"another_form_of_hour": "часа",
|
||||
"minutes": "минуты",
|
||||
"minute": "минута",
|
||||
"another_form_of_minute": "минут",
|
||||
"there_is_a_video": "Есть видео",
|
||||
"recipe_author": "Автор рецепта",
|
||||
"about_recipe": "Об этом рецепте",
|
||||
"stages": "этапов",
|
||||
"stage": "этап",
|
||||
"another_form_of_stage": "этапа",
|
||||
"check_out_video_recipe": "Посмотреть видео рецепт",
|
||||
"could_not_launch_video": "Не удалось запустить видео",
|
||||
"ingredients": "Ингредиенты",
|
||||
"step": "Шаг",
|
||||
"step_by_step_photo_recipe": "Пошаговый фоторецепт"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user