From 3f7527f4b2493c4d89ee94014e8bf06086e95d91 Mon Sep 17 00:00:00 2001 From: FaizHashmiCS22 Date: Mon, 1 Jan 2024 17:49:19 +0300 Subject: [PATCH] Appointment Flow Testing --- lib/extensions/string_extensions.dart | 14 +- lib/repositories/appointment_repo.dart | 155 +++---- lib/services/payments_service.dart | 7 +- lib/utils/enums.dart | 1 + lib/view_models/appointments_view_model.dart | 387 ++++++------------ lib/view_models/payment_view_model.dart | 14 +- lib/views/advertisement/ads_detail_view.dart | 2 + .../appointments/appointment_detail_view.dart | 91 ++-- 8 files changed, 260 insertions(+), 411 deletions(-) diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index afff381..1a8125d 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -3,7 +3,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; -import 'package:mc_common_app/utils/enums.dart'; extension EmailValidator on String { Widget toText( @@ -25,10 +24,7 @@ extension EmailValidator on String { style: TextStyle( fontStyle: isItalic ? FontStyle.italic : null, height: height, - decoration: isUnderLine - ? TextDecoration.underline - : textDecoration ?? TextDecoration.none, - + decoration: isUnderLine ? TextDecoration.underline : textDecoration ?? TextDecoration.none, fontSize: fontSize ?? 10, fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.w600, color: color ?? MyColors.darkTextColor, @@ -37,9 +33,7 @@ extension EmailValidator on String { ); bool isValidEmail() { - return RegExp( - r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$') - .hasMatch(this); + return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this); } bool isNum() { @@ -428,6 +422,10 @@ extension PaymentTypesToInt on PaymentTypes { case PaymentTypes.request: return 5; + case PaymentTypes.extendAds: + return 6; + case PaymentTypes.partialAppointment: + return 7; default: return 0; diff --git a/lib/repositories/appointment_repo.dart b/lib/repositories/appointment_repo.dart index 540d25a..126bc6e 100644 --- a/lib/repositories/appointment_repo.dart +++ b/lib/repositories/appointment_repo.dart @@ -4,18 +4,16 @@ import 'package:mc_common_app/api/api_client.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/dependencies.dart'; +import 'package:mc_common_app/models/appointments_models/schedule_model.dart'; +import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/m_response.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/services.dart'; -import 'package:mc_common_app/models/appointments_models/schedule_model.dart'; -import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; -import 'package:mc_common_app/utils/enums.dart'; import '../models/appointments_models/appointment_list_model.dart'; abstract class AppointmentRepo { - Future> getMyAppointments( - Map map); + Future> getMyAppointments(Map map); Future updateAppointmentStatus(Map map); @@ -37,20 +35,14 @@ abstract class AppointmentRepo { Future updateServicesInSchedule(Map map); - Future> - mergeServiceIntoAvailableSchedules({ + Future> mergeServiceIntoAvailableSchedules({ required List serviceItemIdsForHome, required List serviceItemIdsForWorkshop, }); - Future createServiceAppointment( - {required List schedules, - required int serviceProviderID}); + Future createServiceAppointment({required List schedules, required int serviceProviderID}); - Future cancelOrRescheduleServiceAppointment( - {required int serviceAppointmentID, - required int serviceSlotID, - required int appointmentScheduleAction}); + Future cancelOrRescheduleServiceAppointment({required int serviceAppointmentID, required int serviceSlotID, required int appointmentScheduleAction}); } class AppointmentRepoImp implements AppointmentRepo { @@ -58,25 +50,19 @@ class AppointmentRepoImp implements AppointmentRepo { Future getAllServices(String branchId) async { Map map = {"ProviderBranchID": branchId}; String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject( - (json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, - token: t, queryParameters: map); + return await injector.get().getJsonForObject((json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, token: t, queryParameters: map); } @override Future createSchedule(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject( - (json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, - token: t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, token: t); } @override Future addServicesInSchedule(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject( - (json) => MResponse.fromJson(json), ApiConsts.createGroup, map, - token: t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createGroup, map, token: t); } @override @@ -84,36 +70,29 @@ class AppointmentRepoImp implements AppointmentRepo { Map map = {"ServiceProviderBranchID": branchId}; String t = AppState().getUser.data!.accessToken ?? ""; - GenericRespModel adsGenericModel = - await injector.get().getJsonForObject( + GenericRespModel adsGenericModel = await injector.get().getJsonForObject( (json) => GenericRespModel.fromJson(json), - ApiConsts.getSchedule, - token: t, - queryParameters: map, - ); + ApiConsts.getSchedule, + token: t, + queryParameters: map, + ); - return List.generate(adsGenericModel.data.length, - (index) => ScheduleData.fromJson(adsGenericModel.data[index])); + return List.generate(adsGenericModel.data.length, (index) => ScheduleData.fromJson(adsGenericModel.data[index])); } @override Future updateSchedule(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject( - (json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, - token: t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, token: t); } @override Future updateServicesInSchedule(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject( - (json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, - token: t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, token: t); } - Future> - mergeServiceIntoAvailableSchedules({ + Future> mergeServiceIntoAvailableSchedules({ required List serviceItemIdsForHome, required List serviceItemIdsForWorkshop, }) async { @@ -128,29 +107,21 @@ class AppointmentRepoImp implements AppointmentRepo { "ServiceItemIDs": serviceItemIdsForWorkshop, } ]; - GenericRespModel adsGenericModel = - await injector.get().postJsonForObject( + GenericRespModel adsGenericModel = await injector.get().postJsonForObject( (json) => GenericRespModel.fromJson(json), - ApiConsts.GetServiceItemAppointmentScheduleSlots, - queryParameters, - token: t, - ); + ApiConsts.GetServiceItemAppointmentScheduleSlots, + queryParameters, + token: t, + ); if (adsGenericModel.data == null) { return []; } List serviceAppointmentScheduleModel = - List.generate( - adsGenericModel.data.length, - (index) => - ServiceAppointmentScheduleModel.fromJson( - adsGenericModel.data[index], - isForAppointment: true)); + List.generate(adsGenericModel.data.length, (index) => ServiceAppointmentScheduleModel.fromJson(adsGenericModel.data[index], isForAppointment: true)); return serviceAppointmentScheduleModel; } - Future createServiceAppointment( - {required List schedules, - required int serviceProviderID}) async { + Future createServiceAppointment({required List schedules, required int serviceProviderID}) async { String t = AppState().getUser.data!.accessToken ?? ""; int customerId = AppState().getUser.data!.userInfo!.customerId ?? 0; @@ -169,23 +140,20 @@ class AppointmentRepoImp implements AppointmentRepo { "serviceItemID": serviceItemIds, }); }); + log("maplist: ${mapList.toString() }"); - GenericRespModel adsGenericModel = - await injector.get().postJsonForObject( + GenericRespModel adsGenericModel = await injector.get().postJsonForObject( (json) => GenericRespModel.fromJson(json), - ApiConsts.ServiceProvidersAppointmentCreate, - mapList, - token: t, - ); + ApiConsts.ServiceProvidersAppointmentCreate, + mapList, + token: t, + ); return adsGenericModel; } @override - Future cancelOrRescheduleServiceAppointment( - {required int serviceAppointmentID, - required int serviceSlotID, - required int appointmentScheduleAction}) async { + Future cancelOrRescheduleServiceAppointment({required int serviceAppointmentID, required int serviceSlotID, required int appointmentScheduleAction}) async { String t = AppState().getUser.data!.accessToken ?? ""; final payload = { @@ -194,33 +162,27 @@ class AppointmentRepoImp implements AppointmentRepo { "appointmentScheduleAction": appointmentScheduleAction, }; - GenericRespModel adsGenericModel = - await injector.get().postJsonForObject( + GenericRespModel adsGenericModel = await injector.get().postJsonForObject( (json) => GenericRespModel.fromJson(json), - ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment, - payload, - token: t, - ); + ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment, + payload, + token: t, + ); return adsGenericModel; } @override - Future> getMyAppointments( - Map map) async { + Future> getMyAppointments(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - GenericRespModel genericRespModel = - await injector.get().getJsonForObject( - token: t, + GenericRespModel genericRespModel = await injector.get().getJsonForObject( + token: t, (json) => GenericRespModel.fromJson(json), - queryParameters: map, - ApiConsts.serviceProvidersAppointmentGet, - ); - List appointmentList = List.generate( - genericRespModel.data.length, - (index) => - AppointmentListModel.fromJson(genericRespModel.data[index])); + queryParameters: map, + ApiConsts.serviceProvidersAppointmentGet, + ); + List appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index])); return appointmentList; } @@ -228,42 +190,31 @@ class AppointmentRepoImp implements AppointmentRepo { Future getAppointmentSlots(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - MResponse adsGenericModel = - await injector.get().getJsonForObject( + MResponse adsGenericModel = await injector.get().getJsonForObject( (json) => MResponse.fromJson(json), - ApiConsts.getAppointmentSlots, - token: t, - queryParameters: map, - ); + ApiConsts.getAppointmentSlots, + token: t, + queryParameters: map, + ); return adsGenericModel; } @override - Future updateAppointmentPaymentStatus( - Map map) async { + Future updateAppointmentPaymentStatus(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject( - (json) => MResponse.fromJson(json), - ApiConsts.updateAppointmentPaymentStatus, map, - token: t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateAppointmentPaymentStatus, map, token: t); } @override Future updateAppointmentStatus(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject( - (json) => MResponse.fromJson(json), - ApiConsts.updateAppointmentStatus, map, - token: t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateAppointmentStatus, map, token: t); } @override Future createMergeAppointment(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject( - (json) => MResponse.fromJson(json), - ApiConsts.createMergeAppointment, map, - token: t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createMergeAppointment, map, token: t); } } diff --git a/lib/services/payments_service.dart b/lib/services/payments_service.dart index 917a7cf..aed50b8 100644 --- a/lib/services/payments_service.dart +++ b/lib/services/payments_service.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'dart:developer'; import 'package:flutter/material.dart'; @@ -8,7 +7,6 @@ import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/services/my_in_app_browser.dart'; import 'package:mc_common_app/utils/enums.dart'; -import 'package:mc_common_app/utils/utils.dart'; abstract class PaymentService { Future placePayment({ @@ -30,11 +28,11 @@ class PaymentServiceImp implements PaymentService { MyInAppBrowser? myInAppBrowser; var inAppBrowserOptions = InAppBrowserClassOptions( inAppWebViewGroupOptions: - InAppWebViewGroupOptions(crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false), ios: IOSInAppWebViewOptions(applePayAPIEnabled: true)), + InAppWebViewGroupOptions(crossPlatform: InAppWebViewOptions(useShouldOverrideUrlLoading: true, transparentBackground: false), ios: IOSInAppWebViewOptions(applePayAPIEnabled: true)), crossPlatform: InAppBrowserOptions(hideUrlBar: true, toolbarTopBackgroundColor: Colors.black), android: AndroidInAppBrowserOptions(), ios: - IOSInAppBrowserOptions(hideToolbarBottom: true, toolbarBottomBackgroundColor: Colors.white, closeButtonColor: Colors.white, presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN)); + IOSInAppBrowserOptions(hideToolbarBottom: true, toolbarBottomBackgroundColor: Colors.white, closeButtonColor: Colors.white, presentationStyle: IOSUIModalPresentationStyle.OVER_FULL_SCREEN)); @override Future placePayment({ @@ -51,6 +49,7 @@ class PaymentServiceImp implements PaymentService { urlRequest = "${ApiConsts.paymentWebViewUrl}?PaymentType=${paymentType.getIdFromPaymentTypesEnum()}&OrderProviderSubscriptionID=$id"; break; case PaymentTypes.appointment: + case PaymentTypes.partialAppointment: String appointIds = ''; for (int i = 0; i < appointmentIds!.length; i++) { var element = appointmentIds[i]; diff --git a/lib/utils/enums.dart b/lib/utils/enums.dart index 8fcfa8a..b70f540 100644 --- a/lib/utils/enums.dart +++ b/lib/utils/enums.dart @@ -82,6 +82,7 @@ enum PaymentTypes { ads, request, extendAds, + partialAppointment } enum AdCreationSteps { diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart index 8235c54..118ccc6 100644 --- a/lib/view_models/appointments_view_model.dart +++ b/lib/view_models/appointments_view_model.dart @@ -4,15 +4,15 @@ import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; +import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/models/general_models/enums_model.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/m_response.dart'; +import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart'; -import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/models/services_models/item_model.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; -import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/repositories/appointment_repo.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; import 'package:mc_common_app/repositories/provider_repo.dart'; @@ -39,10 +39,7 @@ class AppointmentsVM extends BaseVM { final ProviderRepo providerRepo; final AppointmentRepo scheduleRepo; - AppointmentsVM({required this.commonServices, - required this.scheduleRepo, - required this.providerRepo, - required this.commonRepo}); + AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo}); bool isUpcommingEnabled = true; bool isFetchingLists = false; @@ -69,8 +66,7 @@ class AppointmentsVM extends BaseVM { List serviceAppointmentScheduleList = []; bool ifItemAlreadySelected(int id) { - int indexFound = allSelectedItemsInAppointments - .indexWhere((element) => element.id == id); + int indexFound = allSelectedItemsInAppointments.indexWhere((element) => element.id == id); if (indexFound != -1) { return true; } @@ -81,25 +77,17 @@ class AppointmentsVM extends BaseVM { setupProviderAppointmentFilter() { appointmentsFilterOptions.clear(); - appointmentsFilterOptions.add( - FilterListModel(id: 0, title: "All Appointments", isSelected: true)); - appointmentsFilterOptions - .add(FilterListModel(id: 2, title: "Confirmed", isSelected: false)); - appointmentsFilterOptions - .add(FilterListModel(id: 3, title: "Arrived", isSelected: false)); - appointmentsFilterOptions - .add( - FilterListModel(id: 7, title: "Work In Progress", isSelected: false)); - appointmentsFilterOptions - .add(FilterListModel(id: 8, title: "Completed", isSelected: false)); - appointmentsFilterOptions - .add(FilterListModel(id: 4, title: "Canceled", isSelected: false)); + appointmentsFilterOptions.add(FilterListModel(id: 0, title: "All Appointments", isSelected: true)); + appointmentsFilterOptions.add(FilterListModel(id: 2, title: "Confirmed", isSelected: false)); + appointmentsFilterOptions.add(FilterListModel(id: 3, title: "Arrived", isSelected: false)); + appointmentsFilterOptions.add(FilterListModel(id: 7, title: "Work In Progress", isSelected: false)); + appointmentsFilterOptions.add(FilterListModel(id: 8, title: "Completed", isSelected: false)); + appointmentsFilterOptions.add(FilterListModel(id: 4, title: "Canceled", isSelected: false)); } Future onItemsSelectedInService() async { if (currentServiceSelection != null) { - int index = servicesInCurrentAppointment.indexWhere((element) => - element.serviceId == currentServiceSelection!.serviceId!); + int index = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!); if (index == -1) { double totalPrice = 0.0; @@ -115,47 +103,49 @@ class AppointmentsVM extends BaseVM { } } + Future onPayNowPressedForAppointment({required BuildContext context, required int appointmentID}) async { + context.read().updateAppointmentIdsForPayment(ids: [appointmentID]); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.partialAppointment); + } + Future onBookAppointmentPressed(BuildContext context) async { Utils.showLoading(context); bool isSuccess = false; List appointmentIdsList = []; try { - GenericRespModel genericRespModel = - await scheduleRepo.createServiceAppointment( + GenericRespModel genericRespModel = await scheduleRepo.createServiceAppointment( schedules: serviceAppointmentScheduleList, serviceProviderID: selectedBranchModel!.serviceProviderId ?? 0, ); - if (genericRespModel.messageStatus == 2 || - genericRespModel.data == null) { + if (genericRespModel.data.isEmpty) { Utils.hideLoading(context); Utils.showToast("${genericRespModel.message.toString()}"); return; } - if (genericRespModel.data != null) { + + if (genericRespModel.data != null && genericRespModel.data.isNotEmpty) { genericRespModel.data.forEach((element) { if (element['appointmentID'] != 0) { appointmentIdsList.add(element['appointmentID']); isSuccess = true; } else { isSuccess = false; + Utils.showToast(element['message']); + return; } }); } context.read().onNavbarTapped(1); - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.booked); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.booked); Utils.hideLoading(context); resetAfterBookingAppointment(); if (isSuccess) { if (amountToPayForAppointment > 0) { - context - .read() - .updateAppointmentIdsForPayment(ids: appointmentIdsList); - navigateWithName(context, AppRoutes.paymentMethodsView, - arguments: PaymentTypes.appointment); + context.read().updateAppointmentIdsForPayment(ids: appointmentIdsList); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment); } else { Utils.showToast("Your appointment has been booked successfully!"); getMyAppointments(); @@ -167,36 +157,28 @@ class AppointmentsVM extends BaseVM { } } - Future onConfirmAppointmentPressed( - {required BuildContext context, required appointmentId}) async { - context - .read() - .updateAppointmentIdsForPayment(ids: [appointmentId]); - navigateWithName(context, AppRoutes.paymentMethodsView, - arguments: PaymentTypes.appointment); + Future onConfirmAppointmentPressed({required BuildContext context, required appointmentId}) async { + context.read().updateAppointmentIdsForPayment(ids: [appointmentId]); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment); } - Future onCancelAppointmentPressed({required BuildContext context, - required AppointmentListModel appointmentListModel}) async { + Future onCancelAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async { Utils.showLoading(context); try { - GenericRespModel genericRespModel = - await scheduleRepo.cancelOrRescheduleServiceAppointment( + GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment( serviceAppointmentID: appointmentListModel.id ?? 0, serviceSlotID: appointmentListModel.serviceSlotID ?? 0, appointmentScheduleAction: 2, // 1 for Reschedule and 2 for Cancel ); - if (genericRespModel.messageStatus == 2 || - genericRespModel.data == null) { + if (genericRespModel.messageStatus == 2 || genericRespModel.data == null) { Utils.hideLoading(context); Utils.showToast("${genericRespModel.message.toString()}"); return; } if (genericRespModel.messageStatus == 1) { context.read().onNavbarTapped(1); - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.cancelled); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); Utils.showToast("${genericRespModel.message.toString()}"); await getMyAppointments(); Utils.hideLoading(context); @@ -227,8 +209,7 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - SelectionModel branchSelectedCategoryId = - SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); void updateProviderCategoryId(SelectionModel id) { branchSelectedCategoryId = id; @@ -247,37 +228,30 @@ class AppointmentsVM extends BaseVM { void updateBranchServiceId(SelectionModel id) async { branchSelectedServiceId = id; - currentServiceSelection = branchServices.firstWhere( - (element) => element.serviceProviderServiceId == id.selectedId); + currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId); notifyListeners(); } void removeServiceInCurrentAppointment(int index) { - int serviceId = servicesInCurrentAppointment - .elementAt(index) - .serviceProviderServiceId ?? - -1; - allSelectedItemsInAppointments.removeWhere( - (element) => element.serviceProviderServiceId == serviceId); + int serviceId = servicesInCurrentAppointment.elementAt(index).serviceProviderServiceId ?? -1; + allSelectedItemsInAppointments.removeWhere((element) => element.serviceProviderServiceId == serviceId); servicesInCurrentAppointment.removeAt(index); notifyListeners(); } resetCategorySelectionBottomSheet() { selectedSubServicesCounter = 0; - branchSelectedCategoryId = - SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); isHomeTapped = false; - branchSelectedServiceId = - SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); currentServiceSelection = null; } resetAfterBookingAppointment() { - allSelectedItemsInAppointments.clear(); - // servicesInCurrentAppointment.clear(); - serviceAppointmentScheduleList.clear(); + // allSelectedItemsInAppointments.clear(); + servicesInCurrentAppointment.clear(); + // serviceAppointmentScheduleList.clear(); } List myAppointmentsEnum = []; @@ -285,32 +259,28 @@ class AppointmentsVM extends BaseVM { populateAppointmentsFilterList() async { appointmentsFilterOptions.clear(); - myAppointmentsEnum = await commonRepo.getEnumTypeValues( - enumTypeID: 13); //TODO: 13 is to get Appointments Filter Enums + myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: 13); //TODO: 13 is to get Appointments Filter Enums for (int i = 0; i < myAppointmentsEnum.length; i++) { - appointmentsFilterOptions.add(FilterListModel( - title: myAppointmentsEnum[i].enumValueStr, - isSelected: false, - id: myAppointmentsEnum[i].enumValue)); + appointmentsFilterOptions.add(FilterListModel(title: myAppointmentsEnum[i].enumValueStr, isSelected: false, id: myAppointmentsEnum[i].enumValue)); } - appointmentsFilterOptions.insert( - 0, FilterListModel(title: "All Appointments", isSelected: true, id: 0)); + appointmentsFilterOptions.insert(0, FilterListModel(title: "All Appointments", isSelected: true, id: 0)); + + // TODO: THIS SHOULD REMOVED AND ADDED IN THE ENUMS API + appointmentsFilterOptions.add(FilterListModel(title: "Work In Progress", isSelected: false, id: 7)); + appointmentsFilterOptions.add(FilterListModel(title: "Visit Completed", isSelected: false, id: 8)); notifyListeners(); } - applyFilterOnAppointmentsVM( - {required AppointmentStatusEnum appointmentStatusEnum, - bool isNeedCustomerFilter = false}) { + applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) { if (appointmentsFilterOptions.isEmpty) return; for (var value in appointmentsFilterOptions) { value.isSelected = false; } appointmentsFilterOptions.forEach((element) { - if (element.id == - appointmentStatusEnum.getIdFromAppointmentStatusEnum()) { + if (element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()) { element.isSelected = true; } }); @@ -325,16 +295,11 @@ class AppointmentsVM extends BaseVM { return; } - myFilteredAppointments = myAppointments - .where((element) => - element.appointmentStatusID! == - appointmentStatusEnum.getIdFromAppointmentStatusEnum()) - .toList(); + myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList(); if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(); notifyListeners(); } - findAppointmentsBasedOnCustomers() { // Use a Set to ensure uniqueness of customerIDs Set uniqueCustomerIDs = Set(); @@ -346,9 +311,7 @@ class AppointmentsVM extends BaseVM { // Create a list of CustomerData instances myFilteredAppointments2 = uniqueCustomerIDs.map((id) { - List list = myFilteredAppointments - .where((item) => item.customerID == id) - .toList(); + List list = myFilteredAppointments.where((item) => item.customerID == id).toList(); AppointmentListModel model = list.first; model.customerAppointmentList = list; return model; @@ -373,10 +336,7 @@ class AppointmentsVM extends BaseVM { myAppointments = await commonRepo.getMyAppointments(); myFilteredAppointments = myAppointments; - myUpComingAppointments = myAppointments - .where((element) => - element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) - .toList(); + myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList(); setState(ViewState.idle); // applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); notifyListeners(); @@ -384,9 +344,7 @@ class AppointmentsVM extends BaseVM { AppointmentSlots? appointmentSlots; - Future getAppointmentSlotsInfo({required Map map, - required BuildContext context, - bool isNeedToRebuild = false}) async { + Future getAppointmentSlotsInfo({required Map map, required BuildContext context, bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { MResponse genericRespModel = await scheduleRepo.getAppointmentSlots(map); @@ -400,20 +358,14 @@ class AppointmentsVM extends BaseVM { } } - Future getProviderMyAppointments(Map map, - {bool isNeedToRebuild = false}) async { + Future getProviderMyAppointments(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); myAppointments = await scheduleRepo.getMyAppointments(map); myFilteredAppointments = myAppointments; - myUpComingAppointments = myAppointments - .where((element) => - element.appointmentStatusEnum == AppointmentStatusEnum.booked) - .toList(); - - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.allAppointments, - isNeedCustomerFilter: true); + myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked).toList(); + + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true); setState(ViewState.idle); } @@ -423,12 +375,10 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - updateAppointmentStatus(Map map, - {bool isNeedToRebuild = false}) async { + updateAppointmentStatus(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { - MResponse genericRespModel = - await scheduleRepo.updateAppointmentStatus(map); + MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map); if (genericRespModel.messageStatus == 1) { Utils.showToast("appointment status updated"); @@ -440,12 +390,10 @@ class AppointmentsVM extends BaseVM { } } - updateAppointmentPaymentStatus(Map map, - {bool isNeedToRebuild = false}) async { + updateAppointmentPaymentStatus(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { - MResponse genericRespModel = - await scheduleRepo.updateAppointmentPaymentStatus(map); + MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map); if (genericRespModel.messageStatus == 1) { Utils.showToast("payment status updated"); @@ -457,11 +405,9 @@ class AppointmentsVM extends BaseVM { } } - Future createMergeAppointment(Map map, - {bool isNeedToRebuild = false}) async { + Future createMergeAppointment(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); - MResponse genericRespModel = - await scheduleRepo.createMergeAppointment(map); + MResponse genericRespModel = await scheduleRepo.createMergeAppointment(map); return genericRespModel; } @@ -469,16 +415,10 @@ class AppointmentsVM extends BaseVM { bool inNeedToEnableMergeButton = false; updateCheckBoxInMergeRequest(int currentIndex) { - myFilteredAppointments2[selectedAppointmentIndex] - .customerAppointmentList![currentIndex] - .isSelected = !(myFilteredAppointments2[selectedAppointmentIndex] - .customerAppointmentList?[currentIndex] - .isSelected ?? - false); - - int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex] - .customerAppointmentList ?? - []); + myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected = + !(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false); + + int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []); if (count > 1) inNeedToEnableMergeButton = true; else @@ -487,61 +427,35 @@ class AppointmentsVM extends BaseVM { } int countSelected(List appointments) { - return appointments - .where((appointment) => appointment.isSelected == true) - .toList() - .length; + return appointments.where((appointment) => appointment.isSelected == true).toList().length; } - updateSelectedAppointmentDate( - {required int dateIndex, required int scheduleIndex}) { - for (var element in serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList!) { + updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) { + for (var element in serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!) { element.date!.isSelected = false; } - serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList![dateIndex] - .date! - .isSelected = true; + serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.isSelected = true; serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex = dateIndex; final date = TimeSlotModel( - date: serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList![dateIndex] - .date! - .date, - slotId: serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList![dateIndex] - .date! - .slotId, + date: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.date, + slotId: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.slotId, isSelected: true, slot: "", ); - serviceAppointmentScheduleList[scheduleIndex] - .selectedCustomTimeDateSlotModel = CustomTimeDateSlotModel(date: date); + serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel = CustomTimeDateSlotModel(date: date); notifyListeners(); } - updateSelectedAppointmentSlotByDate( - {required int scheduleIndex, required int slotIndex}) { - for (var element in serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList!) { + updateSelectedAppointmentSlotByDate({required int scheduleIndex, required int slotIndex}) { + for (var element in serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!) { for (var element in element.availableSlots!) { element.isSelected = false; } } - int index = - serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!; - serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList![index] - .availableSlots![slotIndex] - .isSelected = true; - serviceAppointmentScheduleList[scheduleIndex] - .selectedCustomTimeDateSlotModel! - .availableSlots = - serviceAppointmentScheduleList[scheduleIndex] - .customTimeDateSlotList![index] - .availableSlots!; + int index = serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!; + serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![index].availableSlots![slotIndex].isSelected = true; + serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel!.availableSlots = serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![index].availableSlots!; notifyListeners(); } @@ -555,9 +469,7 @@ class AppointmentsVM extends BaseVM { int selectedSubServicesCounter = 0; onItemUpdateOrSelected(int index, bool selected, int itemId) { - int serviceIndex = servicesInCurrentAppointment.indexWhere( - (element) => - element.serviceId == currentServiceSelection!.serviceId!); + int serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!); // print("servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}"); // if (serviceIndex == -1) { // return; @@ -572,28 +484,19 @@ class AppointmentsVM extends BaseVM { allSelectedItemsInAppointments.add(serviceItemsFromApi[index]); for (var element in allSelectedItemsInAppointments) { if (!ifItemAlreadySelected(element.id!)) { - servicesInCurrentAppointment[serviceIndex] - .serviceItems! - .add(serviceItemsFromApi[index]); + servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]); servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = - servicesInCurrentAppointment[serviceIndex] - .currentTotalServicePrice + - double.parse((serviceItemsFromApi[index].price) ?? "0.0"); + servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice + double.parse((serviceItemsFromApi[index].price) ?? "0.0"); } } } if (!selected) { selectedSubServicesCounter = selectedSubServicesCounter - 1; - currentServiceSelection!.serviceItems! - .removeWhere((element) => element.id == itemId); - allSelectedItemsInAppointments - .removeWhere((element) => element.id == itemId); + currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId); + allSelectedItemsInAppointments.removeWhere((element) => element.id == itemId); servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = - servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - - double.parse((serviceItemsFromApi[index].price) ?? "0.0"); - servicesInCurrentAppointment[serviceIndex] - .serviceItems! - .removeWhere((element) => element.id == itemId); + servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0"); + servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId); } notifyListeners(); } @@ -649,8 +552,7 @@ class AppointmentsVM extends BaseVM { String pickHomeLocationError = ""; String selectSubServicesError = ""; - SelectionModel branchSelectedServiceId = - SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); bool isCategoryAlreadyPresent(int id) { final contain = branchCategories.where((element) => element.id == id); @@ -663,16 +565,14 @@ class AppointmentsVM extends BaseVM { void getBranchCategories() async { for (var value in selectedBranchModel!.branchServices!) { if (!isCategoryAlreadyPresent(value.categoryId!)) { - branchCategories - .add(DropValue(value.categoryId!, value.categoryName!, "")); + branchCategories.add(DropValue(value.categoryId!, value.categoryName!, "")); } } notifyListeners(); } getBranchServices({required int categoryId}) async { - branchSelectedServiceId = - SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); isHomeTapped = false; pickedHomeLocation = ""; pickHomeLocationError = ""; @@ -685,9 +585,7 @@ class AppointmentsVM extends BaseVM { } List getFilteredBranchServices({required int categoryId}) { - List filteredServices = selectedBranchModel!.branchServices! - .where((element) => element.categoryId == categoryId) - .toList(); + List filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList(); return filteredServices; } @@ -729,8 +627,7 @@ class AppointmentsVM extends BaseVM { return totalPrice.toString(); } - void openTheAddServiceBottomSheet(BuildContext context, - AppointmentsVM appointmentsVM) { + void openTheAddServiceBottomSheet(BuildContext context, AppointmentsVM appointmentsVM) { showModalBottomSheet( context: context, isScrollControlled: true, @@ -741,8 +638,7 @@ class AppointmentsVM extends BaseVM { ); } - void priceBreakDownClicked(BuildContext context, - ServiceModel selectedService) { + void priceBreakDownClicked(BuildContext context, ServiceModel selectedService) { showModalBottomSheet( context: context, isScrollControlled: true, @@ -758,27 +654,19 @@ class AppointmentsVM extends BaseVM { Column( children: List.generate( selectedService.serviceItems!.length, - (index) => - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - "${selectedService.serviceItems![index].name}" - .toText( - fontSize: 12, - color: MyColors.lightTextColor, - isBold: true), - "${selectedService.serviceItems![index] - .price} SAR" - .toText(fontSize: 12, isBold: true), - ], - ), + (index) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + "${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true), + ], + ), ), ), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - "${selectedService.currentTotalServicePrice} SAR" - .toText(fontSize: 16, isBold: true), + "${selectedService.currentTotalServicePrice} SAR".toText(fontSize: 16, isBold: true), ], ), if (selectedService.isHomeSelected) ...[ @@ -787,20 +675,15 @@ class AppointmentsVM extends BaseVM { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "${totalKms}km ".toText( - fontSize: 12, - color: MyColors.lightTextColor, - isBold: true), - "${selectedService.rangePricePerKm} x $totalKms" - .toText(fontSize: 12, isBold: true), + "${totalKms}km ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + "${selectedService.rangePricePerKm} x $totalKms".toText(fontSize: 12, isBold: true), ], ), 8.height, Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - "${selectedService.rangePricePerKm ?? 0 * totalKms} SAR" - .toText(fontSize: 16, isBold: true), + "${selectedService.rangePricePerKm ?? 0 * totalKms} SAR".toText(fontSize: 16, isBold: true), ], ), ], @@ -813,18 +696,11 @@ class AppointmentsVM extends BaseVM { crossAxisAlignment: CrossAxisAlignment.end, children: [ (selectedService.isHomeSelected - ? "${(selectedService.currentTotalServicePrice) + - (double.parse((selectedService.rangePricePerKm ?? - "0.0")) * totalKms)}" - : "${selectedService.currentTotalServicePrice}") + ? "${(selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)}" + : "${selectedService.currentTotalServicePrice}") .toText(fontSize: 29, isBold: true), 2.width, - "SAR" - .toText( - color: MyColors.lightTextColor, - fontSize: 16, - isBold: true) - .paddingOnly(bottom: 5), + "SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5), ], ) ], @@ -844,8 +720,7 @@ class AppointmentsVM extends BaseVM { isValidated = false; break; } - if (schedule.selectedCustomTimeDateSlotModel!.date == null || - !schedule.selectedCustomTimeDateSlotModel!.date!.isSelected) { + if (schedule.selectedCustomTimeDateSlotModel!.date == null || !schedule.selectedCustomTimeDateSlotModel!.date!.isSelected) { isValidated = false; break; } else { @@ -853,9 +728,7 @@ class AppointmentsVM extends BaseVM { isValidated = false; break; } else { - TimeSlotModel slot = schedule - .selectedCustomTimeDateSlotModel!.availableSlots! - .firstWhere((element) => element.isSelected); + TimeSlotModel slot = schedule.selectedCustomTimeDateSlotModel!.availableSlots!.firstWhere((element) => element.isSelected); if (slot.date.isNotEmpty) { isValidated = true; break; @@ -864,8 +737,7 @@ class AppointmentsVM extends BaseVM { } } if (!isValidated) { - Utils.showToast( - "You must select appointment time for each schedule's appointment."); + Utils.showToast("You must select appointment time for each schedule's appointment."); return; } navigateWithName(context, AppRoutes.reviewAppointmentView); @@ -884,36 +756,30 @@ class AppointmentsVM extends BaseVM { } } - serviceAppointmentScheduleList = - await scheduleRepo.mergeServiceIntoAvailableSchedules( + serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules( serviceItemIdsForHome: serviceItemIdsForHome, serviceItemIdsForWorkshop: serviceItemIdsForWorkshop, ); if (serviceAppointmentScheduleList.isEmpty) { Utils.hideLoading(context); - Utils.showToast( - "There are no available appointments for selected Items."); + Utils.showToast("There are no available appointments for selected Items."); return; } totalAmount = 0.0; amountToPayForAppointment = 0.0; for (var schedule in serviceAppointmentScheduleList) { - amountToPayForAppointment = - amountToPayForAppointment + (schedule.amountToPay ?? 0.0); + amountToPayForAppointment = amountToPayForAppointment + (schedule.amountToPay ?? 0.0); totalAmount = totalAmount + (schedule.amountTotal ?? 0.0); } Utils.hideLoading(context); - navigateWithName(context, AppRoutes.bookAppointmenSchedulesView, - arguments: ScreenArgumentsForAppointmentDetailPage( - routeFlag: 1, appointmentId: 0)); // 1 For Creating an Appointment + navigateWithName(context, AppRoutes.bookAppointmenSchedulesView, arguments: ScreenArgumentsForAppointmentDetailPage(routeFlag: 1, appointmentId: 0)); // 1 For Creating an Appointment notifyListeners(); } - Future onRescheduleAppointmentPressed({required BuildContext context, - required AppointmentListModel appointmentListModel}) async { + Future onRescheduleAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async { Utils.showLoading(context); List serviceItemIdsForHome = []; @@ -930,16 +796,14 @@ class AppointmentsVM extends BaseVM { } } - serviceAppointmentScheduleList = - await scheduleRepo.mergeServiceIntoAvailableSchedules( + serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules( serviceItemIdsForHome: serviceItemIdsForHome, serviceItemIdsForWorkshop: serviceItemIdsForWorkshop, ); if (serviceAppointmentScheduleList.isEmpty) { Utils.hideLoading(context); - Utils.showToast( - "There are no available appointments for selected Items."); + Utils.showToast("There are no available appointments for selected Items."); return; } Utils.hideLoading(context); @@ -947,36 +811,29 @@ class AppointmentsVM extends BaseVM { navigateWithName( context, AppRoutes.bookAppointmenSchedulesView, - arguments: ScreenArgumentsForAppointmentDetailPage( - routeFlag: 2, appointmentId: appointmentListModel.id ?? 0), + arguments: ScreenArgumentsForAppointmentDetailPage(routeFlag: 2, appointmentId: appointmentListModel.id ?? 0), ); // 2 For Rescheduling an Appointment notifyListeners(); } - Future onRescheduleAppointmentConfirmPressed( - {required BuildContext context, - required int appointmentId, - required int selectedSlotId}) async { + Future onRescheduleAppointmentConfirmPressed({required BuildContext context, required int appointmentId, required int selectedSlotId}) async { Utils.showLoading(context); try { - GenericRespModel genericRespModel = - await scheduleRepo.cancelOrRescheduleServiceAppointment( + GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment( serviceAppointmentID: appointmentId, serviceSlotID: selectedSlotId, appointmentScheduleAction: 1, // 1 for Reschedule and 2 for Cancel ); - if (genericRespModel.messageStatus == 2 || - genericRespModel.data == null) { + if (genericRespModel.messageStatus == 2 || genericRespModel.data == null) { Utils.hideLoading(context); Utils.showToast("${genericRespModel.message.toString()}"); return; } if (genericRespModel.messageStatus == 1) { context.read().onNavbarTapped(1); - applyFilterOnAppointmentsVM( - appointmentStatusEnum: AppointmentStatusEnum.cancelled); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); Utils.showToast("${genericRespModel.message.toString()}"); getMyAppointments(); Utils.hideLoading(context); diff --git a/lib/view_models/payment_view_model.dart b/lib/view_models/payment_view_model.dart index 539731b..c3f9f9d 100644 --- a/lib/view_models/payment_view_model.dart +++ b/lib/view_models/payment_view_model.dart @@ -76,7 +76,7 @@ class PaymentVM extends ChangeNotifier { await Future.delayed(const Duration(seconds: 2)); Utils.hideLoading(context); - print("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}"); + log("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}"); if (payOrderDetailRespModel.isPaid == null || !payOrderDetailRespModel.isPaid!) { Utils.showToast("Payment Failed!"); @@ -96,7 +96,7 @@ class PaymentVM extends ChangeNotifier { await Future.delayed(const Duration(seconds: 2)); Utils.hideLoading(context); - print("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}"); + log("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}"); if (payOrderDetailRespModel.isPaid == null || !payOrderDetailRespModel.isPaid!) { Utils.showToast("Payment Failed!"); @@ -114,6 +114,7 @@ class PaymentVM extends ChangeNotifier { case PaymentTypes.subscription: return orderProviderSubscriptionId; case PaymentTypes.appointment: + case PaymentTypes.partialAppointment: return -1; case PaymentTypes.request: return requestId; @@ -151,10 +152,15 @@ class PaymentVM extends ChangeNotifier { break; case PaymentTypes.extendAds: // TODO: Handle this case. + break; + case PaymentTypes.partialAppointment: + log("Partial Appointment Payment has been Failed!!"); + break; } }, onSuccess: () async { + // TOD0: we have to take payment confirmation methods from Backend team and make success callbacks like onAdsPaymentSuccess switch (paymentTypeEnum) { case PaymentTypes.subscription: break; @@ -168,6 +174,9 @@ class PaymentVM extends ChangeNotifier { case PaymentTypes.extendAds: await onAdsPaymentSuccess(context: context, paymentTypeId: paymentTypeEnum.getIdFromPaymentTypesEnum(), currentAdId: currentAdId); break; + case PaymentTypes.partialAppointment: + log("Partial Appointment Payment has been Succeeded"); + break; } }, ); @@ -177,6 +186,7 @@ class PaymentVM extends ChangeNotifier { currentPaymentType = paymentType; switch (currentPaymentType) { case PaymentTypes.appointment: + case PaymentTypes.partialAppointment: if (appointmentIdsForPayment.isEmpty) return; await placeThePayment(context: context, paymentTypeEnum: paymentType); break; diff --git a/lib/views/advertisement/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view.dart index 47058c8..959eb15 100644 --- a/lib/views/advertisement/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; @@ -40,6 +41,7 @@ class AdsDetailView extends StatefulWidget { class _AdsDetailViewState extends State { @override void initState() { + log("ad: ${widget.adDetails.id}"); scheduleMicrotask(() { onAdDetailsLoaded(); }); diff --git a/lib/views/appointments/appointment_detail_view.dart b/lib/views/appointments/appointment_detail_view.dart index 1c1afe6..65402f0 100644 --- a/lib/views/appointments/appointment_detail_view.dart +++ b/lib/views/appointments/appointment_detail_view.dart @@ -33,6 +33,7 @@ class AppointmentDetailView extends StatelessWidget { } Widget getArrivedBottomActionButton({required BuildContext context, required AppointmentPaymentStatusEnum appointmentPaymentStatusEnum}) { + final appointmentVM = context.read(); switch (appointmentPaymentStatusEnum) { case AppointmentPaymentStatusEnum.defaultStatus: case AppointmentPaymentStatusEnum.paid: @@ -42,19 +43,34 @@ class AppointmentDetailView extends StatelessWidget { alignment: Alignment.bottomCenter, child: Row( children: [ - getBaseActionButtonWidget(color: MyColors.grey98Color.withOpacity(0.3), textColor: MyColors.lightTextColor, onPressed: () {}, text: "In Progress"), + getBaseActionButtonWidget( + color: MyColors.grey98Color.withOpacity(0.3), + textColor: MyColors.lightTextColor, + onPressed: () {}, + text: "Work In Progress", + ), ], ), ); case AppointmentPaymentStatusEnum.payNow: - return Expanded( - child: ShowFillButton( - maxHeight: 55, - title: "Pay Now", - onPressed: () {}, - backgroundColor: MyColors.darkPrimaryColor, - txtColor: MyColors.white, - fontSize: 18, + 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: "Pay Now", + ), + ], ), ); } @@ -87,7 +103,23 @@ class AppointmentDetailView extends StatelessWidget { ], ), ); + case AppointmentStatusEnum.visitCompleted: + return Align( + alignment: Alignment.bottomCenter, + child: Row( + children: [ + getBaseActionButtonWidget( + color: MyColors.grey98Color.withOpacity(0.3), + textColor: MyColors.lightTextColor, + onPressed: () {}, + text: "Visit Completed", + ), + ], + ), + ); + case AppointmentStatusEnum.arrived: + case AppointmentStatusEnum.workStarted: return getArrivedBottomActionButton(appointmentPaymentStatusEnum: appointmentListModel.appointmentPaymentStatusEnum ?? AppointmentPaymentStatusEnum.defaultStatus, context: context); case AppointmentStatusEnum.cancelled: return Align( @@ -223,10 +255,7 @@ class AppointmentDetailView extends StatelessWidget { ((service.currentTotalServicePrice).toString()).toText(fontSize: 25, isBold: true), 2.width, "SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5), - Icon( - Icons.arrow_drop_down, - size: 30, - ) + const Icon(Icons.arrow_drop_down, size: 30) ], ).onPress(() => appointmentsVM.priceBreakDownClicked(context, service)), ], @@ -235,28 +264,30 @@ class AppointmentDetailView extends StatelessWidget { ), ], 15.height, - Row( - children: [ - CardButtonWithIcon( - title: "Reschedule Appointment", - onCardTapped: () { - context.read().onRescheduleAppointmentPressed(context: context, appointmentListModel: appointmentListModel); - }, - icon: MyAssets.scheduleAppointmentIcon.buildSvg(), - ), - if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked) ...[ - 10.width, + if (appointmentListModel.appointmentStatusEnum != AppointmentStatusEnum.workStarted && appointmentListModel.appointmentStatusEnum != AppointmentStatusEnum.visitCompleted) ...[ + Row( + children: [ CardButtonWithIcon( - title: "Pay for Appointment", + title: "Reschedule Appointment", onCardTapped: () { - context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); + context.read().onRescheduleAppointmentPressed(context: context, appointmentListModel: appointmentListModel); }, - icon: MyAssets.creditCardIcon.buildSvg(), + icon: MyAssets.scheduleAppointmentIcon.buildSvg(), ), + if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked) ...[ + 10.width, + CardButtonWithIcon( + title: "Pay for Appointment", + onCardTapped: () { + context.read().onConfirmAppointmentPressed(context: context, appointmentId: appointmentListModel.id); + }, + icon: MyAssets.creditCardIcon.buildSvg(), + ), + ], ], - ], - ), - 15.height, + ), + 15.height, + ], ], ).toWhiteContainer(width: double.infinity, allPading: 12), buildBottomActionButton(appointmentStatusEnum: appointmentListModel.appointmentStatusEnum!, context: context),