From 2d3ef9dd760a24c44c02d7fdc9d9dfcbe8d1a3ae Mon Sep 17 00:00:00 2001 From: Username1548 Date: Thu, 23 Jan 2025 14:21:05 +0700 Subject: [PATCH] added dev tools --- .DS_Store | Bin 8196 -> 10244 bytes lib/core/app_router.dart | 6 + lib/core/initialization_cubit/ws_manager.dart | 2 +- lib/core/utils/toasts.dart | 12 + .../presentation/dev_tools_screen.dart | 156 +++++ lib/features/dev_tools/test_cases.dart | 115 ++++ lib/features/diets/services/diet_service.dart | 11 + .../diets/services/diet_service.g.dart | 54 ++ .../bloc/diets_cubit/diets_cubit.dart | 2 +- .../bloc/recipes_cubit/recipes_cubit.dart | 44 +- .../feed/presentation/pages/feed_screen.dart | 537 ++++++------------ .../feed/presentation/widgets/blog_posts.dart | 53 ++ .../feed/presentation/widgets/diets.dart | 66 +++ .../feed/presentation/widgets/plans.dart | 68 +++ .../feed/presentation/widgets/recipes.dart | 50 ++ .../menu/presentation/pages/menu_screen.dart | 9 + .../my_diets/services/my_diets_service.dart | 2 +- .../my_diets/services/my_diets_service.g.dart | 2 +- .../models/chosen_diets_pagination_model.dart | 32 ++ ...chosen_diets_pagination_model.freezed.dart | 441 ++++++++++++++ .../chosen_diets_pagination_model.g.dart | 41 ++ .../profile/services/profile_service.dart | 4 + .../profile/services/profile_service.g.dart | 33 ++ .../services/profile_service_test.mocks.dart | 201 ++++--- 24 files changed, 1476 insertions(+), 465 deletions(-) create mode 100644 lib/features/dev_tools/presentation/dev_tools_screen.dart create mode 100644 lib/features/dev_tools/test_cases.dart create mode 100644 lib/features/feed/presentation/widgets/blog_posts.dart create mode 100644 lib/features/feed/presentation/widgets/diets.dart create mode 100644 lib/features/feed/presentation/widgets/plans.dart create mode 100644 lib/features/feed/presentation/widgets/recipes.dart create mode 100644 lib/features/profile/models/chosen_diets_pagination_model.dart create mode 100644 lib/features/profile/models/chosen_diets_pagination_model.freezed.dart create mode 100644 lib/features/profile/models/chosen_diets_pagination_model.g.dart diff --git a/.DS_Store b/.DS_Store index 4bd8225be6d1b6e8ec3d7076c9e102e1fa7f05d8..b237a450f14bf60bedd2561b8eb1898ef575efd1 100644 GIT binary patch literal 10244 zcmeHMPiP!f82={OHj^fnlp4^3Feubi;x>sA{LdOUh=L$pu?H=i*~~WC?##}zf3ir3 z?4buy4+`S3BJ`l3h$j^f_8>w%Da8ha9t1%t5fu?BDDCfi^LF>WnVp(TQ1nfh`DW(( z^M3F5zW2R-6C$#f+TJ{oLqs-CmQ$0s3^`cOXW|%PpqE;Hx8JCSA=g!z2Q4@=P7e+3tQ_`3VWqv^KZ zu5Ih@a zTx&qo((t@_g-camr{dV$IrLKdtiYk@2kj5jYwccj5SsS)+NCnNTHAEzpK-m~{*moI z4_XYBgESirM^v20fMWyWv5N0LUVKzWJ_nMRg^J~)18;5pxFNVmSPd9Sx6<*5>OYNK zuHp3Q1)$ zY`V2JBEKviNybxoaKGKT{qh;fgVw4#D(O}l55Jv9W5^E|eZ@RM&zmvqA3(2S*K9T9 zi{~!KW2v~`{`uYCFTE&mYcW*RX*L?>hgZ-H?V}R4!L=V}dt?pcb5LPhu`G3(bvcS3 zm+F3{*_xZXWQ~kw_U#|D$LtCFWMMt*6k2Yp-CS}T&+*eUVd$57_ipLgO1V>D#;7;k0Is(;;=YP_*D*u0M?|k!4 zR7(_pmHpusD)+%>0*B(iQE1fsum;Y>ufJ)Y*O=qIZ@asnQQR+eMjhl@g*Y2xE*5cL z$6ppt$=P@{<~u5UVwr4l3u-1yE0sYC&m4u7)Tr#;`sw%E@4qUtx33*koupP}jo$bQ zK@rslu97~#EXJ;*5?23_OqG4sIKJ!flLIzXjxU^?c>KK{$ASelJCjC2Awrbv0*G{j~m5<{11^ZB<4d zx$;TxcgPLw2YI*~dyO@60EG@=X1Q3EtGKSApLe6Tp?J>HX{-xa3w6eLMbm2RWGq6O zA6AouUmKOY3I8%$%=TK=+vD~2Z~TU@)0p#`-#8toWuVU^BbL!x5MMobK58Br)F6yJ zwRA+p>!LdLeLH=uAL7-#uT#hN%cpcP*FqXsg`qF6PZ=1EqB|3i z%jy6B-%|`GxM9FB@Xs<}W%7mm5-{{Or*Sy^t=+-7f|C!n>qb(z;KC;SUVM(n1AmU6 tk?-bM@&SEL%5EfuJKhU-NZ}3{ea+vqe+HQSzo-7@H2Z&Kw{9IUP^K21z#>q-zQ+4?m(in0WN*PLkFqNSQsKtQ6kU)shs!FDGpbowNV8FmI z`G`dJ=I4?wj2p`;m;{-DQa~WV4J2GauHRVroq009N+1W&?I1rfOpfQ7I(eqlq>W{z FOaP&4JC* DevToolsScreen(), + ), ], ); } diff --git a/lib/core/initialization_cubit/ws_manager.dart b/lib/core/initialization_cubit/ws_manager.dart index 3a72512e..e7676868 100644 --- a/lib/core/initialization_cubit/ws_manager.dart +++ b/lib/core/initialization_cubit/ws_manager.dart @@ -71,7 +71,7 @@ class WsManager { } }); client?.eventStream.listen((event) { - log(event.rootObject.toString()); + // log(event.rootObject.toString()); }); _subscribe(); } catch (e, st) { diff --git a/lib/core/utils/toasts.dart b/lib/core/utils/toasts.dart index 2730d6ce..7a0f3db9 100644 --- a/lib/core/utils/toasts.dart +++ b/lib/core/utils/toasts.dart @@ -26,3 +26,15 @@ void showErrorToast(String message) { fontSize: 16.0, ); } + +void showSuccessToast(String message) { + Fluttertoast.showToast( + msg: message, + toastLength: Toast.LENGTH_SHORT, + gravity: ToastGravity.TOP, + timeInSecForIosWeb: _toastDuration, + backgroundColor: appTheme.greenA70001, + textColor: appTheme.whiteA700, + fontSize: 16.0, + ); +} \ No newline at end of file diff --git a/lib/features/dev_tools/presentation/dev_tools_screen.dart b/lib/features/dev_tools/presentation/dev_tools_screen.dart new file mode 100644 index 00000000..34d7f4f9 --- /dev/null +++ b/lib/features/dev_tools/presentation/dev_tools_screen.dart @@ -0,0 +1,156 @@ +import 'package:eatvio_app/core/const.dart'; +import 'package:eatvio_app/core/utils/toasts.dart'; +import 'package:eatvio_app/core/widgets/custom_outlined_button.dart'; +import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; +import 'package:eatvio_app/features/dev_tools/test_cases.dart'; +import 'package:flutter/material.dart'; + +class DevToolsScreen extends StatelessWidget { + const DevToolsScreen({super.key}); + static const name = 'devToolsScreen'; + static const path = '/dev-tools-screen'; + + @override + Widget build(BuildContext context) { + return const DevToolsScreenContent(); + } +} + +class DevToolsScreenContent extends StatefulWidget { + const DevToolsScreenContent({super.key}); + + @override + State createState() => _DevToolsScreenContentState(); +} + +class _DevToolsScreenContentState extends State { + String baseUrlForTest = ''; + final List testCases = [Test850task()]; + final controller = TextEditingController(); + late final List testsStates; + @override + void initState() { + super.initState(); + setState(() { + this.baseUrlForTest = baseUrl; + }); + testsStates = List.generate(testCases.length, (index) => TestState.notRun); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Text('BaseUrl: ${baseUrlForTest}'), + ], + ), + ), + Row( + children: [ + Expanded( + child: CustomTextFormField( + controller: controller, + hintText: 'type new base url', + ), + ), + IconButton( + onPressed: () { + setState(() { + baseUrlForTest = controller.text; + controller.clear(); + }); + }, + icon: const Icon(Icons.done), + ), + ], + ), + SizedBox( + height: 10, + ), + if (baseUrlForTest != 'https://eatvio.com') + ListView.builder( + shrinkWrap: true, + itemCount: testCases.length, + itemBuilder: (context, index) => Row( + children: [ + Text('${index + 1}. ${testCases[index].name}'), + SizedBox( + width: 50, + ), + Expanded( + child: CustomOutlinedButton( + text: 'run', + height: 20, + width: 60, + onPressed: () async { + if (testsStates[index] == TestState.loading) return; + + setState(() { + testsStates[index] = TestState.loading; + }); + final result = await testCases[index].run(baseUrl: baseUrlForTest); + if (result) { + setState(() { + testsStates[index] = TestState.success; + }); + showSuccessToast('${testCases[index].name} passed'); + } else { + setState(() { + testsStates[index] = TestState.fail; + }); + showErrorToast('${testCases[index].name} failed'); + } + }, + buttonStyle: ButtonStyle(), + ), + ), + SizedBox( + width: 30, + ), + switch (testsStates[index]) { + TestState.success => Expanded( + child: Container( + height: 20, + color: Colors.green, + ), + ), + TestState.fail => Expanded( + child: Container( + height: 20, + color: Colors.red, + ), + ), + TestState.notRun => Expanded( + child: Container( + height: 20, + color: Colors.grey, + ), + ), + TestState.loading => Expanded( + child: Container( + height: 20, + child: SizedBox(height: 20, width: 20, child: Center(child: CircularProgressIndicator())), + ), + ), + }, + ], + ), + ), + ], + ), + ), + ), + ); + } +} + +enum TestState { success, fail, notRun, loading } diff --git a/lib/features/dev_tools/test_cases.dart b/lib/features/dev_tools/test_cases.dart new file mode 100644 index 00000000..3f0891b7 --- /dev/null +++ b/lib/features/dev_tools/test_cases.dart @@ -0,0 +1,115 @@ +import 'dart:async'; +import 'dart:developer'; + +import 'package:dio/dio.dart'; +import 'package:eatvio_app/core/locator_service.dart'; +import 'package:eatvio_app/core/utils/date_time_utils.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'; + +sealed class TestCases { + String get name => throw UnimplementedError(); + + Future run({required String baseUrl}) async => throw UnimplementedError(); +} + +class Test850task implements TestCases { + @override + String get name => 'task #850'; + + @override + Future run({required String baseUrl}) async { + try { + // get all of needed services + final dio = sl(); + final feedService = FeedService(dio, baseUrl: baseUrl); + final profileService = ProfileService(dio, baseUrl: baseUrl); + final dietsService = DietService(dio, baseUrl: baseUrl); + + // get all of needed data + final dietsPaginationModel = await feedService.getDiets(page: 1); + final chosenDietsPaginationModel = await profileService.getChosenDiets(); + final lastChosenDiet = chosenDietsPaginationModel.diets.firstOrNull; + final today = DateTime.now(); + final yesterday = today.subtract(const Duration(days: 1)); + final tomorrow = today.add(const Duration(days: 1)); + + // run test case + for (final diet in dietsPaginationModel.data) { + if (!diet.author.authorIsMe) { + if (lastChosenDiet?.state == 'started' || lastChosenDiet?.state == 'inited') { + try { + await dietsService.cancelDiet(id: lastChosenDiet?.dietId ?? 0); + } catch (e) { + log('unexpected error7: $e'); + return false; + } + await Future.delayed(Duration(seconds: 3)); + } + try { + await dietsService.startDiet( + id: diet.id, + body: { + 'date': yesterday.format('yyyy-MM-dd'), + }, + ); + + return false; + } catch (e) { + log('expect ot have error: $e'); + } + + // test start diet with correct date + try { + await dietsService.startDiet( + id: diet.id, + body: { + 'date': today.format('yyyy-MM-dd'), + }, + ); + } catch (e) { + log('unexpected error2: $e'); + return false; + } + + // test cancelation of diet + try { + await dietsService.cancelDiet(id: diet.id); + } catch (e) { + log('unexpected error3: $e'); + return false; + } + + await Future.delayed(Duration(seconds: 3)); + + // test start diet with correct date + try { + await dietsService.startDiet( + id: diet.id, + body: { + 'date': tomorrow.format('yyyy-MM-dd'), + }, + ); + } catch (e) { + log('unexpected error4: $e'); + return false; + } + + // test cancelation of diet + try { + await dietsService.cancelDiet(id: diet.id); + } catch (e) { + log('unexpected error5: $e'); + } + break; + } + } + + return true; + } catch (e) { + log('unexpected error6: $e'); + return false; + } + } +} diff --git a/lib/features/diets/services/diet_service.dart b/lib/features/diets/services/diet_service.dart index 0d9aebc3..c93e3296 100644 --- a/lib/features/diets/services/diet_service.dart +++ b/lib/features/diets/services/diet_service.dart @@ -28,4 +28,15 @@ abstract class DietService { Future getDiet({ @Path() required int id, }); + + @POST('/api/diets/{id}/start') + Future startDiet({ + @Path() required int id, + @Body() required Map body, + }); + + @POST('/api/diets/{id}/cancel') + Future cancelDiet({ + @Path() required int id, + }); } diff --git a/lib/features/diets/services/diet_service.g.dart b/lib/features/diets/services/diet_service.g.dart index 63e35fb5..b701c1a3 100644 --- a/lib/features/diets/services/diet_service.g.dart +++ b/lib/features/diets/services/diet_service.g.dart @@ -153,6 +153,60 @@ class _DietService implements DietService { return _value; } + @override + Future startDiet({ + required int id, + required Map body, + }) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + final _data = {}; + _data.addAll(body); + final _options = _setStreamType(Options( + method: 'POST', + headers: _headers, + extra: _extra, + ) + .compose( + _dio.options, + '/api/diets/${id}/start', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls( + _dio.options.baseUrl, + baseUrl, + ))); + await _dio.fetch(_options); + } + + @override + Future cancelDiet({required int id}) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + const Map? _data = null; + final _options = _setStreamType(Options( + method: 'POST', + headers: _headers, + extra: _extra, + ) + .compose( + _dio.options, + '/api/diets/${id}/cancel', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls( + _dio.options.baseUrl, + baseUrl, + ))); + await _dio.fetch(_options); + } + RequestOptions _setStreamType(RequestOptions requestOptions) { if (T != dynamic && !(requestOptions.responseType == ResponseType.bytes || diff --git a/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart b/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart index 87e8b342..1f585375 100644 --- a/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart +++ b/lib/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart @@ -150,7 +150,7 @@ class DietsCubit extends Cubit { Future likeDiet(int id, int index) async { final currentDiets = state.dietsList; - if (currentDiets.isEmpty) return; + // if (currentDiets.isEmpty) return; final dietsForModification = [...currentDiets]; final currentDiet = currentDiets[index]; if (currentDiet.wasLikedByMe) { diff --git a/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart b/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart index 5147445a..d3a6a47e 100644 --- a/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart +++ b/lib/features/feed/presentation/bloc/recipes_cubit/recipes_cubit.dart @@ -28,13 +28,16 @@ class RecipesCubit extends Cubit { query: query, ); final recipesTags = (await recipeRepository.getRecipesTags()); - emit(RecipesState.loaded( - recipesList: recipesList, - recipesTags: recipesTags, - selectedTags: _selectedTags, - selectedTagsCounter: _selectedTags.length, - isLoading: isLoading, - ),); + emit( + RecipesState.loaded( + recipesList: recipesList, + recipesTags: recipesTags, + selectedTags: _selectedTags, + selectedTagsCounter: _selectedTags.length, + isLoading: isLoading, + ), + ); + lastPage = currentPage; } catch (e) { emit(RecipesState.error(errorMessage: e.toString())); } @@ -55,14 +58,17 @@ class RecipesCubit extends Cubit { query: _query, ); isLoading = false; - emit((state as RecipesStateLoaded).copyWith( - recipesList: [ - ...(state as RecipesStateLoaded).recipesList, - ...recipesList, - ], - isLoading: isLoading, - ),); + emit( + (state as RecipesStateLoaded).copyWith( + recipesList: [ + ...(state as RecipesStateLoaded).recipesList, + ...recipesList, + ], + isLoading: isLoading, + ), + ); } + lastPage = currentPage; } catch (e) { emit(RecipesState.error(errorMessage: e.toString())); } @@ -71,9 +77,11 @@ class RecipesCubit extends Cubit { updateTags(RecipeTag tag) { _selectedTags.contains(tag.id) ? _selectedTags.remove(tag.id) : _selectedTags.add(tag.id); - emit((state as RecipesStateLoaded).copyWith( - selectedTags: _selectedTags, - selectedTagsCounter: _selectedTags.length, - ),); + emit( + (state as RecipesStateLoaded).copyWith( + selectedTags: _selectedTags, + selectedTagsCounter: _selectedTags.length, + ), + ); } } diff --git a/lib/features/feed/presentation/pages/feed_screen.dart b/lib/features/feed/presentation/pages/feed_screen.dart index 20573fc4..360dd488 100644 --- a/lib/features/feed/presentation/pages/feed_screen.dart +++ b/lib/features/feed/presentation/pages/feed_screen.dart @@ -2,49 +2,70 @@ import 'package:easy_debounce/easy_debounce.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/features/create_diet/presentation/create_diet_screen.dart'; -import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/create_plan/presentation/create_plan_screen.dart'; +import 'package:eatvio_app/features/dev_tools/presentation/dev_tools_screen.dart'; +import 'package:eatvio_app/features/dev_tools/test_cases.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/profile_cubit/profile_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/profile_cubit/profile_state.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/features/feed/presentation/widgets/blog_post_widget.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/blog_posts.dart'; import 'package:eatvio_app/features/feed/presentation/widgets/choice_chip_widget.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/diet_filter_bottom_sheet.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/diets_widget.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/filter_badge.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/plan_widget.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/plans_filter_bottom_sheet.dart'; -import 'package:eatvio_app/features/feed/presentation/widgets/recipes_widget.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/diets.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/plans.dart'; import 'package:eatvio_app/features/feed/presentation/widgets/tags_modal_widget.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_state.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:go_router/go_router.dart'; +import '../widgets/recipes.dart'; + final bucket = PageStorageBucket(); -class FeedScreen extends StatefulWidget { +class FeedScreen extends StatelessWidget { const FeedScreen({super.key}); @override - State createState() => _FeedScreenState(); + Widget build(BuildContext context) { + return MultiBlocProvider( + providers: [ + BlocProvider( + create: (context) => sl()..loadRecipesList(), + ), + BlocProvider( + create: (context) => sl()..getProfile(), + ), + BlocProvider( + create: (context) => sl()..loadFeedBlogPostList(), + ), + BlocProvider( + create: (context) => sl()..loadDiets(), + ), + BlocProvider( + create: (context) => sl()..loadPlans(), + ), + ], + child: const FeedScreenContent(), + ); + } } -class _FeedScreenState extends State { - final FeedCubit feedCubit = sl(); - final RecipesCubit recipesCubit = sl()..loadRecipesList(); - final DietsCubit dietsCubit = sl()..loadDiets(); - final PlansCubit plansCubit = sl()..loadPlans(); +class FeedScreenContent extends StatefulWidget { + const FeedScreenContent({super.key}); - final searchController = TextEditingController(); + @override + State createState() => _FeedScreenContentState(); +} + +class _FeedScreenContentState extends State { + final postsController = TextEditingController(); + final recipesController = TextEditingController(); + final dietsController = TextEditingController(); + final plansController = TextEditingController(); final List chipsLabelList = ['Все', 'Рецепты', 'Диеты', 'Планы питания', 'Консультанты']; int _selectedChipIndex = 0; final blogPostsScrollController = ScrollController(); @@ -54,7 +75,6 @@ class _FeedScreenState extends State { @override void initState() { - feedCubit.loadFeedBlogPostList(); blogPostsScrollController.addListener(_onScrollBlogPosts); recipesScrollController.addListener(_onScrollRecipes); dietsScrollController.addListener(_onScrollDiets); @@ -64,25 +84,25 @@ class _FeedScreenState extends State { _onScrollBlogPosts() { if (blogPostsScrollController.offset >= blogPostsScrollController.position.maxScrollExtent && !blogPostsScrollController.position.outOfRange) { - feedCubit.loadNextPage(); + context.read().loadNextPage(); } } _onScrollRecipes() { if (recipesScrollController.offset >= recipesScrollController.position.maxScrollExtent && !recipesScrollController.position.outOfRange) { - recipesCubit.loadNextPage(); + context.read().loadNextPage(); } } _onScrollDiets() { if (dietsScrollController.offset >= dietsScrollController.position.maxScrollExtent && !dietsScrollController.position.outOfRange) { - dietsCubit.loadNextPage(); + context.read().loadNextPage(); } } _onScrollPlans() { if (plansScrollController.offset >= plansScrollController.position.maxScrollExtent && !plansScrollController.position.outOfRange) { - plansCubit.loadNextPage(); + context.read().loadNextPage(); } } @@ -97,341 +117,139 @@ class _FeedScreenState extends State { @override Widget build(BuildContext context) { - return MultiBlocProvider( - providers: [ - BlocProvider( - create: (context) => sl()..getProfile(), - ), - BlocProvider( - create: (context) => sl()..loadRecipesList(), - ), - BlocProvider( - create: (context) => sl()..loadDiets(), - ), - BlocProvider( - create: (context) => sl()..loadPlans(), - ), - ], - child: Scaffold( - floatingActionButton: _selectedChipIndex == 1 - ? FloatingActionButton.small( - heroTag: 'recipesTagsFilter', - backgroundColor: appTheme.blueA400, - shape: CircleBorder(), - child: Icon( - Icons.filter_list_rounded, - color: Colors.white, - ), - onPressed: () async { - await showModalBottomSheet( - useRootNavigator: true, - context: context, - builder: (context) => TagsModalWidget( - recipesCubit: recipesCubit, - ), - ); - recipesCubit.loadRecipesList(); - }, - ) - : null, - appBar: AppBar( - backgroundColor: Colors.white, - toolbarHeight: 0, - ), - backgroundColor: Colors.grey.shade200, - body: NestedScrollView( - controller: switch (_selectedChipIndex) { - 0 => blogPostsScrollController, - 1 => recipesScrollController, - 2 => dietsScrollController, - 3 => plansScrollController, - _ => blogPostsScrollController - }, - headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { - return [ - BlocBuilder( - builder: (context, state) { - return SliverAppBar( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)), - ), - backgroundColor: Colors.white, - foregroundColor: Colors.white, - automaticallyImplyLeading: false, - stretchTriggerOffset: 1, - floating: true, - snap: true, - scrolledUnderElevation: 0, - bottom: _chipGroup(), - title: Row( - children: [ - CustomSearchBar( - searchController: searchController, - onChanged: (query) { - if (query.length > 2) { - EasyDebounce.debounce( - 'searchFeed', - Duration(milliseconds: 500), - () { - switch (_selectedChipIndex) { - case 0: - feedCubit.loadFeedBlogPostList(query: query); - break; - case 1: - recipesCubit.loadRecipesList(query: query); - break; - case 2: - dietsCubit.loadDiets(query: query); - break; - case 3: - plansCubit.loadPlans(query: query); - break; - } - }, - ); - } else { - EasyDebounce.debounce( - 'searchFeed', - Duration(milliseconds: 500), - () { - switch (_selectedChipIndex) { - case 0: - feedCubit.loadFeedBlogPostList(); - break; - case 1: - recipesCubit.loadRecipesList(); - break; - case 2: - dietsCubit.loadDiets(); - break; - case 3: - plansCubit.loadPlans(); - break; - } - }, - ); - } - }, - ), - SizedBox(width: 12), - switch (_selectedChipIndex) { - 1 => AddItemButton( - onTap: () => GoRouter.of(context).pushNamed('recipeCreateScreen'), - ), - 2 => AddItemButton( - onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreateDietScreen.name) : null, - ), - 3 => AddItemButton( - onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null, - ), - _ => AddItemButton() + return Scaffold( + floatingActionButton: _selectedChipIndex == 1 + ? FloatingActionButton.small( + heroTag: 'recipesTagsFilter', + backgroundColor: appTheme.blueA400, + shape: CircleBorder(), + child: Icon( + Icons.filter_list_rounded, + color: Colors.white, + ), + onPressed: () async { + final recipesCubit = context.read(); + await showModalBottomSheet( + useRootNavigator: true, + context: context, + builder: (context) => TagsModalWidget( + recipesCubit: recipesCubit, + ), + ); + recipesCubit.loadRecipesList(); + }, + ) + : null, + appBar: AppBar( + backgroundColor: Colors.white, + toolbarHeight: 0, + ), + backgroundColor: Colors.grey.shade200, + body: NestedScrollView( + controller: switch (_selectedChipIndex) { + 0 => blogPostsScrollController, + 1 => recipesScrollController, + 2 => dietsScrollController, + 3 => plansScrollController, + _ => blogPostsScrollController + }, + headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { + return [ + BlocBuilder( + builder: (context, state) { + return SliverAppBar( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)), + ), + backgroundColor: Colors.white, + foregroundColor: Colors.white, + automaticallyImplyLeading: false, + stretchTriggerOffset: 1, + floating: true, + snap: true, + scrolledUnderElevation: 0, + bottom: _chipGroup(), + title: Row( + children: [ + CustomSearchBar( + searchController: switch (_selectedChipIndex) { + 1 => recipesController, + 2 => dietsController, + 3 => plansController, + _ => postsController, }, - ], - ), - ); - }, - ), - ]; - }, - body: switch (_selectedChipIndex) { - 0 => _buildAllBlogPosts(), - 1 => _buildAllRecipes(), - 2 => _buildDiets(), - 3 => _buildPlans(), - _ => Center(child: Text(chipsLabelList[_selectedChipIndex])), - }, - ), - ), - ); - } - - _buildAllBlogPosts() { - return RefreshIndicator( - onRefresh: () => feedCubit.loadFeedBlogPostList(), - child: BlocBuilder( - builder: (BuildContext context, FeedState state) { - if (state is FeedStateLoaded) { - return ListView.separated( - padding: EdgeInsets.symmetric(vertical: 8), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, index) { - if (index == state.feedBlogPostList.length) { - return const Loader(); - } - return BlogPostWidget(index: index); - }, - separatorBuilder: (context, index) { - return SizedBox(height: 8); - }, - itemCount: state.isLoading ? state.feedBlogPostList.length + 1 : state.feedBlogPostList.length, - ); - } else if (state is FeedStateError) { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: Padding( - padding: const EdgeInsets.all(16), - child: Center( - child: Text(state.errorMessage), - ), - ), - ); - } else { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: const Loader(), - ); - } - }, - ), - ); - } - - _buildAllRecipes() { - return RefreshIndicator( - onRefresh: () => recipesCubit.loadRecipesList(), - child: BlocBuilder( - bloc: recipesCubit, - 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]); - }, - 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 { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: const Loader(), - ); - } - }, - ), - ); - } - - _buildDiets() { - return RefreshIndicator( - onRefresh: () => dietsCubit.loadDiets(), - child: BlocBuilder( - bloc: dietsCubit, - builder: (BuildContext context, DietsState state) { - if (state.isLoading) { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: const Loader(), - ); - } else if (state.errorMessage != null) { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: Padding( - padding: const EdgeInsets.all(16), - child: Center( - child: Text(state.errorMessage ?? ''), - ), - ), - ); - } else { - return Stack( - children: [ - SizedBox.expand(), - ListView.separated( - padding: EdgeInsets.symmetric(vertical: 8), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, index) { - return DietsWidget(diet: state.dietsList[index], index: index); - }, - separatorBuilder: (context, index) { - return SizedBox(height: 8); - }, - itemCount: state.dietsList.length, - ), - Positioned( - right: 0, - bottom: 74, - child: FilterBadge( - filterBottomSheet: DietFilterBottomSheet( - dietsCubit: dietsCubit, - ), + onChanged: (query) { + if (query.length > 2) { + EasyDebounce.debounce( + 'searchFeed', + Duration(milliseconds: 500), + () { + switch (_selectedChipIndex) { + case 0: + context.read().loadFeedBlogPostList(query: query); + break; + case 1: + context.read().loadRecipesList(query: query); + break; + case 2: + context.read().loadDiets(query: query); + break; + case 3: + context.read().loadPlans(query: query); + break; + } + }, + ); + } else { + EasyDebounce.debounce( + 'searchFeed', + Duration(milliseconds: 500), + () { + switch (_selectedChipIndex) { + case 0: + context.read().loadFeedBlogPostList(); + break; + case 1: + context.read().loadRecipesList(); + break; + case 2: + context.read().loadDiets(); + break; + case 3: + context.read().loadPlans(); + break; + } + }, + ); + } + }, + ), + SizedBox(width: 12), + switch (_selectedChipIndex) { + 1 => AddItemButton( + onTap: () => GoRouter.of(context).pushNamed('recipeCreateScreen'), + ), + 2 => AddItemButton( + onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreateDietScreen.name) : null, + ), + 3 => AddItemButton( + onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null, + ), + _ => AddItemButton() + }, + ], ), - ), - ], - ); - } + ); + }, + ), + ]; }, - ), - ); - } - - _buildPlans() { - return RefreshIndicator( - onRefresh: () => plansCubit.loadPlans(), - child: BlocBuilder( - bloc: plansCubit, - builder: (BuildContext context, PlansState state) { - if (state.isLoading) { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: const Loader(), - ); - } else if (state.errorMessage != null) { - return Scaffold( - backgroundColor: Colors.grey.shade200, - body: Padding( - padding: const EdgeInsets.all(16), - child: Center( - child: Text(state.errorMessage ?? ''), - ), - ), - ); - } - return Stack( - children: [ - SizedBox.expand(), - ListView.separated( - padding: EdgeInsets.symmetric(vertical: 8), - shrinkWrap: true, - physics: BouncingScrollPhysics(), - itemBuilder: (context, index) { - return PlanWidget( - plan: state.plans[index], - index: index, - ); - }, - separatorBuilder: (context, index) { - return SizedBox(height: 8); - }, - itemCount: state.plans.length, - ), - Positioned( - right: 0, - bottom: 74, - child: FilterBadge( - filterBottomSheet: PlansFilterBottomSheet( - plansCubit: plansCubit, - ), - ), - ), - ], - ); + body: switch (_selectedChipIndex) { + 0 => BlogPosts(), + 1 => Recipes(), + 2 => Diets(), + 3 => Plans(), + _ => Center(child: Text(chipsLabelList[_selectedChipIndex])), }, ), ); @@ -454,7 +272,6 @@ class _FeedScreenState extends State { onSelected: (bool selected) { setState(() { _selectedChipIndex = 0; - searchController.clear(); FocusScope.of(context).requestFocus(new FocusNode()); }); }, @@ -467,7 +284,6 @@ class _FeedScreenState extends State { onSelected: (bool selected) { setState(() { _selectedChipIndex = 1; - searchController.clear(); FocusScope.of(context).requestFocus(new FocusNode()); }); }, @@ -480,7 +296,6 @@ class _FeedScreenState extends State { onSelected: (bool selected) { setState(() { _selectedChipIndex = 2; - searchController.clear(); FocusScope.of(context).requestFocus(new FocusNode()); }); }, @@ -493,7 +308,6 @@ class _FeedScreenState extends State { onSelected: (bool selected) { setState(() { _selectedChipIndex = 3; - searchController.clear(); FocusScope.of(context).requestFocus(new FocusNode()); }); }, @@ -506,7 +320,6 @@ class _FeedScreenState extends State { onSelected: (bool selected) { setState(() { _selectedChipIndex = 4; - searchController.clear(); FocusScope.of(context).requestFocus(new FocusNode()); }); }, diff --git a/lib/features/feed/presentation/widgets/blog_posts.dart b/lib/features/feed/presentation/widgets/blog_posts.dart new file mode 100644 index 00000000..f76e35ce --- /dev/null +++ b/lib/features/feed/presentation/widgets/blog_posts.dart @@ -0,0 +1,53 @@ +import 'package:eatvio_app/core/widgets/loader.dart'; +import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; +import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/blog_post_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class BlogPosts extends StatelessWidget { + const BlogPosts({super.key}); + + @override + Widget build(BuildContext context) { + return RefreshIndicator( + onRefresh: () => context.read().loadFeedBlogPostList(), + child: BlocBuilder( + builder: (BuildContext context, FeedState state) { + if (state is FeedStateLoaded) { + return ListView.separated( + padding: EdgeInsets.symmetric(vertical: 8), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + if (index == state.feedBlogPostList.length) { + return const Loader(); + } + return BlogPostWidget(index: index); + }, + separatorBuilder: (context, index) { + return SizedBox(height: 8); + }, + itemCount: state.isLoading ? state.feedBlogPostList.length + 1 : state.feedBlogPostList.length, + ); + } else if (state is FeedStateError) { + return Scaffold( + backgroundColor: Colors.grey.shade200, + body: Padding( + padding: const EdgeInsets.all(16), + child: Center( + child: Text(state.errorMessage), + ), + ), + ); + } else { + return Scaffold( + backgroundColor: Colors.grey.shade200, + body: const Loader(), + ); + } + }, + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/feed/presentation/widgets/diets.dart b/lib/features/feed/presentation/widgets/diets.dart new file mode 100644 index 00000000..4d1ca2f3 --- /dev/null +++ b/lib/features/feed/presentation/widgets/diets.dart @@ -0,0 +1,66 @@ +import 'package:eatvio_app/core/widgets/loader.dart'; +import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart'; +import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_state.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/diet_filter_bottom_sheet.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/diets_widget.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/filter_badge.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class Diets extends StatelessWidget { + const Diets({super.key}); + + @override + Widget build(BuildContext context) { + return RefreshIndicator( + onRefresh: () => context.read().loadDiets(), + child: BlocBuilder( + builder: (BuildContext context, DietsState state) { + if (state.isLoading) { + return Scaffold( + backgroundColor: Colors.grey.shade200, + body: const Loader(), + ); + } else if (state.errorMessage != null) { + return Scaffold( + backgroundColor: Colors.grey.shade200, + body: Padding( + padding: const EdgeInsets.all(16), + child: Center( + child: Text(state.errorMessage ?? ''), + ), + ), + ); + } else { + return Stack( + children: [ + SizedBox.expand(), + ListView.separated( + padding: EdgeInsets.symmetric(vertical: 8), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + return DietsWidget(diet: state.dietsList[index], index: index); + }, + separatorBuilder: (context, index) { + return SizedBox(height: 8); + }, + itemCount: state.dietsList.length, + ), + Positioned( + right: 0, + bottom: 74, + child: FilterBadge( + filterBottomSheet: DietFilterBottomSheet( + dietsCubit: context.read(), + ), + ), + ), + ], + ); + } + }, + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/feed/presentation/widgets/plans.dart b/lib/features/feed/presentation/widgets/plans.dart new file mode 100644 index 00000000..940e677b --- /dev/null +++ b/lib/features/feed/presentation/widgets/plans.dart @@ -0,0 +1,68 @@ +import 'package:eatvio_app/core/widgets/loader.dart'; +import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_cubit.dart'; +import 'package:eatvio_app/features/feed/presentation/bloc/plans_cubit/plans_state.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/filter_badge.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/plan_widget.dart'; +import 'package:eatvio_app/features/feed/presentation/widgets/plans_filter_bottom_sheet.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class Plans extends StatelessWidget { + const Plans({super.key}); + + @override + Widget build(BuildContext context) { + return RefreshIndicator( + onRefresh: () => context.read().loadPlans(), + child: BlocBuilder( + builder: (BuildContext context, PlansState state) { + if (state.isLoading) { + return Scaffold( + backgroundColor: Colors.grey.shade200, + body: const Loader(), + ); + } else if (state.errorMessage != null) { + return Scaffold( + backgroundColor: Colors.grey.shade200, + body: Padding( + padding: const EdgeInsets.all(16), + child: Center( + child: Text(state.errorMessage ?? ''), + ), + ), + ); + } + return Stack( + children: [ + SizedBox.expand(), + ListView.separated( + padding: EdgeInsets.symmetric(vertical: 8), + shrinkWrap: true, + physics: BouncingScrollPhysics(), + itemBuilder: (context, index) { + return PlanWidget( + plan: state.plans[index], + index: index, + ); + }, + separatorBuilder: (context, index) { + return SizedBox(height: 8); + }, + itemCount: state.plans.length, + ), + Positioned( + right: 0, + bottom: 74, + child: FilterBadge( + filterBottomSheet: PlansFilterBottomSheet( + plansCubit: context.read(), + ), + ), + ), + ], + ); + }, + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/feed/presentation/widgets/recipes.dart b/lib/features/feed/presentation/widgets/recipes.dart new file mode 100644 index 00000000..9679e81c --- /dev/null +++ b/lib/features/feed/presentation/widgets/recipes.dart @@ -0,0 +1,50 @@ +import 'package:eatvio_app/core/widgets/loader.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/features/feed/presentation/widgets/recipes_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class Recipes extends StatelessWidget { + const Recipes({super.key}); + + @override + Widget build(BuildContext context) { + return RefreshIndicator( + onRefresh: () => context.read().loadRecipesList(), + child: BlocBuilder( + 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]); + }, + 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 { + return Scaffold( + backgroundColor: Colors.grey.shade200, + body: const Loader(), + ); + } + }, + ), + ); + } +} \ No newline at end of file diff --git a/lib/features/menu/presentation/pages/menu_screen.dart b/lib/features/menu/presentation/pages/menu_screen.dart index ad974e54..098b2411 100644 --- a/lib/features/menu/presentation/pages/menu_screen.dart +++ b/lib/features/menu/presentation/pages/menu_screen.dart @@ -4,6 +4,7 @@ import 'package:eatvio_app/core/token_storage.dart'; import 'package:eatvio_app/core/utils/image_constant.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; +import 'package:eatvio_app/features/dev_tools/presentation/dev_tools_screen.dart'; import 'package:eatvio_app/features/my_diets/presentation/my_diets_screen.dart'; import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart'; import 'package:flutter/material.dart'; @@ -65,6 +66,14 @@ class MenuScreen extends StatelessWidget { onTap: () {}, ), _divider(context), + _tile( + leading: ImageConstant.icnSupport, + title: 'Для разработчиков', + onTap: () { + GoRouter.of(context).pushNamed(DevToolsScreen.name); + }, + ), + _divider(context), _tile( leading: ImageConstant.icnExit, title: 'Выход', diff --git a/lib/features/my_diets/services/my_diets_service.dart b/lib/features/my_diets/services/my_diets_service.dart index e2bba8a0..3a78d25e 100644 --- a/lib/features/my_diets/services/my_diets_service.dart +++ b/lib/features/my_diets/services/my_diets_service.dart @@ -9,7 +9,7 @@ abstract class MyDietsService { factory MyDietsService(Dio dio, {String baseUrl}) = _MyDietsService; - @GET('/api/diets/index') + @GET('/api/profile/my_diets') Future getDiets({ @Query('page') required int page, @Query('filters[name][\$startsWith]') String? query, diff --git a/lib/features/my_diets/services/my_diets_service.g.dart b/lib/features/my_diets/services/my_diets_service.g.dart index fec66099..61371ae2 100644 --- a/lib/features/my_diets/services/my_diets_service.g.dart +++ b/lib/features/my_diets/services/my_diets_service.g.dart @@ -47,7 +47,7 @@ class _MyDietsService implements MyDietsService { ) .compose( _dio.options, - '/api/diets/index', + '/api/profile/my_diets', queryParameters: queryParameters, data: _data, ) diff --git a/lib/features/profile/models/chosen_diets_pagination_model.dart b/lib/features/profile/models/chosen_diets_pagination_model.dart new file mode 100644 index 00000000..7f025d5f --- /dev/null +++ b/lib/features/profile/models/chosen_diets_pagination_model.dart @@ -0,0 +1,32 @@ +import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'chosen_diets_pagination_model.freezed.dart'; +part 'chosen_diets_pagination_model.g.dart'; + +@freezed +class ChosenDietsPaginationModel with _$ChosenDietsPaginationModel { + factory ChosenDietsPaginationModel({ + @JsonKey(name: 'data') required List diets, + }) = _ChosenDietsPaginationModel; + + factory ChosenDietsPaginationModel.fromJson(Map json) => _$ChosenDietsPaginationModelFromJson(json); +} + +@freezed +class ChosenDietModel with _$ChosenDietModel { + factory ChosenDietModel({ + @JsonKey(name: 'id') required int chosenDietID, + @JsonKey(name: 'chosen_plan_id') required int chosenPlanId, + @JsonKey() required String state, + @JsonKey(name: 'start_date', fromJson: parseDate) required DateTime startDate, + @JsonKey(name: 'diet', fromJson: _parseDietId) required int? dietId, + }) = _ChosenDietModel; + + factory ChosenDietModel.fromJson(Map json) => _$ChosenDietModelFromJson(json); +} + +int? _parseDietId(json) { + if (json == null) return null; + return json['id'] as int?; +} diff --git a/lib/features/profile/models/chosen_diets_pagination_model.freezed.dart b/lib/features/profile/models/chosen_diets_pagination_model.freezed.dart new file mode 100644 index 00000000..3514c6a3 --- /dev/null +++ b/lib/features/profile/models/chosen_diets_pagination_model.freezed.dart @@ -0,0 +1,441 @@ +// 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 'chosen_diets_pagination_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(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'); + +ChosenDietsPaginationModel _$ChosenDietsPaginationModelFromJson( + Map json) { + return _ChosenDietsPaginationModel.fromJson(json); +} + +/// @nodoc +mixin _$ChosenDietsPaginationModel { + @JsonKey(name: 'data') + List get diets => throw _privateConstructorUsedError; + + /// Serializes this ChosenDietsPaginationModel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ChosenDietsPaginationModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ChosenDietsPaginationModelCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ChosenDietsPaginationModelCopyWith<$Res> { + factory $ChosenDietsPaginationModelCopyWith(ChosenDietsPaginationModel value, + $Res Function(ChosenDietsPaginationModel) then) = + _$ChosenDietsPaginationModelCopyWithImpl<$Res, + ChosenDietsPaginationModel>; + @useResult + $Res call({@JsonKey(name: 'data') List diets}); +} + +/// @nodoc +class _$ChosenDietsPaginationModelCopyWithImpl<$Res, + $Val extends ChosenDietsPaginationModel> + implements $ChosenDietsPaginationModelCopyWith<$Res> { + _$ChosenDietsPaginationModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ChosenDietsPaginationModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? diets = null, + }) { + return _then(_value.copyWith( + diets: null == diets + ? _value.diets + : diets // ignore: cast_nullable_to_non_nullable + as List, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ChosenDietsPaginationModelImplCopyWith<$Res> + implements $ChosenDietsPaginationModelCopyWith<$Res> { + factory _$$ChosenDietsPaginationModelImplCopyWith( + _$ChosenDietsPaginationModelImpl value, + $Res Function(_$ChosenDietsPaginationModelImpl) then) = + __$$ChosenDietsPaginationModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({@JsonKey(name: 'data') List diets}); +} + +/// @nodoc +class __$$ChosenDietsPaginationModelImplCopyWithImpl<$Res> + extends _$ChosenDietsPaginationModelCopyWithImpl<$Res, + _$ChosenDietsPaginationModelImpl> + implements _$$ChosenDietsPaginationModelImplCopyWith<$Res> { + __$$ChosenDietsPaginationModelImplCopyWithImpl( + _$ChosenDietsPaginationModelImpl _value, + $Res Function(_$ChosenDietsPaginationModelImpl) _then) + : super(_value, _then); + + /// Create a copy of ChosenDietsPaginationModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? diets = null, + }) { + return _then(_$ChosenDietsPaginationModelImpl( + diets: null == diets + ? _value._diets + : diets // ignore: cast_nullable_to_non_nullable + as List, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ChosenDietsPaginationModelImpl implements _ChosenDietsPaginationModel { + _$ChosenDietsPaginationModelImpl( + {@JsonKey(name: 'data') required final List diets}) + : _diets = diets; + + factory _$ChosenDietsPaginationModelImpl.fromJson( + Map json) => + _$$ChosenDietsPaginationModelImplFromJson(json); + + final List _diets; + @override + @JsonKey(name: 'data') + List get diets { + if (_diets is EqualUnmodifiableListView) return _diets; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_diets); + } + + @override + String toString() { + return 'ChosenDietsPaginationModel(diets: $diets)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChosenDietsPaginationModelImpl && + const DeepCollectionEquality().equals(other._diets, _diets)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => + Object.hash(runtimeType, const DeepCollectionEquality().hash(_diets)); + + /// Create a copy of ChosenDietsPaginationModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ChosenDietsPaginationModelImplCopyWith<_$ChosenDietsPaginationModelImpl> + get copyWith => __$$ChosenDietsPaginationModelImplCopyWithImpl< + _$ChosenDietsPaginationModelImpl>(this, _$identity); + + @override + Map toJson() { + return _$$ChosenDietsPaginationModelImplToJson( + this, + ); + } +} + +abstract class _ChosenDietsPaginationModel + implements ChosenDietsPaginationModel { + factory _ChosenDietsPaginationModel( + {@JsonKey(name: 'data') required final List diets}) = + _$ChosenDietsPaginationModelImpl; + + factory _ChosenDietsPaginationModel.fromJson(Map json) = + _$ChosenDietsPaginationModelImpl.fromJson; + + @override + @JsonKey(name: 'data') + List get diets; + + /// Create a copy of ChosenDietsPaginationModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ChosenDietsPaginationModelImplCopyWith<_$ChosenDietsPaginationModelImpl> + get copyWith => throw _privateConstructorUsedError; +} + +ChosenDietModel _$ChosenDietModelFromJson(Map json) { + return _ChosenDietModel.fromJson(json); +} + +/// @nodoc +mixin _$ChosenDietModel { + @JsonKey(name: 'id') + int get chosenDietID => throw _privateConstructorUsedError; + @JsonKey(name: 'chosen_plan_id') + int get chosenPlanId => throw _privateConstructorUsedError; + @JsonKey() + String get state => throw _privateConstructorUsedError; + @JsonKey(name: 'start_date', fromJson: parseDate) + DateTime get startDate => throw _privateConstructorUsedError; + @JsonKey(name: 'diet', fromJson: _parseDietId) + int? get dietId => throw _privateConstructorUsedError; + + /// Serializes this ChosenDietModel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of ChosenDietModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $ChosenDietModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ChosenDietModelCopyWith<$Res> { + factory $ChosenDietModelCopyWith( + ChosenDietModel value, $Res Function(ChosenDietModel) then) = + _$ChosenDietModelCopyWithImpl<$Res, ChosenDietModel>; + @useResult + $Res call( + {@JsonKey(name: 'id') int chosenDietID, + @JsonKey(name: 'chosen_plan_id') int chosenPlanId, + @JsonKey() String state, + @JsonKey(name: 'start_date', fromJson: parseDate) DateTime startDate, + @JsonKey(name: 'diet', fromJson: _parseDietId) int? dietId}); +} + +/// @nodoc +class _$ChosenDietModelCopyWithImpl<$Res, $Val extends ChosenDietModel> + implements $ChosenDietModelCopyWith<$Res> { + _$ChosenDietModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ChosenDietModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? chosenDietID = null, + Object? chosenPlanId = null, + Object? state = null, + Object? startDate = null, + Object? dietId = freezed, + }) { + return _then(_value.copyWith( + chosenDietID: null == chosenDietID + ? _value.chosenDietID + : chosenDietID // ignore: cast_nullable_to_non_nullable + as int, + chosenPlanId: null == chosenPlanId + ? _value.chosenPlanId + : chosenPlanId // ignore: cast_nullable_to_non_nullable + as int, + state: null == state + ? _value.state + : state // ignore: cast_nullable_to_non_nullable + as String, + startDate: null == startDate + ? _value.startDate + : startDate // ignore: cast_nullable_to_non_nullable + as DateTime, + dietId: freezed == dietId + ? _value.dietId + : dietId // ignore: cast_nullable_to_non_nullable + as int?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$ChosenDietModelImplCopyWith<$Res> + implements $ChosenDietModelCopyWith<$Res> { + factory _$$ChosenDietModelImplCopyWith(_$ChosenDietModelImpl value, + $Res Function(_$ChosenDietModelImpl) then) = + __$$ChosenDietModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {@JsonKey(name: 'id') int chosenDietID, + @JsonKey(name: 'chosen_plan_id') int chosenPlanId, + @JsonKey() String state, + @JsonKey(name: 'start_date', fromJson: parseDate) DateTime startDate, + @JsonKey(name: 'diet', fromJson: _parseDietId) int? dietId}); +} + +/// @nodoc +class __$$ChosenDietModelImplCopyWithImpl<$Res> + extends _$ChosenDietModelCopyWithImpl<$Res, _$ChosenDietModelImpl> + implements _$$ChosenDietModelImplCopyWith<$Res> { + __$$ChosenDietModelImplCopyWithImpl( + _$ChosenDietModelImpl _value, $Res Function(_$ChosenDietModelImpl) _then) + : super(_value, _then); + + /// Create a copy of ChosenDietModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? chosenDietID = null, + Object? chosenPlanId = null, + Object? state = null, + Object? startDate = null, + Object? dietId = freezed, + }) { + return _then(_$ChosenDietModelImpl( + chosenDietID: null == chosenDietID + ? _value.chosenDietID + : chosenDietID // ignore: cast_nullable_to_non_nullable + as int, + chosenPlanId: null == chosenPlanId + ? _value.chosenPlanId + : chosenPlanId // ignore: cast_nullable_to_non_nullable + as int, + state: null == state + ? _value.state + : state // ignore: cast_nullable_to_non_nullable + as String, + startDate: null == startDate + ? _value.startDate + : startDate // ignore: cast_nullable_to_non_nullable + as DateTime, + dietId: freezed == dietId + ? _value.dietId + : dietId // ignore: cast_nullable_to_non_nullable + as int?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$ChosenDietModelImpl implements _ChosenDietModel { + _$ChosenDietModelImpl( + {@JsonKey(name: 'id') required this.chosenDietID, + @JsonKey(name: 'chosen_plan_id') required this.chosenPlanId, + @JsonKey() required this.state, + @JsonKey(name: 'start_date', fromJson: parseDate) required this.startDate, + @JsonKey(name: 'diet', fromJson: _parseDietId) required this.dietId}); + + factory _$ChosenDietModelImpl.fromJson(Map json) => + _$$ChosenDietModelImplFromJson(json); + + @override + @JsonKey(name: 'id') + final int chosenDietID; + @override + @JsonKey(name: 'chosen_plan_id') + final int chosenPlanId; + @override + @JsonKey() + final String state; + @override + @JsonKey(name: 'start_date', fromJson: parseDate) + final DateTime startDate; + @override + @JsonKey(name: 'diet', fromJson: _parseDietId) + final int? dietId; + + @override + String toString() { + return 'ChosenDietModel(chosenDietID: $chosenDietID, chosenPlanId: $chosenPlanId, state: $state, startDate: $startDate, dietId: $dietId)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ChosenDietModelImpl && + (identical(other.chosenDietID, chosenDietID) || + other.chosenDietID == chosenDietID) && + (identical(other.chosenPlanId, chosenPlanId) || + other.chosenPlanId == chosenPlanId) && + (identical(other.state, state) || other.state == state) && + (identical(other.startDate, startDate) || + other.startDate == startDate) && + (identical(other.dietId, dietId) || other.dietId == dietId)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, chosenDietID, chosenPlanId, state, startDate, dietId); + + /// Create a copy of ChosenDietModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ChosenDietModelImplCopyWith<_$ChosenDietModelImpl> get copyWith => + __$$ChosenDietModelImplCopyWithImpl<_$ChosenDietModelImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$ChosenDietModelImplToJson( + this, + ); + } +} + +abstract class _ChosenDietModel implements ChosenDietModel { + factory _ChosenDietModel( + {@JsonKey(name: 'id') required final int chosenDietID, + @JsonKey(name: 'chosen_plan_id') required final int chosenPlanId, + @JsonKey() required final String state, + @JsonKey(name: 'start_date', fromJson: parseDate) + required final DateTime startDate, + @JsonKey(name: 'diet', fromJson: _parseDietId) + required final int? dietId}) = _$ChosenDietModelImpl; + + factory _ChosenDietModel.fromJson(Map json) = + _$ChosenDietModelImpl.fromJson; + + @override + @JsonKey(name: 'id') + int get chosenDietID; + @override + @JsonKey(name: 'chosen_plan_id') + int get chosenPlanId; + @override + @JsonKey() + String get state; + @override + @JsonKey(name: 'start_date', fromJson: parseDate) + DateTime get startDate; + @override + @JsonKey(name: 'diet', fromJson: _parseDietId) + int? get dietId; + + /// Create a copy of ChosenDietModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ChosenDietModelImplCopyWith<_$ChosenDietModelImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/features/profile/models/chosen_diets_pagination_model.g.dart b/lib/features/profile/models/chosen_diets_pagination_model.g.dart new file mode 100644 index 00000000..75d8ffa1 --- /dev/null +++ b/lib/features/profile/models/chosen_diets_pagination_model.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'chosen_diets_pagination_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$ChosenDietsPaginationModelImpl _$$ChosenDietsPaginationModelImplFromJson( + Map json) => + _$ChosenDietsPaginationModelImpl( + diets: (json['data'] as List) + .map((e) => ChosenDietModel.fromJson(e as Map)) + .toList(), + ); + +Map _$$ChosenDietsPaginationModelImplToJson( + _$ChosenDietsPaginationModelImpl instance) => + { + 'data': instance.diets, + }; + +_$ChosenDietModelImpl _$$ChosenDietModelImplFromJson( + Map json) => + _$ChosenDietModelImpl( + chosenDietID: (json['id'] as num).toInt(), + chosenPlanId: (json['chosen_plan_id'] as num).toInt(), + state: json['state'] as String, + startDate: parseDate(json['start_date'] as String), + dietId: _parseDietId(json['diet']), + ); + +Map _$$ChosenDietModelImplToJson( + _$ChosenDietModelImpl instance) => + { + 'id': instance.chosenDietID, + 'chosen_plan_id': instance.chosenPlanId, + 'state': instance.state, + 'start_date': instance.startDate.toIso8601String(), + 'diet': instance.dietId, + }; diff --git a/lib/features/profile/services/profile_service.dart b/lib/features/profile/services/profile_service.dart index d357ea3a..c6bed688 100644 --- a/lib/features/profile/services/profile_service.dart +++ b/lib/features/profile/services/profile_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:dio/dio.dart'; import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart'; +import 'package:eatvio_app/features/profile/models/chosen_diets_pagination_model.dart'; import 'package:eatvio_app/features/profile/models/circumference_model.dart'; import 'package:eatvio_app/features/profile/models/profile_model.dart'; import 'package:eatvio_app/features/profile/models/sub_model.dart'; @@ -99,4 +100,7 @@ abstract class ProfileService { @DELETE('/api/profile/photo/delete') Future deletePhoto(); + + @GET('/api/profile/chosen_diets') + Future getChosenDiets(); } diff --git a/lib/features/profile/services/profile_service.g.dart b/lib/features/profile/services/profile_service.g.dart index e8214593..4d9c61a4 100644 --- a/lib/features/profile/services/profile_service.g.dart +++ b/lib/features/profile/services/profile_service.g.dart @@ -596,6 +596,39 @@ class _ProfileService implements ProfileService { await _dio.fetch(_options); } + @override + Future getChosenDiets() async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + const Map? _data = null; + final _options = _setStreamType(Options( + method: 'GET', + headers: _headers, + extra: _extra, + ) + .compose( + _dio.options, + '/api/profile/chosen_diets', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls( + _dio.options.baseUrl, + baseUrl, + ))); + final _result = await _dio.fetch>(_options); + late ChosenDietsPaginationModel _value; + try { + _value = ChosenDietsPaginationModel.fromJson(_result.data!); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + return _value; + } + RequestOptions _setStreamType(RequestOptions requestOptions) { if (T != dynamic && !(requestOptions.responseType == ResponseType.bytes || diff --git a/test/features/profile/services/profile_service_test.mocks.dart b/test/features/profile/services/profile_service_test.mocks.dart index bb0c633a..194ed8b5 100644 --- a/test/features/profile/services/profile_service_test.mocks.dart +++ b/test/features/profile/services/profile_service_test.mocks.dart @@ -3,18 +3,20 @@ // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; -import 'dart:io' as _i9; +import 'dart:async' as _i6; +import 'dart:io' as _i10; import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart' - as _i6; + as _i7; +import 'package:eatvio_app/features/profile/models/chosen_diets_pagination_model.dart' + as _i4; import 'package:eatvio_app/features/profile/models/circumference_model.dart' - as _i8; + as _i9; import 'package:eatvio_app/features/profile/models/profile_model.dart' as _i2; import 'package:eatvio_app/features/profile/models/sub_model.dart' as _i3; -import 'package:eatvio_app/features/profile/models/weight_model.dart' as _i7; +import 'package:eatvio_app/features/profile/models/weight_model.dart' as _i8; import 'package:eatvio_app/features/profile/services/profile_service.dart' - as _i4; + as _i5; import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: type=lint @@ -62,19 +64,30 @@ class _FakeSubPaginationModel_2 extends _i1.SmartFake ); } +class _FakeChosenDietsPaginationModel_3 extends _i1.SmartFake + implements _i4.ChosenDietsPaginationModel { + _FakeChosenDietsPaginationModel_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + /// A class which mocks [ProfileService]. /// /// See the documentation for Mockito's code generation for more information. -class MockProfileService extends _i1.Mock implements _i4.ProfileService { +class MockProfileService extends _i1.Mock implements _i5.ProfileService { @override - _i5.Future<_i2.ProfileModel> getProfileBySlug({required String? slug}) => + _i6.Future<_i2.ProfileModel> getProfileBySlug({required String? slug}) => (super.noSuchMethod( Invocation.method( #getProfileBySlug, [], {#slug: slug}, ), - returnValue: _i5.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( + returnValue: _i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( this, Invocation.method( #getProfileBySlug, @@ -83,7 +96,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { ), )), returnValueForMissingStub: - _i5.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( + _i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( this, Invocation.method( #getProfileBySlug, @@ -91,15 +104,15 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { {#slug: slug}, ), )), - ) as _i5.Future<_i2.ProfileModel>); + ) as _i6.Future<_i2.ProfileModel>); @override - _i5.Future<_i2.ProfileModel> getMyProfile() => (super.noSuchMethod( + _i6.Future<_i2.ProfileModel> getMyProfile() => (super.noSuchMethod( Invocation.method( #getMyProfile, [], ), - returnValue: _i5.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( + returnValue: _i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( this, Invocation.method( #getMyProfile, @@ -107,23 +120,23 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { ), )), returnValueForMissingStub: - _i5.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( + _i6.Future<_i2.ProfileModel>.value(_FakeProfileModel_0( this, Invocation.method( #getMyProfile, [], ), )), - ) as _i5.Future<_i2.ProfileModel>); + ) as _i6.Future<_i2.ProfileModel>); @override - _i5.Future<_i2.ProfileDetailsModel> getMyProfileDetails() => + _i6.Future<_i2.ProfileDetailsModel> getMyProfileDetails() => (super.noSuchMethod( Invocation.method( #getMyProfileDetails, [], ), - returnValue: _i5.Future<_i2.ProfileDetailsModel>.value( + returnValue: _i6.Future<_i2.ProfileDetailsModel>.value( _FakeProfileDetailsModel_1( this, Invocation.method( @@ -131,7 +144,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { [], ), )), - returnValueForMissingStub: _i5.Future<_i2.ProfileDetailsModel>.value( + returnValueForMissingStub: _i6.Future<_i2.ProfileDetailsModel>.value( _FakeProfileDetailsModel_1( this, Invocation.method( @@ -139,10 +152,10 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { [], ), )), - ) as _i5.Future<_i2.ProfileDetailsModel>); + ) as _i6.Future<_i2.ProfileDetailsModel>); @override - _i5.Future<_i2.ProfileDetailsModel> getProfileDetailsBySlug( + _i6.Future<_i2.ProfileDetailsModel> getProfileDetailsBySlug( {required String? slug}) => (super.noSuchMethod( Invocation.method( @@ -150,7 +163,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { [], {#slug: slug}, ), - returnValue: _i5.Future<_i2.ProfileDetailsModel>.value( + returnValue: _i6.Future<_i2.ProfileDetailsModel>.value( _FakeProfileDetailsModel_1( this, Invocation.method( @@ -159,7 +172,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { {#slug: slug}, ), )), - returnValueForMissingStub: _i5.Future<_i2.ProfileDetailsModel>.value( + returnValueForMissingStub: _i6.Future<_i2.ProfileDetailsModel>.value( _FakeProfileDetailsModel_1( this, Invocation.method( @@ -168,10 +181,10 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { {#slug: slug}, ), )), - ) as _i5.Future<_i2.ProfileDetailsModel>); + ) as _i6.Future<_i2.ProfileDetailsModel>); @override - _i5.Future addCircumference({ + _i6.Future addCircumference({ required int? chestCircumference, required int? waistCircumference, required int? hipCircumference, @@ -186,23 +199,23 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { #hipCircumference: hipCircumference, }, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future addWeight({required double? weight}) => (super.noSuchMethod( + _i6.Future addWeight({required double? weight}) => (super.noSuchMethod( Invocation.method( #addWeight, [], {#weight: weight}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future> getBlogPostByAuthorSlug( + _i6.Future> getBlogPostByAuthorSlug( {required String? slug}) => (super.noSuchMethod( Invocation.method( @@ -210,15 +223,15 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { [], {#slug: slug}, ), - returnValue: _i5.Future>.value( - <_i6.FeedBlogPostModel>[]), + returnValue: _i6.Future>.value( + <_i7.FeedBlogPostModel>[]), returnValueForMissingStub: - _i5.Future>.value( - <_i6.FeedBlogPostModel>[]), - ) as _i5.Future>); + _i6.Future>.value( + <_i7.FeedBlogPostModel>[]), + ) as _i6.Future>); @override - _i5.Future> getWeight({required String? period}) => + _i6.Future> getWeight({required String? period}) => (super.noSuchMethod( Invocation.method( #getWeight, @@ -226,13 +239,13 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { {#period: period}, ), returnValue: - _i5.Future>.value(<_i7.WeightModel>[]), + _i6.Future>.value(<_i8.WeightModel>[]), returnValueForMissingStub: - _i5.Future>.value(<_i7.WeightModel>[]), - ) as _i5.Future>); + _i6.Future>.value(<_i8.WeightModel>[]), + ) as _i6.Future>); @override - _i5.Future> getWeightBySlug({ + _i6.Future> getWeightBySlug({ required String? period, required String? slug, }) => @@ -246,13 +259,13 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { }, ), returnValue: - _i5.Future>.value(<_i7.WeightModel>[]), + _i6.Future>.value(<_i8.WeightModel>[]), returnValueForMissingStub: - _i5.Future>.value(<_i7.WeightModel>[]), - ) as _i5.Future>); + _i6.Future>.value(<_i8.WeightModel>[]), + ) as _i6.Future>); @override - _i5.Future> getCircumferences( + _i6.Future> getCircumferences( {required String? period}) => (super.noSuchMethod( Invocation.method( @@ -260,15 +273,15 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { [], {#period: period}, ), - returnValue: _i5.Future>.value( - <_i8.CircumferenceModel>[]), + returnValue: _i6.Future>.value( + <_i9.CircumferenceModel>[]), returnValueForMissingStub: - _i5.Future>.value( - <_i8.CircumferenceModel>[]), - ) as _i5.Future>); + _i6.Future>.value( + <_i9.CircumferenceModel>[]), + ) as _i6.Future>); @override - _i5.Future> getCircumferencesBySlug({ + _i6.Future> getCircumferencesBySlug({ required String? period, required String? slug, }) => @@ -281,15 +294,15 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { #slug: slug, }, ), - returnValue: _i5.Future>.value( - <_i8.CircumferenceModel>[]), + returnValue: _i6.Future>.value( + <_i9.CircumferenceModel>[]), returnValueForMissingStub: - _i5.Future>.value( - <_i8.CircumferenceModel>[]), - ) as _i5.Future>); + _i6.Future>.value( + <_i9.CircumferenceModel>[]), + ) as _i6.Future>); @override - _i5.Future<_i3.SubPaginationModel> getSubscribers({ + _i6.Future<_i3.SubPaginationModel> getSubscribers({ required String? slug, String? query, }) => @@ -303,7 +316,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { }, ), returnValue: - _i5.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( + _i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( this, Invocation.method( #getSubscribers, @@ -315,7 +328,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { ), )), returnValueForMissingStub: - _i5.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( + _i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( this, Invocation.method( #getSubscribers, @@ -326,10 +339,10 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { }, ), )), - ) as _i5.Future<_i3.SubPaginationModel>); + ) as _i6.Future<_i3.SubPaginationModel>); @override - _i5.Future<_i3.SubPaginationModel> getSubscriptions({ + _i6.Future<_i3.SubPaginationModel> getSubscriptions({ required String? slug, String? query, }) => @@ -343,7 +356,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { }, ), returnValue: - _i5.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( + _i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( this, Invocation.method( #getSubscriptions, @@ -355,7 +368,7 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { ), )), returnValueForMissingStub: - _i5.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( + _i6.Future<_i3.SubPaginationModel>.value(_FakeSubPaginationModel_2( this, Invocation.method( #getSubscriptions, @@ -366,49 +379,75 @@ class MockProfileService extends _i1.Mock implements _i4.ProfileService { }, ), )), - ) as _i5.Future<_i3.SubPaginationModel>); + ) as _i6.Future<_i3.SubPaginationModel>); @override - _i5.Future subscribe({required String? slug}) => (super.noSuchMethod( + _i6.Future subscribe({required String? slug}) => (super.noSuchMethod( Invocation.method( #subscribe, [], {#slug: slug}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future unsubscribe({required String? slug}) => (super.noSuchMethod( + _i6.Future unsubscribe({required String? slug}) => (super.noSuchMethod( Invocation.method( #unsubscribe, [], {#slug: slug}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future uploadPhoto({required _i9.File? photo}) => + _i6.Future uploadPhoto({required _i10.File? photo}) => (super.noSuchMethod( Invocation.method( #uploadPhoto, [], {#photo: photo}, ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); @override - _i5.Future deletePhoto() => (super.noSuchMethod( + _i6.Future deletePhoto() => (super.noSuchMethod( Invocation.method( #deletePhoto, [], ), - returnValue: _i5.Future.value(), - returnValueForMissingStub: _i5.Future.value(), - ) as _i5.Future); + returnValue: _i6.Future.value(), + returnValueForMissingStub: _i6.Future.value(), + ) as _i6.Future); + + @override + _i6.Future<_i4.ChosenDietsPaginationModel> getChosenDiets() => + (super.noSuchMethod( + Invocation.method( + #getChosenDiets, + [], + ), + returnValue: _i6.Future<_i4.ChosenDietsPaginationModel>.value( + _FakeChosenDietsPaginationModel_3( + this, + Invocation.method( + #getChosenDiets, + [], + ), + )), + returnValueForMissingStub: + _i6.Future<_i4.ChosenDietsPaginationModel>.value( + _FakeChosenDietsPaginationModel_3( + this, + Invocation.method( + #getChosenDiets, + [], + ), + )), + ) as _i6.Future<_i4.ChosenDietsPaginationModel>); }