import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; import 'package:mc_common_app/models/chat_models/chat_message_model.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/appointments_view_model.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/common_widgets/card_button_with_icon.dart'; import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:sizer/sizer.dart'; class AppointmentDetailView extends StatelessWidget { final AppointmentListModel appointmentListModel; const AppointmentDetailView({super.key, required this.appointmentListModel}); Widget getBaseActionButtonWidget({required Color color, required String text, Color textColor = MyColors.white, required Function() onPressed}) { return Expanded( child: ShowFillButton( maxHeight: 55, title: text, onPressed: onPressed, backgroundColor: color, txtColor: textColor, fontSize: 18, ), ); } Widget getArrivedBottomActionButton({required BuildContext context, required AppointmentPaymentStatusEnum appointmentPaymentStatusEnum}) { final appointmentVM = context.read(); switch (appointmentPaymentStatusEnum) { case AppointmentPaymentStatusEnum.defaultStatus: case AppointmentPaymentStatusEnum.paid: case AppointmentPaymentStatusEnum.payLater: case AppointmentPaymentStatusEnum.payPartial: return Align( alignment: Alignment.bottomCenter, child: SizedBox( height: 8.h, child: Utils.buildStatusContainer(LocaleKeys.workInProgress.tr()), ), ); case AppointmentPaymentStatusEnum.payNow: return Align( alignment: Alignment.bottomCenter, child: Row( children: [ getBaseActionButtonWidget( color: MyColors.darkPrimaryColor, textColor: MyColors.white, onPressed: () { if (appointmentListModel.remainingAmount != null && appointmentListModel.remainingAmount! > 0.0) { appointmentVM.onPayNowPressedForAppointment( context: context, appointmentID: appointmentListModel.id ?? 0, ); } }, text: LocaleKeys.payNow.tr(), ), ], ), ); } } Widget buildBottomActionButton({required AppointmentStatusEnum appointmentStatusEnum, required BuildContext context}) { switch (appointmentStatusEnum) { case AppointmentStatusEnum.booked: return Align( alignment: Alignment.bottomCenter, child: Row( children: [ getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => buildCancelAppointmentReasonsBottomSheet(context: context), text: LocaleKeys.cancel.tr()), 12.width, getBaseActionButtonWidget( color: MyColors.greenColor, onPressed: () { context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); }, text: LocaleKeys.confirm.tr()), ], ), ); case AppointmentStatusEnum.confirmed: return Align( alignment: Alignment.bottomCenter, child: Row( children: [ getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => buildCancelAppointmentReasonsBottomSheet(context: context), text: LocaleKeys.cancel.tr()), ], ), ); case AppointmentStatusEnum.visitCompleted: return Align( alignment: Alignment.bottomCenter, child: SizedBox( height: 8.h, child: Utils.buildStatusContainer(LocaleKeys.visitCompleted.tr()), ), ); case AppointmentStatusEnum.arrived: case AppointmentStatusEnum.workStarted: return getArrivedBottomActionButton(appointmentPaymentStatusEnum: appointmentListModel.appointmentPaymentStatusEnum ?? AppointmentPaymentStatusEnum.defaultStatus, context: context); case AppointmentStatusEnum.cancelled: return Align( alignment: Alignment.bottomCenter, child: SizedBox( height: 8.h, child: Utils.buildStatusContainer(LocaleKeys.appointmentCancelled.tr()), ), ); case AppointmentStatusEnum.allAppointments: return const SizedBox(); case AppointmentStatusEnum.rescheduled: return Align( alignment: Alignment.bottomCenter, child: Row( children: [ getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => buildCancelAppointmentReasonsBottomSheet(context: context), text: LocaleKeys.cancel.tr()), 12.width, getBaseActionButtonWidget( color: MyColors.greenColor, onPressed: () { context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); }, text: LocaleKeys.confirm.tr()), ], ), ); default: return const SizedBox(); } } void appointmentCancelConfirmationSheet(BuildContext context) { final appointmentsVm = context.read(); return actionConfirmationBottomSheet( context: context, title: LocaleKeys.youWantCancelAppointment.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), subtitle: LocaleKeys.appointmentCancelledCannotUndoAction.tr(), actionButtonYes: Expanded( child: ShowFillButton( maxHeight: 55, title: LocaleKeys.yes.tr(), fontSize: 15, onPressed: () { Navigator.pop(context); appointmentsVm.onCancelAppointmentPressed(context: context, appointmentListModel: appointmentListModel); }, ), ), actionButtonNo: Expanded( child: ShowFillButton( maxHeight: 55, isFilled: false, borderColor: MyColors.darkPrimaryColor, title: LocaleKeys.no.tr(), txtColor: MyColors.darkPrimaryColor, fontSize: 15, onPressed: () { Navigator.pop(context); }, ), ), ); } Future buildCancelAppointmentReasonsBottomSheet({required BuildContext context}) { return showModalBottomSheet( context: context, isScrollControlled: true, enableDrag: true, builder: (BuildContext context) { return Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { return InfoBottomSheet( title: LocaleKeys.pleaseSpecify.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), description: Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ 12.height, ListView.separated( shrinkWrap: true, itemCount: appointmentsVM.cancelAppointmentReasonList.length, separatorBuilder: (BuildContext context, int index) { return const Divider(thickness: 0.5); }, itemBuilder: (BuildContext context, int index) { OfferRequestCommentModel offerRequestCommentModel = appointmentsVM.cancelAppointmentReasonList[index]; return CircleCheckBoxWithTitle( isChecked: offerRequestCommentModel.isSelected ?? false, title: '${offerRequestCommentModel.title}', onSelected: () { appointmentsVM.updateSelectedCancelAppointmentReason(index); }, selectedColor: MyColors.darkPrimaryColor, ); }, ), if (appointmentsVM.selectedCancelAppointmentReason.index == appointmentsVM.cancelAppointmentReasonList.length - 1) ...[ // comparing if the "other" is selected 12.height, TxtField( maxLines: 5, value: appointmentsVM.cancelAppointmentDescription, errorValue: appointmentsVM.cancelAppointmentDescriptionError, keyboardType: TextInputType.text, hint: LocaleKeys.description.tr(), onChanged: (v) => appointmentsVM.updateCancelAppointmentDescription(v), ), ], ], ), 25.height, ShowFillButton( title: LocaleKeys.submit.tr(), onPressed: () { if (appointmentsVM.selectedCancelAppointmentReason.index == 0) { appointmentsVM.onRescheduleAppointmentPressed(context: context, appointmentListModel: appointmentListModel); } else { context.read().onCancelAppointmentPressed(context: context, appointmentListModel: appointmentListModel); } }, maxWidth: double.infinity, ), 19.height, ], ), )); }); }, ); } @override Widget build(BuildContext context) { AppointmentsVM appointmentsVM = context.read(); return Scaffold( appBar: CustomAppBar( title: LocaleKeys.appointment.tr(), profileImageUrl: MyAssets.bnCar, isRemoveBackButton: false, isDrawerEnabled: false, ), body: Container( padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21), child: Stack( children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ appointmentListModel.providerName!.toText(fontSize: 16, isBold: true), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ MyAssets.miniClockDark.buildSvg( height: 12, width: 12, fit: BoxFit.fill, ), 5.width, "${appointmentListModel.duration ?? ""} ${appointmentListModel.appointmentDate!.toFormattedDateWithoutTime()}".toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor), ], ), 13.height, if (appointmentListModel.appointmentServicesList != null && appointmentListModel.appointmentServicesList!.isNotEmpty) ...[ Column( children: List.generate(appointmentListModel.appointmentServicesList!.length, (index) { ServiceModel service = appointmentListModel.appointmentServicesList![index]; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "${index + 1}. ${service.providerServiceDescription}".toText(fontSize: 14, isBold: true), if (service.serviceItems != null && service.serviceItems!.isNotEmpty) ...[ Column( children: List.generate( service.serviceItems!.length, (index) => "${service.serviceItems![index].name}".toText( textAlign: TextAlign.start, fontSize: 12, color: MyColors.lightTextColor, ), ), ).paddingOnly(left: 15), ], ], ), 5.height, Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ ((service.currentTotalServicePrice).toString()).toText(fontSize: 19, isBold: true), 2.width, LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 12, isBold: true).paddingOnly(bottom: 5), const Icon(Icons.arrow_drop_down, size: 25) ], ).onPress(() => appointmentsVM.priceBreakDownClicked(context, service)), ], ).paddingOnly(bottom: 15); }), ), ], 15.height, if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked || appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.confirmed) ...[ Row( children: [ CardButtonWithIcon( title: LocaleKeys.rescheduleAppointment.tr(), onCardTapped: () { context.read().onRescheduleAppointmentPressed(context: context, appointmentListModel: appointmentListModel); }, icon: MyAssets.scheduleAppointmentIcon.buildSvg(), ), if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked) ...[ 10.width, CardButtonWithIcon( title: LocaleKeys.payforAppointment.tr(), onCardTapped: () { context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); }, icon: MyAssets.creditCardIcon.buildSvg(), ), ], ], ), 15.height, ], ], ).toWhiteContainer(width: double.infinity, allPading: 12), buildBottomActionButton(appointmentStatusEnum: appointmentListModel.appointmentStatusEnum!, context: context), ], ), ), ); } }