forked from eatvio/eatvio_app
updated error handling, consultant rating layout and complaining logic
This commit is contained in:
5
assets/icons/cloud.svg
Normal file
5
assets/icons/cloud.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="80" height="56" viewBox="0 0 80 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M29.0059 0.177004C24.0464 1.09374 19.6814 3.90505 16.8028 8.04562C15.2852 10.2305 14.1587 13.1793 13.8146 15.9448L13.6112 17.4727L12.4378 17.8088C6.24236 19.5964 1.59579 24.6232 0.18774 31.0403C-0.0625801 32.2321 -0.0625801 36.2657 0.18774 37.4574C1.83047 45.0052 7.83816 50.4292 15.4886 51.2848C16.5837 51.4071 24.4532 51.4376 42.6953 51.4071L68.3531 51.3612L69.6047 51.0098C74.3295 49.7111 77.9591 46.3497 79.3672 41.9647C81.401 35.6087 78.3972 28.7485 72.2956 25.8302C71.5447 25.4788 70.4339 25.051 69.8394 24.9135L68.7442 24.6385V23.7829C68.7442 22.6217 68.2436 20.4062 67.696 19.0464C65.8342 14.5239 62.0325 11.3459 57.0574 10.1694C55.3521 9.75686 52.3482 9.7263 50.6742 10.0777C50.0797 10.2152 49.5478 10.2916 49.4852 10.2458C49.4226 10.2152 49.1097 9.7263 48.7968 9.16098C46.4344 4.95929 42.132 1.73545 37.1882 0.452024C35.874 0.115889 35.2639 0.0547731 32.9171 0.00893645C31.0084 -0.0216213 29.8194 0.0242153 29.0059 0.177004ZM35.5768 5.3107C38.2677 5.90658 41.3341 7.78588 43.0864 9.92492C43.9312 10.9639 45.089 13.0265 45.4957 14.2488C45.9025 15.4559 46.8099 16.1434 48.0302 16.1434C48.3118 16.1434 49.141 15.9142 49.845 15.6239C52.3013 14.6461 54.3352 14.5544 56.7601 15.3489C59.2008 16.1281 61.2815 17.8547 62.4862 20.1312C63.4249 21.9036 63.6283 22.9731 63.5188 25.5094C63.4249 27.297 63.4562 27.679 63.6752 28.1373C64.0351 28.886 65.0364 29.436 66.022 29.436C68.2436 29.4513 70.6999 30.4444 72.2644 31.9723C75.6437 35.2726 75.675 40.4827 72.3269 43.7982C71.3256 44.7913 70.4339 45.3413 68.9163 45.9219L67.8837 46.3192L42.3824 46.365C23.843 46.3956 16.5681 46.365 15.7389 46.2428C10.7638 45.4789 6.77429 41.9953 5.42882 37.2283C5.0377 35.8226 5.05334 32.6446 5.44447 31.2695C6.14849 28.9166 7.21235 27.2053 9.02718 25.5247C11.0141 23.6759 13.2826 22.6064 15.9736 22.2397C18.3047 21.9341 18.8366 21.2618 18.8366 18.6339C18.8366 16.7851 19.0087 15.6545 19.4937 14.1572C20.5419 10.9486 23.0764 8.03034 26.1898 6.45662C29.2405 4.91345 32.1662 4.56204 35.5768 5.3107Z" fill="#323F4B"/>
|
||||
<path d="M48.6352 1.25136H61.9856V56H48.6352V1.25136Z" fill="#F0F2F5"/>
|
||||
<path d="M54.285 39.6226C53.5798 39.6226 52.9961 39.0869 52.9525 38.3996L50.7255 3.28724C50.6779 2.53706 51.2882 1.90313 52.058 1.90313H58.5655C59.3342 1.90313 59.9442 2.53546 59.8981 3.28473L57.7407 38.3971C57.6984 39.0855 57.1143 39.6226 56.408 39.6226H54.285ZM52.197 54.0447C51.4597 54.0447 50.862 53.4611 50.862 52.7412V46.547C50.862 45.8271 51.4597 45.2435 52.197 45.2435H58.4237C59.161 45.2435 59.7587 45.8271 59.7587 46.547V52.7412C59.7587 53.4611 59.161 54.0447 58.4237 54.0447H52.197Z" fill="#2F80ED"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
6
assets/icons/no_internet.svg
Normal file
6
assets/icons/no_internet.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="120" height="107" viewBox="0 0 120 107" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M60.0188 0C93.1495 0 120 14.4534 120 47.3937C120 80.2967 93.1495 107 60.0188 107C26.8505 107 0 80.2967 0 47.3937C0 14.4534 26.8505 0 60.0188 0Z" fill="#43A6F2"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M60.0188 41.756C52.0463 41.756 44.2243 43.3619 36.9288 46.4618C29.6333 49.5989 23.0523 54.1926 17.5995 59.9441C15.0799 62.5584 15.2303 66.7413 17.8627 69.2063C20.5327 71.7085 24.7069 71.5591 27.2265 68.9448C31.4384 64.5005 36.5152 60.9525 42.156 58.5623C47.7969 56.1347 53.8514 54.9022 60.0188 54.9022C66.1485 54.9022 72.203 56.1347 77.8439 58.5623C83.4848 60.9525 88.5615 64.5005 92.7734 68.9448C95.293 71.5591 99.4672 71.7085 102.137 69.2063C104.77 66.7413 104.92 62.5584 102.4 59.9441C96.9476 54.1926 90.3666 49.5989 83.0711 46.4618C75.7756 43.3619 67.9536 41.756 60.0188 41.756Z" fill="white"/>
|
||||
<ellipse cx="59" cy="57" rx="48" ry="36" fill="#43A6F2"/>
|
||||
<path d="M79.975 81.05L55.325 56.2583C53.8611 56.5889 52.4562 57.0375 51.1104 57.6042C49.7646 58.1708 48.5014 58.8556 47.3208 59.6583C46.3292 60.3194 45.2312 60.6618 44.0271 60.6854C42.8229 60.709 41.8194 60.2958 41.0167 59.4458C40.1667 58.5958 39.7771 57.5688 39.8479 56.3646C39.9187 55.1604 40.4264 54.2042 41.3708 53.4958C42.4569 52.6931 43.6021 51.9611 44.8062 51.3C46.0104 50.6389 47.25 50.025 48.525 49.4583L42.15 43.0833C40.9222 43.7444 39.7298 44.441 38.5729 45.1729C37.416 45.9049 36.2944 46.6958 35.2083 47.5458C34.2639 48.3014 33.1896 48.6792 31.9854 48.6792C30.7812 48.6792 29.7778 48.2542 28.975 47.4042C28.125 46.5542 27.7236 45.5389 27.7708 44.3583C27.818 43.1778 28.3139 42.2097 29.2583 41.4542C30.2972 40.6042 31.3597 39.7896 32.4458 39.0104C33.5319 38.2312 34.6889 37.5111 35.9167 36.85L31.95 32.8833C31.4305 32.3639 31.1708 31.7028 31.1708 30.9C31.1708 30.0972 31.4305 29.4361 31.95 28.9167C32.4694 28.3972 33.1305 28.1375 33.9333 28.1375C34.7361 28.1375 35.3972 28.3972 35.9167 28.9167L84.0125 77.0125C84.5792 77.5792 84.8625 78.2521 84.8625 79.0313C84.8625 79.8104 84.5792 80.4833 84.0125 81.05C83.4458 81.5694 82.7729 81.841 81.9937 81.8646C81.2146 81.8882 80.5416 81.6167 79.975 81.05ZM60 78.5C58.0167 78.5 56.3403 77.8035 54.9708 76.4104C53.6014 75.0174 52.9167 73.3528 52.9167 71.4167C52.9167 69.4333 53.6014 67.7569 54.9708 66.3875C56.3403 65.0181 58.0167 64.3333 60 64.3333C61.9833 64.3333 63.6597 65.0181 65.0291 66.3875C66.3986 67.7569 67.0833 69.4333 67.0833 71.4167C67.0833 73.3528 66.3986 75.0174 65.0291 76.4104C63.6597 77.8035 61.9833 78.5 60 78.5ZM79.3375 59.0208C78.5819 59.7764 77.6965 60.1424 76.6812 60.1187C75.666 60.0951 74.7805 59.7056 74.025 58.95L73.3167 58.2417L72.6083 57.5333L65.8083 50.7333C65.1944 50.1194 65.0764 49.4819 65.4542 48.8208C65.8319 48.1597 66.493 47.9472 67.4375 48.1833C69.5625 48.7028 71.5812 49.4347 73.4937 50.3792C75.4062 51.3236 77.1889 52.4333 78.8416 53.7083C79.6917 54.3694 80.1757 55.2312 80.2937 56.2937C80.4118 57.3563 80.093 58.2653 79.3375 59.0208ZM91.025 47.4042C90.2222 48.2542 89.2305 48.691 88.05 48.7146C86.8694 48.7382 85.8069 48.3722 84.8625 47.6167C81.4625 44.8306 77.6493 42.6701 73.4229 41.1354C69.1965 39.6007 64.7222 38.8333 60 38.8333C59.0083 38.8333 58.0521 38.8687 57.1312 38.9396C56.2104 39.0104 55.2778 39.1167 54.3333 39.2583C53.1528 39.4472 52.0903 39.1993 51.1458 38.5146C50.2014 37.8299 49.6347 36.8972 49.4458 35.7167C49.2569 34.5361 49.5167 33.4736 50.225 32.5292C50.9333 31.5847 51.8778 31.0181 53.0583 30.8292C54.1917 30.6403 55.3368 30.5104 56.4937 30.4396C57.6507 30.3687 58.8194 30.3333 60 30.3333C65.9028 30.3333 71.4632 31.3132 76.6812 33.2729C81.8993 35.2326 86.5861 37.9361 90.7416 41.3833C91.6861 42.1861 92.1819 43.1778 92.2291 44.3583C92.2764 45.5389 91.875 46.5542 91.025 47.4042Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
3
assets/icons/right_arrow.svg
Normal file
3
assets/icons/right_arrow.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="8" height="15" viewBox="0 0 8 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.71986 8.22017C8.09338 7.82242 8.09338 7.17757 7.71986 6.77982L1.63283 0.298304C1.25929 -0.0994345 0.653682 -0.0994345 0.280148 0.298304C-0.0933826 0.696046 -0.0933826 1.3409 0.280148 1.73865L5.69085 7.49999L0.280148 13.2614C-0.0933826 13.6591 -0.0933826 14.3039 0.280148 14.7017C0.653682 15.0994 1.25929 15.0994 1.63283 14.7017L7.71986 8.22017Z" fill="#323F4B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 476 B |
@@ -361,6 +361,8 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = VL68C36HYS;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -382,6 +384,7 @@
|
||||
MARKETING_VERSION = 2.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@@ -507,6 +510,8 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = VL68C36HYS;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -528,6 +533,7 @@
|
||||
MARKETING_VERSION = 2.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -541,6 +547,8 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = VL68C36HYS;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -562,6 +570,7 @@
|
||||
MARKETING_VERSION = 2.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
||||
@@ -12,13 +12,13 @@ import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cub
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/chat_screen.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/chats_screen.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_screen.dart';
|
||||
import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/become_consultant_screen.dart';
|
||||
import 'package:eatvio_app/features/consultant/become_consultant/presentation/pages/stepper_become_consultant_screen.dart';
|
||||
import 'package:eatvio_app/features/consultations/presentation/pages/consultations_screen.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/diet_preview_screen.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/create_plan_screen.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/consultant_rating_screen.dart';
|
||||
import 'package:eatvio_app/features/dev_tools/presentation/dev_tools_screen.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/pages/diary_screen.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/pages/about_diet_screen.dart';
|
||||
@@ -66,7 +66,7 @@ class AppRouter {
|
||||
name: 'authScreen',
|
||||
redirect: (context, state) async {
|
||||
// TokenStorage.removeTokenInStorage();
|
||||
// await TokenStorage.saveTokenInStorage('1|laravel_sanctum_zaU2133RQ0wbxDYdH7IQxTpThmilWtKhzxbSt5X1065fcae3');
|
||||
// await TokenStorage.saveTokenInStorage('Bearer 3|laravel_sanctum_zoubsO9NPXAqgLZEdHV9R3XbuDUHJJMJyXcd77mhbb649f04');
|
||||
if (await TokenStorage.haveTokenInStorage()) {
|
||||
return '/my-profile-screen';
|
||||
}
|
||||
@@ -224,7 +224,10 @@ class AppRouter {
|
||||
final data = state.extra as Map<String, dynamic>;
|
||||
final chatsCubit = data['chatsCubit'] as ChatsCubit;
|
||||
final chatId = data['chatId'] as String;
|
||||
return ChatScreen(chatId: chatId, chatsCubit: chatsCubit,);
|
||||
return ChatScreen(
|
||||
chatId: chatId,
|
||||
chatsCubit: chatsCubit,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
@@ -311,11 +314,6 @@ class AppRouter {
|
||||
index: int.parse(state.pathParameters['index']!),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/complaining-screen',
|
||||
name: 'complainingScreen',
|
||||
builder: (context, state) => ComplainingScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: CreateDietScreen.path,
|
||||
name: CreateDietScreen.name,
|
||||
@@ -361,6 +359,11 @@ class AppRouter {
|
||||
name: DevToolsScreen.name,
|
||||
builder: (context, state) => DevToolsScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: ConsultantRatingScreen.path,
|
||||
name: ConsultantRatingScreen.name,
|
||||
builder: (context, state) => ConsultantRatingScreen(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
enum ProductType {
|
||||
diet,
|
||||
plan,
|
||||
recipe
|
||||
}
|
||||
|
||||
enum BaseState {
|
||||
loading,
|
||||
error,
|
||||
7
lib/core/enums/complained_content.dart
Normal file
7
lib/core/enums/complained_content.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
enum ComplainedContent {
|
||||
diet,
|
||||
plan,
|
||||
recipe,
|
||||
profile,
|
||||
posts
|
||||
}
|
||||
5
lib/core/enums/product_type.dart
Normal file
5
lib/core/enums/product_type.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
enum ProductType {
|
||||
diet,
|
||||
plan,
|
||||
recipe
|
||||
}
|
||||
@@ -5,6 +5,9 @@ import 'package:eatvio_app/core/websockets/ws_service.dart';
|
||||
import 'package:eatvio_app/features/auth/presentation/bloc/auth_cubit.dart';
|
||||
import 'package:eatvio_app/features/auth/repositories/auth_repository.dart';
|
||||
import 'package:eatvio_app/features/auth/services/auth_service.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/cubit/complaining_cubit.dart';
|
||||
import 'package:eatvio_app/features/complaining/repositories/complaining_repository.dart';
|
||||
import 'package:eatvio_app/features/complaining/services/complaining_service.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_diet/repositories/create_diet_repository.dart';
|
||||
import 'package:eatvio_app/features/create_diet/services/create_diet_service.dart';
|
||||
@@ -112,6 +115,7 @@ Future<void> init() async {
|
||||
sl.registerFactory<ConsultantsCubit>(() => ConsultantsCubit(feedRepository: sl()));
|
||||
sl.registerFactory<AboutRecipeCubit>(() => AboutRecipeCubit(recipeRepository: sl(), profileRepository: sl()));
|
||||
sl.registerFactory<AuthCubit>(() => AuthCubit(authRepository: sl()));
|
||||
sl.registerFactory<ComplainingCubit>(() => ComplainingCubit(repository: sl()));
|
||||
|
||||
// Repository
|
||||
sl.registerLazySingleton<ChatRepository>(() => ChatRepository(chatService: sl()));
|
||||
@@ -132,6 +136,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<MyDietsRepository>(() => MyDietsRepository(myDietsService: sl()));
|
||||
sl.registerLazySingleton<MyPlansRepository>(() => MyPlansRepository(myPlansService: sl()));
|
||||
sl.registerLazySingleton<AboutRecipeRepository>(() => AboutRecipeRepository(recipeService: sl()));
|
||||
sl.registerLazySingleton<ComplainingRepository>(() => ComplainingRepository(service: sl()));
|
||||
sl.registerLazySingleton<AuthRepository>(() => AuthRepository(authService: sl()));
|
||||
|
||||
// Services
|
||||
@@ -154,6 +159,7 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<MyPlansService>(() => MyPlansService(sl()));
|
||||
sl.registerLazySingleton<WsService>(() => WsService(sl()));
|
||||
sl.registerLazySingleton<AboutRecipeService>(() => AboutRecipeService(sl()));
|
||||
sl.registerLazySingleton<ComplainingService>(() => ComplainingService(sl()));
|
||||
sl.registerLazySingleton<AuthService>(() => AuthService(sl()));
|
||||
|
||||
// External
|
||||
|
||||
@@ -184,6 +184,12 @@ abstract class TextStyles {
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const headingFS40FW600 = TextStyle(
|
||||
fontSize: 40,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.255,
|
||||
);
|
||||
|
||||
static const textLSemibold = TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
@@ -190,6 +190,10 @@ class PrimaryColors {
|
||||
Color get transparentBlack => Color(0xFF1313264).withValues(alpha: 0.3);
|
||||
|
||||
Color get gray60004 => Color(0xFFD4DAE2).withValues(alpha: 0.2);
|
||||
|
||||
Color get blueGray => Color(0xFF809CB9);
|
||||
|
||||
Color get dialogShadow => Color.fromARGB(125, 0, 0, 0);
|
||||
}
|
||||
|
||||
PrimaryColors get appTheme => ThemeHelper().themeColor();
|
||||
|
||||
68
lib/core/widgets/data_error_widget.dart
Normal file
68
lib/core/widgets/data_error_widget.dart
Normal file
@@ -0,0 +1,68 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class DataErrorWidget extends StatefulWidget {
|
||||
const DataErrorWidget({super.key, required this.onReload});
|
||||
|
||||
final Future<void> Function() onReload;
|
||||
|
||||
@override
|
||||
State<DataErrorWidget> createState() => _DataErrorWidgetState();
|
||||
}
|
||||
|
||||
class _DataErrorWidgetState extends State<DataErrorWidget> {
|
||||
bool isLoading = false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset('assets/icons/cloud.svg'),
|
||||
SizedBox(height: 30),
|
||||
Text(
|
||||
s.something_went_wrong,
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: Text(
|
||||
s.can_not_load_data_please_try_again,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
isLoading
|
||||
? Loader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: CustomOutlinedButton(
|
||||
text: s.try_again,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
),
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
await widget.onReload();
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/type_badges.dart';
|
||||
|
||||
59
lib/core/widgets/show_error_dialog.dart
Normal file
59
lib/core/widgets/show_error_dialog.dart
Normal file
@@ -0,0 +1,59 @@
|
||||
import 'package:eatvio_app/core/app_router.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
void showErrorDialog(BuildContext context, {String? title, String? description}) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
barrierColor: Colors.transparent,
|
||||
builder: (BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.whiteA700,
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
boxShadow: [BoxShadow(color: appTheme.dialogShadow, blurRadius: 32)],
|
||||
),
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
title ?? s.some_error_occurred,
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black, decoration: TextDecoration.none),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 72),
|
||||
child: Text(
|
||||
description ?? s.some_error_occurred_description,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black, decoration: TextDecoration.none),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton(
|
||||
onPressed: () => AppRouter.navigatorKey.currentContext?.pop(),
|
||||
child: Text(s.ok, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
@@ -11,6 +12,7 @@ class SuccessPublishedDietBottomSheet extends StatelessWidget {
|
||||
final String title;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -37,7 +39,7 @@ class SuccessPublishedDietBottomSheet extends StatelessWidget {
|
||||
onPressed: () {
|
||||
AppRouter.navigatorKey.currentContext?.pop();
|
||||
},
|
||||
text: 'Хорошо',
|
||||
text: s.ok,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
|
||||
57
lib/core/widgets/success_published_recipe_bottom_sheet.dart
Normal file
57
lib/core/widgets/success_published_recipe_bottom_sheet.dart
Normal file
@@ -0,0 +1,57 @@
|
||||
import 'package:eatvio_app/core/app_router.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class SuccessPublishedRecipeBottomSheet extends StatelessWidget {
|
||||
const SuccessPublishedRecipeBottomSheet({super.key, required this.title});
|
||||
final String title;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text(
|
||||
s.recipe_publishing,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
Text(
|
||||
'"$title" ${s.successfully_published}',
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: CustomOutlinedButton(
|
||||
onPressed: () {
|
||||
AppRouter.navigatorKey.currentContext?.pop();
|
||||
},
|
||||
text: s.ok,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textSSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
import 'dart:io';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
@@ -11,6 +14,7 @@ import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
@@ -191,9 +195,13 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
title: Text(widget.blogPost.title),
|
||||
actions: [
|
||||
PopupMenuButton(
|
||||
onSelected: (value) {
|
||||
onSelected: (value) async {
|
||||
if (value == 'delete') {
|
||||
sl<BlogPostCreateCubit>().deleteBlogPost(widget.blogPost.id);
|
||||
final result = await sl<BlogPostCreateCubit>().deleteBlogPost(widget.blogPost.id);
|
||||
if (!result) {
|
||||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||||
return;
|
||||
}
|
||||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
@@ -219,6 +227,16 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
PopupMenuItem(
|
||||
value: 'report',
|
||||
child: Text('Пожаловаться'),
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => ComplainingBottomSheet(
|
||||
complainedContentType: ComplainedContent.posts,
|
||||
id: widget.blogPost.id,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_state.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/repositories/blog_post_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -10,23 +12,29 @@ class BlogPostCreateCubit extends Cubit<BlogPostCreateState> {
|
||||
required this.blogPostRepository,
|
||||
}) : super(BlogPostCreateState());
|
||||
|
||||
createBlogPost({
|
||||
Future<bool> createBlogPost({
|
||||
String? title,
|
||||
String? videoUrl,
|
||||
String? description,
|
||||
XFile? image,
|
||||
}) async {
|
||||
emit(BlogPostCreateState.loading());
|
||||
await blogPostRepository.createBlogPost(
|
||||
title,
|
||||
videoUrl,
|
||||
description,
|
||||
image,
|
||||
);
|
||||
emit(BlogPostCreateState.loaded());
|
||||
try {
|
||||
emit(BlogPostCreateState.loading());
|
||||
await blogPostRepository.createBlogPost(
|
||||
title,
|
||||
videoUrl,
|
||||
description,
|
||||
image,
|
||||
);
|
||||
return true;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
emit(BlogPostCreateState.loaded());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
updateBlogPost({
|
||||
Future<bool> updateBlogPost({
|
||||
required int id,
|
||||
String? title,
|
||||
String? videoUrl,
|
||||
@@ -34,19 +42,32 @@ class BlogPostCreateCubit extends Cubit<BlogPostCreateState> {
|
||||
XFile? image,
|
||||
String? oldImageUrl,
|
||||
}) async {
|
||||
emit(BlogPostCreateState.loading());
|
||||
await blogPostRepository.updateBlogPost(
|
||||
id,
|
||||
title,
|
||||
videoUrl,
|
||||
description,
|
||||
image,
|
||||
oldImageUrl,
|
||||
);
|
||||
emit(BlogPostCreateState.loaded());
|
||||
try {
|
||||
emit(BlogPostCreateState.loading());
|
||||
await blogPostRepository.updateBlogPost(
|
||||
id,
|
||||
title,
|
||||
videoUrl,
|
||||
description,
|
||||
image,
|
||||
oldImageUrl,
|
||||
);
|
||||
emit(BlogPostCreateState.loaded());
|
||||
return true;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
emit(BlogPostCreateState.loaded());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
deleteBlogPost(int id) async {
|
||||
await blogPostRepository.deleteBlogPost(id);
|
||||
Future<bool> deleteBlogPost(int id) async {
|
||||
try {
|
||||
await blogPostRepository.deleteBlogPost(id);
|
||||
return true;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/app_decoration.dart';
|
||||
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_state.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
@@ -9,10 +10,12 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
class BlogPostCreateScreen extends StatefulWidget {
|
||||
@@ -65,7 +68,6 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
listener: (BuildContext context, BlogPostCreateState state) {
|
||||
if (state is BlogPostCreateStateLoaded) {
|
||||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: _buildBlogPostCreate(),
|
||||
@@ -148,8 +150,9 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
if (widget.feedBlogPostModel != null) {
|
||||
await blogPostCubit.updateBlogPost(
|
||||
final result = await blogPostCubit.updateBlogPost(
|
||||
id: widget.feedBlogPostModel!.id,
|
||||
title: titleController.text,
|
||||
description: descriptionController.text,
|
||||
@@ -157,13 +160,29 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
image: image,
|
||||
oldImageUrl: widget.feedBlogPostModel!.image,
|
||||
);
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
if (!result) {
|
||||
showErrorDialog(context, title: S.current.could_not_update_blog_post);
|
||||
} else {
|
||||
context.pop();
|
||||
}
|
||||
} else {
|
||||
await blogPostCubit.createBlogPost(
|
||||
final result = await blogPostCubit.createBlogPost(
|
||||
title: titleController.text,
|
||||
description: descriptionController.text,
|
||||
videoUrl: videoUrlController.text,
|
||||
image: image,
|
||||
);
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
if (!result) {
|
||||
showErrorDialog(context, title: S.current.could_not_publish_blog_post);
|
||||
} else {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:dart_pusher_channels/dart_pusher_channels.dart';
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||
import 'package:eatvio_app/core/websockets/ws_manager.dart';
|
||||
@@ -15,6 +17,8 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
|
||||
final ChatRepository chatRepository;
|
||||
final WsManager wsManager;
|
||||
|
||||
StreamSubscription<ChannelReadEvent>? typingSubscription;
|
||||
StreamSubscription<ChannelReadEvent>? messagesSubscription;
|
||||
int currentPage = 1;
|
||||
late final int lastPage;
|
||||
bool isLoading = false;
|
||||
@@ -75,6 +79,9 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
typingSubscription?.cancel();
|
||||
messagesSubscription?.cancel();
|
||||
wsManager.unsubscribeDirectChatChannel();
|
||||
emit(ChatRoomState.error(errorMessage: 'Ошибка получеия данных'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/base_state.dart';
|
||||
import 'package:eatvio_app/core/websockets/ws_manager.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_state.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/base_state.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_room_preview_model.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
|
||||
@@ -66,9 +67,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
} else if (state is ChatRoomStateError) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: Center(
|
||||
child: Text(state.errorMessage),
|
||||
),
|
||||
body: DataErrorWidget(onReload: () => chatRoomCubit.initChat(widget.chatId)),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:easy_debounce/easy_debounce.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/base_state.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chats_cubit/chats_state.dart';
|
||||
@@ -79,9 +80,8 @@ class _ChatsScreenState extends State<ChatsScreen> {
|
||||
} else if (state.state == BaseState.success) {
|
||||
return _buildChatList(context, state);
|
||||
} else if (state.state == BaseState.error) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(child: Text(state.errorMessage ?? '')),
|
||||
return Scaffold(
|
||||
body: DataErrorWidget(onReload: () => context.read<ChatsCubit>().getChatRooms()),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
|
||||
@@ -20,7 +20,6 @@ class ChatEntryWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ChatEntryWidgetState extends State<ChatEntryWidget> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
@@ -61,11 +60,14 @@ class _ChatEntryWidgetState extends State<ChatEntryWidget> {
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
if (widget.chatRoom.lastMessage != null)
|
||||
Text(
|
||||
widget.chatRoom.lastMessage!.data.toString().trim(),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: CustomTextStyles.bodyMediumBluegray800,
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.5,
|
||||
child: Text(
|
||||
widget.chatRoom.lastMessage!.data.toString().trim(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: CustomTextStyles.bodyMediumBluegray800,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
15
lib/features/complaining/models/complain_model.dart
Normal file
15
lib/features/complaining/models/complain_model.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'complain_model.freezed.dart';
|
||||
part 'complain_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class ComplainModel with _$ComplainModel {
|
||||
|
||||
const factory ComplainModel({
|
||||
@Default(null) String? description,
|
||||
@Default([]) List<String> tags,
|
||||
}) = _ComplainModel;
|
||||
|
||||
factory ComplainModel.fromJson(Map<String, dynamic> json) => _$ComplainModelFromJson(json);
|
||||
}
|
||||
193
lib/features/complaining/models/complain_model.freezed.dart
Normal file
193
lib/features/complaining/models/complain_model.freezed.dart
Normal file
@@ -0,0 +1,193 @@
|
||||
// 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 'complain_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
ComplainModel _$ComplainModelFromJson(Map<String, dynamic> json) {
|
||||
return _ComplainModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ComplainModel {
|
||||
String? get description => throw _privateConstructorUsedError;
|
||||
List<String> get tags => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this ComplainModel to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ComplainModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$ComplainModelCopyWith<ComplainModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ComplainModelCopyWith<$Res> {
|
||||
factory $ComplainModelCopyWith(
|
||||
ComplainModel value, $Res Function(ComplainModel) then) =
|
||||
_$ComplainModelCopyWithImpl<$Res, ComplainModel>;
|
||||
@useResult
|
||||
$Res call({String? description, List<String> tags});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ComplainModelCopyWithImpl<$Res, $Val extends ComplainModel>
|
||||
implements $ComplainModelCopyWith<$Res> {
|
||||
_$ComplainModelCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ComplainModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? description = freezed,
|
||||
Object? tags = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
description: freezed == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
tags: null == tags
|
||||
? _value.tags
|
||||
: tags // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ComplainModelImplCopyWith<$Res>
|
||||
implements $ComplainModelCopyWith<$Res> {
|
||||
factory _$$ComplainModelImplCopyWith(
|
||||
_$ComplainModelImpl value, $Res Function(_$ComplainModelImpl) then) =
|
||||
__$$ComplainModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String? description, List<String> tags});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ComplainModelImplCopyWithImpl<$Res>
|
||||
extends _$ComplainModelCopyWithImpl<$Res, _$ComplainModelImpl>
|
||||
implements _$$ComplainModelImplCopyWith<$Res> {
|
||||
__$$ComplainModelImplCopyWithImpl(
|
||||
_$ComplainModelImpl _value, $Res Function(_$ComplainModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ComplainModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? description = freezed,
|
||||
Object? tags = null,
|
||||
}) {
|
||||
return _then(_$ComplainModelImpl(
|
||||
description: freezed == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
tags: null == tags
|
||||
? _value._tags
|
||||
: tags // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ComplainModelImpl implements _ComplainModel {
|
||||
const _$ComplainModelImpl(
|
||||
{this.description = null, final List<String> tags = const []})
|
||||
: _tags = tags;
|
||||
|
||||
factory _$ComplainModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ComplainModelImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? description;
|
||||
final List<String> _tags;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<String> get tags {
|
||||
if (_tags is EqualUnmodifiableListView) return _tags;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_tags);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ComplainModel(description: $description, tags: $tags)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ComplainModelImpl &&
|
||||
(identical(other.description, description) ||
|
||||
other.description == description) &&
|
||||
const DeepCollectionEquality().equals(other._tags, _tags));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, description, const DeepCollectionEquality().hash(_tags));
|
||||
|
||||
/// Create a copy of ComplainModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ComplainModelImplCopyWith<_$ComplainModelImpl> get copyWith =>
|
||||
__$$ComplainModelImplCopyWithImpl<_$ComplainModelImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ComplainModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _ComplainModel implements ComplainModel {
|
||||
const factory _ComplainModel(
|
||||
{final String? description,
|
||||
final List<String> tags}) = _$ComplainModelImpl;
|
||||
|
||||
factory _ComplainModel.fromJson(Map<String, dynamic> json) =
|
||||
_$ComplainModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
String? get description;
|
||||
@override
|
||||
List<String> get tags;
|
||||
|
||||
/// Create a copy of ComplainModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ComplainModelImplCopyWith<_$ComplainModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
21
lib/features/complaining/models/complain_model.g.dart
Normal file
21
lib/features/complaining/models/complain_model.g.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'complain_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$ComplainModelImpl _$$ComplainModelImplFromJson(Map<String, dynamic> json) =>
|
||||
_$ComplainModelImpl(
|
||||
description: json['description'] as String? ?? null,
|
||||
tags:
|
||||
(json['tags'] as List<dynamic>?)?.map((e) => e as String).toList() ??
|
||||
const [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ComplainModelImplToJson(_$ComplainModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'description': instance.description,
|
||||
'tags': instance.tags,
|
||||
};
|
||||
@@ -0,0 +1,590 @@
|
||||
import 'package:eatvio_app/core/app_router.dart';
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.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/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/cubit/complaining_cubit.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/cubit/complaining_state.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
class ComplainingBottomSheet extends StatefulWidget {
|
||||
const ComplainingBottomSheet({super.key, required this.complainedContentType, this.slug, this.id});
|
||||
final ComplainedContent complainedContentType;
|
||||
final String? slug;
|
||||
final int? id;
|
||||
@override
|
||||
State<ComplainingBottomSheet> createState() => _ComplainingBottomSheetState();
|
||||
}
|
||||
|
||||
class _ComplainingBottomSheetState extends State<ComplainingBottomSheet> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => sl<ComplainingCubit>()..setContentTypeAndIdentifier(contentType: widget.complainedContentType, slug: widget.slug, id: widget.id),
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 8, bottom: 24, left: 16, right: 16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
|
||||
),
|
||||
child: BlocBuilder<ComplainingCubit, ComplainingState>(
|
||||
builder: (context, state) {
|
||||
final category = state.category;
|
||||
if (state.wasSentSuccessfully == true) {
|
||||
return _ComplaintSentWidget();
|
||||
} else if (state.wasSentSuccessfully == false) {
|
||||
return _ComplaintFailedWidget();
|
||||
}
|
||||
if (category != null) {
|
||||
return switch (category) {
|
||||
ComplainType.spam => _SpamWidget(),
|
||||
ComplainType.lawViolation => _LawViolationWidget(),
|
||||
ComplainType.deception => _DeceptionWidget(),
|
||||
ComplainType.violenceDndHostility => _ViolenceAndHostility(),
|
||||
ComplainType.explicitImage => _ExplicitImageWidget(),
|
||||
};
|
||||
}
|
||||
return _CategoryWidget();
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CategoryWidget extends StatelessWidget {
|
||||
const _CategoryWidget();
|
||||
final categories = ComplainType.values;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.complaint,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
s.complaint_question,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
...List.generate(
|
||||
categories.length,
|
||||
(index) => Column(
|
||||
children: [
|
||||
_CategoryButton(
|
||||
category: categories[index],
|
||||
onTap: () {
|
||||
context.read<ComplainingCubit>().setCategory(categories[index]);
|
||||
},
|
||||
),
|
||||
if (index != categories.length - 1) SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SpamWidget extends StatelessWidget {
|
||||
const _SpamWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.spam,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
s.spam_description,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
_ComplainButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ExplicitImageWidget extends StatelessWidget {
|
||||
const _ExplicitImageWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.explicitImages,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
s.explicitImagesDescription,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
_ComplainButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LawViolationWidget extends StatefulWidget {
|
||||
const _LawViolationWidget();
|
||||
|
||||
@override
|
||||
State<_LawViolationWidget> createState() => _LawViolationWidgetState();
|
||||
}
|
||||
|
||||
class _LawViolationWidgetState extends State<_LawViolationWidget> {
|
||||
final List<(bool, String)> tags = [];
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final s = S.of(context);
|
||||
if (tags.isEmpty) {
|
||||
tags.addAll([
|
||||
(false, s.alcohol),
|
||||
(false, s.drugs),
|
||||
(false, s.nicotine),
|
||||
(false, s.weapon),
|
||||
(false, s.fake_documents),
|
||||
(false, s.prostitution),
|
||||
(false, s.other),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.lawViolation,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
s.what_do_you_want_to_complaint_about,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
...tags.mapIndexed((index, element) {
|
||||
return Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
activeColor: appTheme.blueA400,
|
||||
side: BorderSide(width: 2, color: tags[index].$1 ? appTheme.blueA400 : appTheme.blueGray),
|
||||
value: element.$1,
|
||||
onChanged: (isChecked) {
|
||||
setState(() {
|
||||
if (isChecked == null) return;
|
||||
if (index == tags.length - 1 && !isChecked) {
|
||||
context.read<ComplainingCubit>().toggleDescription();
|
||||
}
|
||||
tags[index] = (isChecked, element.$2);
|
||||
final activeTags = tags.where((elem) => elem.$1).map((e) => e.$2).toList();
|
||||
context.read<ComplainingCubit>().setTags(activeTags);
|
||||
});
|
||||
},
|
||||
),
|
||||
Text(
|
||||
element.$2,
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
if (tags.last.$1) ...[
|
||||
SizedBox(height: 12),
|
||||
CustomTextFormField(
|
||||
hintText: s.type_here_your_complaint,
|
||||
onChanged: (value) {
|
||||
context.read<ComplainingCubit>().setDescription(value);
|
||||
},
|
||||
),
|
||||
],
|
||||
SizedBox(height: 20),
|
||||
_ComplainButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ViolenceAndHostility extends StatefulWidget {
|
||||
const _ViolenceAndHostility();
|
||||
|
||||
@override
|
||||
State<_ViolenceAndHostility> createState() => _ViolenceAndHostilityState();
|
||||
}
|
||||
|
||||
class _ViolenceAndHostilityState extends State<_ViolenceAndHostility> {
|
||||
final List<(bool, String)> tags = [];
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final s = S.of(context);
|
||||
if (tags.isEmpty) {
|
||||
tags.addAll([
|
||||
(false, s.violence_against_people_or_animal),
|
||||
(false, s.hatred),
|
||||
(false, s.suicide),
|
||||
(false, s.hatred_description),
|
||||
(false, s.extremism),
|
||||
(false, s.calls_for_bullying),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.lawViolation,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
s.what_do_you_want_to_complaint_about,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
...tags.mapIndexed((index, element) {
|
||||
return Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
activeColor: appTheme.blueA400,
|
||||
side: BorderSide(width: 2, color: tags[index].$1 ? appTheme.blueA400 : appTheme.blueGray),
|
||||
value: element.$1,
|
||||
onChanged: (isChecked) {
|
||||
setState(() {
|
||||
if (isChecked == null) return;
|
||||
tags[index] = (isChecked, element.$2);
|
||||
final activeTags = tags.where((elem) => elem.$1).map((e) => e.$2).toList();
|
||||
context.read<ComplainingCubit>().setTags(activeTags);
|
||||
});
|
||||
},
|
||||
),
|
||||
Text(
|
||||
element.$2,
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
SizedBox(height: 20),
|
||||
_ComplainButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DeceptionWidget extends StatefulWidget {
|
||||
const _DeceptionWidget();
|
||||
|
||||
@override
|
||||
State<_DeceptionWidget> createState() => _DeceptionWidgetState();
|
||||
}
|
||||
|
||||
class _DeceptionWidgetState extends State<_DeceptionWidget> {
|
||||
final List<(bool, String)> tags = [];
|
||||
final List<String> descriptions = [];
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final s = S.of(context);
|
||||
if (tags.isEmpty && descriptions.isEmpty) {
|
||||
tags.addAll([
|
||||
(false, s.misrepresentation),
|
||||
(false, s.fraud),
|
||||
]);
|
||||
|
||||
descriptions.addAll([
|
||||
s.misrepresentation_description,
|
||||
s.fraud_description,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.lawViolation,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
s.what_do_you_want_to_complaint_about,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
...tags.mapIndexed((index, element) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Checkbox(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
activeColor: appTheme.blueA400,
|
||||
side: BorderSide(width: 2, color: tags[index].$1 ? appTheme.blueA400 : appTheme.blueGray),
|
||||
value: element.$1,
|
||||
onChanged: (isChecked) {
|
||||
setState(() {
|
||||
if (isChecked == null) return;
|
||||
tags[index] = (isChecked, element.$2);
|
||||
final activeTags = tags.where((elem) => elem.$1).map((e) => e.$2).toList();
|
||||
context.read<ComplainingCubit>().setTags(activeTags);
|
||||
});
|
||||
},
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
element.$2,
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
descriptions[index],
|
||||
style: TextStyles.textSSemibold.copyWith(color: appTheme.lightGray600),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
SizedBox(height: 20),
|
||||
_ComplainButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ComplaintSentWidget extends StatelessWidget {
|
||||
const _ComplaintSentWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.complaint_sent,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
s.complaint_sent_description,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
CustomOutlinedButton(
|
||||
text: s.ok,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
),
|
||||
onPressed: () {
|
||||
AppRouter.navigatorKey.currentContext?.pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ComplaintFailedWidget extends StatelessWidget {
|
||||
const _ComplaintFailedWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BottomSheetHandlerBar(),
|
||||
SizedBox(height: 20),
|
||||
Text(
|
||||
s.could_not_send_complain,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.7,
|
||||
child: Text(
|
||||
s.please_try_again_later,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24),
|
||||
CustomOutlinedButton(
|
||||
text: s.ok,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
),
|
||||
onPressed: () {
|
||||
AppRouter.navigatorKey.currentContext?.pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ComplainButton extends StatelessWidget {
|
||||
const _ComplainButton();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return BlocBuilder<ComplainingCubit, ComplainingState>(
|
||||
builder: (context, state) {
|
||||
if (state.isLoading) {
|
||||
return Loader();
|
||||
}
|
||||
return CustomOutlinedButton(
|
||||
text: s.send_complain,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
),
|
||||
onPressed: () async {
|
||||
await context.read<ComplainingCubit>().complain();
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CategoryButton extends StatelessWidget {
|
||||
const _CategoryButton({required this.category, required this.onTap});
|
||||
final ComplainType category;
|
||||
final void Function() onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Ink(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
category.getTranslatedText(),
|
||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/right_arrow.svg'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum ComplainType {
|
||||
spam,
|
||||
lawViolation,
|
||||
deception,
|
||||
violenceDndHostility,
|
||||
explicitImage;
|
||||
|
||||
String getTranslatedText() => switch (this) {
|
||||
ComplainType.spam => S.current.spam,
|
||||
ComplainType.lawViolation => S.current.lawViolation,
|
||||
ComplainType.deception => S.current.deception,
|
||||
ComplainType.violenceDndHostility => S.current.violenceAndHostility,
|
||||
ComplainType.explicitImage => S.current.explicitImage,
|
||||
};
|
||||
|
||||
String getValue() => switch (this) {
|
||||
ComplainType.spam => 'spam',
|
||||
ComplainType.lawViolation => 'legalViolation',
|
||||
ComplainType.deception => 'fraud',
|
||||
ComplainType.violenceDndHostility => 'violenceAndHatred',
|
||||
ComplainType.explicitImage => 'explicitImage',
|
||||
};
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ComplainingScreen extends StatelessWidget {
|
||||
const ComplainingScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Placeholder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/cubit/complaining_state.dart';
|
||||
import 'package:eatvio_app/features/complaining/repositories/complaining_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class ComplainingCubit extends Cubit<ComplainingState> {
|
||||
final ComplainingRepository repository;
|
||||
ComplainingCubit({required this.repository}) : super(ComplainingState());
|
||||
|
||||
void setContentTypeAndIdentifier({required ComplainedContent contentType, int? id, String? slug}) {
|
||||
emit(state.copyWith(contentType: contentType, contentId: id, contentSlug: slug));
|
||||
}
|
||||
|
||||
void setCategory(ComplainType category) {
|
||||
emit(state.copyWith(category: category));
|
||||
}
|
||||
|
||||
void setTags(List<String> tags) {
|
||||
emit(state.copyWith.complainInfo(tags: tags));
|
||||
}
|
||||
|
||||
void toggleDescription() {
|
||||
if (state.complainInfo.description != null) {
|
||||
emit(state.copyWith.complainInfo(description: null));
|
||||
} else {
|
||||
emit(state.copyWith.complainInfo(description: ''));
|
||||
}
|
||||
}
|
||||
|
||||
void setDescription(String description) {
|
||||
emit(state.copyWith.complainInfo(description: description));
|
||||
}
|
||||
|
||||
Future<void> complain() async {
|
||||
try {
|
||||
final category = state.category;
|
||||
final id = state.contentId;
|
||||
final slug = state.contentSlug;
|
||||
final contentType = state.contentType;
|
||||
if (category != null && contentType != null) {
|
||||
switch (contentType) {
|
||||
case ComplainedContent.diet:
|
||||
emit(state.copyWith(wasSentSuccessfully: true));
|
||||
return;
|
||||
case ComplainedContent.plan:
|
||||
if (slug != null) {
|
||||
await repository.sendPlanComplain(slug: slug, category: category.getValue(), body: state.complainInfo);
|
||||
emit(state.copyWith(wasSentSuccessfully: true));
|
||||
return;
|
||||
}
|
||||
case ComplainedContent.recipe:
|
||||
if (slug != null) {
|
||||
await repository.sendRecipeComplain(slug: slug, category: category.getValue(), body: state.complainInfo);
|
||||
emit(state.copyWith(wasSentSuccessfully: true));
|
||||
return;
|
||||
}
|
||||
case ComplainedContent.profile:
|
||||
if (slug != null) {
|
||||
await repository.sendProfileComplain(slug: slug, category: category.getValue(), body: state.complainInfo);
|
||||
emit(state.copyWith(wasSentSuccessfully: true));
|
||||
return;
|
||||
}
|
||||
case ComplainedContent.posts:
|
||||
if (id != null) {
|
||||
await repository.sendBlogPostsComplain(id: id, category: category.getValue(), body: state.complainInfo);
|
||||
emit(state.copyWith(wasSentSuccessfully: true));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
}
|
||||
emit(state.copyWith(wasSentSuccessfully: false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/features/complaining/models/complain_model.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'complaining_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class ComplainingState with _$ComplainingState {
|
||||
|
||||
factory ComplainingState({
|
||||
@Default(false) bool isLoading,
|
||||
@Default(null) bool? wasSentSuccessfully,
|
||||
@Default(null) ComplainType? category,
|
||||
@Default(null) ComplainedContent? contentType,
|
||||
@Default(null) int? contentId,
|
||||
@Default(null) String? contentSlug,
|
||||
@Default(ComplainModel()) ComplainModel complainInfo,
|
||||
}) = _ComplainingState;
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
// 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 'complaining_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ComplainingState {
|
||||
bool get isLoading => throw _privateConstructorUsedError;
|
||||
bool? get wasSentSuccessfully => throw _privateConstructorUsedError;
|
||||
ComplainType? get category => throw _privateConstructorUsedError;
|
||||
ComplainedContent? get contentType => throw _privateConstructorUsedError;
|
||||
int? get contentId => throw _privateConstructorUsedError;
|
||||
String? get contentSlug => throw _privateConstructorUsedError;
|
||||
ComplainModel get complainInfo => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ComplainingState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$ComplainingStateCopyWith<ComplainingState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ComplainingStateCopyWith<$Res> {
|
||||
factory $ComplainingStateCopyWith(
|
||||
ComplainingState value, $Res Function(ComplainingState) then) =
|
||||
_$ComplainingStateCopyWithImpl<$Res, ComplainingState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool isLoading,
|
||||
bool? wasSentSuccessfully,
|
||||
ComplainType? category,
|
||||
ComplainedContent? contentType,
|
||||
int? contentId,
|
||||
String? contentSlug,
|
||||
ComplainModel complainInfo});
|
||||
|
||||
$ComplainModelCopyWith<$Res> get complainInfo;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ComplainingStateCopyWithImpl<$Res, $Val extends ComplainingState>
|
||||
implements $ComplainingStateCopyWith<$Res> {
|
||||
_$ComplainingStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of ComplainingState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? isLoading = null,
|
||||
Object? wasSentSuccessfully = freezed,
|
||||
Object? category = freezed,
|
||||
Object? contentType = freezed,
|
||||
Object? contentId = freezed,
|
||||
Object? contentSlug = freezed,
|
||||
Object? complainInfo = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
wasSentSuccessfully: freezed == wasSentSuccessfully
|
||||
? _value.wasSentSuccessfully
|
||||
: wasSentSuccessfully // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
category: freezed == category
|
||||
? _value.category
|
||||
: category // ignore: cast_nullable_to_non_nullable
|
||||
as ComplainType?,
|
||||
contentType: freezed == contentType
|
||||
? _value.contentType
|
||||
: contentType // ignore: cast_nullable_to_non_nullable
|
||||
as ComplainedContent?,
|
||||
contentId: freezed == contentId
|
||||
? _value.contentId
|
||||
: contentId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
contentSlug: freezed == contentSlug
|
||||
? _value.contentSlug
|
||||
: contentSlug // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
complainInfo: null == complainInfo
|
||||
? _value.complainInfo
|
||||
: complainInfo // ignore: cast_nullable_to_non_nullable
|
||||
as ComplainModel,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
/// Create a copy of ComplainingState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ComplainModelCopyWith<$Res> get complainInfo {
|
||||
return $ComplainModelCopyWith<$Res>(_value.complainInfo, (value) {
|
||||
return _then(_value.copyWith(complainInfo: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ComplainingStateImplCopyWith<$Res>
|
||||
implements $ComplainingStateCopyWith<$Res> {
|
||||
factory _$$ComplainingStateImplCopyWith(_$ComplainingStateImpl value,
|
||||
$Res Function(_$ComplainingStateImpl) then) =
|
||||
__$$ComplainingStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool isLoading,
|
||||
bool? wasSentSuccessfully,
|
||||
ComplainType? category,
|
||||
ComplainedContent? contentType,
|
||||
int? contentId,
|
||||
String? contentSlug,
|
||||
ComplainModel complainInfo});
|
||||
|
||||
@override
|
||||
$ComplainModelCopyWith<$Res> get complainInfo;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ComplainingStateImplCopyWithImpl<$Res>
|
||||
extends _$ComplainingStateCopyWithImpl<$Res, _$ComplainingStateImpl>
|
||||
implements _$$ComplainingStateImplCopyWith<$Res> {
|
||||
__$$ComplainingStateImplCopyWithImpl(_$ComplainingStateImpl _value,
|
||||
$Res Function(_$ComplainingStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of ComplainingState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? isLoading = null,
|
||||
Object? wasSentSuccessfully = freezed,
|
||||
Object? category = freezed,
|
||||
Object? contentType = freezed,
|
||||
Object? contentId = freezed,
|
||||
Object? contentSlug = freezed,
|
||||
Object? complainInfo = null,
|
||||
}) {
|
||||
return _then(_$ComplainingStateImpl(
|
||||
isLoading: null == isLoading
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
wasSentSuccessfully: freezed == wasSentSuccessfully
|
||||
? _value.wasSentSuccessfully
|
||||
: wasSentSuccessfully // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
category: freezed == category
|
||||
? _value.category
|
||||
: category // ignore: cast_nullable_to_non_nullable
|
||||
as ComplainType?,
|
||||
contentType: freezed == contentType
|
||||
? _value.contentType
|
||||
: contentType // ignore: cast_nullable_to_non_nullable
|
||||
as ComplainedContent?,
|
||||
contentId: freezed == contentId
|
||||
? _value.contentId
|
||||
: contentId // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
contentSlug: freezed == contentSlug
|
||||
? _value.contentSlug
|
||||
: contentSlug // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
complainInfo: null == complainInfo
|
||||
? _value.complainInfo
|
||||
: complainInfo // ignore: cast_nullable_to_non_nullable
|
||||
as ComplainModel,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ComplainingStateImpl implements _ComplainingState {
|
||||
_$ComplainingStateImpl(
|
||||
{this.isLoading = false,
|
||||
this.wasSentSuccessfully = null,
|
||||
this.category = null,
|
||||
this.contentType = null,
|
||||
this.contentId = null,
|
||||
this.contentSlug = null,
|
||||
this.complainInfo = const ComplainModel()});
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isLoading;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool? wasSentSuccessfully;
|
||||
@override
|
||||
@JsonKey()
|
||||
final ComplainType? category;
|
||||
@override
|
||||
@JsonKey()
|
||||
final ComplainedContent? contentType;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int? contentId;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? contentSlug;
|
||||
@override
|
||||
@JsonKey()
|
||||
final ComplainModel complainInfo;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ComplainingState(isLoading: $isLoading, wasSentSuccessfully: $wasSentSuccessfully, category: $category, contentType: $contentType, contentId: $contentId, contentSlug: $contentSlug, complainInfo: $complainInfo)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ComplainingStateImpl &&
|
||||
(identical(other.isLoading, isLoading) ||
|
||||
other.isLoading == isLoading) &&
|
||||
(identical(other.wasSentSuccessfully, wasSentSuccessfully) ||
|
||||
other.wasSentSuccessfully == wasSentSuccessfully) &&
|
||||
(identical(other.category, category) ||
|
||||
other.category == category) &&
|
||||
(identical(other.contentType, contentType) ||
|
||||
other.contentType == contentType) &&
|
||||
(identical(other.contentId, contentId) ||
|
||||
other.contentId == contentId) &&
|
||||
(identical(other.contentSlug, contentSlug) ||
|
||||
other.contentSlug == contentSlug) &&
|
||||
(identical(other.complainInfo, complainInfo) ||
|
||||
other.complainInfo == complainInfo));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, isLoading, wasSentSuccessfully,
|
||||
category, contentType, contentId, contentSlug, complainInfo);
|
||||
|
||||
/// Create a copy of ComplainingState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ComplainingStateImplCopyWith<_$ComplainingStateImpl> get copyWith =>
|
||||
__$$ComplainingStateImplCopyWithImpl<_$ComplainingStateImpl>(
|
||||
this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _ComplainingState implements ComplainingState {
|
||||
factory _ComplainingState(
|
||||
{final bool isLoading,
|
||||
final bool? wasSentSuccessfully,
|
||||
final ComplainType? category,
|
||||
final ComplainedContent? contentType,
|
||||
final int? contentId,
|
||||
final String? contentSlug,
|
||||
final ComplainModel complainInfo}) = _$ComplainingStateImpl;
|
||||
|
||||
@override
|
||||
bool get isLoading;
|
||||
@override
|
||||
bool? get wasSentSuccessfully;
|
||||
@override
|
||||
ComplainType? get category;
|
||||
@override
|
||||
ComplainedContent? get contentType;
|
||||
@override
|
||||
int? get contentId;
|
||||
@override
|
||||
String? get contentSlug;
|
||||
@override
|
||||
ComplainModel get complainInfo;
|
||||
|
||||
/// Create a copy of ComplainingState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$ComplainingStateImplCopyWith<_$ComplainingStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import 'package:eatvio_app/features/complaining/models/complain_model.dart';
|
||||
import 'package:eatvio_app/features/complaining/services/complaining_service.dart';
|
||||
|
||||
class ComplainingRepository {
|
||||
final ComplainingService service;
|
||||
ComplainingRepository({required this.service});
|
||||
|
||||
Future<void> sendPlanComplain({
|
||||
required String slug,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
try {
|
||||
service.sendPlanComplain(slug: slug, category: category, body: body);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sendRecipeComplain({
|
||||
required String slug,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
try {
|
||||
service.sendRecipeComplain(slug: slug, category: category, body: body);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sendBlogPostsComplain({
|
||||
required int id,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
try {
|
||||
service.sendBlogPostsComplain(id: id, category: category, body: body);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sendProfileComplain({
|
||||
required String slug,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
try {
|
||||
service.sendProfileComplain(slug: slug, category: category, body: body);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
lib/features/complaining/services/complaining_service.dart
Normal file
39
lib/features/complaining/services/complaining_service.dart
Normal file
@@ -0,0 +1,39 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/features/complaining/models/complain_model.dart';
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
|
||||
part 'complaining_service.g.dart';
|
||||
|
||||
@RestApi()
|
||||
abstract class ComplainingService {
|
||||
factory ComplainingService(Dio dio, {String baseUrl}) = _ComplainingService;
|
||||
|
||||
@POST('/api/plans/{slug}/complain/{category}')
|
||||
Future<void> sendPlanComplain({
|
||||
@Path() required String slug,
|
||||
@Path() required String category,
|
||||
@Body() required ComplainModel body,
|
||||
});
|
||||
|
||||
@POST('/api/recipes/{slug}/complain/{category}')
|
||||
Future<void> sendRecipeComplain({
|
||||
@Path() required String slug,
|
||||
@Path() required String category,
|
||||
@Body() required ComplainModel body,
|
||||
});
|
||||
|
||||
@POST('/api/blogPosts/{id}/complain/{category}')
|
||||
Future<void> sendBlogPostsComplain({
|
||||
@Path() required int id,
|
||||
@Path() required String category,
|
||||
@Body() required ComplainModel body,
|
||||
});
|
||||
|
||||
@POST('/api/profile/{slug}/complain/{category}')
|
||||
Future<void> sendProfileComplain({
|
||||
@Path() required String slug,
|
||||
@Path() required String category,
|
||||
@Body() required ComplainModel body,
|
||||
});
|
||||
}
|
||||
|
||||
138
lib/features/complaining/services/complaining_service.g.dart
Normal file
138
lib/features/complaining/services/complaining_service.g.dart
Normal file
@@ -0,0 +1,138 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'complaining_service.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RetrofitGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations
|
||||
|
||||
class _ComplainingService implements ComplainingService {
|
||||
_ComplainingService(this._dio, {this.baseUrl, this.errorLogger});
|
||||
|
||||
final Dio _dio;
|
||||
|
||||
String? baseUrl;
|
||||
|
||||
final ParseErrorLogger? errorLogger;
|
||||
|
||||
@override
|
||||
Future<void> sendPlanComplain({
|
||||
required String slug,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = body;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/plans/${slug}/complain/${category}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendRecipeComplain({
|
||||
required String slug,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = body;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/recipes/${slug}/complain/${category}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendBlogPostsComplain({
|
||||
required int id,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = body;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/blogPosts/${id}/complain/${category}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> sendProfileComplain({
|
||||
required String slug,
|
||||
required String category,
|
||||
required ComplainModel body,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = body;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(method: 'POST', headers: _headers, extra: _extra)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/profile/${slug}/complain/${category}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
|
||||
);
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
requestOptions.responseType == ResponseType.stream)) {
|
||||
if (T == String) {
|
||||
requestOptions.responseType = ResponseType.plain;
|
||||
} else {
|
||||
requestOptions.responseType = ResponseType.json;
|
||||
}
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
|
||||
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
|
||||
if (baseUrl == null || baseUrl.trim().isEmpty) {
|
||||
return dioBaseUrl;
|
||||
}
|
||||
|
||||
final url = Uri.parse(baseUrl);
|
||||
|
||||
if (url.isAbsolute) {
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
|
||||
}
|
||||
}
|
||||
16
lib/features/consultant_rating/models/rating_model.dart
Normal file
16
lib/features/consultant_rating/models/rating_model.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'rating_model.freezed.dart';
|
||||
part 'rating_model.g.dart';
|
||||
|
||||
@freezed
|
||||
class RatingModel with _$RatingModel {
|
||||
|
||||
factory RatingModel({
|
||||
required DateTime date,
|
||||
required String title,
|
||||
required int amount,
|
||||
}) = _RatingModel;
|
||||
|
||||
factory RatingModel.fromJson(Map<String, dynamic> json) => _$RatingModelFromJson(json);
|
||||
}
|
||||
200
lib/features/consultant_rating/models/rating_model.freezed.dart
Normal file
200
lib/features/consultant_rating/models/rating_model.freezed.dart
Normal file
@@ -0,0 +1,200 @@
|
||||
// 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 'rating_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
RatingModel _$RatingModelFromJson(Map<String, dynamic> json) {
|
||||
return _RatingModel.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$RatingModel {
|
||||
DateTime get date => throw _privateConstructorUsedError;
|
||||
String get title => throw _privateConstructorUsedError;
|
||||
int get amount => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this RatingModel to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of RatingModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$RatingModelCopyWith<RatingModel> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $RatingModelCopyWith<$Res> {
|
||||
factory $RatingModelCopyWith(
|
||||
RatingModel value, $Res Function(RatingModel) then) =
|
||||
_$RatingModelCopyWithImpl<$Res, RatingModel>;
|
||||
@useResult
|
||||
$Res call({DateTime date, String title, int amount});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$RatingModelCopyWithImpl<$Res, $Val extends RatingModel>
|
||||
implements $RatingModelCopyWith<$Res> {
|
||||
_$RatingModelCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of RatingModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? date = null,
|
||||
Object? title = null,
|
||||
Object? amount = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
date: null == date
|
||||
? _value.date
|
||||
: date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
title: null == title
|
||||
? _value.title
|
||||
: title // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
amount: null == amount
|
||||
? _value.amount
|
||||
: amount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$RatingModelImplCopyWith<$Res>
|
||||
implements $RatingModelCopyWith<$Res> {
|
||||
factory _$$RatingModelImplCopyWith(
|
||||
_$RatingModelImpl value, $Res Function(_$RatingModelImpl) then) =
|
||||
__$$RatingModelImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({DateTime date, String title, int amount});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$RatingModelImplCopyWithImpl<$Res>
|
||||
extends _$RatingModelCopyWithImpl<$Res, _$RatingModelImpl>
|
||||
implements _$$RatingModelImplCopyWith<$Res> {
|
||||
__$$RatingModelImplCopyWithImpl(
|
||||
_$RatingModelImpl _value, $Res Function(_$RatingModelImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of RatingModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? date = null,
|
||||
Object? title = null,
|
||||
Object? amount = null,
|
||||
}) {
|
||||
return _then(_$RatingModelImpl(
|
||||
date: null == date
|
||||
? _value.date
|
||||
: date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
title: null == title
|
||||
? _value.title
|
||||
: title // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
amount: null == amount
|
||||
? _value.amount
|
||||
: amount // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$RatingModelImpl implements _RatingModel {
|
||||
_$RatingModelImpl(
|
||||
{required this.date, required this.title, required this.amount});
|
||||
|
||||
factory _$RatingModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$RatingModelImplFromJson(json);
|
||||
|
||||
@override
|
||||
final DateTime date;
|
||||
@override
|
||||
final String title;
|
||||
@override
|
||||
final int amount;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RatingModel(date: $date, title: $title, amount: $amount)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$RatingModelImpl &&
|
||||
(identical(other.date, date) || other.date == date) &&
|
||||
(identical(other.title, title) || other.title == title) &&
|
||||
(identical(other.amount, amount) || other.amount == amount));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, date, title, amount);
|
||||
|
||||
/// Create a copy of RatingModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$RatingModelImplCopyWith<_$RatingModelImpl> get copyWith =>
|
||||
__$$RatingModelImplCopyWithImpl<_$RatingModelImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$RatingModelImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _RatingModel implements RatingModel {
|
||||
factory _RatingModel(
|
||||
{required final DateTime date,
|
||||
required final String title,
|
||||
required final int amount}) = _$RatingModelImpl;
|
||||
|
||||
factory _RatingModel.fromJson(Map<String, dynamic> json) =
|
||||
_$RatingModelImpl.fromJson;
|
||||
|
||||
@override
|
||||
DateTime get date;
|
||||
@override
|
||||
String get title;
|
||||
@override
|
||||
int get amount;
|
||||
|
||||
/// Create a copy of RatingModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$RatingModelImplCopyWith<_$RatingModelImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
21
lib/features/consultant_rating/models/rating_model.g.dart
Normal file
21
lib/features/consultant_rating/models/rating_model.g.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'rating_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$RatingModelImpl _$$RatingModelImplFromJson(Map<String, dynamic> json) =>
|
||||
_$RatingModelImpl(
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
title: json['title'] as String,
|
||||
amount: (json['amount'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$RatingModelImplToJson(_$RatingModelImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'date': instance.date.toIso8601String(),
|
||||
'title': instance.title,
|
||||
'amount': instance.amount,
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_history_widget.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_widget.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/statistic_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ConsultantRatingScreen extends StatelessWidget {
|
||||
static const name = 'consultantRatingScreen';
|
||||
static const path = '/consultant-rating-screen';
|
||||
const ConsultantRatingScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const ConsultantRatingPageContent();
|
||||
}
|
||||
}
|
||||
|
||||
class ConsultantRatingPageContent extends StatelessWidget {
|
||||
const ConsultantRatingPageContent({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Scaffold(
|
||||
backgroundColor: appTheme.gray100,
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
s.rating_and_statistics,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 16),
|
||||
RatingWidget(
|
||||
rating: 1058,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: CustomOutlinedButton(
|
||||
text: s.copy_referral_link,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||
),
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
StatisticWidget(),
|
||||
SizedBox(height: 16),
|
||||
RatingHistoryWidget(
|
||||
ratingHistory: [
|
||||
RatingModel(date: DateTime.now(), title: ' djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 201300),
|
||||
RatingModel(date: DateTime.now(), title: 'djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 89323),
|
||||
RatingModel(date: DateTime.now(), title: 'djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 20),
|
||||
RatingModel(date: DateTime.now(), title: 'djkasjdasjkdkjasjkdjkaskjdjklasjkld', amount: 1212),
|
||||
RatingModel(date: DateTime.now(), title: 'qweqweeq', amount: 323),
|
||||
RatingModel(date: DateTime.now(), title: 'ee', amount: 1),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_drop_down_button.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
class PeriodFilterWidget extends StatefulWidget {
|
||||
const PeriodFilterWidget({super.key});
|
||||
|
||||
@override
|
||||
State<PeriodFilterWidget> createState() => _PeriodFilterWidgetState();
|
||||
}
|
||||
|
||||
class _PeriodFilterWidgetState extends State<PeriodFilterWidget> {
|
||||
final List<String> periodDropDownTitles = [];
|
||||
int periodDropDownIndex = 0;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final s = S.of(context);
|
||||
if (periodDropDownTitles.isEmpty) {
|
||||
periodDropDownTitles.addAll([
|
||||
s.for_whole_period_of_time,
|
||||
s.for_a_year,
|
||||
s.for_a_month,
|
||||
s.for_a_week,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CustomDropDownButton(
|
||||
hint: Text(
|
||||
s.choose_diet_duration,
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
setState(() {
|
||||
periodDropDownIndex = periodDropDownTitles.indexOf(value);
|
||||
});
|
||||
}
|
||||
},
|
||||
items: periodDropDownTitles
|
||||
.mapIndexed(
|
||||
(index, value) => DropdownMenuItem(
|
||||
child: Text(
|
||||
periodDropDownTitles[index],
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
value: periodDropDownTitles[index],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
value: periodDropDownTitles[periodDropDownIndex],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RatingHistoryItem extends StatelessWidget {
|
||||
const RatingHistoryItem({super.key, required this.title, required this.amount, required this.date});
|
||||
final String title;
|
||||
final int amount;
|
||||
final DateTime date;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 80,
|
||||
padding: EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.gray100,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
date.format('dd.MM.yyyy'),
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.gray),
|
||||
),
|
||||
Spacer(),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'+$amount',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.greenA700),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/models/rating_model.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/period_filter_widget.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/rating_history_item.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class RatingHistoryWidget extends StatelessWidget {
|
||||
const RatingHistoryWidget({super.key, required this.ratingHistory});
|
||||
final List<RatingModel> ratingHistory;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return MainBackgroundBouble(
|
||||
padding: EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 16,
|
||||
top: 16,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
s.rating_history,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset(
|
||||
'assets/icons/question_mark.svg',
|
||||
height: 22,
|
||||
width: 22,
|
||||
colorFilter: ColorFilter.mode(
|
||||
appTheme.blueA400,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
PeriodFilterWidget(),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
ListView.builder(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: index == ratingHistory.length - 1 ? EdgeInsets.zero : const EdgeInsets.only(bottom: 12),
|
||||
child: RatingHistoryItem(
|
||||
title: ratingHistory[index].title,
|
||||
amount: ratingHistory[index].amount,
|
||||
date: ratingHistory[index].date,
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: ratingHistory.length,
|
||||
shrinkWrap: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class RatingWidget extends StatelessWidget {
|
||||
const RatingWidget({super.key, required this.rating});
|
||||
|
||||
final int rating;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return MainBackgroundBouble(
|
||||
child: SizedBox(
|
||||
height: 130,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
right: 12,
|
||||
top: 12,
|
||||
child: SvgPicture.asset(
|
||||
'assets/icons/question_mark.svg',
|
||||
height: 22,
|
||||
width: 22,
|
||||
colorFilter: ColorFilter.mode(
|
||||
appTheme.blueA400,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
rating.toString(),
|
||||
style: TextStyles.headingFS40FW600.copyWith(color: appTheme.blueA400),
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
s.your_rating,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StatisticBouble extends StatelessWidget {
|
||||
const StatisticBouble({super.key, required this.number, required this.title});
|
||||
final int number;
|
||||
final String title;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 80,
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.gray100,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
number.toString(),
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.blueA400),
|
||||
),
|
||||
SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.textXSSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/period_filter_widget.dart';
|
||||
import 'package:eatvio_app/features/consultant_rating/presentation/widgets/statistic_bouble.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class StatisticWidget extends StatelessWidget {
|
||||
const StatisticWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return MainBackgroundBouble(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
s.statistic,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
Spacer(),
|
||||
SvgPicture.asset(
|
||||
'assets/icons/question_mark.svg',
|
||||
height: 22,
|
||||
width: 22,
|
||||
colorFilter: ColorFilter.mode(
|
||||
appTheme.blueA400,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
PeriodFilterWidget(),
|
||||
SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: StatisticBouble(number: 12, title: s.invited_people_count)),
|
||||
SizedBox(width: 8),
|
||||
Expanded(child: StatisticBouble(number: 12, title: s.published_posts_count)),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: StatisticBouble(number: 12, title: s.published_recipes_count)),
|
||||
SizedBox(width: 8),
|
||||
Expanded(child: StatisticBouble(number: 12, title: s.published_diets_count)),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: StatisticBouble(number: 12, title: s.consultations_count)),
|
||||
SizedBox(width: 8),
|
||||
Expanded(child: StatisticBouble(number: 12, title: s.active_consultations_count)),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ 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/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||||
import 'package:eatvio_app/core/widgets/success_published_diet_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/cubit/create_diet_state.dart';
|
||||
@@ -206,13 +207,19 @@ class _CreateDietScreenContentState extends State<CreateDietScreenContent> {
|
||||
Loader()
|
||||
else
|
||||
CustomOutlinedButton(
|
||||
onPressed: () {
|
||||
onPressed: () async {
|
||||
if (widget.diet != null) {
|
||||
context.read<CreateDietCubit>().updateDiet(
|
||||
final result = await context.read<CreateDietCubit>().updateDiet(
|
||||
widget.diet!.id,
|
||||
);
|
||||
if (result == 'error') {
|
||||
showErrorDialog(context, title: '${s.could_not_update_diet} ${state.dietData.name}');
|
||||
}
|
||||
} else {
|
||||
context.read<CreateDietCubit>().createDiet();
|
||||
final result = await context.read<CreateDietCubit>().createDiet();
|
||||
if (result == 'error') {
|
||||
showErrorDialog(context, title: '${s.could_not_publish_diet} ${state.dietData.name}');
|
||||
}
|
||||
}
|
||||
},
|
||||
text: widget.diet != null ? s.save : s.publish,
|
||||
|
||||
@@ -323,7 +323,7 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
|
||||
Future<String?> createDiet() async {
|
||||
emit(state.copyWith(isDietPublishing: true));
|
||||
if (!_isFromValid()) return null;
|
||||
if (!_isFromValid()) return 'validation';
|
||||
try {
|
||||
final image = await ImageCompressUtility.compressFile(File(state.dietData.image!.path));
|
||||
final dietState = state.dietData.state!;
|
||||
@@ -342,16 +342,16 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
);
|
||||
|
||||
emit(state.copyWith(published: dietState != DietState.draft, drafted: dietState == DietState.draft));
|
||||
return state.dietData.name;
|
||||
return null;
|
||||
} on DioException catch (e, stackTrace) {
|
||||
log(e.toString(), stackTrace: stackTrace);
|
||||
}
|
||||
emit(state.copyWith(isDietPublishing: false));
|
||||
return null;
|
||||
return 'error';
|
||||
}
|
||||
|
||||
Future<String?> updateDiet(int dietId) async {
|
||||
if (!_isFromValid()) return null;
|
||||
if (!_isFromValid()) return 'error';
|
||||
try {
|
||||
File? image;
|
||||
if (state.dietData.image != null) {
|
||||
@@ -373,7 +373,7 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
return null;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
return 'Произошла непредвиденная ошибка';
|
||||
return 'error';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
|
||||
@@ -48,7 +48,7 @@ class CreateDietRepository {
|
||||
),
|
||||
});
|
||||
|
||||
final formData = FormData.fromMap(dietMap);
|
||||
final formData = FormData.fromMap(dietMap);
|
||||
switch (state) {
|
||||
case DietState.active:
|
||||
return createDietService.createPublishedDiet(formData: formData);
|
||||
|
||||
@@ -26,21 +26,21 @@ abstract class CreateDietService {
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@PUT('/api/diets/update/published/{diet}')
|
||||
@POST('/api/diets/update/published/{diet}')
|
||||
@MultiPart()
|
||||
Future<void> updatePublished({
|
||||
@Path() required int diet,
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@PUT('/api/diets/update/drafted/{diet}')
|
||||
@POST('/api/diets/update/drafted/{diet}')
|
||||
@MultiPart()
|
||||
Future<void> updateDrafted({
|
||||
@Path() required int diet,
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@PUT('/api/diets/update/personalized/{diet}')
|
||||
@POST('/api/diets/update/personalized/{diet}')
|
||||
@MultiPart()
|
||||
Future<void> updatePersonal({
|
||||
@Path() required int diet,
|
||||
|
||||
@@ -124,7 +124,7 @@ class _CreateDietService implements CreateDietService {
|
||||
final _data = formData;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(
|
||||
method: 'PUT',
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
contentType: 'multipart/form-data',
|
||||
@@ -151,7 +151,7 @@ class _CreateDietService implements CreateDietService {
|
||||
final _data = formData;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(
|
||||
method: 'PUT',
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
contentType: 'multipart/form-data',
|
||||
@@ -178,7 +178,7 @@ class _CreateDietService implements CreateDietService {
|
||||
final _data = formData;
|
||||
final _options = _setStreamType<void>(
|
||||
Options(
|
||||
method: 'PUT',
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
contentType: 'multipart/form-data',
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart';
|
||||
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||||
import 'package:eatvio_app/core/widgets/success_published_recipe_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/bloc/create_recipe_cubit/create_recipe_state.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/info_about_recipe_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/ingredients_widget.dart';
|
||||
import 'package:eatvio_app/features/create_recipe/presentation/widgets/steps_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class RecipeCreateScreen extends StatefulWidget {
|
||||
const RecipeCreateScreen({super.key});
|
||||
@@ -22,6 +26,7 @@ class RecipeCreateScreen extends StatefulWidget {
|
||||
class _RecipeCreateScreenState extends State<RecipeCreateScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
return BlocProvider<CreateRecipeCubit>(
|
||||
create: (BuildContext context) => sl<CreateRecipeCubit>(),
|
||||
child: Scaffold(
|
||||
@@ -53,10 +58,18 @@ class _RecipeCreateScreenState extends State<RecipeCreateScreen> {
|
||||
if (context.read<CreateRecipeCubit>().validateAll()) {
|
||||
final isSuccess = await context.read<CreateRecipeCubit>().publishRecipe();
|
||||
if (isSuccess) {
|
||||
showSuccessToast('Рецепт успешно опубликован');
|
||||
Navigator.pop(context);
|
||||
Future.delayed(Duration(milliseconds: 500), () {
|
||||
context.pop();
|
||||
showBottomSheetWithBlur(
|
||||
userRootNavigator: true,
|
||||
context: context,
|
||||
child: SuccessPublishedRecipeBottomSheet(
|
||||
title: state.entity.title ?? 'Рецепт',
|
||||
),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
showErrorToast('Не удалось опубликовать рецепт');
|
||||
showErrorDialog(context, title: '${s.could_not_publish_recipe} ${state.entity.title}');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
|
||||
@@ -27,6 +28,11 @@ class _DiaryScreenState extends State<DiaryScreen> {
|
||||
if (state is DiaryStateLoaded) {
|
||||
log(state.diary.id.toString());
|
||||
}
|
||||
if (state is DiaryStateError) {
|
||||
return Scaffold(
|
||||
body: DataErrorWidget(onReload: context.read<DiaryCubit>().fetchDiary()),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
appBar: AppBar(
|
||||
|
||||
@@ -26,6 +26,7 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
emit(AboutDietState.loaded(diet: diet, isStarted: isCurrentDietStarted, hasStartedDiet: hasStartedDiet));
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(AboutDietState.error(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +50,7 @@ class AboutDietCubit extends Cubit<AboutDietState> {
|
||||
emit(AboutDietState.loaded(diet: diet, isStarted: isCurrentDietStarted, hasStartedDiet: hasStartedDiet));
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(AboutDietState.error(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@ import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_cubit.dart';
|
||||
@@ -314,6 +316,8 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
path: 'diet/${widget.diet.id}',
|
||||
complainedContentType: ComplainedContent.diet,
|
||||
id: widget.diet.id,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
@@ -420,7 +424,10 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
InfoRow(diet: widget.diet, type: ProductType.diet,),
|
||||
InfoRow(
|
||||
diet: widget.diet,
|
||||
type: ProductType.diet,
|
||||
),
|
||||
ExpandableText(
|
||||
text: widget.diet.details,
|
||||
),
|
||||
@@ -490,7 +497,90 @@ class _AboutDietScreenState extends State<AboutDietScreen> {
|
||||
),
|
||||
);
|
||||
}
|
||||
if (dietState is DietStateError) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.diet.name,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
path: 'diet/${widget.diet.id}',
|
||||
complainedContentType: ComplainedContent.diet,
|
||||
id: widget.diet.id,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: DataErrorWidget(
|
||||
onReload: () => context.read<AboutDietCubit>().getDiet(widget.diet.id, index: widget.index),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.diet.name,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
path: 'diet/${widget.diet.id}',
|
||||
complainedContentType: ComplainedContent.diet,
|
||||
id: widget.diet.id,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: const Loader(),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_divider.dart';
|
||||
import 'package:eatvio_app/core/widgets/main_background_bouble.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
@@ -8,12 +10,13 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class MoreOptions extends StatelessWidget {
|
||||
const MoreOptions({super.key, this.disableActions, required this.path});
|
||||
|
||||
const MoreOptions({super.key, this.disableActions, required this.path, this.complainedContentType, this.slug, this.id});
|
||||
final ComplainedContent? complainedContentType;
|
||||
final int? id;
|
||||
final String? slug;
|
||||
final String path;
|
||||
final bool? disableActions;
|
||||
|
||||
@@ -84,7 +87,16 @@ class MoreOptions extends StatelessWidget {
|
||||
onTap: disableActions == true
|
||||
? null
|
||||
: () {
|
||||
context.push('complainingScreen');
|
||||
if (complainedContentType != null) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => ComplainingBottomSheet(
|
||||
complainedContentType: complainedContentType!,
|
||||
id: id,
|
||||
slug: slug,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
@@ -6,57 +6,49 @@ part of 'diets_pagination_model.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$DietsPaginationImpl _$$DietsPaginationImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$DietsPaginationImpl(
|
||||
data: (json['data'] as List<dynamic>)
|
||||
.map((e) => Diet.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
_$DietsPaginationImpl _$$DietsPaginationImplFromJson(Map<String, dynamic> json) => _$DietsPaginationImpl(
|
||||
data: (json['data'] as List<dynamic>).map((e) => Diet.fromJson(e as Map<String, dynamic>)).toList(),
|
||||
links: Links.fromJson(json['links'] as Map<String, dynamic>),
|
||||
meta: Meta.fromJson(json['meta'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DietsPaginationImplToJson(
|
||||
_$DietsPaginationImpl instance) =>
|
||||
<String, dynamic>{
|
||||
Map<String, dynamic> _$$DietsPaginationImplToJson(_$DietsPaginationImpl instance) => <String, dynamic>{
|
||||
'data': instance.data,
|
||||
'links': instance.links,
|
||||
'meta': instance.meta,
|
||||
};
|
||||
|
||||
_$DietImpl _$$DietImplFromJson(Map<String, dynamic> json) => _$DietImpl(
|
||||
id: (json['id'] as num).toInt(),
|
||||
name: json['name'] as String,
|
||||
image: json['image'] as String,
|
||||
duration: (json['duration'] as num).toInt(),
|
||||
state: $enumDecode(_$DietStateEnumMap, json['state']),
|
||||
type: DietType.fromJson(json['type'] as Map<String, dynamic>),
|
||||
details: json['details'] as String,
|
||||
dailySchedule: (json['daily_schedule'] as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(
|
||||
int.parse(k),
|
||||
(e as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(
|
||||
int.parse(k),
|
||||
(e as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(int.parse(k),
|
||||
DailySchedule.fromJson(e as Map<String, dynamic>)),
|
||||
)),
|
||||
)),
|
||||
),
|
||||
author: Author.fromJson(json['author'] as Map<String, dynamic>),
|
||||
totalLikes: (json['total_likes'] as num).toInt(),
|
||||
totalViews: (json['total_views'] as num).toInt(),
|
||||
totalComments: (json['total_comments'] as num).toInt(),
|
||||
wasLikedByMe: json['was_liked_by_me'] as bool,
|
||||
isFavorite: json['is_favorite'] as bool,
|
||||
dailyNutrition: (json['daily_nutrition'] as List<dynamic>)
|
||||
.map((e) => DailyNutrition.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
_$DietImpl _$$DietImplFromJson(Map<String, dynamic> json) {
|
||||
return _$DietImpl(
|
||||
id: (json['id'] as num).toInt(),
|
||||
name: json['name'] as String,
|
||||
image: json['image'] as String,
|
||||
duration: (json['duration'] as num).toInt(),
|
||||
state: $enumDecode(_$DietStateEnumMap, json['state']),
|
||||
type: DietType.fromJson(json['type'] as Map<String, dynamic>),
|
||||
details: json['details'] as String,
|
||||
dailySchedule: (json['daily_schedule'] as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(
|
||||
int.parse(k),
|
||||
(e as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(
|
||||
int.parse(k),
|
||||
(e as Map<String, dynamic>).map(
|
||||
(k, e) => MapEntry(int.parse(k), DailySchedule.fromJson(e as Map<String, dynamic>)),
|
||||
)),
|
||||
)),
|
||||
),
|
||||
author: Author.fromJson(json['author'] as Map<String, dynamic>),
|
||||
totalLikes: (json['total_likes'] as num).toInt(),
|
||||
totalViews: (json['total_views'] as num).toInt(),
|
||||
totalComments: (json['total_comments'] as num).toInt(),
|
||||
wasLikedByMe: json['was_liked_by_me'] as bool,
|
||||
isFavorite: json['is_favorite'] as bool,
|
||||
dailyNutrition: (json['daily_nutrition'] as List<dynamic>).map((e) => DailyNutrition.fromJson(e as Map<String, dynamic>)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$$DietImplToJson(_$DietImpl instance) =>
|
||||
<String, dynamic>{
|
||||
Map<String, dynamic> _$$DietImplToJson(_$DietImpl instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'name': instance.name,
|
||||
'image': instance.image,
|
||||
@@ -64,10 +56,8 @@ Map<String, dynamic> _$$DietImplToJson(_$DietImpl instance) =>
|
||||
'state': _$DietStateEnumMap[instance.state]!,
|
||||
'type': instance.type,
|
||||
'details': instance.details,
|
||||
'daily_schedule': instance.dailySchedule.map((k, e) => MapEntry(
|
||||
k.toString(),
|
||||
e.map((k, e) => MapEntry(
|
||||
k.toString(), e.map((k, e) => MapEntry(k.toString(), e)))))),
|
||||
'daily_schedule':
|
||||
instance.dailySchedule.map((k, e) => MapEntry(k.toString(), e.map((k, e) => MapEntry(k.toString(), e.map((k, e) => MapEntry(k.toString(), e)))))),
|
||||
'author': instance.author,
|
||||
'total_likes': instance.totalLikes,
|
||||
'total_views': instance.totalViews,
|
||||
@@ -83,13 +73,11 @@ const _$DietStateEnumMap = {
|
||||
DietState.personal: 'personal',
|
||||
};
|
||||
|
||||
_$CreatedDietImpl _$$CreatedDietImplFromJson(Map<String, dynamic> json) =>
|
||||
_$CreatedDietImpl(
|
||||
_$CreatedDietImpl _$$CreatedDietImplFromJson(Map<String, dynamic> json) => _$CreatedDietImpl(
|
||||
id: (json['id'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$CreatedDietImplToJson(_$CreatedDietImpl instance) =>
|
||||
<String, dynamic>{
|
||||
Map<String, dynamic> _$$CreatedDietImplToJson(_$CreatedDietImpl instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
};
|
||||
|
||||
@@ -102,8 +90,7 @@ _$AuthorImpl _$$AuthorImplFromJson(Map<String, dynamic> json) => _$AuthorImpl(
|
||||
authorPlaceInRating: (json['author_place_in_rating'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$AuthorImplToJson(_$AuthorImpl instance) =>
|
||||
<String, dynamic>{
|
||||
Map<String, dynamic> _$$AuthorImplToJson(_$AuthorImpl instance) => <String, dynamic>{
|
||||
'author_slug': instance.authorSlug,
|
||||
'author_name': instance.authorName,
|
||||
'author_profile_icon': instance.authorProfileIcon,
|
||||
@@ -112,23 +99,18 @@ Map<String, dynamic> _$$AuthorImplToJson(_$AuthorImpl instance) =>
|
||||
'author_place_in_rating': instance.authorPlaceInRating,
|
||||
};
|
||||
|
||||
_$DailyScheduleImpl _$$DailyScheduleImplFromJson(Map<String, dynamic> json) =>
|
||||
_$DailyScheduleImpl(
|
||||
_$DailyScheduleImpl _$$DailyScheduleImplFromJson(Map<String, dynamic> json) => _$DailyScheduleImpl(
|
||||
name: json['name'] as String,
|
||||
portion: $enumDecode(_$PortionEnumMap, json['portion']),
|
||||
quantity: _parseQuantity(json['quantity']),
|
||||
dailyNutrition: json['nutrition'] == null
|
||||
? null
|
||||
: DailyNutrition.fromJson(json['nutrition'] as Map<String, dynamic>),
|
||||
dailyNutrition: json['nutrition'] == null ? null : DailyNutrition.fromJson(json['nutrition'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DailyScheduleImplToJson(_$DailyScheduleImpl instance) =>
|
||||
<String, dynamic>{
|
||||
Map<String, dynamic> _$$DailyScheduleImplToJson(_$DailyScheduleImpl instance) => <String, dynamic>{
|
||||
'name': instance.name,
|
||||
'portion': _$PortionEnumMap[instance.portion]!,
|
||||
'quantity': instance.quantity,
|
||||
if (instance.productNutritionalValueId case final value?)
|
||||
'product_nutritional_value_id': value,
|
||||
if (instance.productNutritionalValueId case final value?) 'product_nutritional_value_id': value,
|
||||
};
|
||||
|
||||
const _$PortionEnumMap = {
|
||||
@@ -137,33 +119,28 @@ const _$PortionEnumMap = {
|
||||
Portion.PCS: 'pcs',
|
||||
};
|
||||
|
||||
_$DietTypeImpl _$$DietTypeImplFromJson(Map<String, dynamic> json) =>
|
||||
_$DietTypeImpl(
|
||||
_$DietTypeImpl _$$DietTypeImplFromJson(Map<String, dynamic> json) => _$DietTypeImpl(
|
||||
light: json['light'] as bool?,
|
||||
veg: json['veg'] as bool?,
|
||||
carb: json['carb'] as bool?,
|
||||
meat: json['meat'] as bool?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DietTypeImplToJson(_$DietTypeImpl instance) =>
|
||||
<String, dynamic>{
|
||||
Map<String, dynamic> _$$DietTypeImplToJson(_$DietTypeImpl instance) => <String, dynamic>{
|
||||
'light': instance.light,
|
||||
'veg': instance.veg,
|
||||
'carb': instance.carb,
|
||||
'meat': instance.meat,
|
||||
};
|
||||
|
||||
_$DailyNutritionImpl _$$DailyNutritionImplFromJson(Map<String, dynamic> json) =>
|
||||
_$DailyNutritionImpl(
|
||||
_$DailyNutritionImpl _$$DailyNutritionImplFromJson(Map<String, dynamic> json) => _$DailyNutritionImpl(
|
||||
energy: (json['energy'] as num).toDouble(),
|
||||
proteins: (json['proteins'] as num).toDouble(),
|
||||
fats: (json['fats'] as num).toDouble(),
|
||||
carbohydrates: (json['carbohydrates'] as num).toDouble(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DailyNutritionImplToJson(
|
||||
_$DailyNutritionImpl instance) =>
|
||||
<String, dynamic>{
|
||||
Map<String, dynamic> _$$DailyNutritionImplToJson(_$DailyNutritionImpl instance) => <String, dynamic>{
|
||||
'energy': instance.energy,
|
||||
'proteins': instance.proteins,
|
||||
'fats': instance.fats,
|
||||
|
||||
@@ -110,7 +110,7 @@ class DietsCubit extends Cubit<DietsState> {
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
emit(
|
||||
state.copyWith(isLoading: false),
|
||||
state.copyWith(isLoading: false, errorMessage: e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -144,13 +144,15 @@ class DietsCubit extends Cubit<DietsState> {
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
emit(state.copyWith(isLoading: false));
|
||||
emit(
|
||||
state.copyWith(isLoading: false, errorMessage: e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> likeDiet(int id, int index) async {
|
||||
final currentDiets = state.dietsList;
|
||||
final currentDiets = state.dietsList;
|
||||
final dietsForModification = [...currentDiets];
|
||||
final currentDiet = currentDiets[index];
|
||||
if (currentDiet.wasLikedByMe) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import 'package:eatvio_app/features/create_recipe/presentation/pages/recipe_crea
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../widgets/recipes.dart';
|
||||
|
||||
class FeedScreen extends StatelessWidget {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
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';
|
||||
@@ -31,14 +32,8 @@ class BlogPosts extends StatelessWidget {
|
||||
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),
|
||||
),
|
||||
),
|
||||
return DataErrorWidget(
|
||||
onReload: () => context.read<FeedCubit>().loadFeedBlogPostList(),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
@@ -50,4 +45,4 @@ class BlogPosts extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/consultants_cubit/consultants_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/consultants_cubit/consultants_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/consultant_widget.dart';
|
||||
@@ -12,7 +13,7 @@ class Consultants extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => context.read<ConsultantsCubit>().getConsultants(),
|
||||
child: BlocBuilder<ConsultantsCubit, ConsultantsState>(
|
||||
child: BlocBuilder<ConsultantsCubit, ConsultantsState>(
|
||||
builder: (BuildContext context, ConsultantsState state) {
|
||||
if (state is ConsultantsStateLoaded) {
|
||||
return Padding(
|
||||
@@ -38,15 +39,7 @@ class Consultants extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
} else if (state is ConsultantsStateError) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.errorMessage),
|
||||
),
|
||||
),
|
||||
);
|
||||
return DataErrorWidget(onReload: () => context.read<ConsultantsCubit>().getConsultants());
|
||||
} else {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
@@ -58,5 +51,3 @@ class Consultants extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
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';
|
||||
@@ -22,15 +23,7 @@ class Diets extends StatelessWidget {
|
||||
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 DataErrorWidget(onReload: () => context.read<DietsCubit>().loadDiets());
|
||||
} else {
|
||||
return Stack(
|
||||
children: [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
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';
|
||||
@@ -22,15 +23,7 @@ class Plans extends StatelessWidget {
|
||||
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 DataErrorWidget(onReload: () => context.read<PlansCubit>().loadPlans());
|
||||
}
|
||||
return Stack(
|
||||
children: [
|
||||
@@ -65,4 +58,4 @@ class Plans extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
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';
|
||||
@@ -21,14 +22,10 @@ class Recipes extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
if (state.errorMessage != null) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.errorMessage ?? ''),
|
||||
),
|
||||
),
|
||||
return DataErrorWidget(
|
||||
onReload: () async {
|
||||
context.read<RecipesCubit>().loadRecipesList();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class InternetConnectionCheckerScreen extends StatefulWidget {
|
||||
@@ -128,11 +129,12 @@ class NoInternetScreen extends StatelessWidget {
|
||||
body: Column(
|
||||
children: [
|
||||
Spacer(),
|
||||
SvgPicture.asset('assets/icons/no_internet.svg'),
|
||||
SizedBox(height: 28),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 52),
|
||||
child: Text(
|
||||
'Отсутствует подключение к интернету',
|
||||
'Отсутствует подключение \nк интернету',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyles.headingXLSemibold.copyWith(
|
||||
color: appTheme.black,
|
||||
|
||||
@@ -207,13 +207,14 @@ class MyDietsCubit extends Cubit<MyDietsState> {
|
||||
state.copyWith(
|
||||
activeDiets: dietsPagination.data,
|
||||
isLoading: isLoadingActive,
|
||||
activeDietsError: null,
|
||||
error: null,
|
||||
),
|
||||
);
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
emit(
|
||||
state.copyWith(error: e.toString()),
|
||||
state.copyWith(activeDietsError: e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -237,12 +238,13 @@ class MyDietsCubit extends Cubit<MyDietsState> {
|
||||
state.copyWith(
|
||||
draftDiets: dietsPagination.data,
|
||||
isLoading: isLoadingDraft,
|
||||
draftDietsError: null,
|
||||
error: null,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(error: e.toString()),
|
||||
state.copyWith(draftDietsError: e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -266,19 +268,20 @@ class MyDietsCubit extends Cubit<MyDietsState> {
|
||||
state.copyWith(
|
||||
personalDiets: dietsPagination.data,
|
||||
isLoading: isLoadingPersonal,
|
||||
personalDietsError: null,
|
||||
error: null,
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
emit(
|
||||
state.copyWith(error: e.toString()),
|
||||
state.copyWith(personalDietsError: e.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> deleteDiet(int dietId) async {
|
||||
try {
|
||||
await myDietsRepository.deleteDiet(dietId);
|
||||
await myDietsRepository.deleteDiet(dietId);
|
||||
return true;
|
||||
} catch (e) {
|
||||
emit(
|
||||
@@ -293,7 +296,7 @@ class MyDietsCubit extends Cubit<MyDietsState> {
|
||||
await createDietRepository.updateDiet(
|
||||
dietId: dietId,
|
||||
state: DietState.active,
|
||||
);
|
||||
);
|
||||
return true;
|
||||
} catch (e, st) {
|
||||
log(e.toString(), stackTrace: st);
|
||||
|
||||
@@ -11,6 +11,9 @@ class MyDietsState with _$MyDietsState {
|
||||
@Default([]) List<Diet> draftDiets,
|
||||
@Default([]) List<Diet> personalDiets,
|
||||
@Default(false) bool isLoading,
|
||||
@Default(null) String? activeDietsError,
|
||||
@Default(null) String? draftDietsError,
|
||||
@Default(null) String? personalDietsError,
|
||||
@Default(null) String? error,
|
||||
@Default(0) int selectedStateIndex,
|
||||
@Default(
|
||||
|
||||
@@ -20,6 +20,9 @@ mixin _$MyDietsState {
|
||||
List<Diet> get draftDiets => throw _privateConstructorUsedError;
|
||||
List<Diet> get personalDiets => throw _privateConstructorUsedError;
|
||||
bool get isLoading => throw _privateConstructorUsedError;
|
||||
String? get activeDietsError => throw _privateConstructorUsedError;
|
||||
String? get draftDietsError => throw _privateConstructorUsedError;
|
||||
String? get personalDietsError => throw _privateConstructorUsedError;
|
||||
String? get error => throw _privateConstructorUsedError;
|
||||
int get selectedStateIndex => throw _privateConstructorUsedError;
|
||||
DietsFilterState get activeFilterState => throw _privateConstructorUsedError;
|
||||
@@ -45,6 +48,9 @@ abstract class $MyDietsStateCopyWith<$Res> {
|
||||
List<Diet> draftDiets,
|
||||
List<Diet> personalDiets,
|
||||
bool isLoading,
|
||||
String? activeDietsError,
|
||||
String? draftDietsError,
|
||||
String? personalDietsError,
|
||||
String? error,
|
||||
int selectedStateIndex,
|
||||
DietsFilterState activeFilterState,
|
||||
@@ -75,6 +81,9 @@ class _$MyDietsStateCopyWithImpl<$Res, $Val extends MyDietsState>
|
||||
Object? draftDiets = null,
|
||||
Object? personalDiets = null,
|
||||
Object? isLoading = null,
|
||||
Object? activeDietsError = freezed,
|
||||
Object? draftDietsError = freezed,
|
||||
Object? personalDietsError = freezed,
|
||||
Object? error = freezed,
|
||||
Object? selectedStateIndex = null,
|
||||
Object? activeFilterState = null,
|
||||
@@ -98,6 +107,18 @@ class _$MyDietsStateCopyWithImpl<$Res, $Val extends MyDietsState>
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
activeDietsError: freezed == activeDietsError
|
||||
? _value.activeDietsError
|
||||
: activeDietsError // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
draftDietsError: freezed == draftDietsError
|
||||
? _value.draftDietsError
|
||||
: draftDietsError // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
personalDietsError: freezed == personalDietsError
|
||||
? _value.personalDietsError
|
||||
: personalDietsError // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
error: freezed == error
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
@@ -165,6 +186,9 @@ abstract class _$$MyDietsStateImplCopyWith<$Res>
|
||||
List<Diet> draftDiets,
|
||||
List<Diet> personalDiets,
|
||||
bool isLoading,
|
||||
String? activeDietsError,
|
||||
String? draftDietsError,
|
||||
String? personalDietsError,
|
||||
String? error,
|
||||
int selectedStateIndex,
|
||||
DietsFilterState activeFilterState,
|
||||
@@ -196,6 +220,9 @@ class __$$MyDietsStateImplCopyWithImpl<$Res>
|
||||
Object? draftDiets = null,
|
||||
Object? personalDiets = null,
|
||||
Object? isLoading = null,
|
||||
Object? activeDietsError = freezed,
|
||||
Object? draftDietsError = freezed,
|
||||
Object? personalDietsError = freezed,
|
||||
Object? error = freezed,
|
||||
Object? selectedStateIndex = null,
|
||||
Object? activeFilterState = null,
|
||||
@@ -219,6 +246,18 @@ class __$$MyDietsStateImplCopyWithImpl<$Res>
|
||||
? _value.isLoading
|
||||
: isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
activeDietsError: freezed == activeDietsError
|
||||
? _value.activeDietsError
|
||||
: activeDietsError // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
draftDietsError: freezed == draftDietsError
|
||||
? _value.draftDietsError
|
||||
: draftDietsError // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
personalDietsError: freezed == personalDietsError
|
||||
? _value.personalDietsError
|
||||
: personalDietsError // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
error: freezed == error
|
||||
? _value.error
|
||||
: error // ignore: cast_nullable_to_non_nullable
|
||||
@@ -251,6 +290,9 @@ class _$MyDietsStateImpl implements _MyDietsState {
|
||||
final List<Diet> draftDiets = const [],
|
||||
final List<Diet> personalDiets = const [],
|
||||
this.isLoading = false,
|
||||
this.activeDietsError = null,
|
||||
this.draftDietsError = null,
|
||||
this.personalDietsError = null,
|
||||
this.error = null,
|
||||
this.selectedStateIndex = 0,
|
||||
this.activeFilterState = const DietsFilterState(
|
||||
@@ -295,6 +337,15 @@ class _$MyDietsStateImpl implements _MyDietsState {
|
||||
final bool isLoading;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? activeDietsError;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? draftDietsError;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? personalDietsError;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? error;
|
||||
@override
|
||||
@JsonKey()
|
||||
@@ -311,7 +362,7 @@ class _$MyDietsStateImpl implements _MyDietsState {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MyDietsState(activeDiets: $activeDiets, draftDiets: $draftDiets, personalDiets: $personalDiets, isLoading: $isLoading, error: $error, selectedStateIndex: $selectedStateIndex, activeFilterState: $activeFilterState, draftFilterState: $draftFilterState, personalFilterState: $personalFilterState)';
|
||||
return 'MyDietsState(activeDiets: $activeDiets, draftDiets: $draftDiets, personalDiets: $personalDiets, isLoading: $isLoading, activeDietsError: $activeDietsError, draftDietsError: $draftDietsError, personalDietsError: $personalDietsError, error: $error, selectedStateIndex: $selectedStateIndex, activeFilterState: $activeFilterState, draftFilterState: $draftFilterState, personalFilterState: $personalFilterState)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -327,6 +378,12 @@ class _$MyDietsStateImpl implements _MyDietsState {
|
||||
.equals(other._personalDiets, _personalDiets) &&
|
||||
(identical(other.isLoading, isLoading) ||
|
||||
other.isLoading == isLoading) &&
|
||||
(identical(other.activeDietsError, activeDietsError) ||
|
||||
other.activeDietsError == activeDietsError) &&
|
||||
(identical(other.draftDietsError, draftDietsError) ||
|
||||
other.draftDietsError == draftDietsError) &&
|
||||
(identical(other.personalDietsError, personalDietsError) ||
|
||||
other.personalDietsError == personalDietsError) &&
|
||||
(identical(other.error, error) || other.error == error) &&
|
||||
(identical(other.selectedStateIndex, selectedStateIndex) ||
|
||||
other.selectedStateIndex == selectedStateIndex) &&
|
||||
@@ -345,6 +402,9 @@ class _$MyDietsStateImpl implements _MyDietsState {
|
||||
const DeepCollectionEquality().hash(_draftDiets),
|
||||
const DeepCollectionEquality().hash(_personalDiets),
|
||||
isLoading,
|
||||
activeDietsError,
|
||||
draftDietsError,
|
||||
personalDietsError,
|
||||
error,
|
||||
selectedStateIndex,
|
||||
activeFilterState,
|
||||
@@ -366,6 +426,9 @@ abstract class _MyDietsState implements MyDietsState {
|
||||
final List<Diet> draftDiets,
|
||||
final List<Diet> personalDiets,
|
||||
final bool isLoading,
|
||||
final String? activeDietsError,
|
||||
final String? draftDietsError,
|
||||
final String? personalDietsError,
|
||||
final String? error,
|
||||
final int selectedStateIndex,
|
||||
final DietsFilterState activeFilterState,
|
||||
@@ -381,6 +444,12 @@ abstract class _MyDietsState implements MyDietsState {
|
||||
@override
|
||||
bool get isLoading;
|
||||
@override
|
||||
String? get activeDietsError;
|
||||
@override
|
||||
String? get draftDietsError;
|
||||
@override
|
||||
String? get personalDietsError;
|
||||
@override
|
||||
String? get error;
|
||||
@override
|
||||
int get selectedStateIndex;
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/add_item_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_search_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/create_diet_screen.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/diet_filter_bottom_sheet.dart';
|
||||
@@ -142,21 +143,26 @@ class MyDietsScreenContent extends StatelessWidget {
|
||||
body: const Loader(),
|
||||
);
|
||||
} else if (state.error != null) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.error ?? ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
return DataErrorWidget(onReload: () => context.read<MyDietsCubit>().loadAllDiets());
|
||||
} else {
|
||||
final gotDietLoadingError = state.activeDietsError != null && state.selectedStateIndex == 0 ||
|
||||
state.draftDietsError != null && state.selectedStateIndex == 1 ||
|
||||
state.personalDietsError != null && state.selectedStateIndex == 2;
|
||||
|
||||
if (gotDietLoadingError) {
|
||||
return DataErrorWidget(onReload: () => context.read<MyDietsCubit>().loadCurrentDiets());
|
||||
}
|
||||
|
||||
if (state.isLoading) {
|
||||
return Loader();
|
||||
}
|
||||
|
||||
final diets = switch (state.selectedStateIndex) {
|
||||
1 => state.draftDiets,
|
||||
2 => state.personalDiets,
|
||||
_ => state.activeDiets,
|
||||
};
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
SizedBox.expand(),
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/add_item_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_search_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/create_plan/presentation/create_plan_screen.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/filter_badge.dart';
|
||||
@@ -138,15 +139,7 @@ class MyPlansScreenContent extends StatelessWidget {
|
||||
body: const Loader(),
|
||||
);
|
||||
} else if (state.error != null) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.grey.shade200,
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(
|
||||
child: Text(state.error ?? ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
return DataErrorWidget(onReload: () => context.read<MyPlansCubit>().loadPlans());
|
||||
} else {
|
||||
final plans = switch (state.selectedStateIndex) {
|
||||
1 => state.draftPlans,
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
|
||||
@@ -17,7 +17,7 @@ class AboutPlanCubit extends Cubit<AboutPlanState> {
|
||||
emit(state.copyWith(planModel: plan, error: null));
|
||||
} catch (e, stackTrace) {
|
||||
log(e.toString(), stackTrace: stackTrace);
|
||||
emit(state.copyWith(error: e.toString()));
|
||||
emit(state.copyWith(error: e.toString(), isLoading: false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@ import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart';
|
||||
@@ -94,12 +96,96 @@ class _AboutPlanScreenState extends State<AboutPlanScreen> {
|
||||
builder: (BuildContext context, CommentsState commentsState) {
|
||||
return BlocBuilder<AboutPlanCubit, AboutPlanState>(
|
||||
builder: (context, state) {
|
||||
if (state.isLoading) return Scaffold(body: Loader());
|
||||
if (state.isLoading)
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.plan.name,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
complainedContentType: ComplainedContent.plan,
|
||||
path: 'plan/${widget.plan.id}',
|
||||
slug: widget.plan.slug,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Loader(),
|
||||
);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (widget.navigateToComments && !_jumped) {
|
||||
_scrollToBottom();
|
||||
}
|
||||
});
|
||||
if (state.error != null) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.plan.name,
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
complainedContentType: ComplainedContent.plan,
|
||||
path: 'plan/${widget.plan.id}',
|
||||
slug: widget.plan.slug,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: DataErrorWidget(onReload: () => context.read<AboutPlanCubit>().getPlan(widget.plan.slug)),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
backgroundColor: appTheme.gray100,
|
||||
resizeToAvoidBottomInset: true,
|
||||
@@ -294,7 +380,9 @@ class _AboutPlanScreenState extends State<AboutPlanScreen> {
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
complainedContentType: ComplainedContent.plan,
|
||||
path: 'plan/${widget.plan.id}',
|
||||
slug: widget.plan.slug,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
|
||||
@@ -17,7 +17,7 @@ class ProfileCubit extends Cubit<ProfileState> {
|
||||
required this.chatRepository,
|
||||
}) : super(const ProfileState.loading());
|
||||
|
||||
getProfileBySlug(String slug) async {
|
||||
Future<void> getProfileBySlug(String slug) async {
|
||||
try {
|
||||
emit(
|
||||
ProfileState.loaded(
|
||||
@@ -31,7 +31,7 @@ class ProfileCubit extends Cubit<ProfileState> {
|
||||
}
|
||||
}
|
||||
|
||||
getMyProfile({
|
||||
Future<void> getMyProfile({
|
||||
String period = '1',
|
||||
}) async {
|
||||
_currentPeriod = period;
|
||||
|
||||
@@ -3,10 +3,13 @@ import 'dart:io';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:dismissible_page/dismissible_page.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/plan_widget.dart';
|
||||
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
|
||||
@@ -88,14 +91,10 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
}
|
||||
return widget.author == null ? _myProfileScreen(state) : _profileScreen(state);
|
||||
} else if (state is ProfileStateError) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text(state.errorMessage),
|
||||
),
|
||||
),
|
||||
return DataErrorWidget(
|
||||
onReload: () async {
|
||||
widget.author == null ? await profileCubit.getMyProfile() : await profileCubit.getProfileBySlug(widget.author!.authorSlug);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
@@ -578,7 +577,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
() {
|
||||
launchUrl(
|
||||
Uri.parse(
|
||||
state.profile.educationResource?.vkLink ?? '',
|
||||
state.profile.educationResource?.vkLink ?? '',
|
||||
),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
@@ -1011,19 +1010,34 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
const Spacer(),
|
||||
PopupMenuButton(
|
||||
onSelected: (value) {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/profile/' + state.profile.slug,
|
||||
),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
if (value == 'share') {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/profile/' + state.profile.slug,
|
||||
),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
);
|
||||
} else {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => ComplainingBottomSheet(
|
||||
complainedContentType: ComplainedContent.profile,
|
||||
slug: widget.author?.authorSlug,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: 'share',
|
||||
child: Text('Поделиться'),
|
||||
),
|
||||
if (widget.author != null)
|
||||
PopupMenuItem(
|
||||
value: 'complain',
|
||||
child: Text('Пожаловаться'),
|
||||
),
|
||||
],
|
||||
child: Icon(Icons.more_horiz_rounded),
|
||||
),
|
||||
|
||||
@@ -3,11 +3,13 @@ import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/enums.dart';
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/enums/product_type.dart';
|
||||
import 'package:eatvio_app/core/utils/localization_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||
import 'package:eatvio_app/core/widgets/bookmark_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart';
|
||||
@@ -243,7 +245,9 @@ class _AboutRecipeScreenState extends State<AboutRecipeScreen> {
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
complainedContentType: ComplainedContent.recipe,
|
||||
path: 'recipe/${widget.recipe.slug}',
|
||||
slug: widget.recipe.slug,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
@@ -460,7 +464,90 @@ class _AboutRecipeScreenState extends State<AboutRecipeScreen> {
|
||||
),
|
||||
);
|
||||
}
|
||||
if (recipeState is RecipeStateError) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.recipe.title ?? '',
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
complainedContentType: ComplainedContent.recipe,
|
||||
path: 'recipe/${widget.recipe.slug}',
|
||||
slug: widget.recipe.slug,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: DataErrorWidget(
|
||||
onReload: () => context.read<AboutRecipeCubit>().getRecipe(widget.recipe.slug, index: widget.index),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
widget.recipe.title ?? '',
|
||||
maxLines: 2,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||
),
|
||||
actions: [
|
||||
PortalTarget(
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
complainedContentType: ComplainedContent.recipe,
|
||||
path: 'recipe/${widget.recipe.slug}',
|
||||
slug: widget.recipe.slug,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
follower: Alignment.topRight,
|
||||
target: Alignment.bottomRight,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isMoreOptionsVisible = !isMoreOptionsVisible;
|
||||
});
|
||||
},
|
||||
icon: SvgPicture.asset(
|
||||
'assets/icons/more_button.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: const Loader(),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -9,8 +9,7 @@ import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_state
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class AboutRecipeCubit extends Cubit<AboutRecipeState> {
|
||||
AboutRecipeCubit({required this.recipeRepository, required this.profileRepository })
|
||||
: super(AboutRecipeState.initial());
|
||||
AboutRecipeCubit({required this.recipeRepository, required this.profileRepository}) : super(AboutRecipeState.initial());
|
||||
final AboutRecipeRepository recipeRepository;
|
||||
final ProfileRepository profileRepository;
|
||||
bool isCurrentDietStarted = false;
|
||||
@@ -26,6 +25,7 @@ class AboutRecipeCubit extends Cubit<AboutRecipeState> {
|
||||
emit(AboutRecipeState.loaded(recipe: recipe));
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(AboutRecipeState.error(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ class AboutRecipeCubit extends Cubit<AboutRecipeState> {
|
||||
emit(AboutRecipeState.loaded(recipe: recipe));
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
emit(AboutRecipeState.error(message: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +54,8 @@ class AboutRecipeCubit extends Cubit<AboutRecipeState> {
|
||||
wasLikedByMe: false,
|
||||
);
|
||||
if (recipeIndexInFeed != null) {
|
||||
recipeRepository.emitLikesStateToFeed(LikesState(wasLikedByMe: updatedRecipe.wasLikedByMe, totalLikes: updatedRecipe.likesCount, index: recipeIndexInFeed));
|
||||
recipeRepository
|
||||
.emitLikesStateToFeed(LikesState(wasLikedByMe: updatedRecipe.wasLikedByMe, totalLikes: updatedRecipe.likesCount, index: recipeIndexInFeed));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: updatedRecipe));
|
||||
} else {
|
||||
@@ -62,7 +64,8 @@ class AboutRecipeCubit extends Cubit<AboutRecipeState> {
|
||||
wasLikedByMe: true,
|
||||
);
|
||||
if (recipeIndexInFeed != null) {
|
||||
recipeRepository.emitLikesStateToFeed(LikesState(wasLikedByMe: updatedRecipe.wasLikedByMe, totalLikes: updatedRecipe.likesCount, index: recipeIndexInFeed));
|
||||
recipeRepository
|
||||
.emitLikesStateToFeed(LikesState(wasLikedByMe: updatedRecipe.wasLikedByMe, totalLikes: updatedRecipe.likesCount, index: recipeIndexInFeed));
|
||||
}
|
||||
emit(AboutRecipeState.loaded(recipe: updatedRecipe));
|
||||
}
|
||||
@@ -145,5 +148,5 @@ class AboutRecipeCubit extends Cubit<AboutRecipeState> {
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/settings/entities/settings_entity.dart';
|
||||
import 'package:eatvio_app/features/settings/presentation/bloc/settings_cubit/settings_cubit.dart';
|
||||
@@ -69,14 +70,17 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
if (state is SettingsStateError) {
|
||||
return Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Center(child: Text(state.errorMessage)),
|
||||
appBar: AppBar(
|
||||
title: Text('Настройки'),
|
||||
),
|
||||
body: DataErrorWidget(onReload: () => settingsCubit.init()),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
body: const Loader(),
|
||||
appBar: AppBar(
|
||||
title: Text('Настройки'),
|
||||
),
|
||||
body: Loader(),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/utils/string_extentions.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/core/widgets/data_error_widget.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/diets/presentation/widgets/more_options.dart';
|
||||
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
|
||||
@@ -79,6 +81,8 @@ class _UserDetailsContentState extends State<UserDetailsContent> {
|
||||
visible: isMoreOptionsVisible,
|
||||
portalFollower: MoreOptions(
|
||||
path: 'profile/${widget.slug}',
|
||||
complainedContentType: ComplainedContent.profile,
|
||||
slug: widget.slug,
|
||||
),
|
||||
anchor: Aligned(
|
||||
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||
@@ -395,11 +399,20 @@ class _UserDetailsContentState extends State<UserDetailsContent> {
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
} else if (state.error != null) {
|
||||
return Scaffold(
|
||||
body: Loader(),
|
||||
appBar: AppBar(),
|
||||
body: DataErrorWidget(
|
||||
onReload: () async {
|
||||
context.read<UserDetailsCubit>().getUserDetails(widget.slug);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: Loader(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"about_plan": MessageLookupByLibrary.simpleMessage("Об этом плане"),
|
||||
"about_recipe": MessageLookupByLibrary.simpleMessage("Об этом рецепте"),
|
||||
"active": MessageLookupByLibrary.simpleMessage("Активен"),
|
||||
"active_consultations_count": MessageLookupByLibrary.simpleMessage(
|
||||
"Кол-во активных консультаций"),
|
||||
"active_diet_state": MessageLookupByLibrary.simpleMessage("Активная"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("Добавить"),
|
||||
"add_cover": MessageLookupByLibrary.simpleMessage("Добавьте обложку"),
|
||||
@@ -36,6 +38,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"additional_information":
|
||||
MessageLookupByLibrary.simpleMessage("Дополнительная информация"),
|
||||
"admin": MessageLookupByLibrary.simpleMessage("Админ"),
|
||||
"alcohol": MessageLookupByLibrary.simpleMessage("Алкоголь"),
|
||||
"all": MessageLookupByLibrary.simpleMessage("Все"),
|
||||
"allergies_presence":
|
||||
MessageLookupByLibrary.simpleMessage("Наличие аллергии"),
|
||||
@@ -52,7 +55,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Средние показатели давления:"),
|
||||
"bodymass_chart": MessageLookupByLibrary.simpleMessage("График ИМТ"),
|
||||
"by_default": MessageLookupByLibrary.simpleMessage("По умолчянию"),
|
||||
"calls_for_bullying":
|
||||
MessageLookupByLibrary.simpleMessage("Призывы к травле"),
|
||||
"calories": MessageLookupByLibrary.simpleMessage("Калории"),
|
||||
"can_not_load_data_please_try_again":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Не удалось загрузить данные. Попробуйте обновить страницу"),
|
||||
"cancel_diet": MessageLookupByLibrary.simpleMessage("Отменить диету?"),
|
||||
"carb_type": MessageLookupByLibrary.simpleMessage("Мучное"),
|
||||
"carb_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -84,15 +92,40 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"comments": MessageLookupByLibrary.simpleMessage("Комментарии"),
|
||||
"comments_plural": MessageLookupByLibrary.simpleMessage("комментариев"),
|
||||
"complain": MessageLookupByLibrary.simpleMessage("Пожаловаться"),
|
||||
"complaint": MessageLookupByLibrary.simpleMessage("Жалоба"),
|
||||
"complaint_question": MessageLookupByLibrary.simpleMessage(
|
||||
"Что именно в этом материале Вы считаете неприемлемым и нарушающим правила?"),
|
||||
"complaint_sent":
|
||||
MessageLookupByLibrary.simpleMessage("Жалоба успешно отправлена"),
|
||||
"complaint_sent_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Ваше обращение принято! Мы рассмотрим его в ближайшее время и примем необходимые меры. Спасибо за вашу бдительность и помощь в улучшении нашего сервиса."),
|
||||
"confirm": MessageLookupByLibrary.simpleMessage("Подтвердить"),
|
||||
"consultations_count": MessageLookupByLibrary.simpleMessage(
|
||||
"Кол-во проведенных консулдьтаций"),
|
||||
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||
"copy_referral_link": MessageLookupByLibrary.simpleMessage(
|
||||
"Скопировать пригласительную ссылку"),
|
||||
"could_not_cancel_diet":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось отменить диету"),
|
||||
"could_not_delete_blog_post":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось удалить пост"),
|
||||
"could_not_launch_video":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось запустить видео"),
|
||||
"could_not_publish_blog_post": MessageLookupByLibrary.simpleMessage(
|
||||
"Не удалось опубликовать пост"),
|
||||
"could_not_publish_diet": MessageLookupByLibrary.simpleMessage(
|
||||
"Не удалось опубликовать диету"),
|
||||
"could_not_publish_recipe": MessageLookupByLibrary.simpleMessage(
|
||||
"Не удалось опубликовать рецепт"),
|
||||
"could_not_send_complain":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось отправить жалобу"),
|
||||
"could_not_update_blog_post":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось обновить пост"),
|
||||
"could_not_update_diet":
|
||||
MessageLookupByLibrary.simpleMessage("Не удалось обновить диету"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||
"customer_price":
|
||||
@@ -100,6 +133,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"date_of_birth": MessageLookupByLibrary.simpleMessage("Дата рождения"),
|
||||
"day": MessageLookupByLibrary.simpleMessage("День"),
|
||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||
"deception": MessageLookupByLibrary.simpleMessage("Обман"),
|
||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||
@@ -121,6 +155,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Нижние показатели давления:"),
|
||||
"draft": MessageLookupByLibrary.simpleMessage("Черновик"),
|
||||
"drafted": MessageLookupByLibrary.simpleMessage("Черновики"),
|
||||
"drugs": MessageLookupByLibrary.simpleMessage("Наркотики"),
|
||||
"eating_behavior":
|
||||
MessageLookupByLibrary.simpleMessage("Пищевое поведение"),
|
||||
"eating_behavior_type": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -144,6 +179,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Введите информацию..."),
|
||||
"exit": MessageLookupByLibrary.simpleMessage("Выйти"),
|
||||
"expand": MessageLookupByLibrary.simpleMessage("Показать полностью"),
|
||||
"explicitImage":
|
||||
MessageLookupByLibrary.simpleMessage("Откровенное изображение"),
|
||||
"explicitImages":
|
||||
MessageLookupByLibrary.simpleMessage("Откровенные изображения"),
|
||||
"explicitImagesDescription": MessageLookupByLibrary.simpleMessage(
|
||||
"Отправьте жалобу, если кто-то разместил откровенные изображения"),
|
||||
"extremism": MessageLookupByLibrary.simpleMessage("Экстремизм"),
|
||||
"fake_documents":
|
||||
MessageLookupByLibrary.simpleMessage("Поддельные документы"),
|
||||
"fats": MessageLookupByLibrary.simpleMessage("Жиры"),
|
||||
"favorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Любимые продукты"),
|
||||
@@ -162,6 +206,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"fit_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для поддержания формы сбалансированный и разнообразный, чтобы обеспечить организм всеми необходимыми питательными веществами. Общие принципы: \n● Дробное питание; \n● Разнообразие продуктов; \n● Контроль порций; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"fitness": MessageLookupByLibrary.simpleMessage("Поддержка формы"),
|
||||
"for_a_month": MessageLookupByLibrary.simpleMessage("За месяц"),
|
||||
"for_a_week": MessageLookupByLibrary.simpleMessage("За неделю"),
|
||||
"for_a_year": MessageLookupByLibrary.simpleMessage("За год"),
|
||||
"for_whole_period_of_time":
|
||||
MessageLookupByLibrary.simpleMessage("За всё время"),
|
||||
"fraud": MessageLookupByLibrary.simpleMessage("Мошенничество"),
|
||||
"fraud_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Мошенничество с целью наживы. Если вас обманули, пожалуйста, сообщите об этом в правоохранительные органы."),
|
||||
"from": MessageLookupByLibrary.simpleMessage("от"),
|
||||
"from_a_to_z": MessageLookupByLibrary.simpleMessage("Название: А-Я"),
|
||||
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||
@@ -175,6 +227,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Склонность к гипертонии"),
|
||||
"has_hypo":
|
||||
MessageLookupByLibrary.simpleMessage("Склонность к гипотонии"),
|
||||
"hatred": MessageLookupByLibrary.simpleMessage("Оскорбление"),
|
||||
"hatred_description":
|
||||
MessageLookupByLibrary.simpleMessage("Враждебные высказывания"),
|
||||
"height": MessageLookupByLibrary.simpleMessage("Рост"),
|
||||
"height_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Замер роста"),
|
||||
@@ -189,6 +244,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"ingredients": MessageLookupByLibrary.simpleMessage("Ингредиенты"),
|
||||
"initial_measurements":
|
||||
MessageLookupByLibrary.simpleMessage("Первичные замеры"),
|
||||
"invited_people_count":
|
||||
MessageLookupByLibrary.simpleMessage("Количество приглашенных"),
|
||||
"label": MessageLookupByLibrary.simpleMessage("Название"),
|
||||
"language": MessageLookupByLibrary.simpleMessage("Язык"),
|
||||
"last_name": MessageLookupByLibrary.simpleMessage("Фамилия"),
|
||||
@@ -196,6 +253,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Фамилия обязательна для заполнения"),
|
||||
"last_name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В фамилии должен быть минимум 6 символов"),
|
||||
"lawViolation":
|
||||
MessageLookupByLibrary.simpleMessage("Нарушение законодательства"),
|
||||
"lbl_english": MessageLookupByLibrary.simpleMessage("English"),
|
||||
"light_type": MessageLookupByLibrary.simpleMessage("Легкая"),
|
||||
"light_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -217,6 +276,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Минимальная цена для покупателя: 1200₽"),
|
||||
"minute": MessageLookupByLibrary.simpleMessage("минута"),
|
||||
"minutes": MessageLookupByLibrary.simpleMessage("минуты"),
|
||||
"misrepresentation":
|
||||
MessageLookupByLibrary.simpleMessage("Введение в заблуждение"),
|
||||
"misrepresentation_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Новости, которые могут вызвать широкий резонанс или несут угрозу, распространяемые с целью введения людей в заблуждение."),
|
||||
"most_new": MessageLookupByLibrary.simpleMessage("Самые новые"),
|
||||
"most_old": MessageLookupByLibrary.simpleMessage("Самые старые"),
|
||||
"msg_network_err":
|
||||
@@ -231,11 +294,13 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Имя пользователя обязательно для заполнения"),
|
||||
"name_short": MessageLookupByLibrary.simpleMessage(
|
||||
"В имени пользователя должно быть минимум 6 символов"),
|
||||
"nicotine": MessageLookupByLibrary.simpleMessage("Никотин"),
|
||||
"no": MessageLookupByLibrary.simpleMessage("Нет"),
|
||||
"no_account":
|
||||
MessageLookupByLibrary.simpleMessage("У меня нет аккаунта"),
|
||||
"not_liked_groceries":
|
||||
MessageLookupByLibrary.simpleMessage("Не любимые продукты"),
|
||||
"ok": MessageLookupByLibrary.simpleMessage("Хорошо"),
|
||||
"one_option": MessageLookupByLibrary.simpleMessage("1 опция"),
|
||||
"option": MessageLookupByLibrary.simpleMessage("Опция"),
|
||||
"option_content":
|
||||
@@ -251,6 +316,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Опция подразумевает создание индивидуальной диеты"),
|
||||
"option_title": MessageLookupByLibrary.simpleMessage("Заголовок опции"),
|
||||
"order": MessageLookupByLibrary.simpleMessage("Порядок"),
|
||||
"other": MessageLookupByLibrary.simpleMessage("Другое"),
|
||||
"other_info": MessageLookupByLibrary.simpleMessage("Прочая информация"),
|
||||
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
|
||||
"password_confirmation":
|
||||
@@ -280,6 +346,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"plan_type": MessageLookupByLibrary.simpleMessage("Тип плана"),
|
||||
"plans_complete":
|
||||
MessageLookupByLibrary.simpleMessage("Пройденные планы"),
|
||||
"please_try_again_later": MessageLookupByLibrary.simpleMessage(
|
||||
"Пожалуйста, попробуйте еще раз позже"),
|
||||
"popular": MessageLookupByLibrary.simpleMessage("Популярные"),
|
||||
"preferred_language":
|
||||
MessageLookupByLibrary.simpleMessage("Предпочитаемый язык общения"),
|
||||
@@ -293,13 +361,28 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"price_explanation": MessageLookupByLibrary.simpleMessage(
|
||||
"Разница в ценах, это комиссия Итвио"),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Профиль"),
|
||||
"prostitution": MessageLookupByLibrary.simpleMessage("Проституция"),
|
||||
"proteins": MessageLookupByLibrary.simpleMessage("Белки"),
|
||||
"publish": MessageLookupByLibrary.simpleMessage("Опубликовать"),
|
||||
"published": MessageLookupByLibrary.simpleMessage("Опубликованные"),
|
||||
"published_diets_count":
|
||||
MessageLookupByLibrary.simpleMessage("Кол-во опубликованных диет"),
|
||||
"published_posts_count": MessageLookupByLibrary.simpleMessage(
|
||||
"Количество опубликованных постов"),
|
||||
"published_recipes_count": MessageLookupByLibrary.simpleMessage(
|
||||
"Кол-во опубликованных рецептов"),
|
||||
"rating_and_statistics":
|
||||
MessageLookupByLibrary.simpleMessage("Рейтинг и статистика"),
|
||||
"rating_history":
|
||||
MessageLookupByLibrary.simpleMessage("Начисление рейтинга"),
|
||||
"recipe_author": MessageLookupByLibrary.simpleMessage("Автор рецепта"),
|
||||
"recipe_publishing":
|
||||
MessageLookupByLibrary.simpleMessage("Публикация рецепта"),
|
||||
"removeFromActive":
|
||||
MessageLookupByLibrary.simpleMessage("Снять с публикации"),
|
||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||
"send_complain":
|
||||
MessageLookupByLibrary.simpleMessage("Отправить жалобу"),
|
||||
"services": MessageLookupByLibrary.simpleMessage("Оказание услуг"),
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"sex": MessageLookupByLibrary.simpleMessage("Пол"),
|
||||
@@ -309,15 +392,29 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"slim_type": MessageLookupByLibrary.simpleMessage("Похудение"),
|
||||
"slim_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"План питания для похудения должен быть разработан с учётом индивидуальных особенностей организма, возраста, пола, уровня физической активности и состояния здоровья. Общие принципы: \n● Снижение калорийности; \n● Сбалансированный рацион; \n● Разнообразие продуктов; \n● Питьевой режим; \n● Ограничение вредных продуктов;"),
|
||||
"some_error_occurred":
|
||||
MessageLookupByLibrary.simpleMessage("Упс! Произошла ошибка"),
|
||||
"some_error_occurred_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Произошла ошибка. Мы уже работаем над ее устранением. Попробуйте позже."),
|
||||
"something_went_wrong":
|
||||
MessageLookupByLibrary.simpleMessage("Упс! Что-то пошло не так"),
|
||||
"spam": MessageLookupByLibrary.simpleMessage("Спам"),
|
||||
"spam_description": MessageLookupByLibrary.simpleMessage(
|
||||
"Отправьте жалобу, если Вы заметили рекламу, размещенную в не предназначенном для этого месте."),
|
||||
"sport_hobbies":
|
||||
MessageLookupByLibrary.simpleMessage("Спортивные увлечения"),
|
||||
"stage": MessageLookupByLibrary.simpleMessage("этап"),
|
||||
"stages": MessageLookupByLibrary.simpleMessage("этапов"),
|
||||
"standard": MessageLookupByLibrary.simpleMessage("Стандарт"),
|
||||
"startDiet": MessageLookupByLibrary.simpleMessage("Начать диету"),
|
||||
"statistic": MessageLookupByLibrary.simpleMessage("Статистика"),
|
||||
"step": MessageLookupByLibrary.simpleMessage("Шаг"),
|
||||
"step_by_step_photo_recipe":
|
||||
MessageLookupByLibrary.simpleMessage("Пошаговый фоторецепт"),
|
||||
"successfully_published":
|
||||
MessageLookupByLibrary.simpleMessage("успешно опубликован"),
|
||||
"suicide":
|
||||
MessageLookupByLibrary.simpleMessage("Склонение к самоубийству"),
|
||||
"takes_pills":
|
||||
MessageLookupByLibrary.simpleMessage("Принимает лекарства"),
|
||||
"tell_your_schedule": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -327,6 +424,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"time": MessageLookupByLibrary.simpleMessage("Время прохождения"),
|
||||
"toOffer": MessageLookupByLibrary.simpleMessage("Предложить"),
|
||||
"to_draft": MessageLookupByLibrary.simpleMessage("В черновик"),
|
||||
"try_again": MessageLookupByLibrary.simpleMessage("Попробовать снова"),
|
||||
"type_here_your_complaint":
|
||||
MessageLookupByLibrary.simpleMessage("Напишите здесь свою жалобу"),
|
||||
"unfavorite_foods":
|
||||
MessageLookupByLibrary.simpleMessage("Нелюбимые продукты"),
|
||||
"up_pressure": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -343,9 +443,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"vegan_type": MessageLookupByLibrary.simpleMessage("Вегетарианская"),
|
||||
"vegan_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Диета основана на потреблении растительной пищи и отказе от продуктов животного происхождения. Такой тип питания может быть разнообразным и вкусным, а также полезным для здоровья."),
|
||||
"violenceAndHostility":
|
||||
MessageLookupByLibrary.simpleMessage("Насилие и вражда"),
|
||||
"violence_against_people_or_animal":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"Насилие над людьми или животными"),
|
||||
"waist": MessageLookupByLibrary.simpleMessage("Талия"),
|
||||
"waist_circumference":
|
||||
MessageLookupByLibrary.simpleMessage("Обхват талии"),
|
||||
"weapon": MessageLookupByLibrary.simpleMessage("Оружие"),
|
||||
"weight": MessageLookupByLibrary.simpleMessage("Вес"),
|
||||
"weight_chart": MessageLookupByLibrary.simpleMessage("График веса"),
|
||||
"weight_measurements":
|
||||
@@ -356,6 +462,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Улучшение самочувствия"),
|
||||
"wellness_type_desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы."),
|
||||
"what_do_you_want_to_complaint_about":
|
||||
MessageLookupByLibrary.simpleMessage(
|
||||
"На что Вы хотите пожаловаться?"),
|
||||
"what_is_your_name":
|
||||
MessageLookupByLibrary.simpleMessage("Как вас зовут?"),
|
||||
"wrong_credentials": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -367,6 +476,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Ваши спортивные увлечения?"),
|
||||
"your_gender": MessageLookupByLibrary.simpleMessage("Ваш пол?"),
|
||||
"your_height": MessageLookupByLibrary.simpleMessage("Ваш рост:"),
|
||||
"your_rating": MessageLookupByLibrary.simpleMessage("Ваш рейтинг"),
|
||||
"your_schedule": MessageLookupByLibrary.simpleMessage("Ваш режим дня?"),
|
||||
"your_weight": MessageLookupByLibrary.simpleMessage("Ваш вес:")
|
||||
};
|
||||
|
||||
@@ -2549,6 +2549,636 @@ class S {
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Спам`
|
||||
String get spam {
|
||||
return Intl.message(
|
||||
'Спам',
|
||||
name: 'spam',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Нарушение законодательства`
|
||||
String get lawViolation {
|
||||
return Intl.message(
|
||||
'Нарушение законодательства',
|
||||
name: 'lawViolation',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Обман`
|
||||
String get deception {
|
||||
return Intl.message(
|
||||
'Обман',
|
||||
name: 'deception',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Насилие и вражда`
|
||||
String get violenceAndHostility {
|
||||
return Intl.message(
|
||||
'Насилие и вражда',
|
||||
name: 'violenceAndHostility',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Откровенное изображение`
|
||||
String get explicitImage {
|
||||
return Intl.message(
|
||||
'Откровенное изображение',
|
||||
name: 'explicitImage',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Откровенные изображения`
|
||||
String get explicitImages {
|
||||
return Intl.message(
|
||||
'Откровенные изображения',
|
||||
name: 'explicitImages',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Отправьте жалобу, если кто-то разместил откровенные изображения`
|
||||
String get explicitImagesDescription {
|
||||
return Intl.message(
|
||||
'Отправьте жалобу, если кто-то разместил откровенные изображения',
|
||||
name: 'explicitImagesDescription',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Жалоба`
|
||||
String get complaint {
|
||||
return Intl.message(
|
||||
'Жалоба',
|
||||
name: 'complaint',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Что именно в этом материале Вы считаете неприемлемым и нарушающим правила?`
|
||||
String get complaint_question {
|
||||
return Intl.message(
|
||||
'Что именно в этом материале Вы считаете неприемлемым и нарушающим правила?',
|
||||
name: 'complaint_question',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Отправьте жалобу, если Вы заметили рекламу, размещенную в не предназначенном для этого месте.`
|
||||
String get spam_description {
|
||||
return Intl.message(
|
||||
'Отправьте жалобу, если Вы заметили рекламу, размещенную в не предназначенном для этого месте.',
|
||||
name: 'spam_description',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `На что Вы хотите пожаловаться?`
|
||||
String get what_do_you_want_to_complaint_about {
|
||||
return Intl.message(
|
||||
'На что Вы хотите пожаловаться?',
|
||||
name: 'what_do_you_want_to_complaint_about',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Отправить жалобу`
|
||||
String get send_complain {
|
||||
return Intl.message(
|
||||
'Отправить жалобу',
|
||||
name: 'send_complain',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Жалоба успешно отправлена`
|
||||
String get complaint_sent {
|
||||
return Intl.message(
|
||||
'Жалоба успешно отправлена',
|
||||
name: 'complaint_sent',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Ваше обращение принято! Мы рассмотрим его в ближайшее время и примем необходимые меры. Спасибо за вашу бдительность и помощь в улучшении нашего сервиса.`
|
||||
String get complaint_sent_description {
|
||||
return Intl.message(
|
||||
'Ваше обращение принято! Мы рассмотрим его в ближайшее время и примем необходимые меры. Спасибо за вашу бдительность и помощь в улучшении нашего сервиса.',
|
||||
name: 'complaint_sent_description',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Хорошо`
|
||||
String get ok {
|
||||
return Intl.message(
|
||||
'Хорошо',
|
||||
name: 'ok',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Алкоголь`
|
||||
String get alcohol {
|
||||
return Intl.message(
|
||||
'Алкоголь',
|
||||
name: 'alcohol',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Наркотики`
|
||||
String get drugs {
|
||||
return Intl.message(
|
||||
'Наркотики',
|
||||
name: 'drugs',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Никотин`
|
||||
String get nicotine {
|
||||
return Intl.message(
|
||||
'Никотин',
|
||||
name: 'nicotine',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Оружие`
|
||||
String get weapon {
|
||||
return Intl.message(
|
||||
'Оружие',
|
||||
name: 'weapon',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Поддельные документы`
|
||||
String get fake_documents {
|
||||
return Intl.message(
|
||||
'Поддельные документы',
|
||||
name: 'fake_documents',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Проституция`
|
||||
String get prostitution {
|
||||
return Intl.message(
|
||||
'Проституция',
|
||||
name: 'prostitution',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Другое`
|
||||
String get other {
|
||||
return Intl.message(
|
||||
'Другое',
|
||||
name: 'other',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Введение в заблуждение`
|
||||
String get misrepresentation {
|
||||
return Intl.message(
|
||||
'Введение в заблуждение',
|
||||
name: 'misrepresentation',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Новости, которые могут вызвать широкий резонанс или несут угрозу, распространяемые с целью введения людей в заблуждение.`
|
||||
String get misrepresentation_description {
|
||||
return Intl.message(
|
||||
'Новости, которые могут вызвать широкий резонанс или несут угрозу, распространяемые с целью введения людей в заблуждение.',
|
||||
name: 'misrepresentation_description',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Мошенничество`
|
||||
String get fraud {
|
||||
return Intl.message(
|
||||
'Мошенничество',
|
||||
name: 'fraud',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Мошенничество с целью наживы. Если вас обманули, пожалуйста, сообщите об этом в правоохранительные органы.`
|
||||
String get fraud_description {
|
||||
return Intl.message(
|
||||
'Мошенничество с целью наживы. Если вас обманули, пожалуйста, сообщите об этом в правоохранительные органы.',
|
||||
name: 'fraud_description',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Насилие над людьми или животными`
|
||||
String get violence_against_people_or_animal {
|
||||
return Intl.message(
|
||||
'Насилие над людьми или животными',
|
||||
name: 'violence_against_people_or_animal',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Оскорбление`
|
||||
String get hatred {
|
||||
return Intl.message(
|
||||
'Оскорбление',
|
||||
name: 'hatred',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Склонение к самоубийству`
|
||||
String get suicide {
|
||||
return Intl.message(
|
||||
'Склонение к самоубийству',
|
||||
name: 'suicide',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Враждебные высказывания`
|
||||
String get hatred_description {
|
||||
return Intl.message(
|
||||
'Враждебные высказывания',
|
||||
name: 'hatred_description',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Экстремизм`
|
||||
String get extremism {
|
||||
return Intl.message(
|
||||
'Экстремизм',
|
||||
name: 'extremism',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Призывы к травле`
|
||||
String get calls_for_bullying {
|
||||
return Intl.message(
|
||||
'Призывы к травле',
|
||||
name: 'calls_for_bullying',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Напишите здесь свою жалобу`
|
||||
String get type_here_your_complaint {
|
||||
return Intl.message(
|
||||
'Напишите здесь свою жалобу',
|
||||
name: 'type_here_your_complaint',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось отправить жалобу`
|
||||
String get could_not_send_complain {
|
||||
return Intl.message(
|
||||
'Не удалось отправить жалобу',
|
||||
name: 'could_not_send_complain',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Пожалуйста, попробуйте еще раз позже`
|
||||
String get please_try_again_later {
|
||||
return Intl.message(
|
||||
'Пожалуйста, попробуйте еще раз позже',
|
||||
name: 'please_try_again_later',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Рейтинг и статистика`
|
||||
String get rating_and_statistics {
|
||||
return Intl.message(
|
||||
'Рейтинг и статистика',
|
||||
name: 'rating_and_statistics',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Ваш рейтинг`
|
||||
String get your_rating {
|
||||
return Intl.message(
|
||||
'Ваш рейтинг',
|
||||
name: 'your_rating',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Скопировать пригласительную ссылку`
|
||||
String get copy_referral_link {
|
||||
return Intl.message(
|
||||
'Скопировать пригласительную ссылку',
|
||||
name: 'copy_referral_link',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Статистика`
|
||||
String get statistic {
|
||||
return Intl.message(
|
||||
'Статистика',
|
||||
name: 'statistic',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `За всё время`
|
||||
String get for_whole_period_of_time {
|
||||
return Intl.message(
|
||||
'За всё время',
|
||||
name: 'for_whole_period_of_time',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `За год`
|
||||
String get for_a_year {
|
||||
return Intl.message(
|
||||
'За год',
|
||||
name: 'for_a_year',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `За месяц`
|
||||
String get for_a_month {
|
||||
return Intl.message(
|
||||
'За месяц',
|
||||
name: 'for_a_month',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `За неделю`
|
||||
String get for_a_week {
|
||||
return Intl.message(
|
||||
'За неделю',
|
||||
name: 'for_a_week',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Количество приглашенных`
|
||||
String get invited_people_count {
|
||||
return Intl.message(
|
||||
'Количество приглашенных',
|
||||
name: 'invited_people_count',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Количество опубликованных постов`
|
||||
String get published_posts_count {
|
||||
return Intl.message(
|
||||
'Количество опубликованных постов',
|
||||
name: 'published_posts_count',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Кол-во опубликованных рецептов`
|
||||
String get published_recipes_count {
|
||||
return Intl.message(
|
||||
'Кол-во опубликованных рецептов',
|
||||
name: 'published_recipes_count',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Кол-во опубликованных диет`
|
||||
String get published_diets_count {
|
||||
return Intl.message(
|
||||
'Кол-во опубликованных диет',
|
||||
name: 'published_diets_count',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Кол-во проведенных консулдьтаций`
|
||||
String get consultations_count {
|
||||
return Intl.message(
|
||||
'Кол-во проведенных консулдьтаций',
|
||||
name: 'consultations_count',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Кол-во активных консультаций`
|
||||
String get active_consultations_count {
|
||||
return Intl.message(
|
||||
'Кол-во активных консультаций',
|
||||
name: 'active_consultations_count',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Начисление рейтинга`
|
||||
String get rating_history {
|
||||
return Intl.message(
|
||||
'Начисление рейтинга',
|
||||
name: 'rating_history',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Упс! Что-то пошло не так`
|
||||
String get something_went_wrong {
|
||||
return Intl.message(
|
||||
'Упс! Что-то пошло не так',
|
||||
name: 'something_went_wrong',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось загрузить данные. Попробуйте обновить страницу`
|
||||
String get can_not_load_data_please_try_again {
|
||||
return Intl.message(
|
||||
'Не удалось загрузить данные. Попробуйте обновить страницу',
|
||||
name: 'can_not_load_data_please_try_again',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Попробовать снова`
|
||||
String get try_again {
|
||||
return Intl.message(
|
||||
'Попробовать снова',
|
||||
name: 'try_again',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Публикация рецепта`
|
||||
String get recipe_publishing {
|
||||
return Intl.message(
|
||||
'Публикация рецепта',
|
||||
name: 'recipe_publishing',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `успешно опубликован`
|
||||
String get successfully_published {
|
||||
return Intl.message(
|
||||
'успешно опубликован',
|
||||
name: 'successfully_published',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Упс! Произошла ошибка`
|
||||
String get some_error_occurred {
|
||||
return Intl.message(
|
||||
'Упс! Произошла ошибка',
|
||||
name: 'some_error_occurred',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Произошла ошибка. Мы уже работаем над ее устранением. Попробуйте позже.`
|
||||
String get some_error_occurred_description {
|
||||
return Intl.message(
|
||||
'Произошла ошибка. Мы уже работаем над ее устранением. Попробуйте позже.',
|
||||
name: 'some_error_occurred_description',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось опубликовать рецепт`
|
||||
String get could_not_publish_recipe {
|
||||
return Intl.message(
|
||||
'Не удалось опубликовать рецепт',
|
||||
name: 'could_not_publish_recipe',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось опубликовать диету`
|
||||
String get could_not_publish_diet {
|
||||
return Intl.message(
|
||||
'Не удалось опубликовать диету',
|
||||
name: 'could_not_publish_diet',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось обновить диету`
|
||||
String get could_not_update_diet {
|
||||
return Intl.message(
|
||||
'Не удалось обновить диету',
|
||||
name: 'could_not_update_diet',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось опубликовать пост`
|
||||
String get could_not_publish_blog_post {
|
||||
return Intl.message(
|
||||
'Не удалось опубликовать пост',
|
||||
name: 'could_not_publish_blog_post',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось обновить пост`
|
||||
String get could_not_update_blog_post {
|
||||
return Intl.message(
|
||||
'Не удалось обновить пост',
|
||||
name: 'could_not_update_blog_post',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Не удалось удалить пост`
|
||||
String get could_not_delete_blog_post {
|
||||
return Intl.message(
|
||||
'Не удалось удалить пост',
|
||||
name: 'could_not_delete_blog_post',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||
|
||||
@@ -248,5 +248,69 @@
|
||||
"ingredients": "Ингредиенты",
|
||||
"step": "Шаг",
|
||||
"step_by_step_photo_recipe": "Пошаговый фоторецепт",
|
||||
"diet_has_been_sent_to_draft": "снята с публикации и перенесена в черновик"
|
||||
"diet_has_been_sent_to_draft": "снята с публикации и перенесена в черновик",
|
||||
"spam": "Спам",
|
||||
"lawViolation": "Нарушение законодательства",
|
||||
"deception": "Обман",
|
||||
"violenceAndHostility": "Насилие и вражда",
|
||||
"explicitImage": "Откровенное изображение",
|
||||
"explicitImages": "Откровенные изображения",
|
||||
"explicitImagesDescription": "Отправьте жалобу, если кто-то разместил откровенные изображения",
|
||||
"complaint": "Жалоба",
|
||||
"complaint_question": "Что именно в этом материале Вы считаете неприемлемым и нарушающим правила?",
|
||||
"spam_description": "Отправьте жалобу, если Вы заметили рекламу, размещенную в не предназначенном для этого месте.",
|
||||
"what_do_you_want_to_complaint_about": "На что Вы хотите пожаловаться?",
|
||||
"send_complain": "Отправить жалобу",
|
||||
"complaint_sent": "Жалоба успешно отправлена",
|
||||
"complaint_sent_description": "Ваше обращение принято! Мы рассмотрим его в ближайшее время и примем необходимые меры. Спасибо за вашу бдительность и помощь в улучшении нашего сервиса.",
|
||||
"ok": "Хорошо",
|
||||
"alcohol": "Алкоголь",
|
||||
"drugs": "Наркотики",
|
||||
"nicotine": "Никотин",
|
||||
"weapon": "Оружие",
|
||||
"fake_documents": "Поддельные документы",
|
||||
"prostitution": "Проституция",
|
||||
"other": "Другое",
|
||||
"misrepresentation": "Введение в заблуждение",
|
||||
"misrepresentation_description": "Новости, которые могут вызвать широкий резонанс или несут угрозу, распространяемые с целью введения людей в заблуждение.",
|
||||
"fraud": "Мошенничество",
|
||||
"fraud_description": "Мошенничество с целью наживы. Если вас обманули, пожалуйста, сообщите об этом в правоохранительные органы.",
|
||||
"violence_against_people_or_animal": "Насилие над людьми или животными",
|
||||
"hatred": "Оскорбление",
|
||||
"suicide": "Склонение к самоубийству",
|
||||
"hatred_description": "Враждебные высказывания",
|
||||
"extremism": "Экстремизм",
|
||||
"calls_for_bullying": "Призывы к травле",
|
||||
"type_here_your_complaint": "Напишите здесь свою жалобу",
|
||||
"could_not_send_complain": "Не удалось отправить жалобу",
|
||||
"please_try_again_later": "Пожалуйста, попробуйте еще раз позже",
|
||||
"rating_and_statistics": "Рейтинг и статистика",
|
||||
"your_rating": "Ваш рейтинг",
|
||||
"copy_referral_link": "Скопировать пригласительную ссылку",
|
||||
"statistic": "Статистика",
|
||||
"for_whole_period_of_time": "За всё время",
|
||||
"for_a_year": "За год",
|
||||
"for_a_month": "За месяц",
|
||||
"for_a_week": "За неделю",
|
||||
"invited_people_count": "Количество приглашенных",
|
||||
"published_posts_count": "Количество опубликованных постов",
|
||||
"published_recipes_count": "Кол-во опубликованных рецептов",
|
||||
"published_diets_count": "Кол-во опубликованных диет",
|
||||
"consultations_count": "Кол-во проведенных консулдьтаций",
|
||||
"active_consultations_count": "Кол-во активных консультаций",
|
||||
"rating_history": "Начисление рейтинга",
|
||||
"something_went_wrong": "Упс! Что-то пошло не так",
|
||||
"can_not_load_data_please_try_again": "Не удалось загрузить данные. Попробуйте обновить страницу",
|
||||
"try_again": "Попробовать снова",
|
||||
"recipe_publishing": "Публикация рецепта",
|
||||
"successfully_published": "успешно опубликован",
|
||||
"some_error_occurred": "Упс! Произошла ошибка",
|
||||
"some_error_occurred_description": "Произошла ошибка. Мы уже работаем над ее устранением. Попробуйте позже.",
|
||||
"could_not_publish_recipe": "Не удалось опубликовать рецепт",
|
||||
"could_not_publish_diet": "Не удалось опубликовать диету",
|
||||
"could_not_update_diet": "Не удалось обновить диету",
|
||||
"could_not_publish_blog_post": "Не удалось опубликовать пост",
|
||||
"could_not_update_blog_post": "Не удалось обновить пост",
|
||||
"could_not_delete_blog_post": "Не удалось удалить пост"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user