forked from eatvio/eatvio_app
feat(chats,diary): added logic for chosen diet portions and added banner to finish plan to chats
This commit is contained in:
@@ -10,6 +10,7 @@ import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/websockets/ws_manager.dart';
|
||||
import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/models/plan_complain_model.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
|
||||
import 'package:eatvio_app/features/chat/repositories/chat_repository.dart';
|
||||
import 'package:eatvio_app/features/my_finance/models/card_model.dart';
|
||||
@@ -92,7 +93,7 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
|
||||
hasCard: false,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
if (chatRoom.chosenPlan?.consultantId == chatRoom.users.receiver.id) {
|
||||
await checkCards();
|
||||
}
|
||||
@@ -209,6 +210,30 @@ class ChatRoomCubit extends Cubit<ChatRoomState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> complainAboutConsultation({required String description}) async {
|
||||
try {
|
||||
final planId = (state as ChatRoomStateLoaded).chatRoom.chosenPlan?.id;
|
||||
if (planId == null) return false;
|
||||
await chatRepository.complainAboutConsultation(id: planId, body: PlanComplainModel(description: description));
|
||||
return true;
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> finishChosenPlan() async {
|
||||
try {
|
||||
final planId = (state as ChatRoomStateLoaded).chatRoom.chosenPlan?.id;
|
||||
if (planId == null) return false;
|
||||
await chatRepository.finishChosenPlan(id: planId);
|
||||
return true;
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
wsManager.unsubscribeDirectChatChannel();
|
||||
|
||||
@@ -29,7 +29,7 @@ import 'package:visibility_detector/visibility_detector.dart';
|
||||
|
||||
class ChatScreen extends StatefulWidget {
|
||||
final String chatId;
|
||||
final bool sendInitialMessage;
|
||||
final bool? sendInitialMessage;
|
||||
const ChatScreen({required this.chatId, super.key, required this.sendInitialMessage});
|
||||
|
||||
@override
|
||||
@@ -48,7 +48,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
scrollController.addListener(_onScroll);
|
||||
chatRoomCubit.initChat(widget.chatId, sendInitialMessage: widget.sendInitialMessage);
|
||||
chatRoomCubit.initChat(widget.chatId, sendInitialMessage: widget.sendInitialMessage ?? false);
|
||||
}
|
||||
|
||||
_onScroll() {
|
||||
@@ -98,7 +98,7 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
BannerType? bannerType;
|
||||
if (chosenPlan == null) {
|
||||
bannerType = null;
|
||||
} else if (!amIConsultant && !state.hasCard) {
|
||||
} else if (amIConsultant && !state.hasCard) {
|
||||
bannerType = BannerType.card;
|
||||
} else if (amIConsultant && chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateInCoordination) {
|
||||
bannerType = BannerType.date;
|
||||
@@ -107,6 +107,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
||||
bannerType = BannerType.payment;
|
||||
} else if (chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateDone) {
|
||||
bannerType = BannerType.collectCharge;
|
||||
} else if (!(chosenPlan.chosenPlanState == ChosenPlanStateEnum.stateLastDayFinished) && !amIConsultant) {
|
||||
bannerType = BannerType.finishPlan;
|
||||
}
|
||||
|
||||
PacketOptions? chosenOption;
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class CompletePlanBottomSheet extends StatefulWidget {
|
||||
const CompletePlanBottomSheet({super.key, required this.cubit});
|
||||
final ChatRoomCubit cubit;
|
||||
|
||||
@override
|
||||
State<CompletePlanBottomSheet> createState() => _CompletePlanBottomSheetState();
|
||||
}
|
||||
|
||||
class _CompletePlanBottomSheetState extends State<CompletePlanBottomSheet> {
|
||||
bool? isFailure;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
if (isFailure == true) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
const BottomSheetHandlerBar(),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Text('Произошла ошибка, попробуйте позже', style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
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 {
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
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(
|
||||
'Вы уверенны что хотите подтвердить прохождения плана?',
|
||||
style: TextStyles.textSMedium.copyWith(color: appTheme.black),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
CustomOutlinedButton(
|
||||
text: s.confirm,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
||||
onPressed: () async {
|
||||
final result = await widget.cubit.finishChosenPlan();
|
||||
if (result) {
|
||||
if (context.mounted) {
|
||||
context.pop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
setState(() {
|
||||
isFailure = true;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,14 @@
|
||||
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_with_blur.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_state.dart';
|
||||
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/complete_plan_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/plan_complain_bottom_sheet.dart';
|
||||
import 'package:eatvio_app/features/my_finance/presentation/pages/card_settings.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -40,7 +43,7 @@ class _NotificationBannerState extends State<NotificationBanner> {
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (widget.bannerType != BannerType.collectCharge)
|
||||
if (widget.bannerType != BannerType.collectCharge && widget.bannerType != BannerType.finishPlan)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 12, right: 8, left: 12),
|
||||
child: SvgPicture.asset('assets/icons/reversed_exclamation_mark.svg', height: 68, width: 68),
|
||||
@@ -139,6 +142,19 @@ class _NotificationBannerState extends State<NotificationBanner> {
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
BannerType.finishPlan => [
|
||||
SizedBox(
|
||||
width: size.width * 0.6,
|
||||
child: Text('${s.congratsYouHaveFinishedPlan} «${widget.planName}». ${s.pleaseConfirmPlan}',
|
||||
style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black)),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
width: size.width * 0.7,
|
||||
child: Text(s.planWillBeConfirmedAfterThreeDays, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -156,7 +172,57 @@ class _NotificationBannerState extends State<NotificationBanner> {
|
||||
GoRouter.of(context).push(CardSettingsScreen.path, extra: widget.chosenPlanId);
|
||||
},
|
||||
),
|
||||
)
|
||||
),
|
||||
if (widget.bannerType == BannerType.finishPlan) ...[
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: CustomOutlinedButton(
|
||||
text: s.confirm,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
||||
onPressed: () async {
|
||||
final cubit = context.read<ChatRoomCubit>();
|
||||
showBottomSheetWithBlur(
|
||||
userRootNavigator: true,
|
||||
context: context,
|
||||
height: null,
|
||||
child: CompletePlanBottomSheet(
|
||||
cubit: cubit,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SizedBox(
|
||||
child: Text(s.youCanComplain, style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
final cubit = context.read<ChatRoomCubit>();
|
||||
showBottomSheetWithBlur(
|
||||
userRootNavigator: true,
|
||||
context: context,
|
||||
height: null,
|
||||
child: PlanComplainBottomSheet(
|
||||
cubit: cubit,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(s.leaveComplainRequest, style: TextStyles.textSMedium.copyWith(color: appTheme.red))),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -176,4 +242,4 @@ class _StarIcon extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
enum BannerType { date, card, payment, collectCharge }
|
||||
enum BannerType { date, card, payment, collectCharge, finishPlan }
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
import 'package:eatvio_app/core/theme/custom_text_style.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_outlined_button.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
|
||||
import 'package:eatvio_app/features/create_diet/presentation/widgets/error_widget.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class PlanComplainBottomSheet extends StatefulWidget {
|
||||
const PlanComplainBottomSheet({super.key, required this.cubit});
|
||||
final ChatRoomCubit cubit;
|
||||
|
||||
@override
|
||||
State<PlanComplainBottomSheet> createState() => _PlanComplainBottomSheetState();
|
||||
}
|
||||
|
||||
class _PlanComplainBottomSheetState extends State<PlanComplainBottomSheet> {
|
||||
final controller = TextEditingController();
|
||||
bool? result;
|
||||
int? textLength;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = S.of(context);
|
||||
if (result == true) {
|
||||
return 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('Жалоба отправлена на рассмотрение. Обычно это занимает до трёх рабочих дней.', style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
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 {
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (result == false) {
|
||||
return 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('Произошла ошибка, попробуйте позже', style: TextStyles.textSMedium.copyWith(color: appTheme.black)),
|
||||
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 {
|
||||
context.pop();
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
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,
|
||||
),
|
||||
Align(alignment: Alignment.centerLeft, child: Text('Опишите причину жалобы', style: TextStyles.textSMedium.copyWith(color: appTheme.black))),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
CustomTextFormField(
|
||||
controller: controller,
|
||||
hasError: textLength != null && textLength! < 3,
|
||||
onChanged: (p0) {
|
||||
setState(() {
|
||||
textLength = p0.length;
|
||||
});
|
||||
},
|
||||
),
|
||||
if (textLength != null && textLength! < 3) ...[
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
ValidationErrorWidget(error: s.atLeast3Symbols),
|
||||
],
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
CustomOutlinedButton(
|
||||
text: s.confirm,
|
||||
height: 52,
|
||||
buttonTextStyle: TextStyles.textMSemibold.copyWith(color: appTheme.whiteA700),
|
||||
buttonStyle: ButtonStyle(side: const WidgetStatePropertyAll(BorderSide.none), backgroundColor: WidgetStatePropertyAll(appTheme.blueA400)),
|
||||
onPressed: () async {
|
||||
if (controller.text.length < 3) {
|
||||
return;
|
||||
}
|
||||
final result = await widget.cubit.complainAboutConsultation(description: controller.text);
|
||||
setState(() {
|
||||
this.result = result;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user