You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
car_common_app/lib/views/appointments/appointment_detail_view.dart

376 lines
17 KiB
Dart

import 'dart:developer';
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/date_helper.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<AppointmentsVM>();
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, required bool shouldShowConfirmButton}) {
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()),
if (shouldShowConfirmButton) ...[
12.width,
getBaseActionButtonWidget(
color: MyColors.greenColor,
onPressed: () {
context.read<AppointmentsVM>().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()),
if (shouldShowConfirmButton) ...[
12.width,
getBaseActionButtonWidget(
color: MyColors.greenColor,
onPressed: () {
context.read<AppointmentsVM>().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id);
},
text: LocaleKeys.confirm.tr()),
],
],
),
);
default:
return const SizedBox();
}
}
void appointmentCancelConfirmationSheet(BuildContext context) {
final appointmentsVm = context.read<AppointmentsVM>();
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<AppointmentsVM>().onCancelAppointmentPressed(context: context, appointmentListModel: appointmentListModel);
}
},
maxWidth: double.infinity,
),
19.height,
],
),
));
});
},
);
}
@override
Widget build(BuildContext context) {
AppointmentsVM appointmentsVM = context.read<AppointmentsVM>();
bool shouldShowConfirmButton = false;
final currentDateTime = DateTime.now();
if ((appointmentListModel.isPaymentRequiredAtBooking ?? false) && appointmentListModel.appointmentDate != null && appointmentListModel.appointmentDate!.isNotEmpty) {
final DateTime appointmentDatetime = DateHelper.parseStringToDate(appointmentListModel.appointmentDate!);
shouldShowConfirmButton = (appointmentListModel.isPaymentRequiredAtBooking ?? false) && (appointmentDatetime.isAfter(currentDateTime));
}
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<AppointmentsVM>().onRescheduleAppointmentPressed(context: context, appointmentListModel: appointmentListModel);
},
icon: MyAssets.scheduleAppointmentIcon.buildSvg(),
),
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked && (shouldShowConfirmButton)) ...[
10.width,
CardButtonWithIcon(
title: LocaleKeys.payforAppointment.tr(),
onCardTapped: () {
context.read<AppointmentsVM>().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id);
},
icon: MyAssets.creditCardIcon.buildSvg(),
),
],
],
),
15.height,
],
],
).toWhiteContainer(width: double.infinity, allPading: 12),
buildBottomActionButton(appointmentStatusEnum: appointmentListModel.appointmentStatusEnum!, context: context, shouldShowConfirmButton: shouldShowConfirmButton),
],
),
),
);
}
}