From 566a96b18eed6bcd1b1436f9b8e9495579054e92 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Tue, 27 May 2025 17:38:46 +0300 Subject: [PATCH] feat(recipe): my recipes screen --- lib/core/locator_service.dart | 6 + lib/features/feed/models/recipes_model.dart | 4 +- .../presentation/widgets/my_diet_widget.dart | 1 + .../recipe/models/my_recipe_model.dart | 36 +++ .../my_recipes_cubit/my_recieps_cubit.dart | 21 ++ .../my_recipes_cubit/my_recipes_state.dart | 17 ++ .../presentation/pages/my_recipes_screen.dart | 184 ++----------- .../widgets/my_recipe_widget.dart | 242 ++++++++++++++++++ .../repositories/my_recipes_repository.dart | 16 ++ .../recipe/services/my_recipes_service.dart | 13 + 10 files changed, 372 insertions(+), 168 deletions(-) create mode 100644 lib/features/recipe/models/my_recipe_model.dart create mode 100644 lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recieps_cubit.dart create mode 100644 lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recipes_state.dart create mode 100644 lib/features/recipe/presentation/widgets/my_recipe_widget.dart create mode 100644 lib/features/recipe/repositories/my_recipes_repository.dart create mode 100644 lib/features/recipe/services/my_recipes_service.dart diff --git a/lib/core/locator_service.dart b/lib/core/locator_service.dart index a606b5bc..14af4917 100644 --- a/lib/core/locator_service.dart +++ b/lib/core/locator_service.dart @@ -81,8 +81,11 @@ import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recip 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/presentation/cubit/my_recipes_cubit/my_recieps_cubit.dart'; import 'package:eatvio_app/features/recipe/repositories/about_recipe_repository.dart'; +import 'package:eatvio_app/features/recipe/repositories/my_recipes_repository.dart'; import 'package:eatvio_app/features/recipe/services/about_recipe_service.dart'; +import 'package:eatvio_app/features/recipe/services/my_recipes_service.dart'; import 'package:eatvio_app/features/registration/presentation/bloc/registration_cubit/registration_cubit.dart'; import 'package:eatvio_app/features/registration/presentation/bloc/verify_email_cubit/verify_email_cubit.dart'; import 'package:eatvio_app/features/registration/repositories/registration_repository.dart'; @@ -140,6 +143,7 @@ Future init() async { sl.registerFactory(() => ConsultantCommentsCubit(diaryRepository: sl())); sl.registerFactory(() => CancelPlanCubit(cancelPlanRepository: sl())); sl.registerFactory(() => VerifyEmailCubit(profileRepository: sl())); + sl.registerFactory(() => MyRecipesCubit(myRecipesRepository: sl())); // Repository sl.registerLazySingleton(() => ChatRepository(chatService: sl())); @@ -167,6 +171,7 @@ Future init() async { sl.registerLazySingleton(() => CancelPlanRepository(cancelService: sl())); sl.registerLazySingleton(() => CreatePlanRepository(createPlanService: sl())); sl.registerLazySingleton(() => NotificationsRepository(notificationsService: sl())); + sl.registerFactory(() => MyRecipesRepository(myRecipesService: sl())); // Services sl.registerLazySingleton(() => ChatService(sl())); @@ -195,6 +200,7 @@ Future init() async { sl.registerLazySingleton(() => CancelPlanService(sl())); sl.registerLazySingleton(() => CreatePlanService(sl())); sl.registerLazySingleton(() => NotificationsService(sl())); + sl.registerLazySingleton(() => MyRecipesService(sl())); // External sl.registerLazySingleton( diff --git a/lib/features/feed/models/recipes_model.dart b/lib/features/feed/models/recipes_model.dart index 262b9ecc..dcb4d2ea 100644 --- a/lib/features/feed/models/recipes_model.dart +++ b/lib/features/feed/models/recipes_model.dart @@ -16,8 +16,8 @@ abstract class Recipe with _$Recipe { @JsonKey(name: 'description_md') required String description, required List? steps, @JsonKey(name: 'video_url') required String? videoUrl, - @JsonKey(name: 'created_at') required DateTime createdAt, - @JsonKey(name: 'updated_at') required DateTime updatedAt, + @JsonKey(name: 'created_at') DateTime? createdAt, + @JsonKey(name: 'updated_at') DateTime? updatedAt, required String? title, required String? type, required String slug, diff --git a/lib/features/my_diets/presentation/widgets/my_diet_widget.dart b/lib/features/my_diets/presentation/widgets/my_diet_widget.dart index 7eb7f15c..587e05ca 100644 --- a/lib/features/my_diets/presentation/widgets/my_diet_widget.dart +++ b/lib/features/my_diets/presentation/widgets/my_diet_widget.dart @@ -26,6 +26,7 @@ import 'package:share_plus/share_plus.dart'; class MyDietWidget extends StatefulWidget { final Diet diet; + const MyDietWidget({ super.key, required this.diet, diff --git a/lib/features/recipe/models/my_recipe_model.dart b/lib/features/recipe/models/my_recipe_model.dart new file mode 100644 index 00000000..f7068938 --- /dev/null +++ b/lib/features/recipe/models/my_recipe_model.dart @@ -0,0 +1,36 @@ +import 'package:eatvio_app/features/feed/models/recipes_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'my_recipe_model.g.dart'; + +part 'my_recipe_model.freezed.dart'; + +@freezed +abstract class MyRecipePaginationModel with _$MyRecipePaginationModel { + const factory MyRecipePaginationModel({ + required List data, + }) = _MyRecipePaginationModel; + + factory MyRecipePaginationModel.fromJson(Map json) => _$MyRecipePaginationModelFromJson(json); +} + +@freezed +abstract class MyRecipeModel with _$MyRecipeModel { + const factory MyRecipeModel({ + required int id, + required String image, + required String state, + @JsonKey(name: 'cooking_time') required int cookingTime, + @JsonKey(name: 'active_time') required int activeCookingTime, + @JsonKey(name: 'description_md') required String description, + required List? steps, + @JsonKey(name: 'video_url') required String? videoUrl, + required String? title, + required String slug, + @JsonKey(name: 'energy_per_serving') required double calories, + @JsonKey(name: 'total_likes') required int likesCount, + @JsonKey(name: 'total_views') required int viewsCount, + }) = _MyRecipeModel; + + factory MyRecipeModel.fromJson(Map json) => _$MyRecipeModelFromJson(json); +} diff --git a/lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recieps_cubit.dart b/lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recieps_cubit.dart new file mode 100644 index 00000000..43d3a2c4 --- /dev/null +++ b/lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recieps_cubit.dart @@ -0,0 +1,21 @@ +import 'package:eatvio_app/features/recipe/presentation/cubit/my_recipes_cubit/my_recipes_state.dart'; +import 'package:eatvio_app/features/recipe/repositories/my_recipes_repository.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class MyRecipesCubit extends Cubit { + final MyRecipesRepository myRecipesRepository; + + MyRecipesCubit({ + required this.myRecipesRepository, + }) : super(const MyRecipesState.loading()); + + getMyRecipes() async { + emit(const MyRecipesState.loading()); + try { + final myRecipes = await myRecipesRepository.getMyRecipes(); + emit(MyRecipesState.loaded(recipes: myRecipes)); + } catch (e) { + emit(const MyRecipesState.error()); + } + } +} diff --git a/lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recipes_state.dart b/lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recipes_state.dart new file mode 100644 index 00000000..1a7d3d73 --- /dev/null +++ b/lib/features/recipe/presentation/cubit/my_recipes_cubit/my_recipes_state.dart @@ -0,0 +1,17 @@ +import 'package:eatvio_app/features/recipe/models/my_recipe_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'my_recipes_state.freezed.dart'; + +@freezed +abstract class MyRecipesState with _$MyRecipesState { + const factory MyRecipesState() = _MyRecipesState; + + const factory MyRecipesState.loading() = MyRecipesStateLoading; + + const factory MyRecipesState.loaded({ + required List recipes, + }) = MyRecipesStateLoaded; + + const factory MyRecipesState.error() = MyRecipesStateError; +} diff --git a/lib/features/recipe/presentation/pages/my_recipes_screen.dart b/lib/features/recipe/presentation/pages/my_recipes_screen.dart index ad30f146..a9e50b27 100644 --- a/lib/features/recipe/presentation/pages/my_recipes_screen.dart +++ b/lib/features/recipe/presentation/pages/my_recipes_screen.dart @@ -1,42 +1,18 @@ -import 'package:easy_debounce/easy_debounce.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:eatvio_app/core/widgets/add_item_button.dart'; -import 'package:eatvio_app/core/widgets/custom_search_bar.dart'; -import 'package:eatvio_app/core/widgets/data_error_widget.dart'; -import 'package:eatvio_app/core/widgets/loader.dart'; -import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/diet_filter_bottom_sheet.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/filter_badge.dart'; -import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.dart'; -import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart'; -import 'package:eatvio_app/features/my_diets/presentation/widgets/my_diet_widget.dart'; -import 'package:eatvio_app/features/recipe/presentation/widgets/my_recipes_tab.dart'; +import 'package:eatvio_app/features/recipe/presentation/cubit/my_recipes_cubit/my_recieps_cubit.dart'; +import 'package:eatvio_app/features/recipe/presentation/cubit/my_recipes_cubit/my_recipes_state.dart'; +import 'package:eatvio_app/features/recipe/presentation/widgets/my_recipe_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:go_router/go_router.dart'; class MyRecipesScreen extends StatelessWidget { const MyRecipesScreen({super.key}); + static const name = 'myRecipesScreen'; static const path = '/my-recipes-screen'; - @override - Widget build(BuildContext context) { - return BlocProvider(create: (context) => sl()..loadAllDiets(), child: MyRecipesScreenContent()); - } -} - -class MyRecipesScreenContent extends StatelessWidget { - MyRecipesScreenContent({super.key}); - - final activeDietsScrollController = ScrollController(); - final draftDietsScrollController = ScrollController(); - - final activeDietsSearchController = SearchController(); - final draftDietsSearchController = SearchController(); - @override Widget build(BuildContext context) { return Scaffold( @@ -52,144 +28,20 @@ class MyRecipesScreenContent extends StatelessWidget { style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black), ), ), - body: BlocBuilder( - buildWhen: (previous, current) => previous.selectedStateIndex != current.selectedStateIndex, - builder: (context, state) { - return NestedScrollView( - controller: switch (state.selectedStateIndex) { - 1 => draftDietsScrollController, - _ => activeDietsScrollController - }, - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { - return [ - SliverAppBar( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)), - ), - backgroundColor: appTheme.gray100, - foregroundColor: appTheme.gray100, - automaticallyImplyLeading: false, - stretchTriggerOffset: 1, - floating: true, - primary: false, - snap: true, - scrolledUnderElevation: 0, - bottom: PreferredSize( - preferredSize: Size( - MediaQuery.sizeOf(context).width, - 64, - ), - child: Padding( - padding: const EdgeInsets.only(bottom: 0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox(height: 8), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 4), - child: MyRecipesTab(), - ), - const SizedBox(height: 8), - Row( - children: [ - const SizedBox(width: 4), - Expanded( - child: CustomSearchBar( - enableIcon: false, - backgroundColor: appTheme.whiteA700, - borderRadius: 100, - searchController: switch (state.selectedStateIndex) { - 1 => draftDietsSearchController, - _ => activeDietsSearchController - }, - onChanged: (query) { - EasyDebounce.debounce( - 'searchDiets', - const Duration(milliseconds: 500), - () { - context.read().loadCurrentDiets(query: query == '' ? null : query); - }, - ); - }, - ), - ), - const SizedBox(width: 12), - AddItemButton( - onTap: () => GoRouter.of(context).pushNamed(CreateDietScreen.name), - ), - const SizedBox(width: 4), - ], - ), - const SizedBox(height: 16), - ], - ), - ), - ), - ), - ]; - }, - body: RefreshIndicator( - onRefresh: () => context.read().loadCurrentDiets(), - child: BlocBuilder( - builder: (BuildContext context, MyDietsState state) { - if (state.isLoading) { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: const Loader(), - ); - } else if (state.error != null) { - return DataErrorWidget(onReload: () => context.read().loadAllDiets()); - } else { - final gotDietLoadingError = state.activeDietsError != null && state.selectedStateIndex == 0 || - state.draftDietsError != null && state.selectedStateIndex == 1; - - if (gotDietLoadingError) { - return DataErrorWidget(onReload: () => context.read().loadCurrentDiets()); - } - - if (state.isLoading) { - return const Loader(); - } - - final diets = switch (state.selectedStateIndex) { - 1 => state.draftDiets, - _ => state.activeDiets, - }; - - return Stack( - children: [ - const SizedBox.expand(), - ListView.separated( - shrinkWrap: true, - physics: const BouncingScrollPhysics(), - itemBuilder: (context, index) { - return MyDietWidget( - diet: diets[index], - key: ValueKey(diets[index].id), - ); - }, - separatorBuilder: (context, index) { - return const SizedBox(height: 20); - }, - itemCount: diets.length, - ), - Positioned( - right: 0, - bottom: 74, - child: FilterBadge( - filterBottomSheet: DietFilterBottomSheet( - myDietsCubit: context.read(), - ), - ), - ), - ], - ); - } - }, - ), - ), - ); - }, + body: BlocProvider( + create: (BuildContext context) => sl()..getMyRecipes(), + child: BlocBuilder( + builder: (BuildContext context, MyRecipesState state) { + if (state is MyRecipesStateLoaded) { + return ListView.separated( + itemBuilder: (context, index) => MyRecipeWidget(recipe: state.recipes[index]), + separatorBuilder: (context, index) => const SizedBox(height: 12), + itemCount: state.recipes.length, + ); + } + return Container(); + }, + ), ), ); } diff --git a/lib/features/recipe/presentation/widgets/my_recipe_widget.dart b/lib/features/recipe/presentation/widgets/my_recipe_widget.dart new file mode 100644 index 00000000..8acae4c1 --- /dev/null +++ b/lib/features/recipe/presentation/widgets/my_recipe_widget.dart @@ -0,0 +1,242 @@ +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/widgets/custom_outlined_button.dart'; +import 'package:eatvio_app/features/recipe/models/my_recipe_model.dart'; +import 'package:eatvio_app/features/recipe/presentation/cubit/my_recipes_cubit/my_recieps_cubit.dart'; +import 'package:eatvio_app/features/recipe/presentation/cubit/my_recipes_cubit/my_recipes_state.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:share_plus/share_plus.dart'; + +class MyRecipeWidget extends StatelessWidget { + final MyRecipeModel recipe; + + const MyRecipeWidget({ + super.key, + required this.recipe, + }); + + @override + Widget build(BuildContext context) { + // final s = S.of(context); + return DecoratedBox( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.white, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + InkWell( + // onTap: () => GoRouter.of(context).pushNamed('aboutDietScreen', extra: {'diet': widget.diet, 'navigateToComments': false}), + child: ClipRRect( + borderRadius: const BorderRadius.vertical(top: Radius.circular(12)), + child: CachedNetworkImage( + imageUrl: '$baseUrl/storage/${recipe.image}', + fit: BoxFit.fitWidth, + width: MediaQuery.of(context).size.width, + ), + ), + ), + // Positioned( + // bottom: 16, + // child: SizedBox( + // width: MediaQuery.sizeOf(context).width, + // child: InfoRow(diet: widget.diet, itemsBackgroundColor: appTheme.whiteA700, disableDescriptionOfTypes: true, type: ProductType.diet), + // ), + // ), + ], + ), + const SizedBox(height: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + recipe.title!, + style: TextStyles.textMSemibold.copyWith(color: appTheme.black), + ), + ), + if (recipe.description.isNotEmpty) ...[ + const SizedBox( + height: 12, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Html( + data: recipe.description.length > 200 ? '${recipe.description.substring(0, 200)}...' : recipe.description, + style: { + "*": Style( + margin: Margins.zero, + color: appTheme.black, + fontSize: FontSize(TextStyles.textSMedium.fontSize ?? 14), + fontWeight: TextStyles.textSMedium.fontWeight ?? FontWeight.w400, + ), + }, + ), + ), + ], + ], + ), + const SizedBox(height: 20), + BlocBuilder( + builder: (BuildContext context, MyRecipesState state) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: CustomOutlinedButton( + onPressed: () async { + // if (state.selectedStateIndex == 1) { + // final result = await context.read().publishDiet(widget.diet.id); + // if (result) { + // if (!context.mounted) return; + // showBottomSheetWithBlur( + // context: context, + // child: SuccessPublishedDietOrPlanBottomSheet(title: widget.diet.name), + // ); + // await context.read().loadAllDiets(); + // } else { + // showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время'); + // } + // } else if (state.selectedStateIndex == 2) { + // } else { + // GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: widget.diet); + // } + }, + text: '', + // text: switch (state.selectedStateIndex) { + // 1 => s.publish, + // 2 => s.toOffer, + // _ => s.edit, + // }, + height: 52, + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700), + buttonStyle: ButtonStyle( + shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))), + backgroundColor: WidgetStatePropertyAll(appTheme.blueA400), + side: const WidgetStatePropertyAll(BorderSide.none), + ), + ), + ), + // if (state.selectedStateIndex == 0) ...[ + const SizedBox(width: 6), + CustomOutlinedButton( + onPressed: () async { + final box = context.findRenderObject() as RenderBox?; + await SharePlus.instance.share( + ShareParams( + uri: Uri.parse('$baseUrl/ru/recipe/${recipe.id}'), + sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, + ), + ); + }, + height: 52, + width: 52, + leftIcon: SvgPicture.asset( + 'assets/icons/share2.svg', + width: 20, + height: 20, + colorFilter: ColorFilter.mode(appTheme.whiteA700, BlendMode.srcIn), + ), + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.red), + buttonStyle: ButtonStyle( + shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))), + backgroundColor: WidgetStatePropertyAll(appTheme.blueA400), + side: const WidgetStatePropertyAll(BorderSide.none), + ), + text: '', + ), + ], + // ], + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: CustomOutlinedButton( + onPressed: () async { + // if (state.selectedStateIndex == 0) { + // final result = await context.read().unpublishDiet(widget.diet.id); + // if (result) { + // if (!context.mounted) return; + // showBottomSheetWithBlur( + // context: context, + // height: 250, + // child: DietDraftedBottomSheet(title: widget.diet.name), + // ); + // await context.read().loadAllDiets(); + // } else { + // showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время'); + // } + // } else { + // await showErrorDialog(context, title: 'Предупреждение', description: 'Вы можете создать новую диету на основе существующей.'); + // AppRouter.navigatorKey.currentContext?.pushNamed(CreateDietScreen.name, extra: widget.diet); + // } + }, + text: '', + // text: switch (state.selectedStateIndex) { + // 0 => s.removeFromActive, + // _ => s.edit, + // }, + height: 52, + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.black), + buttonStyle: ButtonStyle( + shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))), + backgroundColor: WidgetStatePropertyAll(appTheme.lightGray0), + side: const WidgetStatePropertyAll(BorderSide.none), + ), + ), + ), + const SizedBox(width: 6), + CustomOutlinedButton( + onPressed: () async { + // final result = await context.read().deleteDiet(widget.diet.id); + // if (result) { + // if (!context.mounted) return; + // showBottomSheetWithBlur( + // context: context, + // child: DietDeletedBottomSheet(title: widget.diet.name), + // ); + // await context.read().loadAllDiets(); + // } + }, + height: 52, + width: 52, + leftIcon: SvgPicture.asset( + 'assets/icons/trash_can.svg', + width: 20, + height: 20, + ), + buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.red), + buttonStyle: ButtonStyle( + shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.circular(20))), + backgroundColor: WidgetStatePropertyAll(appTheme.lightGray0), + side: const WidgetStatePropertyAll(BorderSide.none), + ), + text: '', + ), + ], + ), + const SizedBox(height: 8), + ], + ), + ); + }, + ), + ], + ), + ); + } +} diff --git a/lib/features/recipe/repositories/my_recipes_repository.dart b/lib/features/recipe/repositories/my_recipes_repository.dart new file mode 100644 index 00000000..73dc105c --- /dev/null +++ b/lib/features/recipe/repositories/my_recipes_repository.dart @@ -0,0 +1,16 @@ +import 'package:eatvio_app/features/recipe/models/my_recipe_model.dart'; +import 'package:eatvio_app/features/recipe/services/my_recipes_service.dart'; + +class MyRecipesRepository { + final MyRecipesService myRecipesService; + + MyRecipesRepository({required this.myRecipesService}); + + Future> getMyRecipes() async { + try { + return (await myRecipesService.getMyRecipes()).data; + } catch (e) { + rethrow; + } + } +} \ No newline at end of file diff --git a/lib/features/recipe/services/my_recipes_service.dart b/lib/features/recipe/services/my_recipes_service.dart new file mode 100644 index 00000000..7500edcb --- /dev/null +++ b/lib/features/recipe/services/my_recipes_service.dart @@ -0,0 +1,13 @@ +import 'package:dio/dio.dart'; +import 'package:eatvio_app/features/recipe/models/my_recipe_model.dart'; +import 'package:retrofit/retrofit.dart'; + +part 'my_recipes_service.g.dart'; + +@RestApi() +abstract class MyRecipesService { + factory MyRecipesService(Dio dio, {String baseUrl}) = _MyRecipesService; + + @GET('/api/recipes/my') + Future getMyRecipes(); +}