forked from eatvio/eatvio_app
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc400ef5b7 | ||
|
|
992cb38cdd | ||
| ff946a5938 | |||
|
|
a72c40d8ee | ||
|
|
6ed7faed15 | ||
|
|
16fccaea8e | ||
|
|
a723673d23 | ||
|
|
89f697f7a6 | ||
| d883c9e19a | |||
|
|
2e3172bc45 | ||
|
|
46841fb502 | ||
|
|
8e72350152 | ||
|
|
8c2cd5eedd | ||
|
|
996f2ecd70 | ||
|
|
19787f459e | ||
|
|
7e64b24a8c | ||
|
|
a07d085ba7 | ||
|
|
5616bedd25 | ||
|
|
0a3d9e577d | ||
|
|
55e3abec99 |
@@ -406,7 +406,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.3;
|
MARKETING_VERSION = 1.3.3;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
|
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
|
||||||
@@ -557,7 +557,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.3;
|
MARKETING_VERSION = 1.3.3;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
|
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
|
||||||
@@ -596,7 +596,7 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/Flutter",
|
"$(PROJECT_DIR)/Flutter",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.2.3;
|
MARKETING_VERSION = 1.3.3;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
PRODUCT_BUNDLE_IDENTIFIER = com.eatvioapp.app;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
|
PROVISIONING_PROFILE_SPECIFIER = "match AppStore com.eatvioapp.app 1747050044";
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>81</string>
|
<string>82</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import 'package:eatvio_app/features/my_finance/presentation/cubit/user_cards_cub
|
|||||||
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_cubit.dart';
|
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_cubit.dart';
|
||||||
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_cubit.dart';
|
import 'package:eatvio_app/features/notifications/presentation/notifications_cubit/notifications_cubit.dart';
|
||||||
import 'package:eatvio_app/features/order_info/cubit/order_info_cubit.dart';
|
import 'package:eatvio_app/features/order_info/cubit/order_info_cubit.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/cubit/personal_diet_suggestion_cubit.dart';
|
||||||
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_cubit.dart';
|
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_cubit.dart';
|
||||||
import 'package:eatvio_app/features/profile/presentation/bloc/plans_cubit/plans_cubit.dart' as profile_plans;
|
import 'package:eatvio_app/features/profile/presentation/bloc/plans_cubit/plans_cubit.dart' as profile_plans;
|
||||||
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';
|
||||||
@@ -145,5 +146,6 @@ class CubitRegistrations {
|
|||||||
sl.registerFactory<UserDetailsCubit>(() => UserDetailsCubit(profileRepository: sl()));
|
sl.registerFactory<UserDetailsCubit>(() => UserDetailsCubit(profileRepository: sl()));
|
||||||
sl.registerFactory<MenuCubit>(() => MenuCubit(sl()));
|
sl.registerFactory<MenuCubit>(() => MenuCubit(sl()));
|
||||||
sl.registerFactory<MarketingCubit>(() => MarketingCubit(sl()));
|
sl.registerFactory<MarketingCubit>(() => MarketingCubit(sl()));
|
||||||
|
sl.registerFactory<PersonalDietSuggestionCubit>(() => PersonalDietSuggestionCubit(dietRepository: sl(), personalDietSuggestionService: sl()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import 'package:eatvio_app/features/my_diets/repositories/my_diets_repository.da
|
|||||||
import 'package:eatvio_app/features/my_finance/repositories/cards_repository.dart';
|
import 'package:eatvio_app/features/my_finance/repositories/cards_repository.dart';
|
||||||
import 'package:eatvio_app/features/my_plans/repositories/my_diets_repository.dart';
|
import 'package:eatvio_app/features/my_plans/repositories/my_diets_repository.dart';
|
||||||
import 'package:eatvio_app/features/notifications/repository/notifications_repository.dart';
|
import 'package:eatvio_app/features/notifications/repository/notifications_repository.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/repository/personal_diet_suggestion_repository.dart';
|
||||||
import 'package:eatvio_app/features/plans/repositories/plan_repository.dart';
|
import 'package:eatvio_app/features/plans/repositories/plan_repository.dart';
|
||||||
import 'package:eatvio_app/features/plans/repositories/plans_repository.dart';
|
import 'package:eatvio_app/features/plans/repositories/plans_repository.dart';
|
||||||
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
import 'package:eatvio_app/features/profile/repositories/profile_repository.dart';
|
||||||
@@ -68,6 +69,7 @@ class RepositoryRegistrations {
|
|||||||
sl.registerLazySingleton<BlockedUsersRepository>(() => BlockedUsersRepository(blockedUserService: sl()));
|
sl.registerLazySingleton<BlockedUsersRepository>(() => BlockedUsersRepository(blockedUserService: sl()));
|
||||||
sl.registerLazySingleton<CommentsRepository>(() => CommentsRepository(service: sl()));
|
sl.registerLazySingleton<CommentsRepository>(() => CommentsRepository(service: sl()));
|
||||||
sl.registerLazySingleton<NotificationSettingsRepository>(() => NotificationSettingsRepository(sl()));
|
sl.registerLazySingleton<NotificationSettingsRepository>(() => NotificationSettingsRepository(sl()));
|
||||||
|
sl.registerLazySingleton<PersonalDietSuggestionRepository>(() => PersonalDietSuggestionRepository(personalDietSuggestionService: sl()));
|
||||||
|
|
||||||
// Content repositories
|
// Content repositories
|
||||||
sl.registerLazySingleton<BlogPostRepository>(() => BlogPostRepository(blogPostService: sl()));
|
sl.registerLazySingleton<BlogPostRepository>(() => BlogPostRepository(blogPostService: sl()));
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import 'package:eatvio_app/features/my_diets/services/my_diets_service.dart';
|
|||||||
import 'package:eatvio_app/features/my_finance/services/cards_service.dart';
|
import 'package:eatvio_app/features/my_finance/services/cards_service.dart';
|
||||||
import 'package:eatvio_app/features/my_plans/services/my_plans_service.dart';
|
import 'package:eatvio_app/features/my_plans/services/my_plans_service.dart';
|
||||||
import 'package:eatvio_app/features/notifications/service/notifications_service.dart';
|
import 'package:eatvio_app/features/notifications/service/notifications_service.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/services/personal_diet_suggestion_service.dart';
|
||||||
import 'package:eatvio_app/features/plans/services/plan_service.dart';
|
import 'package:eatvio_app/features/plans/services/plan_service.dart';
|
||||||
import 'package:eatvio_app/features/plans/services/plans_service.dart';
|
import 'package:eatvio_app/features/plans/services/plans_service.dart';
|
||||||
import 'package:eatvio_app/features/profile/services/profile_service.dart';
|
import 'package:eatvio_app/features/profile/services/profile_service.dart';
|
||||||
@@ -76,6 +77,7 @@ class ServiceRegistrations {
|
|||||||
sl.registerLazySingleton<ConsultantRatingService>(() => ConsultantRatingService(sl()));
|
sl.registerLazySingleton<ConsultantRatingService>(() => ConsultantRatingService(sl()));
|
||||||
sl.registerLazySingleton<NotificationSettingsService>(() => NotificationSettingsService(sl()));
|
sl.registerLazySingleton<NotificationSettingsService>(() => NotificationSettingsService(sl()));
|
||||||
sl.registerLazySingleton<ViewsService>(() => ViewsService(sl()));
|
sl.registerLazySingleton<ViewsService>(() => ViewsService(sl()));
|
||||||
|
sl.registerLazySingleton<PersonalDietSuggestionService>(() => PersonalDietSuggestionService(sl()));
|
||||||
|
|
||||||
// Content services
|
// Content services
|
||||||
sl.registerLazySingleton<CreateRecipeService>(() => CreateRecipeService(sl()));
|
sl.registerLazySingleton<CreateRecipeService>(() => CreateRecipeService(sl()));
|
||||||
|
|||||||
@@ -29,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/personal_diet_suggestion/presentation/personal_diet_suggestion_screen.dart';
|
||||||
import 'package:eatvio_app/features/profile/models/profile_model.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';
|
||||||
@@ -239,6 +240,11 @@ class OtherRoutes {
|
|||||||
return UserDiaryScreen(diaryId: diaryId, currentPlanDay: currentPlanDay);
|
return UserDiaryScreen(diaryId: diaryId, currentPlanDay: currentPlanDay);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: PersonalDietSuggestionScreen.path,
|
||||||
|
name: PersonalDietSuggestionScreen.name,
|
||||||
|
builder: (context, state) => PersonalDietSuggestionScreen(dietId: state.extra as int,),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ class PrimaryColors {
|
|||||||
// Blue
|
// Blue
|
||||||
Color get blue400 => const Color(0XFF43A6F2);
|
Color get blue400 => const Color(0XFF43A6F2);
|
||||||
|
|
||||||
Color get blueA400 => const Color(0XFF2F80ED);
|
Color get blueA400 => const Color(0XFF2F80ED);
|
||||||
// BlueGray
|
// BlueGray
|
||||||
Color get blueGray400 => const Color(0XFF7B8794);
|
Color get blueGray400 => const Color(0XFF7B8794);
|
||||||
|
|
||||||
@@ -150,6 +150,8 @@ class PrimaryColors {
|
|||||||
|
|
||||||
Color get green => const Color(0XFF0BB450);
|
Color get green => const Color(0XFF0BB450);
|
||||||
|
|
||||||
|
Color get transparentGreen => const Color.fromARGB(12, 1, 154, 63);
|
||||||
|
|
||||||
// LightGreen
|
// LightGreen
|
||||||
Color get lightGreen300 => const Color(0XFFB2DF8A);
|
Color get lightGreen300 => const Color(0XFFB2DF8A);
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import 'package:eatvio_app/generated/l10n.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class OptionWidget extends StatelessWidget {
|
class OptionWidget extends StatelessWidget {
|
||||||
const OptionWidget({super.key, required this.option, this.disableDuration = false});
|
const OptionWidget({super.key, required this.option, this.disableDuration = false, required this.duration});
|
||||||
final PacketOptions? option;
|
final PacketOptions? option;
|
||||||
final bool disableDuration;
|
final bool disableDuration;
|
||||||
|
final int duration;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (option == null) {
|
if (option == null) {
|
||||||
@@ -34,8 +35,12 @@ class OptionWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (!disableDuration) ...[
|
if (!disableDuration) ...[
|
||||||
const _OptionDurationWidget(duration: 7),
|
_OptionDurationWidget(duration: duration),
|
||||||
const SizedBox(height: 16),
|
SizedBox(height: option?.hasPersonalDiet ?? false ? 8 : 12),
|
||||||
|
],
|
||||||
|
if ((option?.hasPersonalDiet ?? false) && !disableDuration) ...[
|
||||||
|
const _OptionHasPersonalDietWidget(),
|
||||||
|
const SizedBox(height: 12),
|
||||||
],
|
],
|
||||||
const CustomDivider(),
|
const CustomDivider(),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
@@ -52,7 +57,6 @@ class OptionWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _OptionDurationWidget extends StatelessWidget {
|
class _OptionDurationWidget extends StatelessWidget {
|
||||||
const _OptionDurationWidget({required this.duration});
|
const _OptionDurationWidget({required this.duration});
|
||||||
final int duration;
|
final int duration;
|
||||||
@@ -92,3 +96,43 @@ class _OptionDurationWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _OptionHasPersonalDietWidget extends StatelessWidget {
|
||||||
|
const _OptionHasPersonalDietWidget();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4), color: appTheme.transparentGreen),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
|
child: Container(
|
||||||
|
width: 4,
|
||||||
|
height: 20,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: appTheme.green,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topRight: Radius.circular(100),
|
||||||
|
bottomRight: Radius.circular(100),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
s.personalDietCreating,
|
||||||
|
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -114,13 +114,21 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
ChosenPlanStateEnum.statePendingPayment,
|
ChosenPlanStateEnum.statePendingPayment,
|
||||||
ChosenPlanStateEnum.stateInCoordination,
|
ChosenPlanStateEnum.stateInCoordination,
|
||||||
].contains(chosenPlan?.chosenPlanState);
|
].contains(chosenPlan?.chosenPlanState);
|
||||||
|
PacketOptions? chosenOption;
|
||||||
|
if (chosenPlan?.optionType == 'options1') {
|
||||||
|
chosenOption = chosenPlan?.plan.packet1Options;
|
||||||
|
} else if (chosenPlan?.optionType == 'options2') {
|
||||||
|
chosenOption = chosenPlan?.plan.packet2Options;
|
||||||
|
} else if (chosenPlan?.optionType == 'options3') {
|
||||||
|
chosenOption = chosenPlan?.plan.packet3Options;
|
||||||
|
}
|
||||||
|
|
||||||
final showAboutOrderButton =
|
final showAboutOrderButton =
|
||||||
state.chatRoom.chosenPlan != null && state.chatRoom.chosenPlan!.chosenPlanState != ChosenPlanStateEnum.stateCanceledByTheInitiator;
|
state.chatRoom.chosenPlan != null && state.chatRoom.chosenPlan!.chosenPlanState != ChosenPlanStateEnum.stateCanceledByTheInitiator;
|
||||||
BannerType? bannerType;
|
BannerType? bannerType;
|
||||||
if (chosenPlan == null || chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateCanceledByTheInitiator) {
|
if (chosenPlan == null || chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateCanceledByTheInitiator) {
|
||||||
bannerType = null;
|
bannerType = null;
|
||||||
} else if (amIConsultant && !state.hasCard) {
|
} else if (amIConsultant && !state.hasCard && chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateInCoordination) {
|
||||||
bannerType = BannerType.card;
|
bannerType = BannerType.card;
|
||||||
} else if (amIConsultant && chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateInCoordination) {
|
} else if (amIConsultant && chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateInCoordination) {
|
||||||
bannerType = BannerType.date;
|
bannerType = BannerType.date;
|
||||||
@@ -131,16 +139,10 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
bannerType = BannerType.collectCharge;
|
bannerType = BannerType.collectCharge;
|
||||||
} else if (chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateLastDayFinished && !amIConsultant) {
|
} else if (chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateLastDayFinished && !amIConsultant) {
|
||||||
bannerType = BannerType.finishPlan;
|
bannerType = BannerType.finishPlan;
|
||||||
|
} else if (chosenOption?.hasPersonalDiet == true && amIConsultant && chosenPlan.chosenPlanState != ChosenPlanStateEnum.stateDone) {
|
||||||
|
bannerType = BannerType.setPersonalDiet;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketOptions? chosenOption;
|
|
||||||
if (chosenPlan?.optionType == 'options1') {
|
|
||||||
chosenOption = chosenPlan?.plan.packet1Options;
|
|
||||||
} else if (chosenPlan?.optionType == 'options2') {
|
|
||||||
chosenOption = chosenPlan?.plan.packet2Options;
|
|
||||||
} else if (chosenPlan?.optionType == 'options3') {
|
|
||||||
chosenOption = chosenPlan?.plan.packet3Options;
|
|
||||||
}
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
resizeToAvoidBottomInset: true,
|
resizeToAvoidBottomInset: true,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -317,6 +319,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||||||
chosenPlanId: chosenPlan?.id,
|
chosenPlanId: chosenPlan?.id,
|
||||||
planName: chosenPlan?.plan.name,
|
planName: chosenPlan?.plan.name,
|
||||||
planPrice: chosenOption?.price.toDouble(),
|
planPrice: chosenOption?.price.toDouble(),
|
||||||
|
hasPersonalDiet: chosenOption?.hasPersonalDiet ?? false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -9,17 +9,28 @@ 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/core/widgets/custom_outlined_button.dart';
|
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_portal/flutter_portal.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
class ChosePlanDateWidget extends StatefulWidget {
|
class ChosePlanDateWidget extends StatefulWidget {
|
||||||
const ChosePlanDateWidget({super.key, required this.chatCubit});
|
const ChosePlanDateWidget({super.key, required this.chatCubit, required this.hasPersonalDiet});
|
||||||
final ChatRoomCubit chatCubit;
|
final ChatRoomCubit chatCubit;
|
||||||
|
final bool hasPersonalDiet;
|
||||||
@override
|
@override
|
||||||
State<ChosePlanDateWidget> createState() => _ChosePlanDateWidget();
|
State<ChosePlanDateWidget> createState() => _ChosePlanDateWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ChosePlanDateWidget extends State<ChosePlanDateWidget> {
|
class _ChosePlanDateWidget extends State<ChosePlanDateWidget> {
|
||||||
final startDate = [DateTime.now()];
|
late final List<DateTime> startDate;
|
||||||
|
bool visible = false;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.hasPersonalDiet) {
|
||||||
|
startDate = [DateTime.now().add(const Duration(days: 2))];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
@@ -27,64 +38,129 @@ class _ChosePlanDateWidget extends State<ChosePlanDateWidget> {
|
|||||||
if (widget.chatCubit.state is ChatRoomStateLoaded) {
|
if (widget.chatCubit.state is ChatRoomStateLoaded) {
|
||||||
planName = (widget.chatCubit.state as ChatRoomStateLoaded).chatRoom.chosenPlan?.plan.name;
|
planName = (widget.chatCubit.state as ChatRoomStateLoaded).chatRoom.chosenPlan?.plan.name;
|
||||||
}
|
}
|
||||||
return Column(
|
return GestureDetector(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Column(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
const SizedBox(height: 4),
|
children: [
|
||||||
const BottomSheetHandlerBar(),
|
const SizedBox(height: 4),
|
||||||
const SizedBox(height: 12),
|
const BottomSheetHandlerBar(),
|
||||||
Text(
|
const SizedBox(height: 12),
|
||||||
planName ?? '',
|
Row(
|
||||||
style: TextStyles.headingXLSemibold.copyWith(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
color: appTheme.black,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
planName ?? '',
|
||||||
|
style: TextStyles.headingXLSemibold.copyWith(
|
||||||
|
color: appTheme.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (widget.hasPersonalDiet) ...[
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
|
),
|
||||||
|
PortalTarget(
|
||||||
|
closeDuration: const Duration(milliseconds: 20),
|
||||||
|
anchor: const Aligned(
|
||||||
|
shiftToWithinBound: AxisFlag(x: true, y: true),
|
||||||
|
follower: Alignment.topRight,
|
||||||
|
target: Alignment.bottomLeft,
|
||||||
|
),
|
||||||
|
portalFollower: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: visible ? appTheme.whiteA700 : Colors.transparent,
|
||||||
|
boxShadow: visible
|
||||||
|
? [
|
||||||
|
BoxShadow(
|
||||||
|
color: appTheme.black900.withValues(alpha: 0.15),
|
||||||
|
blurRadius: 4,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
child: AnimatedDefaultTextStyle(
|
||||||
|
style: TextStyles.textMMediumAuto.copyWith(
|
||||||
|
color: visible ? appTheme.black : Colors.transparent,
|
||||||
|
),
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: Text(
|
||||||
|
s.chosenPlanStartDateDescr,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
visible = !visible;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
'assets/icons/question_mark.svg',
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
colorFilter: ColorFilter.mode(
|
||||||
|
appTheme.blueA400,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 12),
|
||||||
const SizedBox(height: 12),
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.symmetric(horizontal: 25.0),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 25.0),
|
child: Text(
|
||||||
child: Text(
|
s.chose_plan_start_date_2,
|
||||||
s.chose_plan_start_date_2,
|
textAlign: TextAlign.center,
|
||||||
textAlign: TextAlign.center,
|
style: TextStyles.textMMedium.copyWith(
|
||||||
style: TextStyles.textMMedium.copyWith(
|
color: appTheme.black,
|
||||||
color: appTheme.black,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 12),
|
||||||
const SizedBox(height: 12),
|
const Padding(
|
||||||
const Padding(
|
padding: EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16.0),
|
child: CustomDivider(),
|
||||||
child: CustomDivider(),
|
),
|
||||||
),
|
CalendarWidget(
|
||||||
CalendarWidget(
|
startDate: startDate,
|
||||||
startDate: startDate,
|
),
|
||||||
),
|
Padding(
|
||||||
Padding(
|
padding: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 28),
|
||||||
padding: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 28),
|
child: CustomOutlinedButton(
|
||||||
child: CustomOutlinedButton(
|
onPressed: () async {
|
||||||
onPressed: () async {
|
final result = await widget.chatCubit.choseStartPlanDate(startDate[0]);
|
||||||
final result = await widget.chatCubit.choseStartPlanDate(startDate[0]);
|
if (result) {
|
||||||
if (result) {
|
showSuccessToast('Дата установлена');
|
||||||
showSuccessToast('Дата установлена');
|
if (!context.mounted) return;
|
||||||
if (!context.mounted) return;
|
Navigator.pop(context);
|
||||||
Navigator.pop(context);
|
} else {
|
||||||
} else {
|
showErrorToast('Не удалось установить дату');
|
||||||
showErrorToast('Не удалось установить дату');
|
if (!context.mounted) return;
|
||||||
if (!context.mounted) return;
|
Navigator.pop(context);
|
||||||
Navigator.pop(context);
|
}
|
||||||
}
|
},
|
||||||
},
|
height: 60,
|
||||||
height: 60,
|
text: s.confirm,
|
||||||
text: s.confirm,
|
buttonTextStyle: TextStyles.textLSemibold.copyWith(
|
||||||
buttonTextStyle: TextStyles.textLSemibold.copyWith(
|
color: appTheme.whiteA700,
|
||||||
color: appTheme.whiteA700,
|
),
|
||||||
),
|
buttonStyle: ButtonStyle(
|
||||||
buttonStyle: ButtonStyle(
|
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||||
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
side: const WidgetStatePropertyAll(BorderSide.none),
|
||||||
side: const WidgetStatePropertyAll(BorderSide.none),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import 'package:eatvio_app/features/chat/presentation/pages/payment_screen.dart'
|
|||||||
import 'package:eatvio_app/features/chat/presentation/widgets/chose_plan_date_widget.dart';
|
import 'package:eatvio_app/features/chat/presentation/widgets/chose_plan_date_widget.dart';
|
||||||
import 'package:eatvio_app/features/chat/presentation/widgets/complete_plan_bottom_sheet.dart';
|
import 'package:eatvio_app/features/chat/presentation/widgets/complete_plan_bottom_sheet.dart';
|
||||||
import 'package:eatvio_app/features/chat/presentation/widgets/plan_complain_bottom_sheet.dart';
|
import 'package:eatvio_app/features/chat/presentation/widgets/plan_complain_bottom_sheet.dart';
|
||||||
|
import 'package:eatvio_app/features/my_diets/presentation/my_diets_screen.dart';
|
||||||
import 'package:eatvio_app/features/my_finance/presentation/pages/card_settings.dart';
|
import 'package:eatvio_app/features/my_finance/presentation/pages/card_settings.dart';
|
||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -17,12 +18,12 @@ import 'package:flutter_svg/svg.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
class NotificationBanner extends StatefulWidget {
|
class NotificationBanner extends StatefulWidget {
|
||||||
const NotificationBanner({super.key, required this.bannerType, this.planPrice, this.planName, this.chosenPlanId});
|
const NotificationBanner({super.key, required this.bannerType, this.planPrice, this.planName, this.chosenPlanId, this.hasPersonalDiet = false});
|
||||||
final BannerType bannerType;
|
final BannerType bannerType;
|
||||||
final double? planPrice;
|
final double? planPrice;
|
||||||
final String? planName;
|
final String? planName;
|
||||||
final int? chosenPlanId;
|
final int? chosenPlanId;
|
||||||
|
final bool hasPersonalDiet;
|
||||||
@override
|
@override
|
||||||
State<NotificationBanner> createState() => _NotificationBannerState();
|
State<NotificationBanner> createState() => _NotificationBannerState();
|
||||||
}
|
}
|
||||||
@@ -68,7 +69,8 @@ class _NotificationBannerState extends State<NotificationBanner> {
|
|||||||
BannerType.date => [
|
BannerType.date => [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.6,
|
width: size.width * 0.6,
|
||||||
child: Text(s.choose_plan_start_date, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
child: Text(widget.hasPersonalDiet == true ? s.choose_plan_start_date_with_personal_diet : s.choose_plan_start_date,
|
||||||
|
style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
@@ -78,6 +80,7 @@ class _NotificationBannerState extends State<NotificationBanner> {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (context) => ChosePlanDateWidget(
|
builder: (context) => ChosePlanDateWidget(
|
||||||
chatCubit: cubit,
|
chatCubit: cubit,
|
||||||
|
hasPersonalDiet: widget.hasPersonalDiet,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -155,6 +158,20 @@ class _NotificationBannerState extends State<NotificationBanner> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
],
|
],
|
||||||
|
BannerType.setPersonalDiet => [
|
||||||
|
SizedBox(
|
||||||
|
width: size.width * 0.6,
|
||||||
|
child: Text(s.createPersonalDiet, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(MyDietsScreen.name);
|
||||||
|
},
|
||||||
|
child: Text(s.goToMyDiets, style: TextStyles.textLSemibold.copyWith(color: appTheme.blueA400)),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -242,4 +259,4 @@ class _StarIcon extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum BannerType { date, card, payment, collectCharge, finishPlan }
|
enum BannerType { date, card, payment, collectCharge, finishPlan, setPersonalDiet }
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ abstract class ConsultationModel with _$ConsultationModel {
|
|||||||
@JsonKey(name: 'end_date', fromJson: parseDate) required DateTime endDate,
|
@JsonKey(name: 'end_date', fromJson: parseDate) required DateTime endDate,
|
||||||
@JsonKey(name: 'consultant_id') required int consultantId,
|
@JsonKey(name: 'consultant_id') required int consultantId,
|
||||||
required List<DiaryModel> diaries,
|
required List<DiaryModel> diaries,
|
||||||
|
@JsonKey(name: 'personal_diet_id') required int? personalDietId,
|
||||||
}) = _ConsultationModel;
|
}) = _ConsultationModel;
|
||||||
|
|
||||||
factory ConsultationModel.fromJson(Map<String, dynamic> json) => _$ConsultationModelFromJson(json);
|
factory ConsultationModel.fromJson(Map<String, dynamic> json) => _$ConsultationModelFromJson(json);
|
||||||
|
|||||||
@@ -67,6 +67,13 @@ class CreatePlanCubit extends Cubit<CreatePlanState> {
|
|||||||
validateSelectedOptionItems();
|
validateSelectedOptionItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void togglePersonalizedDietOptionState() {
|
||||||
|
final options = [...state.planData.options];
|
||||||
|
options[state.selectedOptionIndex ?? 0] =
|
||||||
|
options[state.selectedOptionIndex ?? 0].copyWith(hasPersonalDiet: !options[state.selectedOptionIndex ?? 0].hasPersonalDiet);
|
||||||
|
emit(state.copyWith(planData: state.planData.copyWith(options: options)));
|
||||||
|
}
|
||||||
|
|
||||||
void setDuration(int index) {
|
void setDuration(int index) {
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
@@ -418,18 +425,21 @@ class CreatePlanCubit extends Cubit<CreatePlanState> {
|
|||||||
'price': int.parse((state.planData.options[0].price as double).toStringAsFixed(0)),
|
'price': int.parse((state.planData.options[0].price as double).toStringAsFixed(0)),
|
||||||
'description_md': state.planData.options[0].description,
|
'description_md': state.planData.options[0].description,
|
||||||
'items': Map.fromIterable(state.planData.options[0].items),
|
'items': Map.fromIterable(state.planData.options[0].items),
|
||||||
|
'has_personal_diet': state.planData.options[0].hasPersonalDiet ? '1' : '0',
|
||||||
},
|
},
|
||||||
'packet2_options': {
|
'packet2_options': {
|
||||||
'short': state.planData.options[1].short,
|
'short': state.planData.options[1].short,
|
||||||
'price': int.parse((state.planData.options[1].price as double).toStringAsFixed(0)),
|
'price': int.parse((state.planData.options[1].price as double).toStringAsFixed(0)),
|
||||||
'description_md': state.planData.options[1].description,
|
'description_md': state.planData.options[1].description,
|
||||||
'items': Map.fromIterable(state.planData.options[1].items),
|
'items': Map.fromIterable(state.planData.options[1].items),
|
||||||
|
'has_personal_diet': state.planData.options[1].hasPersonalDiet ? '1' : '0',
|
||||||
},
|
},
|
||||||
'packet3_options': {
|
'packet3_options': {
|
||||||
'short': state.planData.options[2].short,
|
'short': state.planData.options[2].short,
|
||||||
'price': int.parse((state.planData.options[2].price as double).toStringAsFixed(0)),
|
'price': int.parse((state.planData.options[2].price as double).toStringAsFixed(0)),
|
||||||
'description_md': state.planData.options[2].description,
|
'description_md': state.planData.options[2].description,
|
||||||
'items': Map.fromIterable(state.planData.options[2].items),
|
'items': Map.fromIterable(state.planData.options[2].items),
|
||||||
|
'has_personal_diet': state.planData.options[2].hasPersonalDiet ? '1' : '0',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -440,6 +450,7 @@ class CreatePlanCubit extends Cubit<CreatePlanState> {
|
|||||||
'price': int.parse((state.planData.options[0].price as double).toStringAsFixed(0)),
|
'price': int.parse((state.planData.options[0].price as double).toStringAsFixed(0)),
|
||||||
'description_md': state.planData.options[0].description,
|
'description_md': state.planData.options[0].description,
|
||||||
'items': Map.fromIterable(state.planData.options[0].items),
|
'items': Map.fromIterable(state.planData.options[0].items),
|
||||||
|
'has_personal_diet': state.planData.options[0].hasPersonalDiet ? '1' : '0',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class _OptionWidgetState extends State<OptionWidget> {
|
|||||||
2 => thirdOptionCustomerPriceController,
|
2 => thirdOptionCustomerPriceController,
|
||||||
_ => secondOptionCustomerPriceController,
|
_ => secondOptionCustomerPriceController,
|
||||||
};
|
};
|
||||||
|
|
||||||
final price = double.tryParse(customerPriceController.text.replaceAll('₽', ''));
|
final price = double.tryParse(customerPriceController.text.replaceAll('₽', ''));
|
||||||
creatorPriceController.text = '${((price ?? 0) * 0.8).toStringAsFixed(2)}₽';
|
creatorPriceController.text = '${((price ?? 0) * 0.8).toStringAsFixed(2)}₽';
|
||||||
firstOptionTitleController.text = state.planData.options[selectedOptionIndex].short;
|
firstOptionTitleController.text = state.planData.options[selectedOptionIndex].short;
|
||||||
@@ -255,33 +255,31 @@ class _OptionWidgetState extends State<OptionWidget> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const CustomDivider(),
|
const CustomDivider(),
|
||||||
// const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// Row(
|
Row(
|
||||||
// children: [
|
children: [
|
||||||
// Checkbox(
|
Checkbox(
|
||||||
// value: isChecked,
|
value: state.planData.options[selectedOptionIndex].hasPersonalDiet,
|
||||||
// activeColor: appTheme.gray,
|
activeColor: appTheme.gray,
|
||||||
// checkColor: appTheme.gray,
|
checkColor: appTheme.gray,
|
||||||
// fillColor: const WidgetStatePropertyAll(Colors.transparent),
|
fillColor: const WidgetStatePropertyAll(Colors.transparent),
|
||||||
// side: WidgetStateBorderSide.resolveWith(
|
side: WidgetStateBorderSide.resolveWith(
|
||||||
// (Set<WidgetState> states) {
|
(Set<WidgetState> states) {
|
||||||
// return BorderSide(width: 1, color: appTheme.gray);
|
return BorderSide(width: 1, color: appTheme.gray);
|
||||||
// },
|
},
|
||||||
// ),
|
),
|
||||||
// onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
// setState(() {
|
context.read<CreatePlanCubit>().togglePersonalizedDietOptionState();
|
||||||
// isChecked = value ?? false;
|
},
|
||||||
// });
|
),
|
||||||
// },
|
Expanded(
|
||||||
// ),
|
child: Text(
|
||||||
// Expanded(
|
s.option_personal_diet_desc,
|
||||||
// child: Text(
|
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
||||||
// s.option_personal_diet_desc,
|
),
|
||||||
// style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
),
|
||||||
// ),
|
],
|
||||||
// ),
|
),
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class AuthorCard extends StatelessWidget {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 16, top: 16, bottom: 24),
|
padding: const EdgeInsets.only(left: 16, top: 16, bottom: 24, right: 16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -68,20 +68,23 @@ class AuthorCard extends StatelessWidget {
|
|||||||
if (author.authorPlaceInRating != null)
|
if (author.authorPlaceInRating != null)
|
||||||
InfoBouble(
|
InfoBouble(
|
||||||
radius: 12,
|
radius: 12,
|
||||||
backgroundColor: appTheme.whiteA700,
|
backgroundColor: appTheme.cardBackground,
|
||||||
children: [
|
children: [
|
||||||
Text('${author.authorPlaceInRating}-й в рейтинге', style: TextStyles.textMMediumAuto.copyWith(color: appTheme.blueA400)),
|
Text('${author.authorPlaceInRating}-й в рейтинге', style: TextStyles.textMMediumAuto.copyWith(color: appTheme.blueA400)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
] else
|
] else
|
||||||
GestureDetector(
|
Expanded(
|
||||||
onTap: () {
|
child: GestureDetector(
|
||||||
GoRouter.of(context).pushNamed(UserDetailsScreen.name, extra: customerProfile!.slug);
|
onTap: () {
|
||||||
},
|
GoRouter.of(context).pushNamed(UserDetailsScreen.name, extra: customerProfile!.slug);
|
||||||
child: InfoBouble(
|
},
|
||||||
radius: 12,
|
child: InfoBouble(
|
||||||
backgroundColor: appTheme.whiteA700,
|
radius: 12,
|
||||||
children: [Text('Анкета пользователя', style: TextStyles.textMMediumAuto.copyWith(color: appTheme.blueA400))],
|
backgroundColor: appTheme.cardBackground,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [Text('Анкета пользователя', style: TextStyles.textMMediumAuto.copyWith(color: appTheme.blueA400))],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -13,8 +13,15 @@ class CalendarWidget extends StatefulWidget {
|
|||||||
|
|
||||||
class _CalendarWidgetState extends State<CalendarWidget> {
|
class _CalendarWidgetState extends State<CalendarWidget> {
|
||||||
CalendarFormat _calendarFormat = CalendarFormat.week;
|
CalendarFormat _calendarFormat = CalendarFormat.week;
|
||||||
DateTime _focusedDay = DateTime.now();
|
late DateTime _focusedDay;
|
||||||
DateTime? _selectedDay = DateTime.now();
|
DateTime? _selectedDay;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedDay = widget.startDate.isEmpty ? DateTime.now() : widget.startDate[0];
|
||||||
|
_focusedDay = widget.startDate.isEmpty ? DateTime.now() : widget.startDate[0];
|
||||||
|
}
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
@@ -23,7 +30,7 @@ class _CalendarWidgetState extends State<CalendarWidget> {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: TableCalendar(
|
child: TableCalendar(
|
||||||
firstDay: DateTime.now(),
|
firstDay: widget.startDate.isEmpty ? DateTime.now() : widget.startDate[0],
|
||||||
lastDay: DateTime.utc(2030, 3, 14),
|
lastDay: DateTime.utc(2030, 3, 14),
|
||||||
locale: 'ru_RU',
|
locale: 'ru_RU',
|
||||||
startingDayOfWeek: StartingDayOfWeek.monday,
|
startingDayOfWeek: StartingDayOfWeek.monday,
|
||||||
|
|||||||
@@ -2,20 +2,25 @@ import 'package:eatvio_app/core/theme/theme_helper.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class InfoBouble extends StatelessWidget {
|
class InfoBouble extends StatelessWidget {
|
||||||
const InfoBouble({super.key, required this.children, this.backgroundColor, this.radius = 100, this.padding});
|
const InfoBouble({
|
||||||
|
super.key,
|
||||||
|
required this.children,
|
||||||
|
this.backgroundColor,
|
||||||
|
this.radius = 100,
|
||||||
|
this.padding,
|
||||||
|
this.mainAxisAlignment = MainAxisAlignment.start,
|
||||||
|
});
|
||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
final double radius;
|
final double radius;
|
||||||
final EdgeInsetsGeometry? padding;
|
final EdgeInsetsGeometry? padding;
|
||||||
|
final MainAxisAlignment mainAxisAlignment;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: padding ?? const EdgeInsets.symmetric(horizontal: 12, vertical: 8.5),
|
padding: padding ?? const EdgeInsets.symmetric(horizontal: 12, vertical: 8.5),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: backgroundColor ?? appTheme.gray50, borderRadius: BorderRadius.circular(radius)),
|
||||||
color: backgroundColor ?? appTheme.gray50,
|
child: Row(mainAxisSize: MainAxisSize.min, mainAxisAlignment: mainAxisAlignment, children: children),
|
||||||
borderRadius: BorderRadius.circular(radius),
|
|
||||||
),
|
|
||||||
child: Row(mainAxisSize: MainAxisSize.min, children: children),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,11 +67,19 @@ abstract class PacketOptions with _$PacketOptions {
|
|||||||
@JsonKey(name: "price") required dynamic price,
|
@JsonKey(name: "price") required dynamic price,
|
||||||
@JsonKey(name: "short") required String short,
|
@JsonKey(name: "short") required String short,
|
||||||
@JsonKey(name: "description_md") required String description,
|
@JsonKey(name: "description_md") required String description,
|
||||||
|
@JsonKey(name: "has_personal_diet", fromJson: _parseHasPersonalDietField) required bool hasPersonalDiet,
|
||||||
}) = _PacketOptions;
|
}) = _PacketOptions;
|
||||||
|
|
||||||
factory PacketOptions.fromJson(Map<String, dynamic> json) => _$PacketOptionsFromJson(json);
|
factory PacketOptions.fromJson(Map<String, dynamic> json) => _$PacketOptionsFromJson(json);
|
||||||
|
|
||||||
factory PacketOptions.empty() => PacketOptions(items: [], price: double.parse('1200'), short: '', description: '');
|
factory PacketOptions.empty() => PacketOptions(items: [], price: double.parse('1200'), short: '', description: '', hasPersonalDiet: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _parseHasPersonalDietField(dynamic json) {
|
||||||
|
if (json == null) return false;
|
||||||
|
if (json == '1') return true;
|
||||||
|
if (json == '0') return false;
|
||||||
|
return json as bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> _parseItems(dynamic json) {
|
List<String> _parseItems(dynamic json) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.d
|
|||||||
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
|
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_state.dart';
|
||||||
import 'package:eatvio_app/features/my_diets/presentation/widgets/diet_deleted_bottom_sheet.dart';
|
import 'package:eatvio_app/features/my_diets/presentation/widgets/diet_deleted_bottom_sheet.dart';
|
||||||
import 'package:eatvio_app/features/my_diets/presentation/widgets/diet_drafetd_bottom_sheet.dart';
|
import 'package:eatvio_app/features/my_diets/presentation/widgets/diet_drafetd_bottom_sheet.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/presentation/personal_diet_suggestion_screen.dart';
|
||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.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';
|
||||||
@@ -146,6 +147,7 @@ class _MyDietWidgetState extends State<MyDietWidget> {
|
|||||||
showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время');
|
showErrorToast('Произошла ошибка. Попробуйте ещё раз через некоторое время');
|
||||||
}
|
}
|
||||||
} else if (state.selectedStateIndex == 2) {
|
} else if (state.selectedStateIndex == 2) {
|
||||||
|
GoRouter.of(context).pushNamed(PersonalDietSuggestionScreen.name, extra: widget.diet.id);
|
||||||
} else {
|
} else {
|
||||||
GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: widget.diet);
|
GoRouter.of(context).pushNamed(CreateDietScreen.name, extra: widget.diet);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ class ChosenPlanFinishedToConsultantNotification implements BaseNotificationMode
|
|||||||
type: type,
|
type: type,
|
||||||
planName: json['plan_name'],
|
planName: json['plan_name'],
|
||||||
customerName: json['client_name'],
|
customerName: json['client_name'],
|
||||||
planId: json['plan_id'],
|
planId: json['chosen_plan_id'],
|
||||||
isRead: isRead ?? false,
|
isRead: isRead ?? false,
|
||||||
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
|
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
|
||||||
);
|
);
|
||||||
@@ -1695,6 +1695,35 @@ class DiaryReminderForUsersNotification implements BaseNotificationModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PersonalDietIsDefinedToCustomerNotification implements BaseNotificationModel {
|
||||||
|
@override
|
||||||
|
final NotificationType type;
|
||||||
|
@override
|
||||||
|
final bool isRead;
|
||||||
|
@override
|
||||||
|
final DateTime createdAt;
|
||||||
|
final String dietName;
|
||||||
|
final int dietId;
|
||||||
|
|
||||||
|
PersonalDietIsDefinedToCustomerNotification({
|
||||||
|
required this.type,
|
||||||
|
required this.isRead,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.dietName,
|
||||||
|
required this.dietId,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory PersonalDietIsDefinedToCustomerNotification.fromJson(Map<String, dynamic> json, NotificationType type, {bool? isRead, String? createdAt}) {
|
||||||
|
return PersonalDietIsDefinedToCustomerNotification(
|
||||||
|
type: type,
|
||||||
|
isRead: isRead ?? false,
|
||||||
|
createdAt: parseDate(createdAt ?? json['created_at'] ?? DateTime.now().toIso8601String()),
|
||||||
|
dietName: json['diet_name'] ?? '',
|
||||||
|
dietId: json['diet_id'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum NotificationType {
|
enum NotificationType {
|
||||||
// Diet related
|
// Diet related
|
||||||
dietCancelled,
|
dietCancelled,
|
||||||
@@ -1726,6 +1755,7 @@ enum NotificationType {
|
|||||||
userDailyReportCompleted,
|
userDailyReportCompleted,
|
||||||
chosenPlanFinishedToConsultant,
|
chosenPlanFinishedToConsultant,
|
||||||
stayOnTrackToCustomer,
|
stayOnTrackToCustomer,
|
||||||
|
personalDietIsDefinedToCustomer,
|
||||||
|
|
||||||
// Comments
|
// Comments
|
||||||
entityCommented,
|
entityCommented,
|
||||||
@@ -1834,6 +1864,7 @@ enum NotificationType {
|
|||||||
'chosen-plan-finished-to-consultant' => NotificationType.chosenPlanFinishedToConsultant,
|
'chosen-plan-finished-to-consultant' => NotificationType.chosenPlanFinishedToConsultant,
|
||||||
'stay-on-track-to-customer' => NotificationType.stayOnTrackToCustomer,
|
'stay-on-track-to-customer' => NotificationType.stayOnTrackToCustomer,
|
||||||
'diary-reminder-for-users' => NotificationType.diaryReminderForUsers,
|
'diary-reminder-for-users' => NotificationType.diaryReminderForUsers,
|
||||||
|
'personal-diet-is-defined-to-customer' => NotificationType.personalDietIsDefinedToCustomer,
|
||||||
|
|
||||||
// Legacy mapping
|
// Legacy mapping
|
||||||
'App\\Notifications\\Plan\\PlanSubscriptionStartedToAuthor' => NotificationType.planSubscriptionStartedToAuthor,
|
'App\\Notifications\\Plan\\PlanSubscriptionStartedToAuthor' => NotificationType.planSubscriptionStartedToAuthor,
|
||||||
|
|||||||
@@ -261,6 +261,12 @@ class NotificationsCubit extends Cubit<NotificationsState> {
|
|||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
),
|
),
|
||||||
NotificationType.diaryReminderForUsers => DiaryReminderForUsersNotification.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
NotificationType.diaryReminderForUsers => DiaryReminderForUsersNotification.fromJson(notificationJson, type, isRead: isRead, createdAt: createdAt),
|
||||||
|
NotificationType.personalDietIsDefinedToCustomer => PersonalDietIsDefinedToCustomerNotification.fromJson(
|
||||||
|
notificationJson,
|
||||||
|
type,
|
||||||
|
isRead: isRead,
|
||||||
|
createdAt: createdAt,
|
||||||
|
),
|
||||||
NotificationType.unknown => UnknownNotification(type: type),
|
NotificationType.unknown => UnknownNotification(type: type),
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:eatvio_app/core/routing/route_constants.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/core/utils/date_time_utils.dart';
|
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||||
@@ -113,7 +114,11 @@ class NotificationWidget extends StatelessWidget {
|
|||||||
notification: notification as ProductStatusUpdatedForAuthorNotification,
|
notification: notification as ProductStatusUpdatedForAuthorNotification,
|
||||||
),
|
),
|
||||||
DiaryReminderForUsersNotification() => _DiaryReminderForUsersWidget(notification: notification as DiaryReminderForUsersNotification),
|
DiaryReminderForUsersNotification() => _DiaryReminderForUsersWidget(notification: notification as DiaryReminderForUsersNotification),
|
||||||
|
PersonalDietIsDefinedToCustomerNotification() => _PersonalDietIsDefinedToCustomerWidget(
|
||||||
|
notification: notification as PersonalDietIsDefinedToCustomerNotification,
|
||||||
|
),
|
||||||
UnknownNotification() => _UnknownNotificationWidget(notification: notification as UnknownNotification),
|
UnknownNotification() => _UnknownNotificationWidget(notification: notification as UnknownNotification),
|
||||||
|
// TODO: Handle this case.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,34 +369,38 @@ class _ChosenPlanFinishedToConsultantWidget extends StatelessWidget {
|
|||||||
|
|
||||||
// CardSettingsScreen
|
// CardSettingsScreen
|
||||||
class _BaseNotificationWidget extends StatelessWidget {
|
class _BaseNotificationWidget extends StatelessWidget {
|
||||||
const _BaseNotificationWidget({required this.notificationsText, required this.isRead, required this.createdAt});
|
const _BaseNotificationWidget({required this.notificationsText, required this.isRead, required this.createdAt, this.onTap});
|
||||||
final String notificationsText;
|
final String notificationsText;
|
||||||
final bool isRead;
|
final bool isRead;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
|
final void Function()? onTap;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return GestureDetector(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
onTap: onTap,
|
||||||
children: [
|
child: Column(
|
||||||
Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Row(
|
||||||
child: Text(notificationsText, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
children: [
|
||||||
),
|
Expanded(
|
||||||
if (!isRead)
|
child: Text(notificationsText, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle),
|
|
||||||
width: 8,
|
|
||||||
height: 8,
|
|
||||||
),
|
),
|
||||||
],
|
if (!isRead)
|
||||||
),
|
Container(
|
||||||
const SizedBox(height: 4),
|
decoration: BoxDecoration(color: appTheme.blueA400, shape: BoxShape.circle),
|
||||||
Text(
|
width: 8,
|
||||||
'${createdAt.day} ${_getMonthName(createdAt.month)} ${createdAt.hour.toString().padLeft(2, '0')}:${createdAt.minute.toString().padLeft(2, '0')}',
|
height: 8,
|
||||||
style: TextStyles.textSMedium.copyWith(color: appTheme.gray600),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
'${createdAt.day} ${_getMonthName(createdAt.month)} ${createdAt.hour.toString().padLeft(2, '0')}:${createdAt.minute.toString().padLeft(2, '0')}',
|
||||||
|
style: TextStyles.textSMedium.copyWith(color: appTheme.gray600),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,3 +1062,17 @@ class _DiaryReminderForUsersWidget extends StatelessWidget {
|
|||||||
return _BaseNotificationWidget(isRead: notification.isRead, notificationsText: 'Напоминание о заполнении дневника', createdAt: notification.createdAt);
|
return _BaseNotificationWidget(isRead: notification.isRead, notificationsText: 'Напоминание о заполнении дневника', createdAt: notification.createdAt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _PersonalDietIsDefinedToCustomerWidget extends StatelessWidget {
|
||||||
|
const _PersonalDietIsDefinedToCustomerWidget({required this.notification});
|
||||||
|
final PersonalDietIsDefinedToCustomerNotification notification;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return _BaseNotificationWidget(
|
||||||
|
isRead: notification.isRead,
|
||||||
|
onTap: () => GoRouter.of(context).push(RouteConstants.aboutDietScreen, extra: {'id': notification.dietId, 'navigateToComments': false}),
|
||||||
|
notificationsText: 'Персональная диета "${notification.dietName}" установлена',
|
||||||
|
createdAt: notification.createdAt,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -407,6 +407,12 @@ class NotificationsService {
|
|||||||
isRead: readDate != null,
|
isRead: readDate != null,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
),
|
),
|
||||||
|
NotificationType.personalDietIsDefinedToCustomer => PersonalDietIsDefinedToCustomerNotification.fromJson(
|
||||||
|
notificationJson['data'],
|
||||||
|
type,
|
||||||
|
isRead: readDate != null,
|
||||||
|
createdAt: createdAt,
|
||||||
|
),
|
||||||
NotificationType.unknown => UnknownNotification(type: type, createdAt: parseDate(createdAt)),
|
NotificationType.unknown => UnknownNotification(type: type, createdAt: parseDate(createdAt)),
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ class _InfoByOrderScreenContentState extends State<InfoByOrderScreenContent> {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
PlanInfo(title: plan.plan.name, description: plan.plan.details, imagePath: plan.plan.image),
|
PlanInfo(title: plan.plan.name, description: plan.plan.details, imagePath: plan.plan.image),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
OptionWidget(option: chosenOption, disableDuration: true),
|
OptionWidget(option: chosenOption, disableDuration: true, duration: plan.plan.duration),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
PlanState(state: plan.chosenPlanState),
|
PlanState(state: plan.chosenPlanState, hasPersonalDiet: chosenOption?.hasPersonalDiet ?? false,),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
if (widget.successfulPayment == null)
|
if (widget.successfulPayment == null)
|
||||||
CustomOutlinedButton(
|
CustomOutlinedButton(
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
class PaymentBanner extends StatefulWidget {
|
class PaymentBanner extends StatefulWidget {
|
||||||
const PaymentBanner({
|
const PaymentBanner({super.key, required this.successfulPayment});
|
||||||
super.key,
|
|
||||||
required this.successfulPayment,
|
|
||||||
|
|
||||||
});
|
|
||||||
final bool successfulPayment;
|
final bool successfulPayment;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -29,8 +25,9 @@ class _PaymentBannerState extends State<PaymentBanner> {
|
|||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
final size = MediaQuery.sizeOf(context);
|
final size = MediaQuery.sizeOf(context);
|
||||||
return MainBackgroundBouble(
|
return MainBackgroundBouble(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
child: Stack(children: [
|
child: Stack(
|
||||||
|
children: [
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
@@ -38,8 +35,9 @@ class _PaymentBannerState extends State<PaymentBanner> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
width: 4,
|
width: 4,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.successfulPayment ? appTheme.blueA400 : appTheme.strongRed,
|
color: widget.successfulPayment ? appTheme.blueA400 : appTheme.strongRed,
|
||||||
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), bottomRight: Radius.circular(20))),
|
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), bottomRight: Radius.circular(20)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
@@ -50,78 +48,65 @@ class _PaymentBannerState extends State<PaymentBanner> {
|
|||||||
? [
|
? [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.6,
|
width: size.width * 0.6,
|
||||||
child: Text(
|
child: Text(s.cunsutation_was_paid_successfully, style: TextStyles.textLSemibold.copyWith(color: appTheme.black)),
|
||||||
s.cunsutation_was_paid_successfully,
|
|
||||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.6,
|
width: size.width * 0.6,
|
||||||
child: Text(
|
child: Text(s.wait_for_start_day, style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black)),
|
||||||
s.wait_for_start_day,
|
|
||||||
style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
isLoading
|
isLoading
|
||||||
? const Center(child: Loader())
|
? const Center(child: Loader())
|
||||||
: CustomOutlinedButton(
|
: CustomOutlinedButton(
|
||||||
text: s.go_to_diary,
|
text: s.go_to_diary,
|
||||||
height: 52,
|
height: 52,
|
||||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
buttonStyle:
|
buttonStyle: ButtonStyle(
|
||||||
ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
side: const WidgetStatePropertyAll(BorderSide.none),
|
||||||
|
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||||
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
GoRouter.of(context).pushReplacement('/diary-screen');
|
GoRouter.of(context).pushReplacement('/diary-screen');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
isLoading
|
isLoading
|
||||||
? const Center(child: Loader())
|
? const Center(child: Loader())
|
||||||
: CustomOutlinedButton(
|
: CustomOutlinedButton(
|
||||||
text: s.back_to_chat,
|
text: s.back_to_chat,
|
||||||
height: 52,
|
height: 52,
|
||||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
buttonStyle:
|
buttonStyle: ButtonStyle(
|
||||||
ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
side: const WidgetStatePropertyAll(BorderSide.none),
|
||||||
|
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
GoRouter.of(context).pop();
|
GoRouter.of(context).pop();
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.6,
|
width: size.width * 0.6,
|
||||||
child: Text(
|
child: Text(s.smth_went_wrong_payment_failed, style: TextStyles.textLSemibold.copyWith(color: appTheme.black)),
|
||||||
s.smth_went_wrong_payment_failed,
|
|
||||||
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: size.width * 0.6,
|
width: size.width * 0.6,
|
||||||
child: Text(
|
child: Text(s.try_again_2, style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black)),
|
||||||
s.try_again_2,
|
|
||||||
style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
isLoading
|
isLoading
|
||||||
? const Center(child: Loader())
|
? const Center(child: Loader())
|
||||||
: CustomOutlinedButton(
|
: CustomOutlinedButton(
|
||||||
text: s.pay,
|
text: s.pay,
|
||||||
height: 52,
|
height: 52,
|
||||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
buttonStyle:
|
buttonStyle: ButtonStyle(
|
||||||
ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
side: const WidgetStatePropertyAll(BorderSide.none),
|
||||||
|
backgroundColor: WidgetStatePropertyAll(appTheme.blueA400),
|
||||||
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final planId = context.read<OrderInfoCubit>().state.chosenPlan?.id;
|
final planId = context.read<OrderInfoCubit>().state.chosenPlan?.id;
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -133,16 +118,15 @@ class _PaymentBannerState extends State<PaymentBanner> {
|
|||||||
});
|
});
|
||||||
if (paymentLink != null && planId != null) {
|
if (paymentLink != null && planId != null) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
GoRouter.of(context).pushReplacement(
|
GoRouter.of(context).pushReplacement(PaymentScreen.path, extra: {'url': paymentLink, 'planId': planId});
|
||||||
PaymentScreen.path,
|
|
||||||
extra: {'url': paymentLink, 'planId': planId},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
]));
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,42 +5,65 @@ import 'package:eatvio_app/features/plans/enums/chosen_plan_state_enum.dart';
|
|||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class PlanState extends StatelessWidget {
|
class PlanState extends StatefulWidget {
|
||||||
PlanState({super.key, required this.state});
|
const PlanState({super.key, required this.state, required this.hasPersonalDiet});
|
||||||
final ChosenPlanStateEnum state;
|
final ChosenPlanStateEnum state;
|
||||||
final List<List<ChosenPlanStateEnum>> states = [
|
final bool hasPersonalDiet;
|
||||||
[
|
|
||||||
ChosenPlanStateEnum.stateInited,
|
@override
|
||||||
ChosenPlanStateEnum.stateInCoordination,
|
State<PlanState> createState() => _PlanStateState();
|
||||||
],
|
}
|
||||||
[
|
|
||||||
ChosenPlanStateEnum.stateStartDateHasBeenSet,
|
class _PlanStateState extends State<PlanState> {
|
||||||
ChosenPlanStateEnum.statePendingPayment,
|
late final List<List<ChosenPlanStateEnum>> states;
|
||||||
],
|
|
||||||
[
|
@override
|
||||||
ChosenPlanStateEnum.statePaid,
|
void initState() {
|
||||||
],
|
super.initState();
|
||||||
[
|
if (widget.hasPersonalDiet) {
|
||||||
ChosenPlanStateEnum.stateStarted,
|
states = [
|
||||||
ChosenPlanStateEnum.stateInProgress,
|
[ChosenPlanStateEnum.stateInited, ChosenPlanStateEnum.stateInCoordination],
|
||||||
ChosenPlanStateEnum.stateLastDayStarted,
|
[ChosenPlanStateEnum.stateStartDateHasBeenSet, ChosenPlanStateEnum.statePendingPayment],
|
||||||
ChosenPlanStateEnum.stateLastDayFinished,
|
[ChosenPlanStateEnum.statePaid],
|
||||||
],
|
[ChosenPlanStateEnum.personalDietSet],
|
||||||
[
|
[
|
||||||
ChosenPlanStateEnum.stateComplained,
|
ChosenPlanStateEnum.stateStarted,
|
||||||
ChosenPlanStateEnum.stateDone,
|
ChosenPlanStateEnum.stateInProgress,
|
||||||
ChosenPlanStateEnum.stateChargeWasCollected,
|
ChosenPlanStateEnum.stateLastDayStarted,
|
||||||
]
|
ChosenPlanStateEnum.stateLastDayFinished,
|
||||||
];
|
],
|
||||||
|
[ChosenPlanStateEnum.stateComplained, ChosenPlanStateEnum.stateDone, ChosenPlanStateEnum.stateChargeWasCollected],
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
states = [
|
||||||
|
[ChosenPlanStateEnum.stateInited, ChosenPlanStateEnum.stateInCoordination],
|
||||||
|
[ChosenPlanStateEnum.stateStartDateHasBeenSet, ChosenPlanStateEnum.statePendingPayment],
|
||||||
|
[ChosenPlanStateEnum.statePaid],
|
||||||
|
[
|
||||||
|
ChosenPlanStateEnum.stateStarted,
|
||||||
|
ChosenPlanStateEnum.stateInProgress,
|
||||||
|
ChosenPlanStateEnum.stateLastDayStarted,
|
||||||
|
ChosenPlanStateEnum.stateLastDayFinished,
|
||||||
|
],
|
||||||
|
[ChosenPlanStateEnum.stateComplained, ChosenPlanStateEnum.stateDone, ChosenPlanStateEnum.stateChargeWasCollected],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
final titles = [s.order_created, s.startDateHasBeenSet, s.order_paid, s.in_progress, s.done];
|
final List<String> titles;
|
||||||
|
if (widget.hasPersonalDiet) {
|
||||||
|
titles = [s.order_created, s.startDateHasBeenSet, s.order_paid, s.personal_diet_set, s.in_progress, s.done];
|
||||||
|
} else {
|
||||||
|
titles = [s.order_created, s.startDateHasBeenSet, s.order_paid, s.in_progress, s.done];
|
||||||
|
}
|
||||||
return MainBackgroundBouble(
|
return MainBackgroundBouble(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: List.generate(states.length, (index) {
|
children: List.generate(states.length, (index) {
|
||||||
final color = index <= states.indexWhere((element) => element.contains(state)) ? appTheme.greenA700 : appTheme.lightGray00;
|
final color = index <= states.indexWhere((element) => element.contains(widget.state)) ? appTheme.greenA700 : appTheme.lightGray00;
|
||||||
final text = titles[index];
|
final text = titles[index];
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -51,29 +74,16 @@ class PlanState extends StatelessWidget {
|
|||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
|
decoration: BoxDecoration(shape: BoxShape.circle, color: color),
|
||||||
child: Center(
|
child: Center(child: Icon(Icons.check, color: appTheme.whiteA700, size: 14)),
|
||||||
child: Icon(
|
|
||||||
Icons.check,
|
|
||||||
color: appTheme.whiteA700,
|
|
||||||
size: 14,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Text(
|
Text(text, style: TextStyles.textMMedium.copyWith(color: appTheme.black)),
|
||||||
text,
|
|
||||||
style: TextStyles.textMMedium.copyWith(color: appTheme.black),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 12),
|
padding: const EdgeInsets.only(left: 12),
|
||||||
child: Container(
|
child: Container(height: 12, width: 1, color: color),
|
||||||
height: 12,
|
),
|
||||||
width: 1,
|
|
||||||
color: color,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:eatvio_app/features/diets/repositories/diet_repository.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/cubit/personal_diet_suggestion_state.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/repository/personal_diet_suggestion_repository.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class PersonalDietSuggestionCubit extends Cubit<PersonalDietSuggestionState> {
|
||||||
|
final DietRepository dietRepository;
|
||||||
|
final PersonalDietSuggestionRepository personalDietSuggestionService;
|
||||||
|
late final int dietId;
|
||||||
|
PersonalDietSuggestionCubit({required this.dietRepository, required this.personalDietSuggestionService}) : super(PersonalDietSuggestionState());
|
||||||
|
|
||||||
|
Future<void> setDietName(int dietId) async {
|
||||||
|
try {
|
||||||
|
emit(state.copyWith(isLoading: true, error: null));
|
||||||
|
final diet = await dietRepository.getDiet(dietId);
|
||||||
|
emit(state.copyWith(isLoading: false, dietName: diet.name));
|
||||||
|
} catch (e, st) {
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
emit(state.copyWith(isLoading: false, error: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getConsultationWithPersonalDiets(int dietId) async {
|
||||||
|
try {
|
||||||
|
this.dietId = dietId;
|
||||||
|
emit(state.copyWith(isLoading: true, error: null));
|
||||||
|
setDietName(dietId);
|
||||||
|
final consultations = await personalDietSuggestionService.getConsultationWithPersonalDiets();
|
||||||
|
final consultationWithDiet = consultations.where((consultation) => consultation.personalDietId != null).toList();
|
||||||
|
final consultationWithoutDiet = consultations.where((consultation) => consultation.personalDietId == null).toList();
|
||||||
|
emit(state.copyWith(
|
||||||
|
isLoading: false,
|
||||||
|
consultationsWithDiet: consultationWithDiet,
|
||||||
|
consultationsWithoutDiet: consultationWithoutDiet,
|
||||||
|
));
|
||||||
|
} catch (e, st) {
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
emit(state.copyWith(isLoading: false, error: e.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> attachDietToConsultation({
|
||||||
|
required int consultationId,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
await personalDietSuggestionService.attachPersonalDiet(consultationId: consultationId, dietId: dietId);
|
||||||
|
return true;
|
||||||
|
} catch (e, st) {
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> reattachDietToConsultation({
|
||||||
|
required int consultationId,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
await personalDietSuggestionService.reattachPersonalDiet(consultationId: consultationId, dietId: dietId);
|
||||||
|
return true;
|
||||||
|
} catch (e, st) {
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'personal_diet_suggestion_state.freezed.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class PersonalDietSuggestionState with _$PersonalDietSuggestionState {
|
||||||
|
factory PersonalDietSuggestionState({
|
||||||
|
@Default([]) List<ConsultationModel> consultationsWithDiet,
|
||||||
|
@Default([]) List<ConsultationModel> consultationsWithoutDiet,
|
||||||
|
@Default('') String dietName,
|
||||||
|
@Default(false) bool isLoading,
|
||||||
|
@Default(null) String? error,
|
||||||
|
}) = _PersonalDietSuggestionState;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,358 @@
|
|||||||
|
import 'package:eatvio_app/core/app_config.dart';
|
||||||
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
|
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||||
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
|
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||||
|
import 'package:eatvio_app/core/widgets/bottom_sheet_with_blur.dart';
|
||||||
|
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||||
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/cubit/personal_diet_suggestion_cubit.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
class ConsultationWidget extends StatelessWidget {
|
||||||
|
const ConsultationWidget({super.key, required this.consultationModel, required this.dietName});
|
||||||
|
final ConsultationModel consultationModel;
|
||||||
|
final String dietName;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: appTheme.whiteA700,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (consultationModel.personalDietId == null)
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
CircleAvatar(
|
||||||
|
radius: 30,
|
||||||
|
backgroundImage: NetworkImage(sl<AppConfig>().baseUrl + consultationModel.userProfilePhotoUrl),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
spacing: 4,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
consultationModel.userName,
|
||||||
|
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
consultationModel.planTitle,
|
||||||
|
style: TextStyles.textMMedium.copyWith(color: const Color(0xFF88949F)),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Старт: ${consultationModel.userName}',
|
||||||
|
style: TextStyles.textMMedium.copyWith(color: const Color(0xFF88949F)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
CircleAvatar(
|
||||||
|
radius: 30,
|
||||||
|
backgroundImage: NetworkImage(sl<AppConfig>().baseUrl + consultationModel.userProfilePhotoUrl),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
spacing: 4,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
consultationModel.userName,
|
||||||
|
style: TextStyles.textLSemibold.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
consultationModel.planTitle,
|
||||||
|
style: TextStyles.textMMedium.copyWith(color: const Color(0xFF88949F)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
if (consultationModel.personalDietId != null)
|
||||||
|
CustomOutlinedButton(
|
||||||
|
text: s.changeDiet,
|
||||||
|
height: 52,
|
||||||
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.gray),
|
||||||
|
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.dividerColor)),
|
||||||
|
onPressed: () async {
|
||||||
|
showBottomSheetWithBlur(
|
||||||
|
userRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
height: null,
|
||||||
|
child: SuggestDietBottomSheet(
|
||||||
|
userName: consultationModel.userName,
|
||||||
|
dietName: dietName,
|
||||||
|
onTap: () async {
|
||||||
|
final result = await context.read<PersonalDietSuggestionCubit>().attachDietToConsultation(consultationId: consultationModel.id);
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
if (result) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
showBottomSheetWithBlur(
|
||||||
|
userRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
height: null,
|
||||||
|
child: SuggestionSuccessBottomSheet(
|
||||||
|
userName: consultationModel.userName,
|
||||||
|
dietName: dietName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!context.mounted) return;
|
||||||
|
showBottomSheetWithBlur(
|
||||||
|
userRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
height: null,
|
||||||
|
child: SuggestionFailureBottomSheet(
|
||||||
|
userName: consultationModel.userName,
|
||||||
|
dietName: dietName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else
|
||||||
|
CustomOutlinedButton(
|
||||||
|
text: s.suggestDiet,
|
||||||
|
height: 52,
|
||||||
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
|
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
||||||
|
onPressed: () async {
|
||||||
|
showBottomSheetWithBlur(
|
||||||
|
userRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
height: null,
|
||||||
|
child: SuggestDietBottomSheet(
|
||||||
|
userName: consultationModel.userName,
|
||||||
|
dietName: dietName,
|
||||||
|
onTap: () async {
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
final result = await context.read<PersonalDietSuggestionCubit>().attachDietToConsultation(consultationId: consultationModel.id);
|
||||||
|
if (result) {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
showBottomSheetWithBlur(
|
||||||
|
userRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
height: null,
|
||||||
|
child: SuggestionSuccessBottomSheet(
|
||||||
|
userName: consultationModel.userName,
|
||||||
|
dietName: dietName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!context.mounted) return;
|
||||||
|
showBottomSheetWithBlur(
|
||||||
|
userRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
height: null,
|
||||||
|
child: SuggestionFailureBottomSheet(
|
||||||
|
userName: consultationModel.userName,
|
||||||
|
dietName: dietName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SuggestDietBottomSheet extends StatefulWidget {
|
||||||
|
const SuggestDietBottomSheet({
|
||||||
|
super.key,
|
||||||
|
required this.userName,
|
||||||
|
required this.dietName,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
final String userName;
|
||||||
|
final String dietName;
|
||||||
|
final Future<void> Function() onTap;
|
||||||
|
@override
|
||||||
|
State<SuggestDietBottomSheet> createState() => _SuggestDietBottomSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SuggestDietBottomSheet extends State<SuggestDietBottomSheet> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
const BottomSheetHandlerBar(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Text('Предложение диеты', style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black)),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Предложить пользователю ${widget.userName} «${widget.dietName}»',
|
||||||
|
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
CustomOutlinedButton(
|
||||||
|
text: s.toOffer,
|
||||||
|
height: 52,
|
||||||
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
|
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
||||||
|
onPressed: widget.onTap,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SuggestionSuccessBottomSheet extends StatefulWidget {
|
||||||
|
const SuggestionSuccessBottomSheet({
|
||||||
|
super.key,
|
||||||
|
required this.userName,
|
||||||
|
required this.dietName,
|
||||||
|
});
|
||||||
|
final String userName;
|
||||||
|
final String dietName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SuggestionSuccessBottomSheet> createState() => _SuggestionSuccessBottomSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SuggestionSuccessBottomSheet extends State<SuggestionSuccessBottomSheet> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
const BottomSheetHandlerBar(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Text('Предложение диеты', style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black)),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'«${widget.dietName}» предложена пользователю ${widget.userName}',
|
||||||
|
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
CustomOutlinedButton(
|
||||||
|
text: s.ok,
|
||||||
|
height: 52,
|
||||||
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
|
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
||||||
|
onPressed: () async {
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SuggestionFailureBottomSheet extends StatefulWidget {
|
||||||
|
const SuggestionFailureBottomSheet({
|
||||||
|
super.key,
|
||||||
|
required this.userName,
|
||||||
|
required this.dietName,
|
||||||
|
});
|
||||||
|
final String userName;
|
||||||
|
final String dietName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SuggestionFailureBottomSheet> createState() => _SuggestionFailureBottomSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SuggestionFailureBottomSheet extends State<SuggestionFailureBottomSheet> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
const BottomSheetHandlerBar(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Text('Предложение диеты', style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black)),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Не удалось предложить диету ${widget.dietName} пользователю ${widget.userName}',
|
||||||
|
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
CustomOutlinedButton(
|
||||||
|
text: s.ok,
|
||||||
|
height: 52,
|
||||||
|
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||||
|
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
||||||
|
onPressed: () async {
|
||||||
|
AppRouter.navigatorKey.currentContext?.pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 40,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
|
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||||
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
|
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/cubit/personal_diet_suggestion_cubit.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/cubit/personal_diet_suggestion_state.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/presentation/consultation_widget.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
class PersonalDietSuggestionScreen extends StatelessWidget {
|
||||||
|
final int dietId;
|
||||||
|
const PersonalDietSuggestionScreen({super.key, required this.dietId});
|
||||||
|
static const path = '/personal-diet-suggestion';
|
||||||
|
static const name = 'personalDietSuggestion';
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => sl<PersonalDietSuggestionCubit>()..getConsultationWithPersonalDiets(dietId),
|
||||||
|
child: const PersonalDietSuggestionScreenContent(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PersonalDietSuggestionScreenContent extends StatelessWidget {
|
||||||
|
const PersonalDietSuggestionScreenContent({super.key});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return BlocBuilder<PersonalDietSuggestionCubit, PersonalDietSuggestionState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: appTheme.gray100,
|
||||||
|
appBar: AppBar(
|
||||||
|
centerTitle: true,
|
||||||
|
title: Text(
|
||||||
|
'${s.dietSuggestion}\n«${state.dietName}»',
|
||||||
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: state.isLoading
|
||||||
|
? const Center(child: Loader())
|
||||||
|
: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
...List.generate(state.consultationsWithDiet.length, (index) {
|
||||||
|
return ConsultationWidget(
|
||||||
|
consultationModel: state.consultationsWithDiet[index],
|
||||||
|
dietName: state.dietName,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
|
),
|
||||||
|
...List.generate(state.consultationsWithoutDiet.length, (index) {
|
||||||
|
return ConsultationWidget(
|
||||||
|
consultationModel: state.consultationsWithoutDiet[index],
|
||||||
|
dietName: state.dietName,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
|
import 'package:eatvio_app/features/personal_diet_suggestion/services/personal_diet_suggestion_service.dart';
|
||||||
|
|
||||||
|
class PersonalDietSuggestionRepository {
|
||||||
|
final PersonalDietSuggestionService personalDietSuggestionService;
|
||||||
|
|
||||||
|
PersonalDietSuggestionRepository({required this.personalDietSuggestionService});
|
||||||
|
|
||||||
|
Future<List<ConsultationModel>> getConsultationWithPersonalDiets() async{
|
||||||
|
try {
|
||||||
|
return (await personalDietSuggestionService.getConsultationWithPersonalDiets()).data;
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> attachPersonalDiet({required int consultationId, required int dietId}) {
|
||||||
|
try {
|
||||||
|
return personalDietSuggestionService.attachPersonalDiet(consultationId: consultationId, dietId: dietId);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> reattachPersonalDiet({required int consultationId, required int dietId}) {
|
||||||
|
try {
|
||||||
|
return personalDietSuggestionService.reattachPersonalDiet(consultationId: consultationId, dietId: dietId);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:eatvio_app/features/consultations/models/consultation_model.dart';
|
||||||
|
|
||||||
|
class PersonalDietSuggestionService {
|
||||||
|
final Dio dio;
|
||||||
|
PersonalDietSuggestionService(this.dio);
|
||||||
|
|
||||||
|
Future<ConsultationPaginationModel> getConsultationWithPersonalDiets() async {
|
||||||
|
try {
|
||||||
|
final response = await dio.get('/api/consultations', queryParameters: {
|
||||||
|
'filters[plan][has_personal_diet][\$personal_diet]': '1',
|
||||||
|
'filters[last_state][\$notIn][]': ['done', 'charge_was_collected', 'complained', 'last_day_finished', 'canceled_by_the_initiator', 'inited'],
|
||||||
|
'sort[]': 'start_date:desc',
|
||||||
|
});
|
||||||
|
return ConsultationPaginationModel.fromJson(response.data);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> attachPersonalDiet({required int consultationId, required int dietId}) async {
|
||||||
|
try {
|
||||||
|
await dio.post('/api/chosen_plans/$consultationId/attach_diet', data: {'diet_id': dietId});
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> reattachPersonalDiet({required int consultationId, required int dietId}) async {
|
||||||
|
try {
|
||||||
|
await dio.post('/api/chosen_plans/$consultationId/re_attach_diet', data: {'diet_id': dietId});
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,8 @@ enum ChosenPlanStateEnum {
|
|||||||
stateComplained,
|
stateComplained,
|
||||||
@JsonValue('done')
|
@JsonValue('done')
|
||||||
stateDone,
|
stateDone,
|
||||||
|
@JsonValue('personal_diet_setted')
|
||||||
|
personalDietSet,
|
||||||
@JsonValue('charge_was_collected')
|
@JsonValue('charge_was_collected')
|
||||||
stateChargeWasCollected;
|
stateChargeWasCollected;
|
||||||
|
|
||||||
@@ -40,6 +42,7 @@ enum ChosenPlanStateEnum {
|
|||||||
ChosenPlanStateEnum.stateLastDayFinished,
|
ChosenPlanStateEnum.stateLastDayFinished,
|
||||||
ChosenPlanStateEnum.stateDone,
|
ChosenPlanStateEnum.stateDone,
|
||||||
ChosenPlanStateEnum.stateInProgress,
|
ChosenPlanStateEnum.stateInProgress,
|
||||||
|
ChosenPlanStateEnum.personalDietSet,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +67,8 @@ enum ChosenPlanStateEnum {
|
|||||||
ChosenPlanStateEnum.stateLastDayStarted,
|
ChosenPlanStateEnum.stateLastDayStarted,
|
||||||
ChosenPlanStateEnum.stateLastDayFinished,
|
ChosenPlanStateEnum.stateLastDayFinished,
|
||||||
ChosenPlanStateEnum.stateComplained,
|
ChosenPlanStateEnum.stateComplained,
|
||||||
ChosenPlanStateEnum.stateDone
|
ChosenPlanStateEnum.stateDone,
|
||||||
|
ChosenPlanStateEnum.personalDietSet
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -505,12 +505,15 @@ class _AboutPlanScreenState extends State<AboutPlanScreen> {
|
|||||||
switch (state.chosenOptionIndex) {
|
switch (state.chosenOptionIndex) {
|
||||||
1 => OptionWidget(
|
1 => OptionWidget(
|
||||||
option: state.planModel?.packet2Options,
|
option: state.planModel?.packet2Options,
|
||||||
|
duration: state.planModel?.duration ?? 0,
|
||||||
),
|
),
|
||||||
2 => OptionWidget(
|
2 => OptionWidget(
|
||||||
option: state.planModel?.packet3Options,
|
option: state.planModel?.packet3Options,
|
||||||
|
duration: state.planModel?.duration ?? 0,
|
||||||
),
|
),
|
||||||
_ => OptionWidget(
|
_ => OptionWidget(
|
||||||
option: state.planModel?.packet1Options,
|
option: state.planModel?.packet1Options,
|
||||||
|
duration: state.planModel?.duration ?? 0,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
|
|||||||
@@ -49,8 +49,7 @@ class _UserDetailsContentState extends State<UserDetailsContent> {
|
|||||||
final List<String> chipsIntervalList = ['1', '3', '6', '12', 'all'];
|
final List<String> chipsIntervalList = ['1', '3', '6', '12', 'all'];
|
||||||
|
|
||||||
List<WeightModel> weightPoints = [];
|
List<WeightModel> weightPoints = [];
|
||||||
List<CircumferenceModel> circumferencePoints = [];
|
List<CircumferenceModel> circumferencePoints = []; int _selectedChipIndex = 0;
|
||||||
int _selectedChipIndex = 0;
|
|
||||||
int _selectedIntervalChipIndex = 0;
|
int _selectedIntervalChipIndex = 0;
|
||||||
bool isMoreOptionsVisible = false;
|
bool isMoreOptionsVisible = false;
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
"Если вы любите мучные продукты, но хотите придерживаться диеты, вам подходит диета с добавленим мучных блюд на основе цельнозерновых вариантов. В них больше сложных углеводов и клетчатки, что способствует длительному чувству сытости и поддерживает здоровье пищеварительной системы.",
|
||||||
),
|
),
|
||||||
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
"carbohydrates": MessageLookupByLibrary.simpleMessage("Углеводы"),
|
||||||
|
"changeDiet": MessageLookupByLibrary.simpleMessage("Заменить диету"),
|
||||||
"chargeApproved": MessageLookupByLibrary.simpleMessage("Выплата одобрена"),
|
"chargeApproved": MessageLookupByLibrary.simpleMessage("Выплата одобрена"),
|
||||||
"chargeCollectionFailed": MessageLookupByLibrary.simpleMessage(
|
"chargeCollectionFailed": MessageLookupByLibrary.simpleMessage(
|
||||||
"Не удалось оформить выплату",
|
"Не удалось оформить выплату",
|
||||||
@@ -158,6 +159,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"choose_plan_start_date": MessageLookupByLibrary.simpleMessage(
|
"choose_plan_start_date": MessageLookupByLibrary.simpleMessage(
|
||||||
"Выберите дату старта плана питания",
|
"Выберите дату старта плана питания",
|
||||||
),
|
),
|
||||||
|
"choose_plan_start_date_with_personal_diet":
|
||||||
|
MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Выберите дату старта плана питания с учетом составления персональной диеты",
|
||||||
|
),
|
||||||
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
"choose_start_diet_date": MessageLookupByLibrary.simpleMessage(
|
||||||
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике",
|
"Выберите дату старты диеты. Она отобразиться у Вас в дневнике",
|
||||||
),
|
),
|
||||||
@@ -165,6 +170,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"chose_plan_start_date_2": MessageLookupByLibrary.simpleMessage(
|
"chose_plan_start_date_2": MessageLookupByLibrary.simpleMessage(
|
||||||
"Выберите дату старты плана. Она отобразиться в дневнике пользователя",
|
"Выберите дату старты плана. Она отобразиться в дневнике пользователя",
|
||||||
),
|
),
|
||||||
|
"chosenPlanStartDateDescr": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Дату старта плана можно выбрать не ранее, чем через два. Такое ограничение дается на создание персональной диеты",
|
||||||
|
),
|
||||||
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
"circumference_empty": MessageLookupByLibrary.simpleMessage(
|
||||||
"Все замеры обязательны к заполнению",
|
"Все замеры обязательны к заполнению",
|
||||||
),
|
),
|
||||||
@@ -246,6 +254,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Не удалось обновить диету",
|
"Не удалось обновить диету",
|
||||||
),
|
),
|
||||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||||
|
"createPersonalDiet": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Составьте персональную диету",
|
||||||
|
),
|
||||||
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
"create_diet": MessageLookupByLibrary.simpleMessage("Создание диеты"),
|
||||||
"cunsutation_was_paid_successfully": MessageLookupByLibrary.simpleMessage(
|
"cunsutation_was_paid_successfully": MessageLookupByLibrary.simpleMessage(
|
||||||
"Поздравляем, консультация успешно оплачена",
|
"Поздравляем, консультация успешно оплачена",
|
||||||
@@ -274,6 +285,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||||
|
"dietSuggestion": MessageLookupByLibrary.simpleMessage("Предложение диеты"),
|
||||||
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
"diet_author": MessageLookupByLibrary.simpleMessage("Автор диеты"),
|
||||||
"diet_has_been_sent_to_draft": MessageLookupByLibrary.simpleMessage(
|
"diet_has_been_sent_to_draft": MessageLookupByLibrary.simpleMessage(
|
||||||
"снята с публикации и перенесена в черновик",
|
"снята с публикации и перенесена в черновик",
|
||||||
@@ -393,6 +405,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
"from_z_to_a": MessageLookupByLibrary.simpleMessage("Название: Я-А"),
|
||||||
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
|
"gallery": MessageLookupByLibrary.simpleMessage("Галерея"),
|
||||||
"general_info": MessageLookupByLibrary.simpleMessage("Общая информация"),
|
"general_info": MessageLookupByLibrary.simpleMessage("Общая информация"),
|
||||||
|
"goToMyDiets": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Перейти к моим диетам",
|
||||||
|
),
|
||||||
"go_to_diary": MessageLookupByLibrary.simpleMessage("Перейти в дневник"),
|
"go_to_diary": MessageLookupByLibrary.simpleMessage("Перейти в дневник"),
|
||||||
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
"gr": MessageLookupByLibrary.simpleMessage("гр"),
|
||||||
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
"grams": MessageLookupByLibrary.simpleMessage("гр"),
|
||||||
@@ -570,6 +585,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
"pcs": MessageLookupByLibrary.simpleMessage("шт"),
|
||||||
"pending_payment": MessageLookupByLibrary.simpleMessage("Ожидается оплата"),
|
"pending_payment": MessageLookupByLibrary.simpleMessage("Ожидается оплата"),
|
||||||
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
|
"personal": MessageLookupByLibrary.simpleMessage("Персональные"),
|
||||||
|
"personalDietCreating": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Составление индивидуальной диеты",
|
||||||
|
),
|
||||||
|
"personal_diet_set": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Персональная диета установлена",
|
||||||
|
),
|
||||||
"personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"),
|
"personal_diet_state": MessageLookupByLibrary.simpleMessage("Персональная"),
|
||||||
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
|
"photo": MessageLookupByLibrary.simpleMessage("Фото"),
|
||||||
"physical_fitness": MessageLookupByLibrary.simpleMessage(
|
"physical_fitness": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -699,6 +720,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"successfully_published": MessageLookupByLibrary.simpleMessage(
|
"successfully_published": MessageLookupByLibrary.simpleMessage(
|
||||||
"успешно опубликован",
|
"успешно опубликован",
|
||||||
),
|
),
|
||||||
|
"suggestDiet": MessageLookupByLibrary.simpleMessage("Предложить диету"),
|
||||||
"suicide": MessageLookupByLibrary.simpleMessage("Склонение к самоубийству"),
|
"suicide": MessageLookupByLibrary.simpleMessage("Склонение к самоубийству"),
|
||||||
"takes_pills": MessageLookupByLibrary.simpleMessage("Принимает лекарства"),
|
"takes_pills": MessageLookupByLibrary.simpleMessage("Принимает лекарства"),
|
||||||
"tap_on_link_to_pay": MessageLookupByLibrary.simpleMessage(
|
"tap_on_link_to_pay": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|||||||
@@ -3434,6 +3434,86 @@ class S {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Составление индивидуальной диеты`
|
||||||
|
String get personalDietCreating {
|
||||||
|
return Intl.message(
|
||||||
|
'Составление индивидуальной диеты',
|
||||||
|
name: 'personalDietCreating',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Предложение диеты`
|
||||||
|
String get dietSuggestion {
|
||||||
|
return Intl.message(
|
||||||
|
'Предложение диеты',
|
||||||
|
name: 'dietSuggestion',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Предложить диету`
|
||||||
|
String get suggestDiet {
|
||||||
|
return Intl.message(
|
||||||
|
'Предложить диету',
|
||||||
|
name: 'suggestDiet',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Заменить диету`
|
||||||
|
String get changeDiet {
|
||||||
|
return Intl.message(
|
||||||
|
'Заменить диету',
|
||||||
|
name: 'changeDiet',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Выберите дату старта плана питания с учетом составления персональной диеты`
|
||||||
|
String get choose_plan_start_date_with_personal_diet {
|
||||||
|
return Intl.message(
|
||||||
|
'Выберите дату старта плана питания с учетом составления персональной диеты',
|
||||||
|
name: 'choose_plan_start_date_with_personal_diet',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Дату старта плана можно выбрать не ранее, чем через два. Такое ограничение дается на создание персональной диеты`
|
||||||
|
String get chosenPlanStartDateDescr {
|
||||||
|
return Intl.message(
|
||||||
|
'Дату старта плана можно выбрать не ранее, чем через два. Такое ограничение дается на создание персональной диеты',
|
||||||
|
name: 'chosenPlanStartDateDescr',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Составьте персональную диету`
|
||||||
|
String get createPersonalDiet {
|
||||||
|
return Intl.message(
|
||||||
|
'Составьте персональную диету',
|
||||||
|
name: 'createPersonalDiet',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Перейти к моим диетам`
|
||||||
|
String get goToMyDiets {
|
||||||
|
return Intl.message(
|
||||||
|
'Перейти к моим диетам',
|
||||||
|
name: 'goToMyDiets',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// `Удаление аккаунта`
|
/// `Удаление аккаунта`
|
||||||
String get accountDeleting {
|
String get accountDeleting {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
@@ -3504,6 +3584,16 @@ class S {
|
|||||||
return Intl.message('Покупатель', name: 'customer', desc: '', args: []);
|
return Intl.message('Покупатель', name: 'customer', desc: '', args: []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `Персональная диета установлена`
|
||||||
|
String get personal_diet_set {
|
||||||
|
return Intl.message(
|
||||||
|
'Персональная диета установлена',
|
||||||
|
name: 'personal_diet_set',
|
||||||
|
desc: '',
|
||||||
|
args: [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// `Поздравляем!`
|
/// `Поздравляем!`
|
||||||
String get congratulations {
|
String get congratulations {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
|
|||||||
@@ -408,6 +408,14 @@
|
|||||||
"copy": "Скопировать",
|
"copy": "Скопировать",
|
||||||
"reply": "Ответить",
|
"reply": "Ответить",
|
||||||
"deleteComment": "Удалить комментарий",
|
"deleteComment": "Удалить комментарий",
|
||||||
|
"personalDietCreating": "Составление индивидуальной диеты",
|
||||||
|
"dietSuggestion": "Предложение диеты",
|
||||||
|
"suggestDiet": "Предложить диету",
|
||||||
|
"changeDiet": "Заменить диету",
|
||||||
|
"choose_plan_start_date_with_personal_diet": "Выберите дату старта плана питания с учетом составления персональной диеты",
|
||||||
|
"chosenPlanStartDateDescr": "Дату старта плана можно выбрать не ранее, чем через два. Такое ограничение дается на создание персональной диеты",
|
||||||
|
"createPersonalDiet": "Составьте персональную диету",
|
||||||
|
"goToMyDiets": "Перейти к моим диетам",
|
||||||
"accountDeleting": "Удаление аккаунта",
|
"accountDeleting": "Удаление аккаунта",
|
||||||
"youShureYouWantToDeleteAccount": "Вы уверены, что хотите удалить аккаунт?",
|
"youShureYouWantToDeleteAccount": "Вы уверены, что хотите удалить аккаунт?",
|
||||||
"itCantBeRecovered": "Его нельзя будет восстановить",
|
"itCantBeRecovered": "Его нельзя будет восстановить",
|
||||||
@@ -416,6 +424,7 @@
|
|||||||
"resend": "Отправить повторно",
|
"resend": "Отправить повторно",
|
||||||
"notifications": "Уведомления",
|
"notifications": "Уведомления",
|
||||||
"customer": "Покупатель",
|
"customer": "Покупатель",
|
||||||
|
"personal_diet_set": "Персональная диета установлена",
|
||||||
"congratulations": "Поздравляем!",
|
"congratulations": "Поздравляем!",
|
||||||
"youWithUs": "Вы с итвио уже\n",
|
"youWithUs": "Вы с итвио уже\n",
|
||||||
"fourteenDays": "14 дней",
|
"fourteenDays": "14 дней",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: eatvio_app
|
name: eatvio_app
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
version: 1.3.2+81
|
version: 1.3.3+82
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
Reference in New Issue
Block a user