diff --git a/lib/core/app_router.dart b/lib/core/app_router.dart index 39daded4..bc76a766 100644 --- a/lib/core/app_router.dart +++ b/lib/core/app_router.dart @@ -22,6 +22,7 @@ import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart'; import 'package:eatvio_app/features/feed/models/recipes_model.dart'; import 'package:eatvio_app/features/feed/presentation/pages/feed_screen.dart'; +import 'package:eatvio_app/features/glossary/presentation/pages/glossary_screen.dart'; import 'package:eatvio_app/features/menu/presentation/pages/menu_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'; @@ -64,7 +65,17 @@ class AppRouter { } return null; }, - builder: (context, state) => AuthScreen.builder(context), + builder: (context, state) { + final bool needLogout; + if (state.extra == null) { + needLogout = false; + } else { + needLogout = true; + } + return AuthScreen( + needLogout: needLogout, + ); + }, routes: [ GoRoute( path: 'registration-screen', @@ -126,6 +137,11 @@ class AppRouter { ); }, ), + GoRoute( + path: '/glossary-screen', + name: '/glossaryScreen', + builder: (context, state) => GlossaryScreen(), + ), GoRoute( path: '/about-recipes-screen', name: 'aboutRecipesScreen', diff --git a/lib/core/const.dart b/lib/core/const.dart index 4e8b3650..dfeae1fc 100644 --- a/lib/core/const.dart +++ b/lib/core/const.dart @@ -1,5 +1,5 @@ -// String baseUrl = 'https://eatvio.ru'; -String baseUrl = 'https://dev2.eatvio.com'; +String baseUrl = 'https://eatvio.ru'; +// String baseUrl = 'https://dev2.eatvio.com'; const List durationValues = [7, 14, 21]; diff --git a/lib/core/credentials_storage.dart b/lib/core/credentials_storage.dart new file mode 100644 index 00000000..6cf97c90 --- /dev/null +++ b/lib/core/credentials_storage.dart @@ -0,0 +1,32 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +abstract class CredentialsStorage { + static Future haveCredentialsInStorage() async { + try { + if (await FlutterSecureStorage().read(key: 'email') == null || await FlutterSecureStorage().read(key: 'password') == null) { + return false; + } else { + return true; + } + } catch (e) { + return false; + } + } + + static Future> getCredentialsFromStorage() async { + return { + 'email': (await FlutterSecureStorage().read(key: 'email'))!, + 'password': (await FlutterSecureStorage().read(key: 'password'))!, + }; + } + + static saveCredentials(String email, String password) async { + await FlutterSecureStorage().write(key: 'email', value: email); + await FlutterSecureStorage().write(key: 'password', value: password); + } + + static removeCredentials() async { + await FlutterSecureStorage().delete(key: 'email'); + await FlutterSecureStorage().delete(key: 'password'); + } +} diff --git a/lib/core/locator_service.dart b/lib/core/locator_service.dart index e258d702..c0377a79 100644 --- a/lib/core/locator_service.dart +++ b/lib/core/locator_service.dart @@ -64,6 +64,7 @@ import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/se import 'package:eatvio_app/features/settings/repositories/service_repository.dart'; import 'package:eatvio_app/features/settings/services/settings_service.dart'; import 'package:eatvio_app/features/user_details/presentation/cubit/user_details_cubit.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:get_it/get_it.dart'; import 'package:eatvio_app/features/profile/presentation/bloc/plans_cubit/plans_cubit.dart' as profilePlans; @@ -155,4 +156,5 @@ Future init() async { ), ), ); + sl.registerLazySingleton(() async => await FlutterSecureStorage()); } diff --git a/lib/core/token_storage.dart b/lib/core/token_storage.dart index 4a8bb21d..9332ceb5 100644 --- a/lib/core/token_storage.dart +++ b/lib/core/token_storage.dart @@ -7,7 +7,7 @@ abstract class TokenStorage { sl().options.headers['Authorization'] = 'Bearer $token'; } - static haveTokenInStorage() async { + static Future haveTokenInStorage() async { try { if (await FlutterSecureStorage().read(key: 'token') == null) { return false; diff --git a/lib/features/auth/auth_screen/auth_screen.dart b/lib/features/auth/auth_screen/auth_screen.dart index 31169305..3fbc57e3 100644 --- a/lib/features/auth/auth_screen/auth_screen.dart +++ b/lib/features/auth/auth_screen/auth_screen.dart @@ -1,40 +1,22 @@ import 'dart:convert'; - -import 'package:dio/dio.dart'; import 'package:eatvio_app/core/const.dart'; +import 'package:eatvio_app/core/credentials_storage.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/token_storage.dart'; -import 'package:eatvio_app/core/utils/image_constant.dart'; -import 'package:eatvio_app/core/widgets/custom_text_form_field.dart'; +import 'package:eatvio_app/features/auth/const/strings.dart'; import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart'; -import 'package:eatvio_app/generated/l10n.dart'; -import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; -import 'package:url_launcher/url_launcher.dart'; -import 'package:validators/validators.dart'; import 'package:webview_flutter/webview_flutter.dart'; -import 'bloc/auth_bloc.dart'; -import 'models/auth_model.dart'; - class AuthScreen extends StatefulWidget { - static Widget builder(BuildContext context) { - return BlocProvider( - create: (context) => AuthBloc( - AuthState( - authModelObj: AuthModel(), - ), - )..add( - AuthInitialEvent(), - ), - child: AuthScreen(), - ); - } + final bool needLogout; + + const AuthScreen({ + this.needLogout = false, + }); @override State createState() => _AuthScreenState(); @@ -46,6 +28,16 @@ class _AuthScreenState extends State { final baseUrlController = TextEditingController(); late final WebViewController _controller; + String email = ''; + String password = ''; + + Future logout() async { + await CredentialsStorage.removeCredentials(); + await _controller.runJavaScript(''' + document.querySelector('.header-list__link button[type="submit"]').click(); + '''); + } + @override void initState() { super.initState(); @@ -55,42 +47,73 @@ class _AuthScreenState extends State { ..addJavaScriptChannel( 'FlutterChannel', onMessageReceived: (JavaScriptMessage message) { - // Handle messages from JavaScript final data = jsonDecode(message.message); - final email = data['email']; - final password = data['password']; - print('Email: $email, Password: $password'); + email = data['email']; + password = data['password']; }, ) ..setNavigationDelegate( NavigationDelegate( - onPageFinished: (String url) async { - await _controller.runJavaScript(''' - function initializeListeners() { - const emailInput = document.getElementById("inputEmail_main"); - const passwordInput = document.getElementById("inputPassword_main"); - - if (emailInput && passwordInput) { - function sendToFlutter() { - const email = emailInput.value; - const password = passwordInput.value; - const data = JSON.stringify({ email: email, password: password }); - if (window.FlutterChannel) { - window.FlutterChannel.postMessage(data); - } + onNavigationRequest: (NavigationRequest navigationRequest) async { + if (navigationRequest.url.contains('profile')) { + if (await CredentialsStorage.haveCredentialsInStorage()) { + email = (await CredentialsStorage.getCredentialsFromStorage())['email']!; + password = (await CredentialsStorage.getCredentialsFromStorage())['password']!; + } else { + if (email.isNotEmpty && password.isNotEmpty && !(await TokenStorage.haveTokenInStorage())) { + await CredentialsStorage.saveCredentials(email, password); + try { + final Map credentials = { + 'email': email, + 'password': password, + }; + final response = await http.post( + Uri.parse(baseUrl + '/api/login'), + headers: {'Content-Type': 'application/json'}, + body: json.encode(credentials), + encoding: utf8, + ); + var res = await jsonDecode(response.body); + final token = res['token']; + await TokenStorage.saveTokenInStorage(token); + GoRouter.of(context).go('/my-profile-screen'); + await sl().getMyProfile(); + } catch (e) { + print(e); } - - emailInput.addEventListener("input", sendToFlutter); - passwordInput.addEventListener("input", sendToFlutter); } else { - console.error("Email or Password input not found."); + await logout(); } } - - // Ensure DOM is loaded before attaching listeners - document.addEventListener("DOMContentLoaded", initializeListeners); - initializeListeners(); - '''); + } + return NavigationDecision.navigate; + }, + onPageStarted: (String url) async { + final bool tokenInStorage = await TokenStorage.haveTokenInStorage(); + final bool credentialsInStorage = await CredentialsStorage.haveCredentialsInStorage(); + if (tokenInStorage && credentialsInStorage) { + GoRouter.of(context).go('/my-profile-screen'); + } else if (!tokenInStorage && credentialsInStorage) { + final credentialsFromStorage = await CredentialsStorage.getCredentialsFromStorage(); + final Map credentials = { + 'email': credentialsFromStorage['email']!, + 'password': credentialsFromStorage['password']!, + }; + final response = await http.post( + Uri.parse(baseUrl + '/api/login'), + headers: {'Content-Type': 'application/json'}, + body: json.encode(credentials), + encoding: utf8, + ); + var res = await jsonDecode(response.body); + final token = res['token']; + await TokenStorage.saveTokenInStorage(token); + GoRouter.of(context).go('/my-profile-screen'); + await sl().getMyProfile(); + } + }, + onPageFinished: (String url) async { + await _controller.runJavaScript(jsChannelAuthScript); }, ), ) @@ -100,269 +123,13 @@ class _AuthScreenState extends State { @override Widget build(BuildContext context) { FlutterNativeSplash.remove(); - final s = S.of(context); - return Scaffold( appBar: AppBar( toolbarHeight: 0, ), - body: WebViewWidget(controller: _controller), - ); - - return Scaffold( - appBar: AppBar( - centerTitle: true, - title: GestureDetector( - onLongPress: () { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Base url без https:// и /api'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CustomTextFormField( - controller: baseUrlController, - hintText: 'dev2.eatvio.com', - ), - const SizedBox(height: 12), - InkWell( - onTap: () async { - baseUrl = 'https://${baseUrlController.text}'; - sl().options.baseUrl = baseUrl; - }, - borderRadius: BorderRadius.circular(20), - child: Ink( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: appTheme.blueA400, - ), - child: Container( - padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), - alignment: Alignment.center, - child: Text( - 'Сохранить', - style: TextStyle( - color: Colors.white, - fontWeight: FontWeight.w600, - ), - ), - ), - ), - ), - ], - ), - ), - ); - }, - child: SvgPicture.asset( - ImageConstant.imgLogoEatvio, - height: 48, - fit: BoxFit.contain, - ), - ), - ), body: SafeArea( - child: Padding( - padding: EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(s.email), - const SizedBox(height: 4), - BlocSelector( - selector: (state) => state.emailController, - builder: (context, emailController) { - return CustomTextFormField( - controller: emailController, - textInputAction: TextInputAction.next, - keyboardType: TextInputType.emailAddress, - textInputType: TextInputType.emailAddress, - hintText: 'Введите email', - ); - }, - ), - const SizedBox(height: 16), - Text(s.password), - const SizedBox(height: 4), - BlocSelector( - selector: (state) => state.passwordController, - builder: (context, passwordController) { - return CustomTextFormField( - obscureText: hidePassword, - controller: passwordController, - hintText: 'Введите пароль', - suffix: IconButton( - onPressed: () { - setState(() { - hidePassword = !hidePassword; - }); - }, - icon: Icon( - hidePassword ? Icons.visibility_outlined : Icons.visibility_off_outlined, - color: Colors.grey, - ), - ), - ); - }, - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('Нет аккаунта? '), - GestureDetector( - onTap: () => GoRouter.of(context).goNamed('registrationScreen'), - child: Text( - 'Зарегистрироваться', - style: TextStyle( - color: appTheme.blueA400, - decorationColor: appTheme.blueA400, - decoration: TextDecoration.underline, - ), - ), - ), - ], - ), - Spacer(), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Нажимая "Войти", Вы соглашаетесь с ', - style: TextStyle( - fontSize: 12, - ), - ), - GestureDetector( - onTap: () async { - await launchUrl(Uri.parse(baseUrl + '/oferta_bs.pdf')); - }, - child: Text( - 'Публичной офертой', - style: TextStyle( - fontSize: 12, - color: appTheme.blueA400, - decorationColor: appTheme.blueA400, - decoration: TextDecoration.underline, - ), - ), - ), - ], - ), - const SizedBox(height: 16), - BlocBuilder( - builder: (context, state) { - return Container( - height: 48, - width: MediaQuery.of(context).size.width - 32, - child: FloatingActionButton.extended( - heroTag: 'authButton', - highlightElevation: 0, - elevation: 0, - focusElevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - backgroundColor: appTheme.blueA400, - onPressed: onTapAuth(state, context), - label: Text( - 'Войти', - style: theme.textTheme.titleSmall!.copyWith(color: Colors.white), - ), - ), - ); - }, - ), - ], - ), - ), + child: WebViewWidget(controller: _controller), ), ); } - - onTapAuth(AuthState state, BuildContext context) { - final s = S.of(context); - return () async { - List errors = validateFields(state.emailController!.text, state.passwordController!.text); - if (errors.isEmpty) { - final Map credentials = { - 'email': state.emailController!.text, - 'password': state.passwordController!.text, - }; - final response = await http.post( - Uri.parse(baseUrl + '/api/login'), - headers: {'Content-Type': 'application/json'}, - body: json.encode(credentials), - encoding: utf8, - ); - - if (response.statusCode == 200) { - var res = await jsonDecode(response.body); - final token = res['token']; - await TokenStorage.saveTokenInStorage(token); - GoRouter.of(context).go('/my-profile-screen'); - sl().getMyProfile(); - } else { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(s.wrong_credentials), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text('OK'), - ), - ], - ), - ); - } - } else { - String errorMessage = ''; - - for (var error in errors) { - errorMessage += error + '\n\n'; - } - - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text('Ошибка'), - content: Text(errorMessage), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context), - child: Text('OK'), - ), - ], - ), - ); - } - }; - } - - List validateFields(String email, String password) { - final s = S.of(context); - - List errors = []; - - if (!isEmail(email)) { - errors.add(s.email_invalid); - } - - if (email.isEmpty) { - errors.add(s.email_empty); - } - - if (password.isEmpty) { - errors.add(s.password_empty); - } - - if (password.length < 6) { - errors.add(s.password_short); - } - - return errors; - } } diff --git a/lib/features/auth/auth_screen/bloc/auth_bloc.dart b/lib/features/auth/auth_screen/bloc/auth_bloc.dart deleted file mode 100644 index f2df813c..00000000 --- a/lib/features/auth/auth_screen/bloc/auth_bloc.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:eatvio_app/features/auth/auth_screen/models/auth_model.dart'; -import 'package:equatable/equatable.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -part 'auth_event.dart'; -part 'auth_state.dart'; - -/// A bloc that manages the state of a Auth according to the event that is dispatched to it. -class AuthBloc extends Bloc { - AuthBloc(AuthState initialState) : super(initialState) { - on(_onInitialize); - } - - _onInitialize( - AuthInitialEvent event, - Emitter emit, - ) async { - emit( - state.copyWith( - emailController: TextEditingController(), - passwordController: TextEditingController(), - ), - ); - } -} diff --git a/lib/features/auth/auth_screen/bloc/auth_event.dart b/lib/features/auth/auth_screen/bloc/auth_event.dart deleted file mode 100644 index a395a45b..00000000 --- a/lib/features/auth/auth_screen/bloc/auth_event.dart +++ /dev/null @@ -1,16 +0,0 @@ -// ignore_for_file: must_be_immutable - -part of 'auth_bloc.dart'; - -/// Abstract class for all events that can be dispatched from the -///Credentials widget. -/// -/// Events must be immutable and implement the [Equatable] interface. -@immutable -abstract class AuthEvent extends Equatable {} - -/// Event that is dispatched when the Credentials widget is first created. -class AuthInitialEvent extends AuthEvent { - @override - List get props => []; -} diff --git a/lib/features/auth/auth_screen/bloc/auth_state.dart b/lib/features/auth/auth_screen/bloc/auth_state.dart deleted file mode 100644 index 86e8e3b0..00000000 --- a/lib/features/auth/auth_screen/bloc/auth_state.dart +++ /dev/null @@ -1,37 +0,0 @@ -// ignore_for_file: must_be_immutable - -part of 'auth_bloc.dart'; - -/// Represents the state of Auth in the application. -class AuthState extends Equatable { - AuthState({ - this.emailController, - this.passwordController, - this.authModelObj, - }); - - TextEditingController? emailController; - - TextEditingController? passwordController; - - AuthModel? authModelObj; - - @override - List get props => [ - emailController, - passwordController, - authModelObj, - ]; - - AuthState copyWith({ - TextEditingController? emailController, - TextEditingController? passwordController, - AuthModel? authModelObj, - }) { - return AuthState( - emailController: emailController ?? this.emailController, - passwordController: passwordController ?? this.passwordController, - authModelObj: authModelObj ?? this.authModelObj, - ); - } -} diff --git a/lib/features/auth/auth_screen/models/auth_model.dart b/lib/features/auth/auth_screen/models/auth_model.dart deleted file mode 100644 index 829b38c8..00000000 --- a/lib/features/auth/auth_screen/models/auth_model.dart +++ /dev/null @@ -1,16 +0,0 @@ -// ignore_for_file: must_be_immutable - -import 'package:equatable/equatable.dart'; - -/// This class defines the variables used in the [auth_screen], -/// and is typically used to hold data that is passed between different parts of the application. -class AuthModel extends Equatable { - AuthModel(); - - AuthModel copyWith() { - return AuthModel(); - } - - @override - List get props => []; -} diff --git a/lib/features/auth/const/strings.dart b/lib/features/auth/const/strings.dart new file mode 100644 index 00000000..66d05c4d --- /dev/null +++ b/lib/features/auth/const/strings.dart @@ -0,0 +1,22 @@ +const String jsChannelAuthScript = ''' + function initializeListeners() { + const emailInput = document.getElementById("inputEmail_main"); + const passwordInput = document.getElementById("inputPassword_main"); + if (emailInput && passwordInput) { + function sendToFlutter() { + const email = emailInput.value; + const password = passwordInput.value; + const data = JSON.stringify({ email: email, password: password }); + if (window.FlutterChannel) { + window.FlutterChannel.postMessage(data); + } + } + emailInput.addEventListener("input", sendToFlutter); + passwordInput.addEventListener("input", sendToFlutter); + } else { + console.error("Email or Password input not found."); + } + } + document.addEventListener("DOMContentLoaded", initializeListeners); + initializeListeners(); + '''; diff --git a/lib/features/blog_post_create/services/blog_post_service.g.dart b/lib/features/blog_post_create/services/blog_post_service.g.dart index 33f4251a..1f338526 100644 --- a/lib/features/blog_post_create/services/blog_post_service.g.dart +++ b/lib/features/blog_post_create/services/blog_post_service.g.dart @@ -9,11 +9,7 @@ part of 'blog_post_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _BlogPostService implements BlogPostService { - _BlogPostService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _BlogPostService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -27,23 +23,21 @@ class _BlogPostService implements BlogPostService { final queryParameters = {}; final _headers = {}; final _data = formData; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - contentType: 'multipart/form-data', - ) - .compose( - _dio.options, - '/api/blogPosts/create', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options( + method: 'POST', + headers: _headers, + extra: _extra, + contentType: 'multipart/form-data', + ) + .compose( + _dio.options, + '/api/blogPosts/create', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -56,23 +50,21 @@ class _BlogPostService implements BlogPostService { final queryParameters = {}; final _headers = {}; final _data = formData; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - contentType: 'multipart/form-data', - ) - .compose( - _dio.options, - '/api/blogPosts/update/${id}', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options( + method: 'POST', + headers: _headers, + extra: _extra, + contentType: 'multipart/form-data', + ) + .compose( + _dio.options, + '/api/blogPosts/update/${id}', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -82,22 +74,16 @@ class _BlogPostService implements BlogPostService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/blogPosts/delete/${id}', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/blogPosts/delete/${id}', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -114,10 +100,7 @@ class _BlogPostService implements BlogPostService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/calendar/services/calendar_service.g.dart b/lib/features/calendar/services/calendar_service.g.dart index 787983c8..5055d002 100644 --- a/lib/features/calendar/services/calendar_service.g.dart +++ b/lib/features/calendar/services/calendar_service.g.dart @@ -9,11 +9,7 @@ part of 'calendar_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _CalendarService implements CalendarService { - _CalendarService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _CalendarService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -27,27 +23,23 @@ class _CalendarService implements CalendarService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType>(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/calendar/index', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/calendar/index', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late List _value; try { _value = _result.data! - .map((dynamic i) => CalendarModel.fromJson(i as Map)) + .map( + (dynamic i) => CalendarModel.fromJson(i as Map), + ) .toList(); } on Object catch (e, s) { errorLogger?.logError(e, s, _options); @@ -69,10 +61,7 @@ class _CalendarService implements CalendarService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/consultant/become_consultant/services/consultant_service.g.dart b/lib/features/consultant/become_consultant/services/consultant_service.g.dart index d895b861..79dd924e 100644 --- a/lib/features/consultant/become_consultant/services/consultant_service.g.dart +++ b/lib/features/consultant/become_consultant/services/consultant_service.g.dart @@ -9,11 +9,7 @@ part of 'consultant_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _ConsultantService implements ConsultantService { - _ConsultantService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _ConsultantService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -22,28 +18,23 @@ class _ConsultantService implements ConsultantService { final ParseErrorLogger? errorLogger; @override - Future consultantRegistration( - {required ConsultantProfileModel consultantModel}) async { + Future consultantRegistration({ + required ConsultantProfileModel consultantModel, + }) async { final _extra = {}; final queryParameters = {}; final _headers = {}; final _data = consultantModel; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/consultant_request/registration', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/consultant_request/registration', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -57,23 +48,21 @@ class _ConsultantService implements ConsultantService { if (photos != null) { _data.files.addAll(photos.map((i) => MapEntry('photos[]', i))); } - final _options = _setStreamType>(Options( - method: 'POST', - headers: _headers, - extra: _extra, - contentType: 'multipart/form-data', - ) - .compose( - _dio.options, - '/api/consultant_request/photos/upload', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType>( + Options( + method: 'POST', + headers: _headers, + extra: _extra, + contentType: 'multipart/form-data', + ) + .compose( + _dio.options, + '/api/consultant_request/photos/upload', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late List _value; try { @@ -98,10 +87,7 @@ class _ConsultantService implements ConsultantService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/create_diet/services/create_diet_service.g.dart b/lib/features/create_diet/services/create_diet_service.g.dart index 0c5a4606..84a8c9a1 100644 --- a/lib/features/create_diet/services/create_diet_service.g.dart +++ b/lib/features/create_diet/services/create_diet_service.g.dart @@ -9,11 +9,7 @@ part of 'create_diet_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _CreateDietService implements CreateDietService { - _CreateDietService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _CreateDietService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -39,81 +35,57 @@ class _CreateDietService implements CreateDietService { final _headers = {}; final _data = FormData(); if (name != null) { - _data.fields.add(MapEntry( - 'name', - name, - )); + _data.fields.add(MapEntry('name', name)); } if (duration != null) { - _data.fields.add(MapEntry( - 'duration', - duration.toString(), - )); + _data.fields.add(MapEntry('duration', duration.toString())); } if (state != null) { - _data.fields.add(MapEntry( - 'state', - state, - )); + _data.fields.add(MapEntry('state', state)); } if (meatType != null) { - _data.fields.add(MapEntry( - 'type[meat]', - meatType, - )); + _data.fields.add(MapEntry('type[meat]', meatType)); } if (carbType != null) { - _data.fields.add(MapEntry( - 'type[carb]', - carbType, - )); + _data.fields.add(MapEntry('type[carb]', carbType)); } if (vegType != null) { - _data.fields.add(MapEntry( - 'type[veg]', - vegType, - )); + _data.fields.add(MapEntry('type[veg]', vegType)); } if (lightType != null) { - _data.fields.add(MapEntry( - 'type[light]', - lightType, - )); + _data.fields.add(MapEntry('type[light]', lightType)); } if (details != null) { - _data.fields.add(MapEntry( - 'details', - details, - )); + _data.fields.add(MapEntry('details', details)); } if (image != null) { if (image != null) { - _data.files.add(MapEntry( - 'image', - MultipartFile.fromFileSync( - image.path, - filename: image.path.split(Platform.pathSeparator).last, + _data.files.add( + MapEntry( + 'image', + MultipartFile.fromFileSync( + image.path, + filename: image.path.split(Platform.pathSeparator).last, + ), ), - )); + ); } } - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - contentType: 'multipart/form-data', - ) - .compose( - _dio.options, - '/api/diets/create', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options( + method: 'POST', + headers: _headers, + extra: _extra, + contentType: 'multipart/form-data', + ) + .compose( + _dio.options, + '/api/diets/create', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late CreatedDiet _value; try { @@ -135,22 +107,16 @@ class _CreateDietService implements CreateDietService { final _headers = {}; final _data = {}; _data.addAll(model); - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diets/create/${id}/daily_schedule', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diets/create/${id}/daily_schedule', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -167,10 +133,7 @@ class _CreateDietService implements CreateDietService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/create_plan/services/create_plan_service.g.dart b/lib/features/create_plan/services/create_plan_service.g.dart index af44f549..c93251e7 100644 --- a/lib/features/create_plan/services/create_plan_service.g.dart +++ b/lib/features/create_plan/services/create_plan_service.g.dart @@ -9,11 +9,7 @@ part of 'create_plan_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _CreatePlanService implements CreatePlanService { - _CreatePlanService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _CreatePlanService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -28,23 +24,21 @@ class _CreatePlanService implements CreatePlanService { final _headers = {}; final _data = {}; _data.addAll(model); - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - contentType: 'multipart/form-data', - ) - .compose( - _dio.options, - '/api/plans/create', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options( + method: 'POST', + headers: _headers, + extra: _extra, + contentType: 'multipart/form-data', + ) + .compose( + _dio.options, + '/api/plans/create', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -58,22 +52,16 @@ class _CreatePlanService implements CreatePlanService { final _headers = {}; final _data = {}; _data.addAll(model); - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/plans/create/${slug}/packet_option', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/plans/create/${slug}/packet_option', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -87,22 +75,16 @@ class _CreatePlanService implements CreatePlanService { final _headers = {}; final _data = {}; _data.addAll(model); - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/plans/create/${slug}/packet_options', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/plans/create/${slug}/packet_options', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -119,10 +101,7 @@ class _CreatePlanService implements CreatePlanService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/diary/services/diary_service.g.dart b/lib/features/diary/services/diary_service.g.dart index 4544f6bf..c7b3820f 100644 --- a/lib/features/diary/services/diary_service.g.dart +++ b/lib/features/diary/services/diary_service.g.dart @@ -9,11 +9,7 @@ part of 'diary_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _DiaryService implements DiaryService { - _DiaryService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _DiaryService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -22,33 +18,30 @@ class _DiaryService implements DiaryService { final ParseErrorLogger? errorLogger; @override - Future> getDiaryIndexByDate( - {required String date}) async { + Future> getDiaryIndexByDate({ + required String date, + }) 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/diary/index/${date}', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/index/${date}', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late List _value; try { _value = _result.data! - .map((dynamic i) => DiaryDayModel.fromJson(i as Map)) + .map( + (dynamic i) => DiaryDayModel.fromJson(i as Map), + ) .toList(); } on Object catch (e, s) { errorLogger?.logError(e, s, _options); @@ -63,22 +56,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/show', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/show', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late DiaryDayWrapperModel _value; try { @@ -96,22 +83,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/dailyNutritionData', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/dailyNutritionData', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late NutritionDataModel _value; try { @@ -133,30 +114,30 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; final _data = FormData(); - _data.files.add(MapEntry( - 'photo', - MultipartFile.fromFileSync( - photo.path, - filename: photo.path.split(Platform.pathSeparator).last, + _data.files.add( + MapEntry( + 'photo', + MultipartFile.fromFileSync( + photo.path, + filename: photo.path.split(Platform.pathSeparator).last, + ), ), - )); - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - contentType: 'multipart/form-data', - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/photo/upload', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + ); + final _options = _setStreamType( + Options( + method: 'POST', + headers: _headers, + extra: _extra, + contentType: 'multipart/form-data', + ) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/photo/upload', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -170,22 +151,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'DELETE', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diaryId}/meals/${typeNo}/photo/${userAttachment}/delete', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'DELETE', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diaryId}/meals/${typeNo}/photo/${userAttachment}/delete', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -203,40 +178,27 @@ class _DiaryService implements DiaryService { queryParameters.removeWhere((k, v) => v == null); final _headers = {}; final _data = FormData(); - _data.fields.add(MapEntry( - 'product_name', - productName, - )); - _data.fields.add(MapEntry( - 'portion', - portion, - )); - _data.fields.add(MapEntry( - 'quantity', - quantity.toString(), - )); + _data.fields.add(MapEntry('product_name', productName)); + _data.fields.add(MapEntry('portion', portion)); + _data.fields.add(MapEntry('quantity', quantity.toString())); if (productNutritionalValueId != null) { - _data.fields.add(MapEntry( - 'product_nutritional_value_id', - productNutritionalValueId.toString(), - )); + _data.fields.add( + MapEntry( + 'product_nutritional_value_id', + productNutritionalValueId.toString(), + ), + ); } - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/portion/create', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/portion/create', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -252,22 +214,16 @@ class _DiaryService implements DiaryService { final _headers = {}; final _data = {}; _data.addAll(productInMeal); - final _options = _setStreamType(Options( - method: 'PUT', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/update', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'PUT', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/update', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -281,22 +237,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/${portionModel}/mark_eaten', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/${portionModel}/mark_eaten', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -310,22 +260,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/${portionModel}/unmark_eaten', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/${portionModel}/unmark_eaten', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -339,22 +283,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/restore', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/restore', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -368,22 +306,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'DELETE', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/delete', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'DELETE', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/portions/${portionModel}/delete', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -396,22 +328,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; final _data = finishDiaryDayModel; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/finishDay', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/finishDay', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -425,22 +351,16 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; final _data = {'satiety': satiety}; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/satiety/fill', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/satiety/fill', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @@ -454,49 +374,38 @@ class _DiaryService implements DiaryService { final queryParameters = {}; final _headers = {}; final _data = {'time': time}; - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/${diary}/meals/${typeNo}/time/fill', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/${diary}/meals/${typeNo}/time/fill', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); await _dio.fetch(_options); } @override - Future sendProductToModeration( - {required Map data}) async { + Future sendProductToModeration({ + required Map data, + }) async { final _extra = {}; final queryParameters = {}; final _headers = {}; final _data = {}; _data.addAll(data); - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/product_nutritional_values/sendToModeration', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/product_nutritional_values/sendToModeration', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late GlossaryModerationModel _value; try { @@ -521,10 +430,7 @@ class _DiaryService implements DiaryService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/feed/presentation/pages/feed_screen.dart b/lib/features/feed/presentation/pages/feed_screen.dart index 0dbe0b31..56252d0d 100644 --- a/lib/features/feed/presentation/pages/feed_screen.dart +++ b/lib/features/feed/presentation/pages/feed_screen.dart @@ -260,10 +260,10 @@ class _FeedScreenContentState extends State { onTap: () => GoRouter.of(context).pushNamed(RecipeCreateScreen.name), ), 2 => AddItemButton( - onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreateDietScreen.name) : null, + onTap: state.profile!.roles.contains('consultant') ? () => GoRouter.of(context).pushNamed(CreateDietScreen.name) : null, ), 3 => AddItemButton( - onTap: state.profile?.role == 'consultant' ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null, + onTap: state.profile!.roles.contains('consultant') ? () => GoRouter.of(context).pushNamed(CreatePlanScreen.name) : null, ), _ => AddItemButton() }, diff --git a/lib/features/glossary/presentation/pages/glossary_screen.dart b/lib/features/glossary/presentation/pages/glossary_screen.dart new file mode 100644 index 00000000..97d59810 --- /dev/null +++ b/lib/features/glossary/presentation/pages/glossary_screen.dart @@ -0,0 +1,33 @@ +import 'package:eatvio_app/core/const.dart'; +import 'package:flutter/material.dart'; +import 'package:webview_flutter/webview_flutter.dart'; + +class GlossaryScreen extends StatefulWidget { + const GlossaryScreen({super.key}); + + @override + State createState() => _GlossaryScreenState(); +} + +class _GlossaryScreenState extends State { + late final WebViewController _controller; + + @override + void initState() { + super.initState(); + + _controller = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..loadRequest(Uri.parse(baseUrl + '/product_nutritional_value')); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Глоссарий'), + ), + body: WebViewWidget(controller: _controller), + ); + } +} diff --git a/lib/features/glossary/services/glossary_service.g.dart b/lib/features/glossary/services/glossary_service.g.dart index bd3a1137..cd6584f6 100644 --- a/lib/features/glossary/services/glossary_service.g.dart +++ b/lib/features/glossary/services/glossary_service.g.dart @@ -9,11 +9,7 @@ part of 'glossary_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _GlossaryService implements GlossaryService { - _GlossaryService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _GlossaryService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -22,28 +18,23 @@ class _GlossaryService implements GlossaryService { final ParseErrorLogger? errorLogger; @override - Future getGlossaryByQuery( - {required String query}) async { + Future getGlossaryByQuery({ + required String query, + }) async { final _extra = {}; final queryParameters = {r'search': query}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/glossaries/search', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/glossaries/search', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late GlossaryPaginationModel _value; try { @@ -68,10 +59,7 @@ class _GlossaryService implements GlossaryService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/menu/presentation/pages/menu_screen.dart b/lib/features/menu/presentation/pages/menu_screen.dart index a1102186..cfc2e8a1 100644 --- a/lib/features/menu/presentation/pages/menu_screen.dart +++ b/lib/features/menu/presentation/pages/menu_screen.dart @@ -127,7 +127,7 @@ class MenuScreen extends StatelessWidget { } catch (e) { } finally { await TokenStorage.removeTokenInStorage(); - GoRouter.of(context).go('/auth-screen'); + GoRouter.of(context).go('/auth-screen', extra: true); } }; } diff --git a/lib/features/profile/models/profile_model.dart b/lib/features/profile/models/profile_model.dart index b6debe84..93c61635 100644 --- a/lib/features/profile/models/profile_model.dart +++ b/lib/features/profile/models/profile_model.dart @@ -18,7 +18,7 @@ class ProfileModel with _$ProfileModel { @JsonKey(name: 'is_entity_subscribed_by_me') required bool isEntitySubscribedByMe, @JsonKey(name: "slug") required String slug, @JsonKey(name: "profile_photo_url") required String profilePhotoUrl, - @JsonKey(name: "role") required String role, + @JsonKey(name: "roles") required List roles, @JsonKey(name: "badges") required List badges, @JsonKey(name: "subscriptions") required List subscriptions, @JsonKey(name: "subscribers") required List subscribers, diff --git a/lib/features/profile/models/profile_model.freezed.dart b/lib/features/profile/models/profile_model.freezed.dart index c46e1027..0f3eee2c 100644 --- a/lib/features/profile/models/profile_model.freezed.dart +++ b/lib/features/profile/models/profile_model.freezed.dart @@ -42,8 +42,8 @@ mixin _$ProfileModel { String get slug => throw _privateConstructorUsedError; @JsonKey(name: "profile_photo_url") String get profilePhotoUrl => throw _privateConstructorUsedError; - @JsonKey(name: "role") - String get role => throw _privateConstructorUsedError; + @JsonKey(name: "roles") + List get roles => throw _privateConstructorUsedError; @JsonKey(name: "badges") List get badges => throw _privateConstructorUsedError; @JsonKey(name: "subscriptions") @@ -86,7 +86,7 @@ abstract class $ProfileModelCopyWith<$Res> { @JsonKey(name: 'is_entity_subscribed_by_me') bool isEntitySubscribedByMe, @JsonKey(name: "slug") String slug, @JsonKey(name: "profile_photo_url") String profilePhotoUrl, - @JsonKey(name: "role") String role, + @JsonKey(name: "roles") List roles, @JsonKey(name: "badges") List badges, @JsonKey(name: "subscriptions") List subscriptions, @JsonKey(name: "subscribers") List subscribers, @@ -123,7 +123,7 @@ class _$ProfileModelCopyWithImpl<$Res, $Val extends ProfileModel> Object? isEntitySubscribedByMe = null, Object? slug = null, Object? profilePhotoUrl = null, - Object? role = null, + Object? roles = null, Object? badges = null, Object? subscriptions = null, Object? subscribers = null, @@ -175,10 +175,10 @@ class _$ProfileModelCopyWithImpl<$Res, $Val extends ProfileModel> ? _value.profilePhotoUrl : profilePhotoUrl // ignore: cast_nullable_to_non_nullable as String, - role: null == role - ? _value.role - : role // ignore: cast_nullable_to_non_nullable - as String, + roles: null == roles + ? _value.roles + : roles // ignore: cast_nullable_to_non_nullable + as List, badges: null == badges ? _value.badges : badges // ignore: cast_nullable_to_non_nullable @@ -237,7 +237,7 @@ abstract class _$$ProfileModelImplCopyWith<$Res> @JsonKey(name: 'is_entity_subscribed_by_me') bool isEntitySubscribedByMe, @JsonKey(name: "slug") String slug, @JsonKey(name: "profile_photo_url") String profilePhotoUrl, - @JsonKey(name: "role") String role, + @JsonKey(name: "roles") List roles, @JsonKey(name: "badges") List badges, @JsonKey(name: "subscriptions") List subscriptions, @JsonKey(name: "subscribers") List subscribers, @@ -273,7 +273,7 @@ class __$$ProfileModelImplCopyWithImpl<$Res> Object? isEntitySubscribedByMe = null, Object? slug = null, Object? profilePhotoUrl = null, - Object? role = null, + Object? roles = null, Object? badges = null, Object? subscriptions = null, Object? subscribers = null, @@ -325,10 +325,10 @@ class __$$ProfileModelImplCopyWithImpl<$Res> ? _value.profilePhotoUrl : profilePhotoUrl // ignore: cast_nullable_to_non_nullable as String, - role: null == role - ? _value.role - : role // ignore: cast_nullable_to_non_nullable - as String, + roles: null == roles + ? _value._roles + : roles // ignore: cast_nullable_to_non_nullable + as List, badges: null == badges ? _value._badges : badges // ignore: cast_nullable_to_non_nullable @@ -369,7 +369,7 @@ class _$ProfileModelImpl implements _ProfileModel { required this.isEntitySubscribedByMe, @JsonKey(name: "slug") required this.slug, @JsonKey(name: "profile_photo_url") required this.profilePhotoUrl, - @JsonKey(name: "role") required this.role, + @JsonKey(name: "roles") required final List roles, @JsonKey(name: "badges") required final List badges, @JsonKey(name: "subscriptions") required final List subscriptions, @@ -378,7 +378,8 @@ class _$ProfileModelImpl implements _ProfileModel { @JsonKey(name: "education_resource") this.educationResource, @JsonKey(name: "cert_photos") final List? diplomasAndCertificates}) - : _badges = badges, + : _roles = roles, + _badges = badges, _subscriptions = subscriptions, _subscribers = subscribers, _diplomasAndCertificates = diplomasAndCertificates; @@ -419,9 +420,15 @@ class _$ProfileModelImpl implements _ProfileModel { @override @JsonKey(name: "profile_photo_url") final String profilePhotoUrl; + final List _roles; @override - @JsonKey(name: "role") - final String role; + @JsonKey(name: "roles") + List get roles { + if (_roles is EqualUnmodifiableListView) return _roles; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_roles); + } + final List _badges; @override @JsonKey(name: "badges") @@ -466,7 +473,7 @@ class _$ProfileModelImpl implements _ProfileModel { @override String toString() { - return 'ProfileModel(id: $id, name: $name, email: $email, ratingPlace: $ratingPlace, emailVerifiedAt: $emailVerifiedAt, createdAt: $createdAt, updatedAt: $updatedAt, isPublicProfile: $isPublicProfile, isEntitySubscribedByMe: $isEntitySubscribedByMe, slug: $slug, profilePhotoUrl: $profilePhotoUrl, role: $role, badges: $badges, subscriptions: $subscriptions, subscribers: $subscribers, educationResource: $educationResource, diplomasAndCertificates: $diplomasAndCertificates)'; + return 'ProfileModel(id: $id, name: $name, email: $email, ratingPlace: $ratingPlace, emailVerifiedAt: $emailVerifiedAt, createdAt: $createdAt, updatedAt: $updatedAt, isPublicProfile: $isPublicProfile, isEntitySubscribedByMe: $isEntitySubscribedByMe, slug: $slug, profilePhotoUrl: $profilePhotoUrl, roles: $roles, badges: $badges, subscriptions: $subscriptions, subscribers: $subscribers, educationResource: $educationResource, diplomasAndCertificates: $diplomasAndCertificates)'; } @override @@ -492,7 +499,7 @@ class _$ProfileModelImpl implements _ProfileModel { (identical(other.slug, slug) || other.slug == slug) && (identical(other.profilePhotoUrl, profilePhotoUrl) || other.profilePhotoUrl == profilePhotoUrl) && - (identical(other.role, role) || other.role == role) && + const DeepCollectionEquality().equals(other._roles, _roles) && const DeepCollectionEquality().equals(other._badges, _badges) && const DeepCollectionEquality() .equals(other._subscriptions, _subscriptions) && @@ -519,7 +526,7 @@ class _$ProfileModelImpl implements _ProfileModel { isEntitySubscribedByMe, slug, profilePhotoUrl, - role, + const DeepCollectionEquality().hash(_roles), const DeepCollectionEquality().hash(_badges), const DeepCollectionEquality().hash(_subscriptions), const DeepCollectionEquality().hash(_subscribers), @@ -556,7 +563,7 @@ abstract class _ProfileModel implements ProfileModel { required final bool isEntitySubscribedByMe, @JsonKey(name: "slug") required final String slug, @JsonKey(name: "profile_photo_url") required final String profilePhotoUrl, - @JsonKey(name: "role") required final String role, + @JsonKey(name: "roles") required final List roles, @JsonKey(name: "badges") required final List badges, @JsonKey(name: "subscriptions") required final List subscriptions, @@ -605,8 +612,8 @@ abstract class _ProfileModel implements ProfileModel { @JsonKey(name: "profile_photo_url") String get profilePhotoUrl; @override - @JsonKey(name: "role") - String get role; + @JsonKey(name: "roles") + List get roles; @override @JsonKey(name: "badges") List get badges; diff --git a/lib/features/profile/models/profile_model.g.dart b/lib/features/profile/models/profile_model.g.dart index c7d0d444..e07e74c6 100644 --- a/lib/features/profile/models/profile_model.g.dart +++ b/lib/features/profile/models/profile_model.g.dart @@ -25,7 +25,7 @@ _$ProfileModelImpl _$$ProfileModelImplFromJson(Map json) => isEntitySubscribedByMe: json['is_entity_subscribed_by_me'] as bool, slug: json['slug'] as String, profilePhotoUrl: json['profile_photo_url'] as String, - role: json['role'] as String, + roles: (json['roles'] as List).map((e) => e as String).toList(), badges: (json['badges'] as List) .map((e) => BadgeModel.fromJson(e as Map)) .toList(), @@ -58,7 +58,7 @@ Map _$$ProfileModelImplToJson(_$ProfileModelImpl instance) => 'is_entity_subscribed_by_me': instance.isEntitySubscribedByMe, 'slug': instance.slug, 'profile_photo_url': instance.profilePhotoUrl, - 'role': instance.role, + 'roles': instance.roles, 'badges': instance.badges, 'subscriptions': instance.subscriptions, 'subscribers': instance.subscribers, diff --git a/lib/features/profile/presentation/pages/profile_screen.dart b/lib/features/profile/presentation/pages/profile_screen.dart index 788a5f3f..64d4fa41 100644 --- a/lib/features/profile/presentation/pages/profile_screen.dart +++ b/lib/features/profile/presentation/pages/profile_screen.dart @@ -81,7 +81,7 @@ class _ProfileScreenState extends State { } if (isFirstFetch) { canSub = !state.profile.isEntitySubscribedByMe; - if (state.profile.role == 'consultant') { + if (state.profile.roles.contains('consultant')) { plansCubit..getPlans(state.profile.slug); } isFirstFetch = false; @@ -127,7 +127,7 @@ class _ProfileScreenState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ _header(state), - if (state.profile.role == 'consultant') + if (state.profile.roles.contains('consultant')) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -192,10 +192,10 @@ class _ProfileScreenState extends State { ), _subscriptionsAndSubscribers(state), if (state.profile.badges.isNotEmpty) Padding(padding: EdgeInsets.only(bottom: 16), child: _badges(state)), - if (state.profile.role == 'consultant') _socialLinks(state), - if (state.profile.role == 'consultant') _education(state), - if (state.profile.role == 'consultant') _diplomasAndCertificates(state), - if (state.profile.role == 'consultant') _activePlans(state), + if (state.profile.roles.contains('consultant')) _socialLinks(state), + if (state.profile.roles.contains('consultant')) _education(state), + if (state.profile.roles.contains('consultant')) _diplomasAndCertificates(state), + if (state.profile.roles.contains('consultant')) _activePlans(state), _blogPosts(state), ], ), @@ -228,11 +228,11 @@ class _ProfileScreenState extends State { ), _subscriptionsAndSubscribers(state), if (state.profile.badges.isNotEmpty) Padding(padding: EdgeInsets.only(bottom: 16), child: _badges(state)), - if (state.profile.role == 'consultant') _socialLinks(state), - if (state.profile.role == 'consultant') _education(state), - if (state.profile.role == 'consultant') _diplomasAndCertificates(state), + if (state.profile.roles.contains('consultant')) _socialLinks(state), + if (state.profile.roles.contains('consultant')) _education(state), + if (state.profile.roles.contains('consultant')) _diplomasAndCertificates(state), Padding(padding: EdgeInsets.only(bottom: 16), child: _charts()), - if (state.profile.role == 'consultant') _activePlans(state), + if (state.profile.roles.contains('consultant')) _activePlans(state), _newBlogPostButton(), _blogPosts(state), ], @@ -242,7 +242,7 @@ class _ProfileScreenState extends State { } _activePlans(ProfileStateLoaded state) { - if (state.profile.role != 'consultant') { + if (state.profile.roles.contains('consultant')) { return const SizedBox.shrink(); } return BlocBuilder( @@ -372,7 +372,7 @@ class _ProfileScreenState extends State { } _diplomasAndCertificates(ProfileStateLoaded state) { - if (state.profile.role != 'consultant' || state.profile.diplomasAndCertificates == null || state.profile.diplomasAndCertificates!.isEmpty) { + if (state.profile.roles.contains('consultant') || state.profile.diplomasAndCertificates == null || state.profile.diplomasAndCertificates!.isEmpty) { return const SizedBox.shrink(); } return Padding( @@ -456,7 +456,7 @@ class _ProfileScreenState extends State { } _education(ProfileStateLoaded state) { - if (state.profile.role != 'consultant' || + if (state.profile.roles.contains('consultant') || state.profile.educationResource?.completedCourses == null || state.profile.educationResource?.completedCourses?.length == 0) { return const SizedBox.shrink(); @@ -549,7 +549,7 @@ class _ProfileScreenState extends State { } _socialLinks(ProfileStateLoaded state) { - if (state.profile.role != 'consultant') { + if (state.profile.roles.contains('consultant')) { return const SizedBox.shrink(); } return Padding( diff --git a/lib/features/recipes/services/recipe_service.g.dart b/lib/features/recipes/services/recipe_service.g.dart index 396070b1..3699f878 100644 --- a/lib/features/recipes/services/recipe_service.g.dart +++ b/lib/features/recipes/services/recipe_service.g.dart @@ -9,11 +9,7 @@ part of 'recipe_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _RecipeService implements RecipeService { - _RecipeService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _RecipeService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -27,22 +23,16 @@ class _RecipeService implements RecipeService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/recipes/show/${id}', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/recipes/show/${id}', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late RecipeModel _value; try { @@ -60,30 +50,27 @@ class _RecipeService implements RecipeService { final queryParameters = {r'name': name}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType>>(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/diary/product_nutritional_values/filter', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType>>( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/diary/product_nutritional_values/filter', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late Map> _value; try { - _value = _result.data!.map((k, dynamic v) => MapEntry( + _value = _result.data!.map( + (k, dynamic v) => MapEntry( k, (v as List) .map((i) => Product.fromJson(i as Map)) - .toList())); + .toList(), + ), + ); } on Object catch (e, s) { errorLogger?.logError(e, s, _options); rethrow; @@ -112,29 +99,14 @@ class _RecipeService implements RecipeService { queryParameters.removeWhere((k, v) => v == null); final _headers = {}; final _data = FormData(); - _data.fields.add(MapEntry( - 'type', - type, - )); - _data.fields.add(MapEntry( - 'state', - state, - )); + _data.fields.add(MapEntry('type', type)); + _data.fields.add(MapEntry('state', state)); if (title != null) { - _data.fields.add(MapEntry( - 'title', - title, - )); + _data.fields.add(MapEntry('title', title)); } - _data.fields.add(MapEntry( - 'description', - description, - )); + _data.fields.add(MapEntry('description', description)); if (video_url != null) { - _data.fields.add(MapEntry( - 'video_url', - video_url, - )); + _data.fields.add(MapEntry('video_url', video_url)); } ingredients?.forEach((i) { _data.fields.add(MapEntry('ingredients', jsonEncode(i))); @@ -146,53 +118,43 @@ class _RecipeService implements RecipeService { _data.fields.add(MapEntry('tags', i)); }); if (cooking_time != null) { - _data.fields.add(MapEntry( - 'cooking_time', - cooking_time.toString(), - )); + _data.fields.add(MapEntry('cooking_time', cooking_time.toString())); } if (active_time != null) { - _data.fields.add(MapEntry( - 'active_time', - active_time.toString(), - )); + _data.fields.add(MapEntry('active_time', active_time.toString())); } - _data.fields.add(MapEntry( - 'servings', - servings.toString(), - )); - _data.fields.add(MapEntry( - 'energy_per_serving', - energy_per_serving.toString(), - )); + _data.fields.add(MapEntry('servings', servings.toString())); + _data.fields.add( + MapEntry('energy_per_serving', energy_per_serving.toString()), + ); if (image != null) { if (image != null) { - _data.files.add(MapEntry( - 'image', - MultipartFile.fromFileSync( - image.path, - filename: image.path.split(Platform.pathSeparator).last, + _data.files.add( + MapEntry( + 'image', + MultipartFile.fromFileSync( + image.path, + filename: image.path.split(Platform.pathSeparator).last, + ), ), - )); + ); } } - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - contentType: 'multipart/form-data', - ) - .compose( - _dio.options, - '/api/recipes/create', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options( + method: 'POST', + headers: _headers, + extra: _extra, + contentType: 'multipart/form-data', + ) + .compose( + _dio.options, + '/api/recipes/create', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late RecipeModel _value; try { @@ -205,30 +167,21 @@ class _RecipeService implements RecipeService { } @override - Future editRecipe( - Map recipe, - String id, - ) async { + Future editRecipe(Map recipe, String id) async { final _extra = {}; final queryParameters = {}; final _headers = {}; final _data = FormData.fromMap(recipe); - final _options = _setStreamType(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/recipes/update/{id}', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/recipes/update/{id}', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late RecipeModel _value; try { @@ -246,22 +199,16 @@ class _RecipeService implements RecipeService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/recipes/tags', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/recipes/tags', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late RecipeTagModel _value; try { @@ -286,10 +233,7 @@ class _RecipeService implements RecipeService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/registration/services/registration_service.g.dart b/lib/features/registration/services/registration_service.g.dart index c7b90410..f9560e28 100644 --- a/lib/features/registration/services/registration_service.g.dart +++ b/lib/features/registration/services/registration_service.g.dart @@ -9,11 +9,7 @@ part of 'registration_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _RegistrationService implements RegistrationService { - _RegistrationService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _RegistrationService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -22,29 +18,24 @@ class _RegistrationService implements RegistrationService { final ParseErrorLogger? errorLogger; @override - Future> register( - {required Map sheet}) async { + Future> register({ + required Map sheet, + }) async { final _extra = {}; final queryParameters = {}; final _headers = {}; final _data = {}; _data.addAll(sheet); - final _options = _setStreamType>(Options( - method: 'POST', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/register', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType>( + Options(method: 'POST', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/register', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late Map _value; try { @@ -62,22 +53,16 @@ class _RegistrationService implements RegistrationService { final queryParameters = {r'user_address': query}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/location_by_address', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/location_by_address', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late LocationModel _value; try { @@ -101,22 +86,16 @@ class _RegistrationService implements RegistrationService { }; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/location_by_coordinate', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/location_by_coordinate', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late LocationModel _value; try { @@ -141,10 +120,7 @@ class _RegistrationService implements RegistrationService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/features/settings/presentation/pages/settings_screen.dart b/lib/features/settings/presentation/pages/settings_screen.dart index af2e9387..15ef9844 100644 --- a/lib/features/settings/presentation/pages/settings_screen.dart +++ b/lib/features/settings/presentation/pages/settings_screen.dart @@ -56,7 +56,7 @@ class _SettingsScreenState extends State { const SizedBox(height: 12), _aboutEatvio(state), const SizedBox(height: 12), - if (state.profile.role != 'consultant') + if (state.profile.roles.contains('consultant')) Padding( padding: const EdgeInsets.only(bottom: 8), child: _becomeConsultantButton(state), diff --git a/lib/features/settings/services/settings_service.g.dart b/lib/features/settings/services/settings_service.g.dart index d08c842a..0ba4263c 100644 --- a/lib/features/settings/services/settings_service.g.dart +++ b/lib/features/settings/services/settings_service.g.dart @@ -9,11 +9,7 @@ part of 'settings_service.dart'; // ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations class _SettingsService implements SettingsService { - _SettingsService( - this._dio, { - this.baseUrl, - this.errorLogger, - }); + _SettingsService(this._dio, {this.baseUrl, this.errorLogger}); final Dio _dio; @@ -27,22 +23,16 @@ class _SettingsService implements SettingsService { final queryParameters = {}; final _headers = {}; const Map? _data = null; - final _options = _setStreamType(Options( - method: 'GET', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/profile/settings', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'GET', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/profile/settings', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late ProfileSettingsModel _value; try { @@ -55,29 +45,24 @@ class _SettingsService implements SettingsService { } @override - Future updateProfileSettings( - {required Map data}) async { + Future updateProfileSettings({ + required Map data, + }) async { final _extra = {}; final queryParameters = {}; final _headers = {}; final _data = {}; _data.addAll(data); - final _options = _setStreamType(Options( - method: 'PUT', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/profile/settings/update', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'PUT', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/profile/settings/update', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late ProfileSettingsModel _value; try { @@ -90,29 +75,24 @@ class _SettingsService implements SettingsService { } @override - Future updateProfileDetails( - {required Map data}) async { + Future updateProfileDetails({ + required Map data, + }) async { final _extra = {}; final queryParameters = {}; final _headers = {}; final _data = {}; _data.addAll(data); - final _options = _setStreamType(Options( - method: 'PUT', - headers: _headers, - extra: _extra, - ) - .compose( - _dio.options, - '/api/profile/update', - queryParameters: queryParameters, - data: _data, - ) - .copyWith( - baseUrl: _combineBaseUrls( - _dio.options.baseUrl, - baseUrl, - ))); + final _options = _setStreamType( + Options(method: 'PUT', headers: _headers, extra: _extra) + .compose( + _dio.options, + '/api/profile/update', + queryParameters: queryParameters, + data: _data, + ) + .copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)), + ); final _result = await _dio.fetch>(_options); late ProfileDetailsModel _value; try { @@ -137,10 +117,7 @@ class _SettingsService implements SettingsService { return requestOptions; } - String _combineBaseUrls( - String dioBaseUrl, - String? baseUrl, - ) { + String _combineBaseUrls(String dioBaseUrl, String? baseUrl) { if (baseUrl == null || baseUrl.trim().isEmpty) { return dioBaseUrl; } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 7fbaf5bc..2bcea0e1 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -53,6 +53,7 @@ class MessageLookup extends MessageLookupByLibrary { "bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"), "by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"), "calories": MessageLookupByLibrary.simpleMessage("Калории"), + "cancel_diet": MessageLookupByLibrary.simpleMessage("Отменить диету?"), "carb_type": MessageLookupByLibrary.simpleMessage("Мучное"), "carb_type_desc": MessageLookupByLibrary.simpleMessage( "Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.", @@ -86,10 +87,14 @@ class MessageLookup extends MessageLookupByLibrary { "comments": MessageLookupByLibrary.simpleMessage("Комментарии"), "comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"), "complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"), + "confirm": MessageLookupByLibrary.simpleMessage("Подтвердить"), "continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"), "continue_": MessageLookupByLibrary.simpleMessage("Продолжить"), "copied": MessageLookupByLibrary.simpleMessage("cкопирован"), "copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"), + "could_not_cancel_diet": MessageLookupByLibrary.simpleMessage( + "Не удалось отменить диету", + ), "country": MessageLookupByLibrary.simpleMessage("Страна"), "create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"), "customer_price": MessageLookupByLibrary.simpleMessage( @@ -103,6 +108,7 @@ class MessageLookup extends MessageLookupByLibrary { "diet": MessageLookupByLibrary.simpleMessage("Диета"), "diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"), "diet_plan": MessageLookupByLibrary.simpleMessage("План диеты"), + "diet_started": MessageLookupByLibrary.simpleMessage("Диета уже начата"), "diet_state": MessageLookupByLibrary.simpleMessage("Статус диеты"), "diet_type": MessageLookupByLibrary.simpleMessage("Тип диеты"), "do_you_have_hypertension_tendency": MessageLookupByLibrary.simpleMessage( diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 68b55718..62d2834b 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -1799,6 +1799,41 @@ class S { args: [], ); } + + /// `Диета уже начата` + String get diet_started { + return Intl.message( + 'Диета уже начата', + name: 'diet_started', + desc: '', + args: [], + ); + } + + /// `Отменить диету?` + String get cancel_diet { + return Intl.message( + 'Отменить диету?', + name: 'cancel_diet', + desc: '', + args: [], + ); + } + + /// `Подтвердить` + String get confirm { + return Intl.message('Подтвердить', name: 'confirm', desc: '', args: []); + } + + /// `Не удалось отменить диету` + String get could_not_cancel_diet { + return Intl.message( + 'Не удалось отменить диету', + name: 'could_not_cancel_diet', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/main.dart b/lib/main.dart index 62b91d0e..138ffbfc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -13,12 +13,19 @@ import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:keyboard_dismisser/keyboard_dismisser.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; Future main() async { WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); await di.init(); - runApp(MyApp()); + await SentryFlutter.init( + (options) { + options.dsn = 'http://ba7f2653067776f3034e6e89850e85a1@sentry.md-desk.ru:9000/2'; + options.tracesSampleRate = 1.0; + }, + appRunner: () => runApp(MyApp()), + ); FlutterNativeSplash.remove(); } @@ -26,7 +33,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MultiBlocProvider( - providers: [ + providers: [ BlocProvider(create: (context) => sl()), BlocProvider(create: (context) => sl()), BlocProvider(create: (context) => sl()..loadFeedBlogPostList()), diff --git a/pubspec.yaml b/pubspec.yaml index 5ff110eb..c2b1d954 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,14 +23,14 @@ dependencies: validators: ^3.0.0 path_provider: ^2.1.5 carousel_slider_plus: ^7.1.0 - flutter_form_builder: ^7.0.0-alpha.3 + flutter_form_builder: ^9.7.0 image_picker: ^1.1.2 flutter_typeahead: ^5.2.0 - go_router: ^14.7.1 + go_router: ^14.7.2 keyboard_dismisser: ^3.0.0 retrofit: ^4.4.2 get_it: ^8.0.3 - dio: ^5.7.0 + dio: ^5.8.0+1 dart_pusher_channels: ^1.2.3 photo_view: ^0.15.0 dismissible_page: ^1.0.2 @@ -38,14 +38,14 @@ dependencies: easy_debounce: ^2.0.3 badges: ^3.1.2 google_fonts: ^6.2.1 - syncfusion_flutter_charts: ^28.1.38 - syncfusion_flutter_gauges: ^28.1.38 + syncfusion_flutter_charts: ^28.2.3 + syncfusion_flutter_gauges: ^28.2.3 table_calendar: ^3.2.0 flutter_keyboard_visibility: ^6.0.0 share_plus: ^10.1.4 flutter_html: ^3.0.0-beta.2 - file_picker: ^8.1.7 - audioplayers: ^6.1.0 + file_picker: ^8.3.1 + audioplayers: ^6.1.1 intl: ^0.20.2 rive: ^0.13.20 mask_text_input_formatter: ^2.9.0 @@ -59,6 +59,7 @@ dependencies: http: ^1.3.0 flutter_native_splash: ^2.4.4 webview_flutter: ^4.10.0 + sentry_flutter: ^8.13.0 dev_dependencies: build_runner: ^2.4.14 diff --git a/test/features/profile/services/profile_service_test.dart b/test/features/profile/services/profile_service_test.dart index 4db6526b..dc04bfd2 100644 --- a/test/features/profile/services/profile_service_test.dart +++ b/test/features/profile/services/profile_service_test.dart @@ -23,7 +23,7 @@ void main() { isEntitySubscribedByMe: false, slug: 'slug', profilePhotoUrl: '', - role: 'user', + roles: ['user'], badges: [], subscriptions: [], subscribers: [],