forked from eatvio/eatvio_app
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d8f414672 | ||
| 49453c8b31 | |||
|
|
138e2c1073 | ||
| eb39ae5e7c | |||
|
|
250d9614e3 | ||
| b9b06f11a6 | |||
|
|
f35cdd26a3 | ||
|
|
5ee86ddc92 | ||
|
|
fceaf3d162 | ||
|
|
ca3bd7cc0d | ||
|
|
782f75d26b | ||
|
|
79dc590beb | ||
|
|
517e493b5e | ||
|
|
1bc0ab3237 | ||
|
|
a8994eecf4 | ||
|
|
8d3ae15112 | ||
|
|
6b7b1f2d18 | ||
|
|
82bc51e45c | ||
|
|
77666aca0e | ||
|
|
16430af989 |
@@ -63,6 +63,18 @@
|
|||||||
|
|
||||||
<data android:pathPattern="/ru/plan/.*" />
|
<data android:pathPattern="/ru/plan/.*" />
|
||||||
<data android:pathPattern="/en/plan/.*" />
|
<data android:pathPattern="/en/plan/.*" />
|
||||||
|
|
||||||
|
<data android:pathPattern="/ru/chat/.*" />
|
||||||
|
<data android:pathPattern="/en/chat/.*" />
|
||||||
|
|
||||||
|
<data android:pathPattern="/ru/chat" />
|
||||||
|
<data android:pathPattern="/en/chat" />
|
||||||
|
|
||||||
|
<data android:pathPattern="/ru/profile/.*" />
|
||||||
|
<data android:pathPattern="/en/profile/.*" />
|
||||||
|
|
||||||
|
<data android:pathPattern="/ru/diary/.*" />
|
||||||
|
<data android:pathPattern="/en/diary/.*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
|
|||||||
@@ -29,23 +29,45 @@ class AppRouter {
|
|||||||
/// Обработка редиректов для deep links
|
/// Обработка редиректов для deep links
|
||||||
static String? _handleRedirect(BuildContext context, GoRouterState state) {
|
static String? _handleRedirect(BuildContext context, GoRouterState state) {
|
||||||
final segments = state.uri.pathSegments;
|
final segments = state.uri.pathSegments;
|
||||||
if (segments.length >= 3) {
|
if (segments.length == 4) {
|
||||||
|
final type = segments[1];
|
||||||
|
switch (type) {
|
||||||
|
case 'diary':
|
||||||
|
FlutterNativeSplash.remove();
|
||||||
|
return '/diary-screen';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (segments.length == 3) {
|
||||||
final type = segments[1];
|
final type = segments[1];
|
||||||
final contentIdentifier = segments[2];
|
final contentIdentifier = segments[2];
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'recipe':
|
case 'recipe':
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
return '${RouteConstants.aboutRecipesScreen}?slug=$contentIdentifier';
|
return '/about-recipes-screen?slug=$contentIdentifier';
|
||||||
case 'blog_post':
|
case 'blog_post':
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
return '${RouteConstants.blogPostScreen}?id=$contentIdentifier';
|
return '/blog-post-screen?id=$contentIdentifier';
|
||||||
case 'plan':
|
case 'plan':
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
return '${RouteConstants.aboutPlanScreen}?slug=$contentIdentifier';
|
return '/about-plan-screen?slug=$contentIdentifier';
|
||||||
case 'diet':
|
case 'diet':
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
return '${RouteConstants.aboutDietScreen}?slug=$contentIdentifier';
|
return '/about-diet-screen?slug=$contentIdentifier';
|
||||||
|
case 'chat':
|
||||||
|
FlutterNativeSplash.remove();
|
||||||
|
return '/chat-select-screen';
|
||||||
|
case 'profile':
|
||||||
|
FlutterNativeSplash.remove();
|
||||||
|
return '/profile-screen?slug=$contentIdentifier';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (segments.length == 2) {
|
||||||
|
final type = segments[1];
|
||||||
|
switch (type) {
|
||||||
|
case 'chat':
|
||||||
|
FlutterNativeSplash.remove();
|
||||||
|
return '/chat-select-screen';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:eatvio_app/core/app_config.dart';
|
import 'package:eatvio_app/core/app_config.dart';
|
||||||
import 'package:eatvio_app/core/interceptors/phone_verify_error_interceptor.dart';
|
import 'package:eatvio_app/core/interceptors/phone_verify_error_interceptor.dart';
|
||||||
import 'package:eatvio_app/core/interceptors/token_interceptor.dart';
|
import 'package:eatvio_app/core/interceptors/token_interceptor.dart';
|
||||||
|
import 'package:eatvio_app/core/prefs.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
/// Регистрация внешних зависимостей в системе внедрения зависимостей
|
/// Регистрация внешних зависимостей в системе внедрения зависимостей
|
||||||
class ExternalRegistrations {
|
class ExternalRegistrations {
|
||||||
@@ -11,23 +13,20 @@ class ExternalRegistrations {
|
|||||||
/// Регистрация всех внешних зависимостей
|
/// Регистрация всех внешних зависимостей
|
||||||
static void registerAll() {
|
static void registerAll() {
|
||||||
_registerDio();
|
_registerDio();
|
||||||
|
_registerPrefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Регистрация Dio HTTP клиента
|
/// Регистрация Dio HTTP клиента
|
||||||
static void _registerDio() {
|
static void _registerDio() {
|
||||||
sl.registerLazySingleton(
|
sl.registerLazySingleton(
|
||||||
() => Dio(
|
() =>
|
||||||
BaseOptions(
|
Dio(BaseOptions(baseUrl: sl<AppConfig>().baseUrl, headers: {'accept': 'application/json', 'content-type': 'application/json'}))
|
||||||
baseUrl: sl<AppConfig>().baseUrl,
|
..interceptors.addAll([TokenInterceptor(), PhoneVerifyErrorInterceptor()]),
|
||||||
headers: {
|
|
||||||
'accept': 'application/json',
|
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)..interceptors.addAll([
|
|
||||||
TokenInterceptor(),
|
|
||||||
PhoneVerifyErrorInterceptor(),
|
|
||||||
]),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Регистрация Prefs
|
||||||
|
static void _registerPrefs() {
|
||||||
|
sl.registerSingletonAsync<Prefs>(()async => Prefs(await SharedPreferences.getInstance()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,22 @@ class FirebaseApi {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> registerAnonymousPushToken() async {
|
||||||
|
try {
|
||||||
|
final deviceInfo = DeviceInfoPlugin();
|
||||||
|
await sl<Dio>().post(
|
||||||
|
'/api/anonymous_token',
|
||||||
|
data: {
|
||||||
|
'platform': Platform.isIOS ? 'ios' : 'android',
|
||||||
|
'hw_id': Platform.isIOS ? (await deviceInfo.iosInfo).identifierForVendor : (await deviceInfo.androidInfo).id,
|
||||||
|
'token': await getToken(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (e, st) {
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> registerPushToken() async {
|
Future<void> registerPushToken() async {
|
||||||
if (await TokenStorage.haveTokenInStorage()) {
|
if (await TokenStorage.haveTokenInStorage()) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
43
lib/core/prefs.dart
Normal file
43
lib/core/prefs.dart
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import 'package:eatvio_app/core/prefs_keys.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class Prefs {
|
||||||
|
final SharedPreferences _prefs;
|
||||||
|
|
||||||
|
Prefs(this._prefs);
|
||||||
|
|
||||||
|
String _key(PrefsKeys key) => key.name;
|
||||||
|
|
||||||
|
Future<void> setString(PrefsKeys key, String value) async {
|
||||||
|
await _prefs.setString(_key(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
String? getString(PrefsKeys key) {
|
||||||
|
return _prefs.getString(_key(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setInt(PrefsKeys key, int value) async {
|
||||||
|
await _prefs.setInt(_key(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int? getInt(PrefsKeys key) {
|
||||||
|
return _prefs.getInt(_key(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setBool(PrefsKeys key, bool value) async {
|
||||||
|
await _prefs.setBool(_key(key), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool? getBool(PrefsKeys key) {
|
||||||
|
return _prefs.getBool(_key(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> remove(PrefsKeys key) async {
|
||||||
|
await _prefs.remove(_key(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> clear() async {
|
||||||
|
await _prefs.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
1
lib/core/prefs_keys.dart
Normal file
1
lib/core/prefs_keys.dart
Normal file
@@ -0,0 +1 @@
|
|||||||
|
enum PrefsKeys { hasAnonymousTokenBeenSent, welcomeScreenWasShowed }
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:eatvio_app/core/firebase_api.dart';
|
||||||
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/core/routing/route_constants.dart';
|
import 'package:eatvio_app/core/routing/route_constants.dart';
|
||||||
import 'package:eatvio_app/features/auth/entities/auth_result_entity.dart';
|
import 'package:eatvio_app/features/auth/entities/auth_result_entity.dart';
|
||||||
import 'package:eatvio_app/features/auth/presentation/pages/auth_screen.dart';
|
import 'package:eatvio_app/features/auth/presentation/pages/auth_screen.dart';
|
||||||
@@ -18,6 +20,10 @@ class AuthRoutes {
|
|||||||
path: RouteConstants.authScreen,
|
path: RouteConstants.authScreen,
|
||||||
name: 'authScreen',
|
name: 'authScreen',
|
||||||
builder: (context, state) => const AuthScreen(),
|
builder: (context, state) => const AuthScreen(),
|
||||||
|
redirect: (context, state) {
|
||||||
|
sl<FirebaseApi>().registerAnonymousPushToken();
|
||||||
|
return null;
|
||||||
|
},
|
||||||
routes: [
|
routes: [
|
||||||
GoRoute(path: RouteConstants.registrationScreen, name: 'registrationScreen', builder: (context, state) => const RegistrationScreen()),
|
GoRoute(path: RouteConstants.registrationScreen, name: 'registrationScreen', builder: (context, state) => const RegistrationScreen()),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:eatvio_app/core/app_config.dart';
|
import 'package:eatvio_app/core/app_config.dart';
|
||||||
import 'package:eatvio_app/core/firebase_api.dart';
|
import 'package:eatvio_app/core/firebase_api.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
|
import 'package:eatvio_app/core/prefs.dart';
|
||||||
|
import 'package:eatvio_app/core/prefs_keys.dart';
|
||||||
import 'package:eatvio_app/core/routing/route_constants.dart';
|
import 'package:eatvio_app/core/routing/route_constants.dart';
|
||||||
import 'package:eatvio_app/core/token_storage.dart';
|
import 'package:eatvio_app/core/token_storage.dart';
|
||||||
import 'package:eatvio_app/features/calendar/presentation/pages/calendar_screen.dart';
|
import 'package:eatvio_app/features/calendar/presentation/pages/calendar_screen.dart';
|
||||||
@@ -27,6 +29,7 @@ import 'package:eatvio_app/features/my_finance/presentation/pages/card_settings.
|
|||||||
import 'package:eatvio_app/features/my_finance/presentation/pages/user_finance_screen.dart';
|
import 'package:eatvio_app/features/my_finance/presentation/pages/user_finance_screen.dart';
|
||||||
import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart';
|
import 'package:eatvio_app/features/my_plans/presentation/my_plans_screen.dart';
|
||||||
import 'package:eatvio_app/features/order_info/presentation/info_by_order_screen.dart';
|
import 'package:eatvio_app/features/order_info/presentation/info_by_order_screen.dart';
|
||||||
|
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||||
import 'package:eatvio_app/features/profile/presentation/pages/profile_screen.dart';
|
import 'package:eatvio_app/features/profile/presentation/pages/profile_screen.dart';
|
||||||
import 'package:eatvio_app/features/profile/presentation/pages/subs_screen.dart';
|
import 'package:eatvio_app/features/profile/presentation/pages/subs_screen.dart';
|
||||||
import 'package:eatvio_app/features/recipe/presentation/pages/my_recipes_screen.dart';
|
import 'package:eatvio_app/features/recipe/presentation/pages/my_recipes_screen.dart';
|
||||||
@@ -40,7 +43,6 @@ import 'package:eatvio_app/features/finances_and_consultations_archive/presentat
|
|||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:version/version.dart';
|
import 'package:version/version.dart';
|
||||||
|
|
||||||
/// Остальные маршруты приложения
|
/// Остальные маршруты приложения
|
||||||
@@ -55,18 +57,24 @@ class OtherRoutes {
|
|||||||
builder: (context, state) => const WelcomeScreen(),
|
builder: (context, state) => const WelcomeScreen(),
|
||||||
redirect: (context, state) async {
|
redirect: (context, state) async {
|
||||||
try {
|
try {
|
||||||
final sharedPreferences = await SharedPreferences.getInstance();
|
final prefs = sl<Prefs>();
|
||||||
final welcomeScreenWasShowed = sharedPreferences.getBool('welcomeScreenWasShowed') ?? false;
|
final firebaseApi = sl<FirebaseApi>();
|
||||||
await sl<FirebaseApi>().registerPushToken();
|
final welcomeScreenWasShowed = prefs.getBool(PrefsKeys.welcomeScreenWasShowed) ?? false;
|
||||||
if (welcomeScreenWasShowed == false) {
|
await firebaseApi.registerPushToken();
|
||||||
|
if (!welcomeScreenWasShowed) {
|
||||||
return null;
|
return null;
|
||||||
} else if (await TokenStorage.haveTokenInStorage()) {
|
} else if (await TokenStorage.haveTokenInStorage()) {
|
||||||
return RouteConstants.feedScreen;
|
return '/feed-screen';
|
||||||
} else {
|
} else {
|
||||||
return RouteConstants.authScreen;
|
final hasAnonymousTokenBeenSent = prefs.getBool(PrefsKeys.hasAnonymousTokenBeenSent) ?? false;
|
||||||
|
if (!hasAnonymousTokenBeenSent) {
|
||||||
|
await firebaseApi.registerAnonymousPushToken();
|
||||||
|
prefs.setBool(PrefsKeys.hasAnonymousTokenBeenSent, true);
|
||||||
|
}
|
||||||
|
return '/auth-screen';
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return RouteConstants.feedScreen;
|
return '/feed-screen';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -139,7 +147,13 @@ class OtherRoutes {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
path: RouteConstants.profileScreen,
|
path: RouteConstants.profileScreen,
|
||||||
name: 'profileScreen',
|
name: 'profileScreen',
|
||||||
builder: (context, state) => ProfileScreen(author: state.extra as Author),
|
builder: (context, state) {
|
||||||
|
final slug = state.uri.queryParameters['slug'];
|
||||||
|
if (slug != null) {
|
||||||
|
return ProfileScreen(slug: slug);
|
||||||
|
}
|
||||||
|
return ProfileScreen(slug: state.extra as String);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: RouteConstants.subsScreen,
|
path: RouteConstants.subsScreen,
|
||||||
@@ -161,7 +175,7 @@ class OtherRoutes {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
path: RouteConstants.emptyChatScreen,
|
path: RouteConstants.emptyChatScreen,
|
||||||
name: 'emptyChatScreen',
|
name: 'emptyChatScreen',
|
||||||
builder: (context, state) => EmptyChatScreen(author: state.extra as Author),
|
builder: (context, state) => EmptyChatScreen(user: state.extra as ProfileModel),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Consultant routes
|
// Consultant routes
|
||||||
|
|||||||
@@ -46,6 +46,17 @@ extension DateTimeExtension on DateTime {
|
|||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
return now.year == localDate.year && now.month == localDate.month && now.day == localDate.day;
|
return now.year == localDate.year && now.month == localDate.month && now.day == localDate.day;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String toISO8601WithTimeZoneOffset() {
|
||||||
|
final formatter = DateFormat("yyyy-MM-ddTHH:mm:ss");
|
||||||
|
final formatted = formatter.format(this);
|
||||||
|
final offset = timeZoneOffset;
|
||||||
|
final hours = offset.inHours.abs().toString().padLeft(2, '0');
|
||||||
|
final minutes = (offset.inMinutes.abs() % 60).toString().padLeft(2, '0');
|
||||||
|
final sign = offset.isNegative ? '-' : '+';
|
||||||
|
|
||||||
|
return "$formatted$sign$hours:$minutes";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String calculateDifference(DateTime dateTime, [String? format]) {
|
String calculateDifference(DateTime dateTime, [String? format]) {
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => GoRouter.of(context).pushNamed('profileScreen', extra: blogPostState.blogPostModel?.author),
|
onTap: () => GoRouter.of(context).pushNamed('profileScreen', extra: blogPostState.blogPostModel?.author.authorSlug),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked
|
|||||||
import 'package:eatvio_app/core/theme/custom_text_style.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/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/chat/presentation/widgets/notification_banner.dart';
|
import 'package:eatvio_app/features/chat/presentation/widgets/notification_banner.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||||
import 'package:eatvio_app/features/order_info/presentation/info_by_order_screen.dart';
|
import 'package:eatvio_app/features/order_info/presentation/info_by_order_screen.dart';
|
||||||
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
||||||
@@ -152,12 +151,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed(
|
||||||
'profileScreen',
|
'profileScreen',
|
||||||
extra: Author(
|
extra: state.chatRoom.users.receiver.slug,
|
||||||
authorSlug: state.chatRoom.users.receiver.slug,
|
|
||||||
authorName: state.chatRoom.users.receiver.name,
|
|
||||||
authorProfileIcon: state.chatRoom.users.receiver.profilePhotoUrl ?? '',
|
|
||||||
authorIsMe: false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:eatvio_app/core/locator_service.dart';
|
|||||||
import 'package:eatvio_app/core/theme/custom_text_style.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/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -16,12 +16,9 @@ import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked
|
|||||||
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_state.dart';
|
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_state.dart';
|
||||||
|
|
||||||
class EmptyChatScreen extends StatefulWidget {
|
class EmptyChatScreen extends StatefulWidget {
|
||||||
final Author author;
|
final ProfileModel user;
|
||||||
|
|
||||||
const EmptyChatScreen({
|
const EmptyChatScreen({super.key, required this.user});
|
||||||
super.key,
|
|
||||||
required this.author,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<EmptyChatScreen> createState() => _EmptyChatScreenState();
|
State<EmptyChatScreen> createState() => _EmptyChatScreenState();
|
||||||
@@ -40,34 +37,19 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
|
|||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: GestureDetector(
|
title: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed('profileScreen', extra: widget.user.slug);
|
||||||
'profileScreen',
|
|
||||||
extra: Author(
|
|
||||||
authorSlug: widget.author.authorSlug,
|
|
||||||
authorName: widget.author.authorName,
|
|
||||||
authorProfileIcon: widget.author.authorProfileIcon,
|
|
||||||
authorIsMe: false,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
radius: 20,
|
radius: 20,
|
||||||
foregroundImage: NetworkImage(widget.author.authorProfileIcon),
|
foregroundImage: NetworkImage(widget.user.profilePhotoUrl),
|
||||||
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
|
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [Text(widget.user.name, style: CustomTextStyles.titleSmallBold.copyWith(color: PrimaryColors().black))],
|
||||||
Text(
|
|
||||||
widget.author.authorName,
|
|
||||||
style: CustomTextStyles.titleSmallBold.copyWith(
|
|
||||||
color: PrimaryColors().black,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -84,18 +66,14 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () => showImagePicker(widget.author.authorSlug),
|
onTap: () => showImagePicker(widget.user.slug),
|
||||||
customBorder: const CircleBorder(),
|
customBorder: const CircleBorder(),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: 40,
|
width: 40,
|
||||||
child: Transform.rotate(
|
child: Transform.rotate(
|
||||||
angle: pi / 4,
|
angle: pi / 4,
|
||||||
child: const Icon(
|
child: const Icon(Icons.attach_file_rounded, size: 30, color: Color(0xFF858E99)),
|
||||||
Icons.attach_file_rounded,
|
|
||||||
size: 30,
|
|
||||||
color: Color(0xFF858E99),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -117,8 +95,10 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
|
|||||||
hintText: 'Сообщение',
|
hintText: 'Сообщение',
|
||||||
hintStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, height: 1, color: Color(0xFFAEAEB2)),
|
hintStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, height: 1, color: Color(0xFFAEAEB2)),
|
||||||
filled: true,
|
filled: true,
|
||||||
border:
|
border: OutlineInputBorder(
|
||||||
OutlineInputBorder(borderRadius: BorderRadius.circular(100), borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1)),
|
borderRadius: BorderRadius.circular(100),
|
||||||
|
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
|
||||||
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(100),
|
borderRadius: BorderRadius.circular(100),
|
||||||
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
|
borderSide: const BorderSide(color: Color(0xFFD1D1D6), width: 1),
|
||||||
@@ -139,40 +119,29 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
|
|||||||
final blockedUsersCubit = sl<BlockedUsersCubit>();
|
final blockedUsersCubit = sl<BlockedUsersCubit>();
|
||||||
await blockedUsersCubit.getBlockedUsers();
|
await blockedUsersCubit.getBlockedUsers();
|
||||||
final blockedState = blockedUsersCubit.state;
|
final blockedState = blockedUsersCubit.state;
|
||||||
|
|
||||||
if (blockedState is BlockedUsersStateLoaded) {
|
if (blockedState is BlockedUsersStateLoaded) {
|
||||||
final isBlocked = blockedState.profilesList.any((profile) => profile.slug == widget.author.authorSlug);
|
final isBlocked = blockedState.profilesList.any((profile) => profile.slug == widget.user.slug);
|
||||||
if (isBlocked) {
|
if (isBlocked) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(content: Text('Вы не можете отправить сообщение заблокированному пользователю'), backgroundColor: Colors.red),
|
||||||
content: Text('Вы не можете отправить сообщение заблокированному пользователю'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textEditingController.text.isNotEmpty) {
|
if (textEditingController.text.isNotEmpty) {
|
||||||
await sl<ChatRepository>().sendMessage(
|
await sl<ChatRepository>().sendMessage(data: textEditingController.text.trim(), slug: widget.user.slug);
|
||||||
data: textEditingController.text.trim(),
|
|
||||||
slug: widget.author.authorSlug,
|
|
||||||
);
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
textEditingController.clear();
|
textEditingController.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.author.authorSlug);
|
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.user.slug);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
|
AppRouter.navigatorKey.currentContext?.pushReplacementNamed('chatScreen', extra: {'uuid': chatIdOrError});
|
||||||
'chatScreen',
|
|
||||||
extra: {
|
|
||||||
'uuid': chatIdOrError,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -201,53 +170,36 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
|
|||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
// Проверяем, заблокирован ли пользователь
|
// Проверяем, заблокирован ли пользователь
|
||||||
final blockedUsersCubit = sl<BlockedUsersCubit>();
|
final blockedUsersCubit = sl<BlockedUsersCubit>();
|
||||||
await blockedUsersCubit.getBlockedUsers();
|
await blockedUsersCubit.getBlockedUsers();
|
||||||
final blockedState = blockedUsersCubit.state;
|
final blockedState = blockedUsersCubit.state;
|
||||||
|
|
||||||
if (blockedState is BlockedUsersStateLoaded) {
|
if (blockedState is BlockedUsersStateLoaded) {
|
||||||
final isBlocked = blockedState.profilesList.any((profile) => profile.slug == widget.author.authorSlug);
|
final isBlocked = blockedState.profilesList.any((profile) => profile.slug == widget.user.slug);
|
||||||
if (isBlocked) {
|
if (isBlocked) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(content: Text('Вы не можете отправить сообщение заблокированному пользователю'), backgroundColor: Colors.red),
|
||||||
content: Text('Вы не можете отправить сообщение заблокированному пользователю'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final picker = ImagePicker();
|
final picker = ImagePicker();
|
||||||
List<XFile>? images = await picker.pickMultiImage();
|
List<XFile>? images = await picker.pickMultiImage();
|
||||||
if (images.isNotEmpty) {
|
if (images.isNotEmpty) {
|
||||||
List<File> files = images.map((image) => File(image.path)).toList();
|
List<File> files = images.map((image) => File(image.path)).toList();
|
||||||
await sl<ChatRepository>().sendMessage(
|
await sl<ChatRepository>().sendMessage(files: files, slug: widget.user.slug);
|
||||||
files: files,
|
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.user.slug);
|
||||||
slug: widget.author.authorSlug,
|
|
||||||
);
|
|
||||||
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.author.authorSlug);
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
|
AppRouter.navigatorKey.currentContext?.pushReplacementNamed('chatScreen', extra: {'uuid': chatIdOrError});
|
||||||
'chatScreen',
|
|
||||||
extra: {
|
|
||||||
'uuid': chatIdOrError,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Row(
|
child: const Row(children: [Icon(Icons.photo_library_rounded), SizedBox(width: 8), Text('Галерея')]),
|
||||||
children: [
|
|
||||||
Icon(Icons.photo_library_rounded),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Text('Галерея'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -256,28 +208,14 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
|
|||||||
List<XFile>? images = await picker.pickMultiImage();
|
List<XFile>? images = await picker.pickMultiImage();
|
||||||
if (images.isNotEmpty) {
|
if (images.isNotEmpty) {
|
||||||
List<File> files = images.map((image) => File(image.path)).toList();
|
List<File> files = images.map((image) => File(image.path)).toList();
|
||||||
await sl<ChatRepository>().sendMessage(
|
await sl<ChatRepository>().sendMessage(files: files, slug: widget.user.slug);
|
||||||
files: files,
|
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.user.slug);
|
||||||
slug: widget.author.authorSlug,
|
|
||||||
);
|
|
||||||
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.author.authorSlug);
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
|
AppRouter.navigatorKey.currentContext?.pushReplacementNamed('chatScreen', extra: {'uuid': chatIdOrError});
|
||||||
'chatScreen',
|
|
||||||
extra: {
|
|
||||||
'uuid': chatIdOrError,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Row(
|
child: const Row(children: [Icon(Icons.photo_camera), SizedBox(width: 8), Text('Фото')]),
|
||||||
children: [
|
|
||||||
Icon(Icons.photo_camera),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Text('Фото'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
CupertinoActionSheetAction(
|
CupertinoActionSheetAction(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -308,35 +246,17 @@ class _EmptyChatScreenState extends State<EmptyChatScreen> {
|
|||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
List<File> files = result.paths.map((path) => File(path!)).toList();
|
List<File> files = result.paths.map((path) => File(path!)).toList();
|
||||||
await sl<ChatRepository>().sendMessage(
|
await sl<ChatRepository>().sendMessage(files: files, slug: widget.user.slug);
|
||||||
files: files,
|
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.user.slug);
|
||||||
slug: widget.author.authorSlug,
|
|
||||||
);
|
|
||||||
final chatIdOrError = await sl<ChatRepository>().getChatByUserSlug(widget.author.authorSlug);
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
AppRouter.navigatorKey.currentContext?.pushReplacementNamed(
|
AppRouter.navigatorKey.currentContext?.pushReplacementNamed('chatScreen', extra: {'uuid': chatIdOrError});
|
||||||
'chatScreen',
|
|
||||||
extra: {
|
|
||||||
'uuid': chatIdOrError,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Row(
|
child: const Row(children: [Icon(Icons.file_present_rounded), SizedBox(width: 8), Text('Файлы')]),
|
||||||
children: [
|
|
||||||
Icon(Icons.file_present_rounded),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Text('Файлы'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
cancelButton: CupertinoActionSheetAction(
|
cancelButton: CupertinoActionSheetAction(onPressed: () => Navigator.of(context).pop(), isDestructiveAction: true, child: const Text('Отмена')),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
isDestructiveAction: true,
|
|
||||||
child: const Text('Отмена'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
22
lib/features/diary/entities/diary_day_entity.dart
Normal file
22
lib/features/diary/entities/diary_day_entity.dart
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'diary_day_entity.freezed.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class DiaryDayEntity with _$DiaryDayEntity {
|
||||||
|
factory DiaryDayEntity({
|
||||||
|
@JsonKey(name: "id") required int id,
|
||||||
|
@JsonKey(name: "date") required String date,
|
||||||
|
@JsonKey(name: "wakeup") String? wakeup,
|
||||||
|
@JsonKey(name: "retire") String? retire,
|
||||||
|
@JsonKey(name: "closed") required int closed,
|
||||||
|
@JsonKey(name: "comment") required String comment,
|
||||||
|
@JsonKey(name: "state") required TypeOfDiaryModel typeOfDiary,
|
||||||
|
@JsonKey(name: "meals") required List<MealModel> meals,
|
||||||
|
@JsonKey(name: "chosen_plan_id") required int? chosenPlanId,
|
||||||
|
@JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet,
|
||||||
|
@JsonKey(name: "chosen_diet", fromJson: parseDiet) required DiaryDietModel? diet,
|
||||||
|
}) = _DiaryDayEntity;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'diary_future_diet_day_entity.freezed.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class DiaryFutureDietDayEntity with _$DiaryFutureDietDayEntity {
|
||||||
|
const factory DiaryFutureDietDayEntity({
|
||||||
|
required String date,
|
||||||
|
required TypeOfDiaryModel typeOfDiary,
|
||||||
|
required List<MealModel> meals,
|
||||||
|
required DiaryDietModel? diet,
|
||||||
|
required int? dayOfChosenDiet,
|
||||||
|
}) = _DiaryFutureDietDayEntity;
|
||||||
|
|
||||||
|
}
|
||||||
11
lib/features/diary/models/create_day_model.dart
Normal file
11
lib/features/diary/models/create_day_model.dart
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'create_day_model.freezed.dart';
|
||||||
|
part 'create_day_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class CreateDayModel with _$CreateDayModel {
|
||||||
|
factory CreateDayModel({required String day}) = _CreateDayModel;
|
||||||
|
|
||||||
|
factory CreateDayModel.fromJson(Map<String, dynamic> json) => _$CreateDayModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
|
import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart';
|
||||||
|
import 'package:eatvio_app/features/diary/entities/diary_future_diet_day_entity.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
part 'diary_day_model.freezed.dart';
|
part 'diary_day_model.freezed.dart';
|
||||||
@@ -30,7 +32,7 @@ abstract class DiaryDayWrapperModel with _$DiaryDayWrapperModel {
|
|||||||
@freezed
|
@freezed
|
||||||
abstract class DiaryDayModel with _$DiaryDayModel {
|
abstract class DiaryDayModel with _$DiaryDayModel {
|
||||||
const factory DiaryDayModel({
|
const factory DiaryDayModel({
|
||||||
@JsonKey(name: "id") required int id,
|
@JsonKey(name: "id") required int? id,
|
||||||
@JsonKey(name: "date") required String date,
|
@JsonKey(name: "date") required String date,
|
||||||
@JsonKey(name: "wakeup") String? wakeup,
|
@JsonKey(name: "wakeup") String? wakeup,
|
||||||
@JsonKey(name: "retire") String? retire,
|
@JsonKey(name: "retire") String? retire,
|
||||||
@@ -40,26 +42,36 @@ abstract class DiaryDayModel with _$DiaryDayModel {
|
|||||||
@JsonKey(name: "meals") required List<MealModel> meals,
|
@JsonKey(name: "meals") required List<MealModel> meals,
|
||||||
@JsonKey(name: "chosen_plan_id") required int? chosenPlanId,
|
@JsonKey(name: "chosen_plan_id") required int? chosenPlanId,
|
||||||
@JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet,
|
@JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet,
|
||||||
@JsonKey(name: "chosen_diet", fromJson: _parseDiet) required DiaryDietModel? diet,
|
@JsonKey(name: "chosen_diet", fromJson: parseDiet) required DiaryDietModel? diet,
|
||||||
}) = _DiaryDayModel;
|
}) = _DiaryDayModel;
|
||||||
|
const DiaryDayModel._();
|
||||||
factory DiaryDayModel.fromJson(Map<String, dynamic> json) => _$DiaryDayModelFromJson(json);
|
factory DiaryDayModel.fromJson(Map<String, dynamic> json) => _$DiaryDayModelFromJson(json);
|
||||||
|
|
||||||
|
DiaryDayEntity? toEntity() {
|
||||||
|
if (id == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return DiaryDayEntity(
|
||||||
|
id: id!,
|
||||||
|
date: date,
|
||||||
|
closed: closed,
|
||||||
|
comment: comment,
|
||||||
|
typeOfDiary: typeOfDiary,
|
||||||
|
meals: meals,
|
||||||
|
chosenPlanId: chosenPlanId,
|
||||||
|
dayOfChosenDiet: dayOfChosenDiet,
|
||||||
|
wakeup: wakeup,
|
||||||
|
retire: retire,
|
||||||
|
diet: diet,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
DiaryFutureDietDayEntity toDiaryFutureDayEntity() {
|
||||||
|
return DiaryFutureDietDayEntity(date: date, typeOfDiary: typeOfDiary, meals: meals, dayOfChosenDiet: dayOfChosenDiet, diet: diet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
DiaryDietModel? parseDiet(dynamic json) {
|
||||||
abstract class DiaryFutureDietDayModel with _$DiaryFutureDietDayModel {
|
|
||||||
const factory DiaryFutureDietDayModel({
|
|
||||||
@JsonKey(name: "date") required String date,
|
|
||||||
@JsonKey(name: "state", fromJson: _parseDayTypeForFutureDay) required TypeOfDiaryModel typeOfDiary,
|
|
||||||
@JsonKey(name: "meals") required List<MealModel> meals,
|
|
||||||
@JsonKey(name: "chosen_diet", fromJson: _parseDiet) required DiaryDietModel? diet,
|
|
||||||
@JsonKey(name: "day_of_chosen_diet") required int? dayOfChosenDiet,
|
|
||||||
}) = _DiaryFutureDietDayModel;
|
|
||||||
|
|
||||||
factory DiaryFutureDietDayModel.fromJson(Map<String, dynamic> json) => _$DiaryFutureDietDayModelFromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
DiaryDietModel? _parseDiet(dynamic json) {
|
|
||||||
if (json == null) return null;
|
if (json == null) return null;
|
||||||
return DiaryDietModel.fromJson(json['diet']);
|
return DiaryDietModel.fromJson(json['diet']);
|
||||||
}
|
}
|
||||||
@@ -71,10 +83,6 @@ abstract class DiaryDietModel with _$DiaryDietModel {
|
|||||||
factory DiaryDietModel.fromJson(Map<String, dynamic> json) => _$DiaryDietModelFromJson(json);
|
factory DiaryDietModel.fromJson(Map<String, dynamic> json) => _$DiaryDietModelFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeOfDiaryModel _parseDayTypeForFutureDay(dynamic json) {
|
|
||||||
return TypeOfDiaryModel(hasChosenDiet: json['has_chosen_diet'] as bool, hasChosenPlan: json['has_chosen_plan'] as bool, diaryState: DiaryStateEnum.init);
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class MealModel with _$MealModel {
|
abstract class MealModel with _$MealModel {
|
||||||
const factory MealModel({
|
const factory MealModel({
|
||||||
@@ -141,7 +149,7 @@ abstract class TypeOfDiaryModel with _$TypeOfDiaryModel {
|
|||||||
const factory TypeOfDiaryModel({
|
const factory TypeOfDiaryModel({
|
||||||
@JsonKey(name: "has_chosen_diet") required bool hasChosenDiet,
|
@JsonKey(name: "has_chosen_diet") required bool hasChosenDiet,
|
||||||
@JsonKey(name: "has_chosen_plan") required bool hasChosenPlan,
|
@JsonKey(name: "has_chosen_plan") required bool hasChosenPlan,
|
||||||
@JsonKey(name: "last_state") required DiaryStateEnum diaryState,
|
@JsonKey(name: "last_state") required DiaryStateEnum? diaryState,
|
||||||
}) = _TypeOfDiaryModel;
|
}) = _TypeOfDiaryModel;
|
||||||
|
|
||||||
factory TypeOfDiaryModel.fromJson(Map<String, dynamic> json) => _$TypeOfDiaryModelFromJson(json);
|
factory TypeOfDiaryModel.fromJson(Map<String, dynamic> json) => _$TypeOfDiaryModelFromJson(json);
|
||||||
|
|||||||
11
lib/features/diary/models/get_day_model.dart
Normal file
11
lib/features/diary/models/get_day_model.dart
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'get_day_model.freezed.dart';
|
||||||
|
part 'get_day_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class GetDayModel with _$GetDayModel {
|
||||||
|
factory GetDayModel({required String day}) = _GetDayModel;
|
||||||
|
|
||||||
|
factory GetDayModel.fromJson(Map<String, dynamic> json) => _$GetDayModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||||||
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
|
import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart';
|
||||||
|
import 'package:eatvio_app/features/diary/entities/diary_future_diet_day_entity.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
||||||
@@ -20,7 +23,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
class DiaryCubit extends Cubit<DiaryState> {
|
class DiaryCubit extends Cubit<DiaryState> {
|
||||||
late final DateTime today;
|
late final DateTime today;
|
||||||
late DateTime selectedDay;
|
late DateTime selectedDay;
|
||||||
late int selectedMeal;
|
int selectedMeal = 1;
|
||||||
final DiaryRepository diaryRepository;
|
final DiaryRepository diaryRepository;
|
||||||
final GlossaryRepository glossaryRepository;
|
final GlossaryRepository glossaryRepository;
|
||||||
final ProfileRepository profileRepository;
|
final ProfileRepository profileRepository;
|
||||||
@@ -39,19 +42,79 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
today = DateTime.now();
|
today = DateTime.now();
|
||||||
selectedDay = today;
|
selectedDay = today;
|
||||||
diaryRepository.forceFetchStream.listen((_) {
|
diaryRepository.forceFetchStream.listen((_) {
|
||||||
fetchDiary(true, diaryId);
|
fetchDiaryV2(needLoading: true, diaryId: diaryId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
String comment = '';
|
String comment = '';
|
||||||
|
|
||||||
Future<bool?> setSelectedDay(DateTime day, {bool? forDietOnly}) async {
|
Future<bool> setSelectedDay(DateTime day) async {
|
||||||
|
final prevDay = selectedDay;
|
||||||
selectedDay = day;
|
selectedDay = day;
|
||||||
if (forDietOnly ?? false) {
|
final canSelect = await fetchDiaryV2(needLoading: true);
|
||||||
final result = await fetchDiaryForDietOnly();
|
|
||||||
return result;
|
if (!canSelect) {
|
||||||
|
selectedDay = prevDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
return canSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> fetchDiaryV2({bool needLoading = false, int? diaryId}) async {
|
||||||
|
final currentState = state;
|
||||||
|
if (needLoading) {
|
||||||
|
emit(const DiaryState.loading());
|
||||||
|
}
|
||||||
|
if (diaryId != null) {
|
||||||
|
final diaryDayById = await diaryRepository.getDiaryDay(diaryId);
|
||||||
|
final diaryEntity = diaryDayById.toEntity();
|
||||||
|
if (diaryEntity != null) {
|
||||||
|
setDiary(diaryDay: diaryEntity, diaryId: diaryId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final diaryDay = await getDiary();
|
||||||
|
if (diaryDay == null) {
|
||||||
|
emit(const DiaryState.error(errorMessage: 'Diary not found'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final diaryEntity = diaryDay.toEntity();
|
||||||
|
if (diaryEntity != null) {
|
||||||
|
setDiary(diaryDay: diaryEntity, diaryId: diaryId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (diaryDay.typeOfDiary.hasChosenDiet == true && diaryDay.typeOfDiary.diaryState == null) {
|
||||||
|
setDiaryForDietOnly(diaryDay.toDiaryFutureDayEntity());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
emit(currentState);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateCurrentDiary() async {
|
||||||
|
try {
|
||||||
|
final diaryDay = await diaryRepository.getDiaryDayV2(day: selectedDay.toISO8601WithTimeZoneOffset());
|
||||||
|
final diaryEntity = diaryDay.toEntity();
|
||||||
|
if (diaryEntity != null) {
|
||||||
|
setDiary(diaryDay: diaryEntity, diaryId: diaryId);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DiaryDayModel?> getDiary() async {
|
||||||
|
try {
|
||||||
|
await diaryRepository.createDiaryDay(day: selectedDay.toISO8601WithTimeZoneOffset());
|
||||||
|
final diaryDay = await diaryRepository.getDiaryDayV2(day: selectedDay.toISO8601WithTimeZoneOffset());
|
||||||
|
return diaryDay;
|
||||||
|
} on DioException catch (e) {
|
||||||
|
if (e.response?.statusCode == 422) {
|
||||||
|
final diaryDay = await diaryRepository.getDiaryDayV2(day: selectedDay.toISO8601WithTimeZoneOffset());
|
||||||
|
return diaryDay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await fetchDiary(true);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,9 +128,7 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> fetchDiaryForDietOnly() async {
|
Future<bool> setDiaryForDietOnly(DiaryFutureDietDayEntity diaryDay) async {
|
||||||
final stringDate = selectedDay.format('yyyy-MM-dd');
|
|
||||||
final diaryDay = await diaryRepository.getDiaryByDateForDietOnly(stringDate);
|
|
||||||
if (!diaryDay.typeOfDiary.hasChosenDiet) {
|
if (!diaryDay.typeOfDiary.hasChosenDiet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -146,22 +207,14 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetchDiary([bool needLoading = false, int? diaryId, int? currentDay]) async {
|
Future<void> setDiary({int? diaryId, required DiaryDayEntity diaryDay}) async {
|
||||||
this.diaryId ??= diaryId;
|
this.diaryId ??= diaryId;
|
||||||
final isConsultantView = this.diaryId != null;
|
final isConsultantView = this.diaryId != null;
|
||||||
if (needLoading) {
|
|
||||||
emit(const DiaryState.loading());
|
|
||||||
selectedMeal = 1;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
final DiaryDayModel diaryDay;
|
|
||||||
bool isMoodEnabled = false;
|
bool isMoodEnabled = false;
|
||||||
bool isWakeUpAndRetireTimeEnabled = false;
|
bool isWakeUpAndRetireTimeEnabled = false;
|
||||||
if (diaryId != null) {
|
if (diaryId != null) {
|
||||||
diaryDay = await diaryRepository.getDiaryDay(diaryId);
|
|
||||||
} else {
|
} else {
|
||||||
final stringDate = selectedDay.format('yyyy-MM-dd');
|
|
||||||
diaryDay = await diaryRepository.getDiaryByDate(stringDate);
|
|
||||||
final profileSettings = await settingsRepository.getProfileSettings();
|
final profileSettings = await settingsRepository.getProfileSettings();
|
||||||
isMoodEnabled = profileSettings.isMoodFillable;
|
isMoodEnabled = profileSettings.isMoodFillable;
|
||||||
isWakeUpAndRetireTimeEnabled = profileSettings.isBedtimeFillable;
|
isWakeUpAndRetireTimeEnabled = profileSettings.isBedtimeFillable;
|
||||||
@@ -214,7 +267,7 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
|
|
||||||
Future<void> finishDiaryDay({required int diaryId, required String wakeUp, required String retire}) async {
|
Future<void> finishDiaryDay({required int diaryId, required String wakeUp, required String retire}) async {
|
||||||
await diaryRepository.finishDiaryDay(diaryId: diaryId, wakeUp: wakeUp, retire: retire, comment: comment.isEmpty ? null : comment);
|
await diaryRepository.finishDiaryDay(diaryId: diaryId, wakeUp: wakeUp, retire: retire, comment: comment.isEmpty ? null : comment);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<NutritionDataModel> getNutrition(int index) async {
|
Future<NutritionDataModel> getNutrition(int index) async {
|
||||||
@@ -238,7 +291,7 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
quantity: quantity,
|
quantity: quantity,
|
||||||
productNutritionalValueId: productNutritionalValueId,
|
productNutritionalValueId: productNutritionalValueId,
|
||||||
);
|
);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateProductInMeal({
|
Future<void> updateProductInMeal({
|
||||||
@@ -272,27 +325,27 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
portionState: portionState,
|
portionState: portionState,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> markEaten({required int diaryId, required int mealId, required int portionId}) async {
|
Future<void> markEaten({required int diaryId, required int mealId, required int portionId}) async {
|
||||||
await diaryRepository.markEaten(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
await diaryRepository.markEaten(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> unmarkEaten({required int diaryId, required int mealId, required int portionId}) async {
|
Future<void> unmarkEaten({required int diaryId, required int mealId, required int portionId}) async {
|
||||||
await diaryRepository.unmarkEaten(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
await diaryRepository.unmarkEaten(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> restore({required int diaryId, required int mealId, required int portionId}) async {
|
Future<void> restore({required int diaryId, required int mealId, required int portionId}) async {
|
||||||
await diaryRepository.restore(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
await diaryRepository.restore(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteProductFromMeal({required int diaryId, required int mealId, required int portionId}) async {
|
Future<void> deleteProductFromMeal({required int diaryId, required int mealId, required int portionId}) async {
|
||||||
await diaryRepository.deleteProductFromMeal(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
await diaryRepository.deleteProductFromMeal(diaryId: diaryId, mealId: mealId, portionId: portionId);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<GlossaryModel>> getGlossaryListByQuery(String query) async {
|
Future<List<GlossaryModel>> getGlossaryListByQuery(String query) async {
|
||||||
@@ -301,12 +354,12 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
|
|
||||||
Future<void> uploadPhotos({required List<File> files, required int diaryId}) async {
|
Future<void> uploadPhotos({required List<File> files, required int diaryId}) async {
|
||||||
await diaryRepository.uploadPhotos(files: await ImageCompressUtility.compressFilesList(files), diaryId: diaryId, mealId: selectedMeal);
|
await diaryRepository.uploadPhotos(files: await ImageCompressUtility.compressFilesList(files), diaryId: diaryId, mealId: selectedMeal);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deletePhoto({required DiaryPhotoModel photo, required int diaryId}) async {
|
Future<void> deletePhoto({required DiaryPhotoModel photo, required int diaryId}) async {
|
||||||
await diaryRepository.deletePhoto(photo: photo, diaryId: diaryId, mealId: selectedMeal);
|
await diaryRepository.deletePhoto(photo: photo, diaryId: diaryId, mealId: selectedMeal);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<GlossaryModerationModel?> sendProductToModeration({
|
Future<GlossaryModerationModel?> sendProductToModeration({
|
||||||
@@ -326,30 +379,32 @@ class DiaryCubit extends Cubit<DiaryState> {
|
|||||||
|
|
||||||
Future<void> fillTime({required int diaryId, required String time}) async {
|
Future<void> fillTime({required int diaryId, required String time}) async {
|
||||||
await diaryRepository.fillTime(diaryId: diaryId, mealId: selectedMeal, time: time);
|
await diaryRepository.fillTime(diaryId: diaryId, mealId: selectedMeal, time: time);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fillWakeup({required int diaryId, required String time}) async {
|
Future<void> fillWakeup({required int diaryId, required String time}) async {
|
||||||
await diaryRepository.fillWakeup(diaryId: diaryId, time: time);
|
await diaryRepository.fillWakeup(diaryId: diaryId, time: time);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fillRetire({required int diaryId, required String time}) async {
|
Future<void> fillRetire({required int diaryId, required String time}) async {
|
||||||
await diaryRepository.fillRetire(diaryId: diaryId, time: time);
|
await diaryRepository.fillRetire(diaryId: diaryId, time: time);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fillSatiety({required int diaryId, required int satiety}) async {
|
Future<void> fillSatiety({required int diaryId, required int satiety}) async {
|
||||||
await diaryRepository.fillSatiety(diaryId: diaryId, mealId: selectedMeal, satiety: satiety);
|
await diaryRepository.fillSatiety(diaryId: diaryId, mealId: selectedMeal, satiety: satiety);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fillMood({required int diaryId, required int mood}) async {
|
Future<void> fillMood({required int diaryId, required int mood}) async {
|
||||||
await diaryRepository.fillMood(diaryId: diaryId, mealId: selectedMeal, mood: mood);
|
await diaryRepository.fillMood(diaryId: diaryId, mealId: selectedMeal, mood: mood);
|
||||||
await fetchDiary();
|
await updateCurrentDiary();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillComment(String comment) {
|
void fillComment(String comment) {
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DiaryFetchingErrors { canNotCreateFutureDays, dayAlreadyExists }
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart';
|
||||||
|
import 'package:eatvio_app/features/diary/entities/diary_future_diet_day_entity.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
|
||||||
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
@@ -11,12 +12,10 @@ abstract class DiaryState with _$DiaryState {
|
|||||||
|
|
||||||
const factory DiaryState.loading() = DiaryStateLoading;
|
const factory DiaryState.loading() = DiaryStateLoading;
|
||||||
|
|
||||||
const factory DiaryState.error({
|
const factory DiaryState.error({required String errorMessage}) = DiaryStateError;
|
||||||
required String errorMessage,
|
|
||||||
}) = DiaryStateError;
|
|
||||||
|
|
||||||
const factory DiaryState.loaded({
|
const factory DiaryState.loaded({
|
||||||
required DiaryDayModel diary,
|
required DiaryDayEntity diary,
|
||||||
required NutritionDataModel nutrition,
|
required NutritionDataModel nutrition,
|
||||||
required DateTime selectedDay,
|
required DateTime selectedDay,
|
||||||
required int selectedMeal,
|
required int selectedMeal,
|
||||||
@@ -32,9 +31,6 @@ abstract class DiaryState with _$DiaryState {
|
|||||||
@Default(false) bool isLoadingAddingProductInMeal,
|
@Default(false) bool isLoadingAddingProductInMeal,
|
||||||
}) = DiaryStateLoaded;
|
}) = DiaryStateLoaded;
|
||||||
|
|
||||||
const factory DiaryState.loadedTomorrowWithDiet({
|
const factory DiaryState.loadedTomorrowWithDiet({required DiaryFutureDietDayEntity diary, required DateTime selectedDay, required int selectedMeal}) =
|
||||||
required DiaryFutureDietDayModel diary,
|
DiaryStateLoadedTomorrowWithDiet;
|
||||||
required DateTime selectedDay,
|
|
||||||
required int selectedMeal,
|
|
||||||
}) = DiaryStateLoadedTomorrowWithDiet;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,19 +35,12 @@ class DiaryScreen extends StatelessWidget {
|
|||||||
class UserDiaryScreen extends StatelessWidget {
|
class UserDiaryScreen extends StatelessWidget {
|
||||||
static const path = '/user-diary-screen';
|
static const path = '/user-diary-screen';
|
||||||
static const name = 'userDiaryScreen';
|
static const name = 'userDiaryScreen';
|
||||||
const UserDiaryScreen({
|
const UserDiaryScreen({super.key, required this.diaryId, required this.currentPlanDay});
|
||||||
super.key,
|
|
||||||
required this.diaryId,
|
|
||||||
required this.currentPlanDay,
|
|
||||||
});
|
|
||||||
final int diaryId;
|
final int diaryId;
|
||||||
final int currentPlanDay;
|
final int currentPlanDay;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return DiaryScreenContent(
|
return DiaryScreenContent(diaryId: diaryId, currentPlanDay: currentPlanDay);
|
||||||
diaryId: diaryId,
|
|
||||||
currentPlanDay: currentPlanDay,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,12 +53,8 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider<DiaryCubit>(
|
BlocProvider<DiaryCubit>(create: (BuildContext context) => sl<DiaryCubit>()..fetchDiaryV2(needLoading: true, diaryId: diaryId)),
|
||||||
create: (BuildContext context) => sl<DiaryCubit>()..fetchDiary(true, diaryId, currentPlanDay),
|
BlocProvider(create: (context) => sl<ConsultantCommentsCubit>()),
|
||||||
),
|
|
||||||
BlocProvider(
|
|
||||||
create: (context) => sl<ConsultantCommentsCubit>(),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
child: BlocBuilder<DiaryCubit, DiaryState>(
|
child: BlocBuilder<DiaryCubit, DiaryState>(
|
||||||
builder: (BuildContext context, DiaryState state) {
|
builder: (BuildContext context, DiaryState state) {
|
||||||
@@ -74,16 +63,14 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
if (state is DiaryStateError) {
|
if (state is DiaryStateError) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: DataErrorWidget(onReload: () => context.read<DiaryCubit>().fetchDiary(false, diaryId)),
|
body: DataErrorWidget(onReload: () => context.read<DiaryCubit>().fetchDiaryV2(needLoading: false, diaryId: diaryId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Colors.grey.shade200,
|
||||||
appBar: diaryId == null
|
appBar: diaryId == null
|
||||||
? AppBar(
|
? AppBar(toolbarHeight: 0)
|
||||||
toolbarHeight: 0,
|
|
||||||
)
|
|
||||||
: AppBar(
|
: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
state is DiaryStateLoaded ? DateTime.parse(state.diary.date).toLocal().format('d MMMM') : '',
|
state is DiaryStateLoaded ? DateTime.parse(state.diary.date).toLocal().format('d MMMM') : '',
|
||||||
@@ -97,12 +84,7 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (diaryId == null) const CalendarWidget(),
|
if (diaryId == null) const CalendarWidget(),
|
||||||
if (state is DiaryStateLoading) ...[
|
if (state is DiaryStateLoading) ...[const SizedBox(height: 60), const Loader()],
|
||||||
const SizedBox(
|
|
||||||
height: 60,
|
|
||||||
),
|
|
||||||
const Loader()
|
|
||||||
],
|
|
||||||
if (state is DiaryStateLoaded)
|
if (state is DiaryStateLoaded)
|
||||||
WakeupAndRetireWidget(
|
WakeupAndRetireWidget(
|
||||||
isEnabled: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isWakeUpAndRetireEnabled,
|
isEnabled: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isWakeUpAndRetireEnabled,
|
||||||
@@ -114,40 +96,31 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
showMood: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isMoodEnabled,
|
showMood: state.diary.typeOfDiary.hasChosenPlan || state.isConsultantView || state.isMoodEnabled,
|
||||||
showAddButton: !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented,
|
showAddButton: !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented,
|
||||||
),
|
),
|
||||||
if (state is DiaryStateLoadedTomorrowWithDiet)
|
if (state is DiaryStateLoadedTomorrowWithDiet) const MealWidget(showMood: false, showAddButton: false),
|
||||||
const MealWidget(
|
|
||||||
showMood: false,
|
|
||||||
showAddButton: false,
|
|
||||||
),
|
|
||||||
if (state is DiaryStateLoaded) const CaloriesChartWidget(),
|
if (state is DiaryStateLoaded) const CaloriesChartWidget(),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Builder(builder: (context) {
|
Builder(
|
||||||
if (state is DiaryStateLoaded && state.diary.typeOfDiary.hasChosenPlan) {
|
builder: (context) {
|
||||||
if (state.diary.comment.isNotEmpty) {
|
if (state is DiaryStateLoaded && state.diary.typeOfDiary.hasChosenPlan) {
|
||||||
return CommentForConsultantWidget(
|
if (state.diary.comment.isNotEmpty) {
|
||||||
comment: state.diary.comment,
|
return CommentForConsultantWidget(comment: state.diary.comment);
|
||||||
);
|
}
|
||||||
|
if (state.isDiaryCommented || state.isDiaryFinished) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
return const CommentForConsultantWidget();
|
||||||
}
|
}
|
||||||
if (state.isDiaryCommented || state.isDiaryFinished) {
|
return const SizedBox.shrink();
|
||||||
return const SizedBox.shrink();
|
},
|
||||||
}
|
),
|
||||||
return const CommentForConsultantWidget();
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}),
|
|
||||||
if (state is DiaryStateLoaded && !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented)
|
if (state is DiaryStateLoaded && !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 12),
|
padding: const EdgeInsets.only(top: 12),
|
||||||
child: FinishDayButtonWidget(
|
child: FinishDayButtonWidget(diaryDay: state.diary),
|
||||||
diaryDay: state.diary,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (state is DiaryStateLoaded && state.isConsultantView && !state.isDiaryCommented) ...[
|
if (state is DiaryStateLoaded && state.isConsultantView && !state.isDiaryCommented) ...[
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const MainBackgroundBouble(
|
const MainBackgroundBouble(padding: EdgeInsets.all(16), child: DayCommentWidget()),
|
||||||
padding: EdgeInsets.all(16),
|
|
||||||
child: DayCommentWidget(),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
if (state is DiaryStateLoaded && state.consultantReview?.consultantComments.dayComment != null) ...[
|
if (state is DiaryStateLoaded && state.consultantReview?.consultantComments.dayComment != null) ...[
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
@@ -155,10 +128,7 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(s.dayComment, style: TextStyles.textLSemibold.copyWith(color: appTheme.black)),
|
||||||
s.dayComment,
|
|
||||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
CommentContainer(comment: state.consultantReview?.consultantComments.dayComment ?? ''),
|
CommentContainer(comment: state.consultantReview?.consultantComments.dayComment ?? ''),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -25,26 +25,30 @@ class _AddProductModalState extends State<AddProductModal> {
|
|||||||
final quantityController = TextEditingController();
|
final quantityController = TextEditingController();
|
||||||
GlossaryModel? selectedGlossary;
|
GlossaryModel? selectedGlossary;
|
||||||
List<GlossaryModel> glossariesList = [];
|
List<GlossaryModel> glossariesList = [];
|
||||||
|
late final String? _previousProductName;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
if (widget.portion != null) {
|
if (widget.portion != null) {
|
||||||
|
_previousProductName = widget.portion!.productName;
|
||||||
productNameController.text = widget.portion!.productName;
|
productNameController.text = widget.portion!.productName;
|
||||||
quantityController.text = '${widget.portion!.quantity}';
|
quantityController.text = '${widget.portion!.quantity}';
|
||||||
selectedGlossary = GlossaryModel(
|
final productNutritionalValueId = widget.portion?.productNutritionalValueId;
|
||||||
id: widget.portion!.id,
|
if (productNutritionalValueId != null) {
|
||||||
name: widget.portion!.productName,
|
selectedGlossary = GlossaryModel(
|
||||||
grInPortion: widget.portion!.portion == 'gr' ? 0 : 1,
|
id: productNutritionalValueId,
|
||||||
energyOn100Gr: 0,
|
name: widget.portion!.productName,
|
||||||
proteinsOn100Gr: 0,
|
grInPortion: widget.portion!.portion == 'gr' ? 0 : 1,
|
||||||
fatsOn100Gr: 0,
|
energyOn100Gr: 0,
|
||||||
carbohydratesOn100Gr: 0,
|
proteinsOn100Gr: 0,
|
||||||
energyOnPortion: 0,
|
fatsOn100Gr: 0,
|
||||||
proteinsOnPortion: 0,
|
carbohydratesOn100Gr: 0,
|
||||||
fatsOnPortion: 0,
|
energyOnPortion: 0,
|
||||||
carbohydratesOnPortion: 0,
|
proteinsOnPortion: 0,
|
||||||
);
|
fatsOnPortion: 0,
|
||||||
|
carbohydratesOnPortion: 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +195,7 @@ class _AddProductModalState extends State<AddProductModal> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
if (selectedGlossary == null) {
|
if (selectedGlossary == null && _previousProductName != productNameController.text) {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
|
|||||||
@@ -43,46 +43,24 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
|||||||
locale: 'ru_RU',
|
locale: 'ru_RU',
|
||||||
startingDayOfWeek: StartingDayOfWeek.monday,
|
startingDayOfWeek: StartingDayOfWeek.monday,
|
||||||
calendarFormat: _calendarFormat,
|
calendarFormat: _calendarFormat,
|
||||||
headerStyle: const HeaderStyle(
|
headerStyle: const HeaderStyle(titleCentered: true, formatButtonVisible: false, leftChevronVisible: false, rightChevronVisible: false),
|
||||||
titleCentered: true,
|
|
||||||
formatButtonVisible: false,
|
|
||||||
leftChevronVisible: false,
|
|
||||||
rightChevronVisible: false,
|
|
||||||
),
|
|
||||||
onDaySelected: (selectedDay, focusedDay) async {
|
onDaySelected: (selectedDay, focusedDay) async {
|
||||||
if (!isSameDay(_selectedDay, selectedDay)) {
|
if (!isSameDay(_selectedDay, selectedDay)) {
|
||||||
final today = DateTime.now();
|
final previousSelectedDay = _selectedDay;
|
||||||
if (selectedDay.isAfter(today)) {
|
final previousFocusedDay = _selectedDay;
|
||||||
if ((state is DiaryStateLoaded)) {
|
|
||||||
final result = await context.read<DiaryCubit>().setSelectedDay(_selectedDay, forDietOnly: true);
|
|
||||||
if (result == false && context.mounted) {
|
|
||||||
showErrorDialog(context, title: s.want_to_see_tomorrow, description: s.can_not_see_next_day);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
_selectedDay = selectedDay;
|
|
||||||
_focusedDay = focusedDay;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (state is DiaryStateLoadedTomorrowWithDiet) {
|
|
||||||
final result = await context.read<DiaryCubit>().setSelectedDay(_selectedDay, forDietOnly: true);
|
|
||||||
if (result == false && context.mounted) {
|
|
||||||
showErrorDialog(context, title: s.want_to_see_tomorrow, description: s.can_not_see_next_day);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
_selectedDay = selectedDay;
|
|
||||||
_focusedDay = focusedDay;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDay = selectedDay;
|
_selectedDay = selectedDay;
|
||||||
_focusedDay = focusedDay;
|
_focusedDay = focusedDay;
|
||||||
});
|
});
|
||||||
context.read<DiaryCubit>().setSelectedDay(_selectedDay);
|
final canOpenNextDay = await context.read<DiaryCubit>().setSelectedDay(selectedDay);
|
||||||
|
if (!canOpenNextDay && context.mounted) {
|
||||||
|
showErrorDialog(context, title: s.want_to_see_tomorrow, description: s.can_not_see_next_day);
|
||||||
|
setState(() {
|
||||||
|
_selectedDay = previousSelectedDay;
|
||||||
|
_focusedDay = previousFocusedDay;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectedDayPredicate: (day) {
|
selectedDayPredicate: (day) {
|
||||||
@@ -101,26 +79,12 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
calendarStyle: CalendarStyle(
|
calendarStyle: CalendarStyle(
|
||||||
weekendDecoration: const BoxDecoration(
|
weekendDecoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle),
|
||||||
color: Colors.white,
|
defaultDecoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle),
|
||||||
shape: BoxShape.circle,
|
selectedDecoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle),
|
||||||
),
|
todayTextStyle: const TextStyle(color: Colors.black),
|
||||||
defaultDecoration: const BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
selectedDecoration: BoxDecoration(
|
|
||||||
color: appTheme.blueA400,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
),
|
|
||||||
todayTextStyle: const TextStyle(
|
|
||||||
color: Colors.black,
|
|
||||||
),
|
|
||||||
todayDecoration: BoxDecoration(
|
todayDecoration: BoxDecoration(
|
||||||
border: Border.all(
|
border: Border.all(color: appTheme.blueA400, width: 2),
|
||||||
color: appTheme.blueA400,
|
|
||||||
width: 2,
|
|
||||||
),
|
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
@@ -152,10 +116,7 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.only(top: 8, bottom: 16),
|
padding: const EdgeInsets.only(top: 8, bottom: 16),
|
||||||
child: Icon(
|
child: Icon(_calendarFormat == CalendarFormat.month ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded, color: Colors.grey.shade600),
|
||||||
_calendarFormat == CalendarFormat.month ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded,
|
|
||||||
color: Colors.grey.shade600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart';
|
||||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class FinishDayButtonWidget extends StatefulWidget {
|
class FinishDayButtonWidget extends StatefulWidget {
|
||||||
final DiaryDayModel diaryDay;
|
final DiaryDayEntity diaryDay;
|
||||||
|
|
||||||
const FinishDayButtonWidget({super.key, required this.diaryDay});
|
const FinishDayButtonWidget({super.key, required this.diaryDay});
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,7 @@ class GlossaryModerationRequestModalWidget extends StatefulWidget {
|
|||||||
final DiaryCubit diaryCubit;
|
final DiaryCubit diaryCubit;
|
||||||
final String productName;
|
final String productName;
|
||||||
|
|
||||||
const GlossaryModerationRequestModalWidget({
|
const GlossaryModerationRequestModalWidget({super.key, required this.productName, required this.diaryCubit});
|
||||||
super.key,
|
|
||||||
required this.productName,
|
|
||||||
required this.diaryCubit,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GlossaryModerationRequestModalWidget> createState() => _GlossaryModerationRequestModalWidgetState();
|
State<GlossaryModerationRequestModalWidget> createState() => _GlossaryModerationRequestModalWidgetState();
|
||||||
@@ -55,21 +51,13 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
const Text(
|
const Text(
|
||||||
'Добавление нового продукта',
|
'Добавление нового продукта',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(color: Color(0xFF323F4B), fontSize: 20, fontWeight: FontWeight.w600),
|
||||||
color: Color(0xFF323F4B),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const Text(
|
const Text(
|
||||||
'Оу... а у нас нет в базе калорийности такого продукта. Если вы знаете, давайте её запишем?',
|
'Оу... а у нас нет в базе калорийности такого продукта. Если вы знаете, давайте её запишем?',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(color: Color(0xFF323F4B), fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
color: Color(0xFF323F4B),
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Row(
|
Row(
|
||||||
@@ -77,25 +65,27 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
Navigator.pop(context);
|
glossary = (await widget.diaryCubit.sendProductToModeration(
|
||||||
|
name: productNameController.text,
|
||||||
|
energy: 0,
|
||||||
|
proteins: 0,
|
||||||
|
fats: 0,
|
||||||
|
carbohydrates: 0,
|
||||||
|
))?.glossary;
|
||||||
|
setState(() {
|
||||||
|
glossaryState = GlossaryState.success;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: const Color(0xFFF6F6F6), borderRadius: BorderRadius.circular(20)),
|
||||||
color: const Color(0xFFF6F6F6),
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'В другой раз',
|
'Отказаться',
|
||||||
style: TextStyle(
|
style: TextStyle(color: Color(0xFF6D6F71), fontSize: 18, fontWeight: FontWeight.w500),
|
||||||
color: Color(0xFF6D6F71),
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -111,20 +101,13 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: appTheme.blueA400, borderRadius: BorderRadius.circular(20)),
|
||||||
color: appTheme.blueA400,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Записать',
|
'Записать',
|
||||||
style: TextStyle(
|
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w500),
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -146,18 +129,10 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
const Text(
|
const Text(
|
||||||
'Продукт успешно отправлен\nна модерацию',
|
'Продукт успешно отправлен\nна модерацию',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(color: Color(0xFF323F4B), fontSize: 20, fontWeight: FontWeight.w600),
|
||||||
color: Color(0xFF323F4B),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Lottie.asset(
|
Lottie.asset('assets/lottie_animations/success.json', width: 160, height: 160),
|
||||||
'assets/lottie_animations/success.json',
|
|
||||||
width: 160,
|
|
||||||
height: 160,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -165,20 +140,13 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: appTheme.blueA400, borderRadius: BorderRadius.circular(20)),
|
||||||
color: appTheme.blueA400,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Закрыть',
|
'Закрыть',
|
||||||
style: TextStyle(
|
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w500),
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -198,27 +166,16 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
const Text(
|
const Text(
|
||||||
'Добавление нового продукта',
|
'Добавление нового продукта',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(color: Color(0xFF323F4B), fontSize: 20, fontWeight: FontWeight.w600),
|
||||||
color: Color(0xFF323F4B),
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const Text(
|
const Text(
|
||||||
'Если у вас данные по нему\nпросим заполнить значения на 100гр.',
|
'Если у вас данные по нему\nпросим заполнить значения на 100гр.',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(color: Color(0xFF323F4B), fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
color: Color(0xFF323F4B),
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
CustomTextFormField(
|
CustomTextFormField(hintText: 'Сырный суп', controller: productNameController),
|
||||||
hintText: 'Сырный суп',
|
|
||||||
controller: productNameController,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -245,11 +202,7 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomTextFormField(
|
child: CustomTextFormField(hintText: 'Жиры', controller: fatsController, keyboardType: const TextInputType.numberWithOptions(decimal: true)),
|
||||||
hintText: 'Жиры',
|
|
||||||
controller: fatsController,
|
|
||||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -270,8 +223,7 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
proteins: double.parse(proteinsController.text.replaceAll(',', '.')),
|
proteins: double.parse(proteinsController.text.replaceAll(',', '.')),
|
||||||
fats: double.parse(fatsController.text.replaceAll(',', '.')),
|
fats: double.parse(fatsController.text.replaceAll(',', '.')),
|
||||||
carbohydrates: double.parse(carbohydratesController.text.replaceAll(',', '.')),
|
carbohydrates: double.parse(carbohydratesController.text.replaceAll(',', '.')),
|
||||||
))
|
))?.glossary;
|
||||||
?.glossary;
|
|
||||||
setState(() {
|
setState(() {
|
||||||
glossaryState = GlossaryState.success;
|
glossaryState = GlossaryState.success;
|
||||||
});
|
});
|
||||||
@@ -279,20 +231,13 @@ class _GlossaryModerationRequestModalWidgetState extends State<GlossaryModeratio
|
|||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: appTheme.blueA400, borderRadius: BorderRadius.circular(20)),
|
||||||
color: appTheme.blueA400,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Сохранить',
|
'Сохранить',
|
||||||
style: TextStyle(
|
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600),
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import 'package:eatvio_app/core/app_router.dart';
|
|||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart';
|
||||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
||||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
|
import 'package:eatvio_app/features/diary/presentation/bloc/diary_state.dart';
|
||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
@@ -35,7 +35,7 @@ class _PhotoGalleryWidgetState extends State<PhotoGalleryWidget> {
|
|||||||
diaryCubit = context.read<DiaryCubit>();
|
diaryCubit = context.read<DiaryCubit>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void showImagePicker(DiaryDayModel diaryDay) {
|
void showImagePicker(DiaryDayEntity diaryDay) {
|
||||||
showCupertinoModalPopup<void>(
|
showCupertinoModalPopup<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:eatvio_app/features/diary/models/consultant_comment_model.dart';
|
import 'package:eatvio_app/features/diary/models/consultant_comment_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
||||||
|
import 'package:eatvio_app/features/diary/models/create_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/finish_diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/models/finish_diary_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
||||||
@@ -69,14 +70,6 @@ class DiaryRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DiaryFutureDietDayModel> getDiaryByDateForDietOnly(String date) async {
|
|
||||||
try {
|
|
||||||
return (await diaryService.getDiaryIndexByDateForDietOnly(date: date)).last;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<DiaryDayModel>> getDiaryIndexByDate(String date) async {
|
Future<List<DiaryDayModel>> getDiaryIndexByDate(String date) async {
|
||||||
return (await diaryService.getDiaryIndexByDate(date: date));
|
return (await diaryService.getDiaryIndexByDate(date: date));
|
||||||
}
|
}
|
||||||
@@ -164,7 +157,7 @@ class DiaryRepository {
|
|||||||
required PortionState portionState,
|
required PortionState portionState,
|
||||||
}) async {
|
}) async {
|
||||||
Map<String, Object?> data = ProductInMeal(productName: productName, portion: portion, quantity: quantity).toJson();
|
Map<String, Object?> data = ProductInMeal(productName: productName, portion: portion, quantity: quantity).toJson();
|
||||||
data['product_nutritional_value_id'] = productNutritionalValueId;
|
if (productNutritionalValueId != null) data['product_nutritional_value_id'] = productNutritionalValueId;
|
||||||
data['state'] = portionState.name;
|
data['state'] = portionState.name;
|
||||||
return await diaryService.updateProductInMeal(diary: diaryId, typeNo: mealId, portionModel: portionId, productInMeal: data);
|
return await diaryService.updateProductInMeal(diary: diaryId, typeNo: mealId, portionModel: portionId, productInMeal: data);
|
||||||
}
|
}
|
||||||
@@ -300,4 +293,69 @@ class DiaryRepository {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<DiaryDayModel> getDiaryDayV2({required String day}) async {
|
||||||
|
try {
|
||||||
|
final diaryDay = await diaryService.getDiaryDayV2(day: day);
|
||||||
|
return setCPFCToDiary(diaryDay);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> createDiaryDay({required String day}) async {
|
||||||
|
try {
|
||||||
|
await diaryService.createDay(body: CreateDayModel(day: day));
|
||||||
|
await getDiaryByDate(day);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DiaryDayModel> setCPFCToDiary(DiaryDayModel diaryDay) async {
|
||||||
|
Set<int> ids = {};
|
||||||
|
for (var meal in diaryDay.meals) {
|
||||||
|
for (var portion in meal.portions) {
|
||||||
|
if (portion.productNutritionalValueId != null) {
|
||||||
|
ids.add(portion.productNutritionalValueId!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ids.isNotEmpty) {
|
||||||
|
final glossary = await getGlossariesIndex(ids: ids.toList());
|
||||||
|
final List<MealModel> updatedMeals = List.from(diaryDay.meals);
|
||||||
|
for (var mealIndex = 0; mealIndex < updatedMeals.length; mealIndex++) {
|
||||||
|
final meal = updatedMeals[mealIndex];
|
||||||
|
final updatedPortions = meal.portions.map((portion) {
|
||||||
|
if (portion.productNutritionalValueId != null) {
|
||||||
|
try {
|
||||||
|
final glossaryItem = glossary.glossariesList.firstWhere((g) => g.id == portion.productNutritionalValueId);
|
||||||
|
return portion.copyWith(
|
||||||
|
productCaloriesInfo: ProductCaloriesInfoModel(
|
||||||
|
id: glossaryItem.id,
|
||||||
|
productName: glossaryItem.name,
|
||||||
|
calories: glossaryItem.energyOn100Gr,
|
||||||
|
proteins: glossaryItem.proteinsOn100Gr,
|
||||||
|
fats: glossaryItem.fatsOn100Gr,
|
||||||
|
carbohydrates: glossaryItem.carbohydratesOn100Gr,
|
||||||
|
energyOnPortion: glossaryItem.energyOnPortion,
|
||||||
|
proteinsOnPortion: glossaryItem.proteinsOnPortion,
|
||||||
|
fatsOnPortion: glossaryItem.fatsOnPortion,
|
||||||
|
carbohydratesOnPortion: glossaryItem.carbohydratesOnPortion,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
return portion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return portion;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
updatedMeals[mealIndex] = meal.copyWith(portions: updatedPortions);
|
||||||
|
}
|
||||||
|
final updatedDiaryDay = diaryDay.copyWith(meals: updatedMeals);
|
||||||
|
return updatedDiaryDay;
|
||||||
|
}
|
||||||
|
return diaryDay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/consultant_comment_model.dart';
|
import 'package:eatvio_app/features/diary/models/consultant_comment_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
import 'package:eatvio_app/features/diary/models/consultant_review_model.dart';
|
||||||
|
import 'package:eatvio_app/features/diary/models/create_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/models/diary_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/finish_diary_day_model.dart';
|
import 'package:eatvio_app/features/diary/models/finish_diary_day_model.dart';
|
||||||
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
import 'package:eatvio_app/features/diary/models/nutrition_model.dart';
|
||||||
@@ -17,8 +18,6 @@ abstract class DiaryService {
|
|||||||
@GET('/api/diary/index/{date}')
|
@GET('/api/diary/index/{date}')
|
||||||
Future<List<DiaryDayModel>> getDiaryIndexByDate({@Path('date') required String date});
|
Future<List<DiaryDayModel>> getDiaryIndexByDate({@Path('date') required String date});
|
||||||
|
|
||||||
@GET('/api/diary/index/{date}')
|
|
||||||
Future<List<DiaryFutureDietDayModel>> getDiaryIndexByDateForDietOnly({@Path('date') required String date});
|
|
||||||
|
|
||||||
@GET('/api/diary/{diary}/show')
|
@GET('/api/diary/{diary}/show')
|
||||||
Future<DiaryDayWrapperModel> getDiaryDay({@Path('diary') required int diary});
|
Future<DiaryDayWrapperModel> getDiaryDay({@Path('diary') required int diary});
|
||||||
@@ -103,4 +102,10 @@ abstract class DiaryService {
|
|||||||
|
|
||||||
@GET('/api/glossaries/index')
|
@GET('/api/glossaries/index')
|
||||||
Future<GlossaryPaginationModel> getGlossariesIndex({@Queries() Map<String, dynamic>? filters});
|
Future<GlossaryPaginationModel> getGlossariesIndex({@Queries() Map<String, dynamic>? filters});
|
||||||
|
|
||||||
|
@POST('/api/v2/diary/create/day')
|
||||||
|
Future<void> createDay({@Body() required CreateDayModel body});
|
||||||
|
|
||||||
|
@GET('/api/v2/diary/index/{day?}')
|
||||||
|
Future<DiaryDayModel> getDiaryDayV2({@Query('day') required String day});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class AuthorCard extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed('profileScreen', extra: author);
|
GoRouter.of(context).pushNamed('profileScreen', extra: author.authorSlug);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
width: MediaQuery.sizeOf(context).width,
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
|||||||
import 'package:eatvio_app/core/widgets/custom_popup.dart';
|
import 'package:eatvio_app/core/widgets/custom_popup.dart';
|
||||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.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_cubit.dart';
|
||||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
|
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
|
||||||
import 'package:eatvio_app/features/feed/presentation/widgets/subscribe_button_widget.dart';
|
import 'package:eatvio_app/features/feed/presentation/widgets/subscribe_button_widget.dart';
|
||||||
@@ -60,14 +59,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed(
|
||||||
'profileScreen',
|
'profileScreen',
|
||||||
extra: Author(
|
extra: state.feedBlogPostList[widget.index].author.authorSlug,
|
||||||
authorSlug: state.feedBlogPostList[widget.index].author.authorSlug,
|
|
||||||
authorName: state.feedBlogPostList[widget.index].author.authorName,
|
|
||||||
authorProfileIcon: state.feedBlogPostList[widget.index].author.authorProfileIcon.contains('https')
|
|
||||||
? state.feedBlogPostList[widget.index].author.authorProfileIcon
|
|
||||||
: sl<AppConfig>().baseUrl + state.feedBlogPostList[widget.index].author.authorProfileIcon,
|
|
||||||
authorIsMe: state.feedBlogPostList[widget.index].author.authorIsMe,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: CircleAvatar(
|
child: CircleAvatar(
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/prof
|
|||||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart';
|
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart';
|
||||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/comment_model.dart';
|
import 'package:eatvio_app/features/feed/models/comment_model.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart';
|
import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart';
|
||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
@@ -96,12 +95,7 @@ class _CommentsWidgetState extends State<CommentsWidget> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed(
|
||||||
'profileScreen',
|
'profileScreen',
|
||||||
extra: Author(
|
extra: comment.authorSlug,
|
||||||
authorSlug: comment.authorSlug,
|
|
||||||
authorName: comment.authorName,
|
|
||||||
authorProfileIcon: comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : sl<AppConfig>().baseUrl + comment.authorProfileIcon,
|
|
||||||
authorIsMe: isMe,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: CircleAvatar(
|
child: CircleAvatar(
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ import 'package:cached_network_image/cached_network_image.dart';
|
|||||||
import 'package:eatvio_app/core/app_config.dart';
|
import 'package:eatvio_app/core/app_config.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
|
||||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart';
|
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/features/feed/models/feed_consultant_model.dart';
|
import 'package:eatvio_app/features/feed/models/feed_consultant_model.dart';
|
||||||
import 'package:eatvio_app/features/profile/models/badge_model.dart';
|
import 'package:eatvio_app/features/profile/models/badge_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -22,12 +19,7 @@ class ConsultantWidget extends StatelessWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed(
|
||||||
'profileScreen',
|
'profileScreen',
|
||||||
extra: Author(
|
extra: consultant.slug,
|
||||||
authorSlug: consultant.slug,
|
|
||||||
authorName: consultant.name,
|
|
||||||
authorProfileIcon: consultant.photo,
|
|
||||||
authorIsMe: (sl<ProfileAvatarCubit>().state as ProfileAvatarStateLoaded).profile.slug == consultant.slug ? true : false,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import 'package:eatvio_app/core/widgets/custom_popup.dart';
|
|||||||
import 'package:eatvio_app/core/widgets/info_row.dart';
|
import 'package:eatvio_app/core/widgets/info_row.dart';
|
||||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
import 'package:eatvio_app/features/feed/models/plan_pagination_model.dart';
|
||||||
import 'package:eatvio_app/core/theme/custom_text_style.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/theme/theme_helper.dart';
|
||||||
@@ -170,12 +169,7 @@ class _PlanWidgetState extends State<PlanWidget> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed(
|
||||||
'profileScreen',
|
'profileScreen',
|
||||||
extra: Author(
|
extra: widget.plan.author.authorSlug,
|
||||||
authorSlug: widget.plan.author.authorSlug,
|
|
||||||
authorName: widget.plan.author.authorName,
|
|
||||||
authorProfileIcon: widget.plan.author.authorProfileIcon,
|
|
||||||
authorIsMe: widget.plan.author.authorIsMe,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:eatvio_app/core/app_config.dart';
|
import 'package:eatvio_app/core/app_config.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
|
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
|
||||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -21,13 +20,7 @@ class _BlockedUserWidgetState extends State<BlockedUserWidget> {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () => GoRouter.of(context).pushNamed(
|
onTap: () => GoRouter.of(context).pushNamed(
|
||||||
'profileScreen',
|
'profileScreen',
|
||||||
extra: Author(
|
extra: widget.profile.slug,
|
||||||
authorSlug: widget.profile.slug,
|
|
||||||
authorName: widget.profile.name,
|
|
||||||
authorProfileIcon: widget.profile.profilePhotoUrl,
|
|
||||||
authorIsMe: false,
|
|
||||||
isEntitySubscribedByMe: false,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
|||||||
import 'package:eatvio_app/core/utils/toasts.dart';
|
import 'package:eatvio_app/core/utils/toasts.dart';
|
||||||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||||||
import 'package:eatvio_app/features/consultant/become_consultant/repositories/consultant_repository.dart';
|
import 'package:eatvio_app/features/consultant/become_consultant/repositories/consultant_repository.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||||
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_state.dart';
|
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_state.dart';
|
||||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||||
@@ -24,9 +23,11 @@ class ProfileCubit extends Cubit<ProfileState> {
|
|||||||
emit(const ProfileState.loading());
|
emit(const ProfileState.loading());
|
||||||
try {
|
try {
|
||||||
final profile = await profileRepository.getProfileBySlug(slug);
|
final profile = await profileRepository.getProfileBySlug(slug);
|
||||||
|
final myProfile = await profileRepository.getMyProfile();
|
||||||
emit(
|
emit(
|
||||||
ProfileState.loaded(
|
ProfileState.loaded(
|
||||||
profile: profile,
|
profile: profile,
|
||||||
|
isMyProfile: myProfile.slug == profile.slug,
|
||||||
profileDetails: await profileRepository.getProfileDetailsBySlug(slug),
|
profileDetails: await profileRepository.getProfileDetailsBySlug(slug),
|
||||||
blogPosts: await profileRepository.getBlogPostsByAuthorSlug(slug: slug),
|
blogPosts: await profileRepository.getBlogPostsByAuthorSlug(slug: slug),
|
||||||
consultantInfo: profile.roles.contains('consultant') ? await consultantRepository.getConsultantRequestStatus(slug) : null,
|
consultantInfo: profile.roles.contains('consultant') ? await consultantRepository.getConsultantRequestStatus(slug) : null,
|
||||||
@@ -46,6 +47,7 @@ class ProfileCubit extends Cubit<ProfileState> {
|
|||||||
emit(
|
emit(
|
||||||
ProfileState.loaded(
|
ProfileState.loaded(
|
||||||
profile: profile,
|
profile: profile,
|
||||||
|
isMyProfile: true,
|
||||||
profileDetails: await profileRepository.getMyProfileDetails(),
|
profileDetails: await profileRepository.getMyProfileDetails(),
|
||||||
blogPosts: await profileRepository.getBlogPostsByAuthorSlug(slug: profile.slug),
|
blogPosts: await profileRepository.getBlogPostsByAuthorSlug(slug: profile.slug),
|
||||||
weightPoints: await profileRepository.getWeight(period: period),
|
weightPoints: await profileRepository.getWeight(period: period),
|
||||||
@@ -74,6 +76,7 @@ class ProfileCubit extends Cubit<ProfileState> {
|
|||||||
weightPoints: (state as ProfileStateLoaded).weightPoints,
|
weightPoints: (state as ProfileStateLoaded).weightPoints,
|
||||||
circumferencePoints: (state as ProfileStateLoaded).circumferencePoints,
|
circumferencePoints: (state as ProfileStateLoaded).circumferencePoints,
|
||||||
consultantInfo: (state as ProfileStateLoaded).consultantInfo,
|
consultantInfo: (state as ProfileStateLoaded).consultantInfo,
|
||||||
|
isMyProfile: (state as ProfileStateLoaded).isMyProfile,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -100,11 +103,12 @@ class ProfileCubit extends Cubit<ProfileState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> getChatRoomIdBySlug({required Author author}) async {
|
Future<String?> getChatRoomIdBySlug({required String slug}) async {
|
||||||
try {
|
try {
|
||||||
final chatIdOrError = await chatRepository.getChatByUserSlug(author.authorSlug);
|
final chatIdOrError = await chatRepository.getChatByUserSlug(slug);
|
||||||
|
final userProfile = await profileRepository.getProfileBySlug(slug);
|
||||||
if (chatIdOrError == '404') {
|
if (chatIdOrError == '404') {
|
||||||
AppRouter.navigatorKey.currentContext?.pushNamed('emptyChatScreen', extra: author);
|
AppRouter.navigatorKey.currentContext?.pushNamed('emptyChatScreen', extra: userProfile);
|
||||||
} else if (chatIdOrError == 'error') {
|
} else if (chatIdOrError == 'error') {
|
||||||
showErrorToast('Ошибка создания чата');
|
showErrorToast('Ошибка создания чата');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ abstract class ProfileState with _$ProfileState {
|
|||||||
const factory ProfileState.loading() = ProfileStateLoading;
|
const factory ProfileState.loading() = ProfileStateLoading;
|
||||||
|
|
||||||
const factory ProfileState.loaded({
|
const factory ProfileState.loaded({
|
||||||
required ProfileModel profile,
|
required ProfileModel profile,
|
||||||
required ProfileDetailsModel profileDetails,
|
required ProfileDetailsModel profileDetails,
|
||||||
required List<FeedBlogPostModel> blogPosts,
|
required List<FeedBlogPostModel> blogPosts,
|
||||||
|
required bool isMyProfile,
|
||||||
List<WeightModel>? weightPoints,
|
List<WeightModel>? weightPoints,
|
||||||
List<CircumferenceModel>? circumferencePoints,
|
List<CircumferenceModel>? circumferencePoints,
|
||||||
ConsultationRequestModel? consultantInfo,
|
ConsultationRequestModel? consultantInfo,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ 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/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/chat/presentation/pages/photo_view_screen.dart';
|
||||||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.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/feed/presentation/widgets/plan_widget.dart';
|
||||||
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
|
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
|
||||||
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
|
import 'package:eatvio_app/features/profile/models/circumference_model.dart';
|
||||||
@@ -44,9 +43,9 @@ import 'package:share_plus/share_plus.dart';
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
class ProfileScreen extends StatefulWidget {
|
class ProfileScreen extends StatefulWidget {
|
||||||
final Author? author;
|
final String? slug;
|
||||||
|
|
||||||
const ProfileScreen({super.key, this.author});
|
const ProfileScreen({super.key, this.slug});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ProfileScreen> createState() => _ProfileScreenState();
|
State<ProfileScreen> createState() => _ProfileScreenState();
|
||||||
@@ -71,7 +70,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
widget.author == null || widget.author!.authorIsMe ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(widget.author!.authorSlug);
|
widget.slug == null ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(widget.slug!);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -95,15 +94,37 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
isFirstFetch = false;
|
isFirstFetch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return widget.author == null || widget.author!.authorIsMe ? _myProfileScreen(state) : _profileScreen(state);
|
// Проверяем, заблокировал ли пользователь меня
|
||||||
|
if (state.profile.isBlockedByUser) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(),
|
||||||
|
body: Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(32.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(Icons.block, size: 64, color: Colors.grey[400]),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'Пользователь ограничил доступ к своей странице',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500, color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.isMyProfile ? _myProfileScreen(state) : _profileScreen(state);
|
||||||
} else if (state is ProfileStateError) {
|
} else if (state is ProfileStateError) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(),
|
appBar: AppBar(),
|
||||||
body: DataErrorWidget(
|
body: DataErrorWidget(
|
||||||
onReload: () async {
|
onReload: () async {
|
||||||
widget.author == null || widget.author!.authorIsMe
|
widget.slug == null ? await profileCubit.getMyProfile() : await profileCubit.getProfileBySlug(widget.slug!);
|
||||||
? await profileCubit.getMyProfile()
|
|
||||||
: await profileCubit.getProfileBySlug(widget.author!.authorSlug);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -118,7 +139,17 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
Scaffold _profileScreen(ProfileStateLoaded state) {
|
Scaffold _profileScreen(ProfileStateLoaded state) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Colors.grey.shade200,
|
||||||
appBar: AppBar(),
|
appBar: AppBar(
|
||||||
|
leading: BackButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (context.canPop()) {
|
||||||
|
GoRouter.of(context).pop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GoRouter.of(context).go('/feed-screen');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -221,7 +252,18 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
Scaffold _myProfileScreen(ProfileStateLoaded state) {
|
Scaffold _myProfileScreen(ProfileStateLoaded state) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Colors.grey.shade200,
|
||||||
appBar: AppBar(toolbarHeight: widget.author == null ? 0 : null),
|
appBar: AppBar(
|
||||||
|
toolbarHeight: widget.slug == null ? 0 : null,
|
||||||
|
leading: BackButton(
|
||||||
|
onPressed: () {
|
||||||
|
if (context.canPop()) {
|
||||||
|
GoRouter.of(context).pop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GoRouter.of(context).go('/feed-screen');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -415,7 +457,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
GoRouter.of(context).pushNamed('stepperBecomeConsultantScreen', extra: state.profile.slug);
|
GoRouter.of(context).pushNamed('stepperBecomeConsultantScreen', extra: state.profile.slug);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.author == null || widget.author!.authorIsMe ? 'Редактировать' : '',
|
state.isMyProfile ? 'Редактировать' : '',
|
||||||
style: const TextStyle(color: Color(0xFF2F80ED), fontSize: 16, fontWeight: FontWeight.w500),
|
style: const TextStyle(color: Color(0xFF2F80ED), fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -493,7 +535,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
GoRouter.of(context).pushNamed('stepperBecomeConsultantScreen', extra: state.profile.slug);
|
GoRouter.of(context).pushNamed('stepperBecomeConsultantScreen', extra: state.profile.slug);
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.author == null || widget.author!.authorIsMe ? 'Редактировать' : '',
|
state.isMyProfile ? 'Редактировать' : '',
|
||||||
style: const TextStyle(color: Color(0xFF2F80ED), fontSize: 16, fontWeight: FontWeight.w500),
|
style: const TextStyle(color: Color(0xFF2F80ED), fontSize: 16, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -807,7 +849,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
context.pushTransparentRoute(rootNavigator: true, PhotoViewScreen(imageUrls: [sl<AppConfig>().baseUrl + state.profile.profilePhotoUrl], index: 0));
|
context.pushTransparentRoute(rootNavigator: true, PhotoViewScreen(imageUrls: [sl<AppConfig>().baseUrl + state.profile.profilePhotoUrl], index: 0));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (widget.author == null || widget.author!.authorIsMe) ...[
|
if (state.isMyProfile) ...[
|
||||||
_buildDivider(),
|
_buildDivider(),
|
||||||
_buildCompactItem(
|
_buildCompactItem(
|
||||||
icon: 'assets/icons/edit_paint.svg',
|
icon: 'assets/icons/edit_paint.svg',
|
||||||
@@ -965,7 +1007,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (widget.author != null) ...[
|
if (!state.isMyProfile) ...[
|
||||||
_buildDivider(),
|
_buildDivider(),
|
||||||
_buildCompactItem(
|
_buildCompactItem(
|
||||||
icon: 'assets/icons/complain.svg',
|
icon: 'assets/icons/complain.svg',
|
||||||
@@ -974,12 +1016,12 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) => ComplainingBottomSheet(complainedContentType: ComplainedContent.profile, slug: widget.author?.authorSlug),
|
builder: (context) => ComplainingBottomSheet(complainedContentType: ComplainedContent.profile, slug: widget.slug),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
if (widget.author != null && !state.profile.isBlockedByMe) ...[
|
if (!state.isMyProfile && !state.profile.isBlockedByMe) ...[
|
||||||
_buildDivider(),
|
_buildDivider(),
|
||||||
_buildCompactItem(
|
_buildCompactItem(
|
||||||
icon: 'assets/icons/complain.svg',
|
icon: 'assets/icons/complain.svg',
|
||||||
@@ -987,7 +1029,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
isFirstFetch = true;
|
isFirstFetch = true;
|
||||||
sl<BlockedUsersCubit>().blockUser(state.profile.slug);
|
sl<BlockedUsersCubit>().blockUser(state.profile.slug);
|
||||||
widget.author == null || widget.author!.authorIsMe ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(widget.author!.authorSlug);
|
state.isMyProfile ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(state.profile.slug);
|
||||||
if (state.profile.roles.contains('consultant')) {
|
if (state.profile.roles.contains('consultant')) {
|
||||||
plansCubit.getPlans(state.profile.slug);
|
plansCubit.getPlans(state.profile.slug);
|
||||||
}
|
}
|
||||||
@@ -995,7 +1037,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
if (widget.author != null && state.profile.isBlockedByMe) ...[
|
if (!state.isMyProfile && state.profile.isBlockedByMe) ...[
|
||||||
_buildDivider(),
|
_buildDivider(),
|
||||||
_buildCompactItem(
|
_buildCompactItem(
|
||||||
icon: 'assets/icons/complain.svg',
|
icon: 'assets/icons/complain.svg',
|
||||||
@@ -1003,7 +1045,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
isFirstFetch = true;
|
isFirstFetch = true;
|
||||||
sl<BlockedUsersCubit>().unblockUser(state.profile.slug);
|
sl<BlockedUsersCubit>().unblockUser(state.profile.slug);
|
||||||
widget.author == null || widget.author!.authorIsMe ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(widget.author!.authorSlug);
|
state.isMyProfile ? profileCubit.getMyProfile() : profileCubit.getProfileBySlug(state.profile.slug);
|
||||||
if (state.profile.roles.contains('consultant')) {
|
if (state.profile.roles.contains('consultant')) {
|
||||||
plansCubit.getPlans(state.profile.slug);
|
plansCubit.getPlans(state.profile.slug);
|
||||||
}
|
}
|
||||||
@@ -1066,7 +1108,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async => await profileCubit.getChatRoomIdBySlug(author: widget.author!),
|
onTap: () async => await profileCubit.getChatRoomIdBySlug(slug: widget.slug!),
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart';
|
import 'package:eatvio_app/features/profile/presentation/bloc/profile_cubit/profile_cubit.dart';
|
||||||
import 'package:eatvio_app/features/profile/presentation/bloc/sub_cubit/sub_cubit.dart';
|
import 'package:eatvio_app/features/profile/presentation/bloc/sub_cubit/sub_cubit.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -15,13 +14,7 @@ class SubActionButtonWidget extends StatefulWidget {
|
|||||||
final String name;
|
final String name;
|
||||||
final String porfileIcon;
|
final String porfileIcon;
|
||||||
|
|
||||||
const SubActionButtonWidget({
|
const SubActionButtonWidget({super.key, required this.subActionType, required this.slug, required this.name, required this.porfileIcon});
|
||||||
super.key,
|
|
||||||
required this.subActionType,
|
|
||||||
required this.slug,
|
|
||||||
required this.name,
|
|
||||||
required this.porfileIcon,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SubActionButtonWidget> createState() => _SubActionButtonWidgetState();
|
State<SubActionButtonWidget> createState() => _SubActionButtonWidgetState();
|
||||||
@@ -49,51 +42,25 @@ class _SubActionButtonWidgetState extends State<SubActionButtonWidget> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8), color: appTheme.blueA400),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
color: appTheme.blueA400,
|
|
||||||
),
|
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Подписаться',
|
'Подписаться',
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500, color: Colors.white),
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
GoRouter.of(context).pushNamed(
|
GoRouter.of(context).pushNamed('chatScreen', extra: {'uuid': await sl<ProfileCubit>().getChatRoomIdBySlug(slug: widget.slug)});
|
||||||
'chatScreen',
|
|
||||||
extra: {
|
|
||||||
'uuid': await sl<ProfileCubit>().getChatRoomIdBySlug(
|
|
||||||
author: Author(
|
|
||||||
authorSlug: widget.slug,
|
|
||||||
authorName: widget.name,
|
|
||||||
authorProfileIcon: widget.porfileIcon,
|
|
||||||
authorIsMe: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8), color: const Color(0xFFF1F2F6)),
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
color: const Color(0xFFF1F2F6),
|
|
||||||
),
|
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Сообщение',
|
'Сообщение',
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500, color: Color(0xFF6D6F71)),
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: FontWeight.w500,
|
|
||||||
color: Color(0xFF6D6F71),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:eatvio_app/core/app_config.dart';
|
import 'package:eatvio_app/core/app_config.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
|
||||||
import 'package:eatvio_app/features/profile/models/sub_model.dart';
|
import 'package:eatvio_app/features/profile/models/sub_model.dart';
|
||||||
import 'package:eatvio_app/features/profile/presentation/widgets/sub_action_button_widget.dart';
|
import 'package:eatvio_app/features/profile/presentation/widgets/sub_action_button_widget.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -24,13 +23,7 @@ class _SubWidgetState extends State<SubWidget> {
|
|||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () => GoRouter.of(context).pushNamed(
|
onTap: () => GoRouter.of(context).pushNamed(
|
||||||
'profileScreen',
|
'profileScreen',
|
||||||
extra: Author(
|
extra: widget.subModel.slug,
|
||||||
authorSlug: widget.subModel.slug,
|
|
||||||
authorName: widget.subModel.name,
|
|
||||||
authorProfileIcon: widget.subModel.profilePhotoUrl,
|
|
||||||
authorIsMe: false,
|
|
||||||
isEntitySubscribedByMe: false,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import 'package:eatvio_app/app_keys.dart';
|
import 'package:eatvio_app/app_keys.dart';
|
||||||
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
|
import 'package:eatvio_app/core/prefs.dart';
|
||||||
|
import 'package:eatvio_app/core/prefs_keys.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:eatvio_app/core/token_storage.dart';
|
import 'package:eatvio_app/core/token_storage.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
|
|
||||||
class WelcomeScreen extends StatefulWidget {
|
class WelcomeScreen extends StatefulWidget {
|
||||||
@@ -82,8 +84,8 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
|
|||||||
InkWell(
|
InkWell(
|
||||||
key: AppKeys.welcomeScreenButton,
|
key: AppKeys.welcomeScreenButton,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final sharedPreferences = await SharedPreferences.getInstance();
|
final sharedPreferences = sl<Prefs>();
|
||||||
await sharedPreferences.setBool('welcomeScreenWasShowed', true);
|
await sharedPreferences.setBool(PrefsKeys.welcomeScreenWasShowed, true);
|
||||||
if (await TokenStorage.haveTokenInStorage()) {
|
if (await TokenStorage.haveTokenInStorage()) {
|
||||||
goRouter.go('/feed-screen');
|
goRouter.go('/feed-screen');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user