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.
		
		
		
		
		
			
		
			
				
	
	
		
			1406 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			1406 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Dart
		
	
import 'dart:developer';
 | 
						|
 | 
						|
import 'package:flutter/material.dart';
 | 
						|
import 'package:mc_common_app/classes/consts.dart';
 | 
						|
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/appointment_slots.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/profile/categroy.dart';
 | 
						|
import 'package:mc_common_app/models/provider_branches_models/profile/services.dart';
 | 
						|
import 'package:mc_common_app/models/provider_branches_models/provider_model.dart';
 | 
						|
import 'package:mc_common_app/models/provider_branches_models/provider_profile_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/repositories/appointment_repo.dart';
 | 
						|
import 'package:mc_common_app/repositories/branch_repo.dart';
 | 
						|
import 'package:mc_common_app/repositories/common_repo.dart';
 | 
						|
import 'package:mc_common_app/services/common_services.dart';
 | 
						|
import 'package:mc_common_app/theme/colors.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/base_view_model.dart';
 | 
						|
import 'package:mc_common_app/view_models/dashboard_view_model_customer.dart';
 | 
						|
import 'package:mc_common_app/view_models/payment_view_model.dart';
 | 
						|
import 'package:mc_common_app/views/appointments/book_appointment_schedules_view.dart';
 | 
						|
import 'package:mc_common_app/views/appointments/widgets/appointment_service_pick_bottom_sheet.dart';
 | 
						|
import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart';
 | 
						|
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
 | 
						|
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
 | 
						|
import 'package:provider/provider.dart';
 | 
						|
 | 
						|
class AppointmentsVM extends BaseVM {
 | 
						|
  final CommonRepo commonRepo;
 | 
						|
  final CommonAppServices commonServices;
 | 
						|
  final BranchRepo branchRepo;
 | 
						|
  final AppointmentRepo appointmentRepo;
 | 
						|
 | 
						|
  AppointmentsVM({required this.commonServices, required this.appointmentRepo, required this.commonRepo, required this.branchRepo});
 | 
						|
 | 
						|
  bool isUpcommingEnabled = true;
 | 
						|
  bool isFetchingLists = false;
 | 
						|
  int selectedBranch = 0;
 | 
						|
  int selectedAppointmentIndex = 0;
 | 
						|
  int selectedAppointmentSubIndex = 0;
 | 
						|
  int selectedAppointmentId = 0;
 | 
						|
 | 
						|
  List<AppointmentListModel> myAppointments = [];
 | 
						|
  List<AppointmentListModel> myUpComingAppointments = [];
 | 
						|
  List<AppointmentListModel> myFilteredAppointments = [];
 | 
						|
  List<FilterListModel> appointmentsFilterOptions = [];
 | 
						|
  List<CustomerData> customersAppointments = [];
 | 
						|
  List<AppointmentListModel> myFilteredAppointments2 = [];
 | 
						|
 | 
						|
  // List<ScheduleData> availableSchedules = [];
 | 
						|
 | 
						|
  bool isFetchingServices = false;
 | 
						|
 | 
						|
  List<DropValue> branchCategories = [];
 | 
						|
 | 
						|
  bool isHomeTapped = false;
 | 
						|
 | 
						|
  List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleList = [];
 | 
						|
 | 
						|
  bool ifItemAlreadySelected(int id) {
 | 
						|
    int indexFound = allSelectedItemsInAppointments.indexWhere((element) => element.id == id);
 | 
						|
    if (indexFound != -1) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  List<ItemData> allSelectedItemsInAppointments = [];
 | 
						|
 | 
						|
  // 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));
 | 
						|
  // }
 | 
						|
 | 
						|
  Future<void> onItemsSelectedInService() async {
 | 
						|
    if (currentServiceSelection != null) {
 | 
						|
      int index = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
 | 
						|
 | 
						|
      if (index == -1) {
 | 
						|
        double totalPrice = 0.0;
 | 
						|
        for (var element in currentServiceSelection!.serviceItems!) {
 | 
						|
          totalPrice = totalPrice + double.parse(element.price ?? "0.0");
 | 
						|
        }
 | 
						|
        currentServiceSelection!.currentTotalServicePrice = totalPrice;
 | 
						|
        servicesInCurrentAppointment.insert(0, currentServiceSelection!);
 | 
						|
      }
 | 
						|
 | 
						|
      resetCategorySelectionBottomSheet();
 | 
						|
      notifyListeners();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> onPayNowPressedForAppointment({required BuildContext context, required int appointmentID}) async {
 | 
						|
    context.read<PaymentVM>().updateAppointmentIdsForPayment(ids: [appointmentID]);
 | 
						|
    navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.partialAppointment);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> onBookAppointmentPressed(BuildContext context) async {
 | 
						|
    Utils.showLoading(context);
 | 
						|
    bool isSuccess = false;
 | 
						|
    List<int> appointmentIdsList = [];
 | 
						|
    try {
 | 
						|
      GenericRespModel genericRespModel = await appointmentRepo.createServiceAppointment(
 | 
						|
        schedules: serviceAppointmentScheduleList,
 | 
						|
        serviceProviderID: selectedBranchModel!.serviceProviderId ?? 0,
 | 
						|
      );
 | 
						|
 | 
						|
      if (genericRespModel.data.isEmpty) {
 | 
						|
        Utils.hideLoading(context);
 | 
						|
        Utils.showToast("${genericRespModel.message.toString()}");
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      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<DashboardVmCustomer>().onNavbarTapped(1);
 | 
						|
      applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.booked);
 | 
						|
      Utils.hideLoading(context);
 | 
						|
      resetAfterBookingAppointment();
 | 
						|
      if (isSuccess) {
 | 
						|
        if (amountToPayForAppointment > 0) {
 | 
						|
          context.read<PaymentVM>().updateAppointmentIdsForPayment(ids: appointmentIdsList);
 | 
						|
          navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment);
 | 
						|
        } else {
 | 
						|
          Utils.showToast("Your appointment has been booked successfully!");
 | 
						|
          getMyAppointments();
 | 
						|
          navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Utils.showToast("${e.toString()}");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> onConfirmAppointmentPressed({required BuildContext context, required appointmentId}) async {
 | 
						|
    context.read<PaymentVM>().updateAppointmentIdsForPayment(ids: [appointmentId]);
 | 
						|
    navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> onCancelAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async {
 | 
						|
    Utils.showLoading(context);
 | 
						|
    try {
 | 
						|
      GenericRespModel genericRespModel = await appointmentRepo.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) {
 | 
						|
        Utils.hideLoading(context);
 | 
						|
        Utils.showToast("${genericRespModel.message.toString()}");
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (genericRespModel.messageStatus == 1) {
 | 
						|
        context.read<DashboardVmCustomer>().onNavbarTapped(1);
 | 
						|
        applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled);
 | 
						|
        Utils.showToast("${genericRespModel.message.toString()}");
 | 
						|
        await getMyAppointments();
 | 
						|
        Utils.hideLoading(context);
 | 
						|
        getMyAppointments();
 | 
						|
        navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Utils.showToast("${e.toString()}");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void updateIsHomeTapped(bool value) {
 | 
						|
    isHomeTapped = value;
 | 
						|
    if (currentServiceSelection != null) {
 | 
						|
      currentServiceSelection!.isHomeSelected = value;
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  String pickedHomeLocation = "";
 | 
						|
 | 
						|
  void updatePickedHomeLocation(String value) {
 | 
						|
    pickedHomeLocation = value;
 | 
						|
    pickHomeLocationError = "";
 | 
						|
    if (currentServiceSelection != null) {
 | 
						|
      currentServiceSelection!.homeLocation = value;
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateProviderCategoryId(SelectionModel id) {
 | 
						|
    branchSelectedCategoryId = id;
 | 
						|
    getBranchServices(categoryId: branchSelectedCategoryId.selectedId);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  List<FilterListModel> branchesFilterOptions = [];
 | 
						|
 | 
						|
  List<ServiceModel> servicesInCurrentAppointment = [];
 | 
						|
  ServiceModel? currentServiceSelection;
 | 
						|
 | 
						|
  void updateBranchServiceId(SelectionModel id) async {
 | 
						|
    branchSelectedServiceId = id;
 | 
						|
    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);
 | 
						|
    servicesInCurrentAppointment.removeAt(index);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  resetCategorySelectionBottomSheet() {
 | 
						|
    selectedSubServicesCounter = 0;
 | 
						|
    branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    isHomeTapped = false;
 | 
						|
    branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    currentServiceSelection = null;
 | 
						|
  }
 | 
						|
 | 
						|
  resetAfterBookingAppointment() {
 | 
						|
    // allSelectedItemsInAppointments.clear();
 | 
						|
    servicesInCurrentAppointment.clear();
 | 
						|
    // serviceAppointmentScheduleList.clear();
 | 
						|
  }
 | 
						|
 | 
						|
  List<EnumsModel> myAppointmentsEnum = [];
 | 
						|
 | 
						|
  Future<void> populateAppointmentsFilterList() async {
 | 
						|
    if (appointmentsFilterOptions.isNotEmpty) return;
 | 
						|
 | 
						|
    myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: 13); // 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.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}) {
 | 
						|
    // isNeedCustomerFilter IS ONLY FOR THE PROVIDER APP
 | 
						|
    if (appointmentsFilterOptions.isEmpty) return;
 | 
						|
    for (var value in appointmentsFilterOptions) {
 | 
						|
      value.isSelected = false;
 | 
						|
    }
 | 
						|
 | 
						|
    for (var element in appointmentsFilterOptions) {
 | 
						|
      if (element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()) {
 | 
						|
        element.isSelected = true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // appointmentsFilterOptions[
 | 
						|
    // appointmentStatusEnum.getIdFromAppointmentStatusEnum()]
 | 
						|
    //     .isSelected = true;
 | 
						|
 | 
						|
    if (appointmentStatusEnum.getIdFromAppointmentStatusEnum() == 0) {
 | 
						|
      myFilteredAppointments = myAppointments;
 | 
						|
      if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList();
 | 
						|
    if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers();
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  findAppointmentsBasedOnCustomers() {
 | 
						|
    // Use a Set to ensure uniqueness of customerIDs
 | 
						|
    Set<int> uniqueCustomerIDs = <int>{};
 | 
						|
 | 
						|
    // Extract unique customerIDs
 | 
						|
    for (var item in myFilteredAppointments) {
 | 
						|
      uniqueCustomerIDs.add(item.customerID ?? 0);
 | 
						|
    }
 | 
						|
 | 
						|
    // Create a list of CustomerData instances
 | 
						|
    myFilteredAppointments2 = uniqueCustomerIDs.map((id) {
 | 
						|
      List<AppointmentListModel> list = myFilteredAppointments.where((item) => item.customerID == id).toList();
 | 
						|
      AppointmentListModel model = list.first;
 | 
						|
      model.customerAppointmentList = list;
 | 
						|
      return model;
 | 
						|
    }).toList();
 | 
						|
    // customersAppointments = uniqueCustomerIDs.map((id) {
 | 
						|
    //   List<AppointmentListModel> list = myFilteredAppointments
 | 
						|
    //       .where((item) => item.customerID == id)
 | 
						|
    //       .toList();
 | 
						|
    //   var customerItem =
 | 
						|
    //       myFilteredAppointments.firstWhere((item) => item.customerID == id);
 | 
						|
    //
 | 
						|
    //   return CustomerData(
 | 
						|
    //     customerID: id,
 | 
						|
    //     customerName: customerItem.customerName ?? "",
 | 
						|
    //     appointmentList: list,
 | 
						|
    //   );
 | 
						|
    // }).toList();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> getMyAppointments({bool isNeedToRebuild = false}) async {
 | 
						|
    if (isNeedToRebuild) setState(ViewState.busy);
 | 
						|
 | 
						|
    myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters();
 | 
						|
    // myFilteredAppointments = myAppointments;
 | 
						|
    myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList();
 | 
						|
    setState(ViewState.idle);
 | 
						|
    applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  AppointmentSlots? appointmentSlots;
 | 
						|
 | 
						|
  Future<void> getAppointmentSlotsInfo({required Map<String, dynamic> map, required BuildContext context, bool isNeedToRebuild = false}) async {
 | 
						|
    if (isNeedToRebuild) setState(ViewState.busy);
 | 
						|
    try {
 | 
						|
      MResponse genericRespModel = await appointmentRepo.getAppointmentSlots(map);
 | 
						|
      if (genericRespModel.messageStatus == 1) {
 | 
						|
        appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data);
 | 
						|
      } else {
 | 
						|
        Utils.showToast(genericRespModel.message.toString());
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Utils.showToast(e.toString());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> getMyAppointmentsForProvider(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
 | 
						|
    if (isNeedToRebuild) setState(ViewState.busy);
 | 
						|
 | 
						|
    myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map);
 | 
						|
    myFilteredAppointments = myAppointments;
 | 
						|
    myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked).toList();
 | 
						|
 | 
						|
    applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  updateAppointmentStatus(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
 | 
						|
    if (isNeedToRebuild) setState(ViewState.busy);
 | 
						|
    try {
 | 
						|
      MResponse genericRespModel = await appointmentRepo.updateAppointmentStatus(map);
 | 
						|
 | 
						|
      if (genericRespModel.messageStatus == 1) {
 | 
						|
        Utils.showToast("appointment status updated");
 | 
						|
      } else {
 | 
						|
        Utils.showToast(genericRespModel.message.toString());
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Utils.showToast(e.toString());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  updateAppointmentPaymentStatus(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
 | 
						|
    if (isNeedToRebuild) setState(ViewState.busy);
 | 
						|
    try {
 | 
						|
      MResponse genericRespModel = await appointmentRepo.updateAppointmentPaymentStatus(map);
 | 
						|
 | 
						|
      if (genericRespModel.messageStatus == 1) {
 | 
						|
        Utils.showToast("payment status updated");
 | 
						|
      } else {
 | 
						|
        Utils.showToast(genericRespModel.message.toString());
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Utils.showToast(e.toString());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Future<MResponse> createMergeAppointment(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
 | 
						|
    if (isNeedToRebuild) setState(ViewState.busy);
 | 
						|
    MResponse genericRespModel = await appointmentRepo.createMergeAppointment(map);
 | 
						|
 | 
						|
    return genericRespModel;
 | 
						|
  }
 | 
						|
 | 
						|
  bool inNeedToEnableMergeButton = false;
 | 
						|
 | 
						|
  updateCheckBoxInMergeRequest(int currentIndex) {
 | 
						|
    myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected =
 | 
						|
        !(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
 | 
						|
 | 
						|
    int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []);
 | 
						|
    if (count > 1)
 | 
						|
      inNeedToEnableMergeButton = true;
 | 
						|
    else
 | 
						|
      inNeedToEnableMergeButton = false;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  int countSelected(List<AppointmentListModel> appointments) {
 | 
						|
    return appointments.where((appointment) => appointment.isSelected == true).toList().length;
 | 
						|
  }
 | 
						|
 | 
						|
  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].selectedDateIndex = dateIndex;
 | 
						|
    final date = TimeSlotModel(
 | 
						|
      date: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.date,
 | 
						|
      slotId: serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].date!.slotId,
 | 
						|
      isSelected: true,
 | 
						|
      slot: "",
 | 
						|
    );
 | 
						|
    serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel = CustomTimeDateSlotModel(date: date);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  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!;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  double amountToPayForAppointment = 0.0;
 | 
						|
  double totalAmount = 0.0;
 | 
						|
 | 
						|
  List<ItemData> serviceItemsFromApi = [];
 | 
						|
 | 
						|
  ProviderProfileModel? providerProfileModel;
 | 
						|
 | 
						|
  int selectedSubServicesCounter = 0;
 | 
						|
 | 
						|
  onItemUpdateOrSelected(int index, bool selected, int itemId) {
 | 
						|
    int serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
 | 
						|
    // print("servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
 | 
						|
    // if (serviceIndex == -1) {
 | 
						|
    //   return;
 | 
						|
    // }
 | 
						|
 | 
						|
    serviceItemsFromApi[index].isUpdateOrSelected = selected;
 | 
						|
    serviceItemsFromApi[index].isHomeSelected = isHomeTapped;
 | 
						|
    if (selected) {
 | 
						|
      selectedSubServicesCounter = selectedSubServicesCounter + 1;
 | 
						|
      selectSubServicesError = "";
 | 
						|
      currentServiceSelection!.serviceItems!.add(serviceItemsFromApi[index]);
 | 
						|
      allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
 | 
						|
      for (var element in allSelectedItemsInAppointments) {
 | 
						|
        if (!ifItemAlreadySelected(element.id!)) {
 | 
						|
          servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]);
 | 
						|
          servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
 | 
						|
              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);
 | 
						|
      servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
 | 
						|
          servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0");
 | 
						|
      servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId);
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> applyFilterOnBranches({required int index}) async {
 | 
						|
    if (branchesFilterOptions.isEmpty) return;
 | 
						|
    for (var value in branchesFilterOptions) {
 | 
						|
      value.isSelected = false;
 | 
						|
    }
 | 
						|
    branchesFilterOptions[index].isSelected = true;
 | 
						|
 | 
						|
    await getBranchesBasedOnCategoryFilters(categoryId: branchesFilterOptions[index].id);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<List<ItemData>> getServiceItems(int serviceId) async {
 | 
						|
    serviceItemsFromApi.clear();
 | 
						|
    serviceItemsFromApi = await branchRepo.getServiceItems(serviceId);
 | 
						|
    for (var item in serviceItemsFromApi) {
 | 
						|
      if (ifItemAlreadySelected(item.id!)) {
 | 
						|
        item.isUpdateOrSelected = true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    setState(ViewState.idle);
 | 
						|
    return serviceItemsFromApi;
 | 
						|
  }
 | 
						|
 | 
						|
  String pickHomeLocationError = "";
 | 
						|
  String selectSubServicesError = "";
 | 
						|
 | 
						|
  SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updatePickHomeLocationError(String value) {
 | 
						|
    pickHomeLocationError = value;
 | 
						|
    // notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  bool isServiceSelectionValidated() {
 | 
						|
    if (branchSelectedServiceId.selectedId == -1) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isHomeTapped) {
 | 
						|
      if (pickedHomeLocation == "") {
 | 
						|
        updatePickHomeLocationError(GlobalConsts.homeLocationEmptyError);
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  bool validateItemsSelection() {
 | 
						|
    for (var value in serviceItemsFromApi) {
 | 
						|
      if (value.isUpdateOrSelected!) {
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    selectSubServicesError = "Please select at least one sub service";
 | 
						|
    notifyListeners();
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  String getTotalPrice(List<ServiceModel> serviceItems) {
 | 
						|
    var totalPrice = 0.0;
 | 
						|
    for (var element in serviceItems) {
 | 
						|
      totalPrice = totalPrice + (element.currentTotalServicePrice);
 | 
						|
    }
 | 
						|
    return totalPrice.toString();
 | 
						|
  }
 | 
						|
 | 
						|
  void openTheAddServiceBottomSheet(BuildContext context, AppointmentsVM appointmentsVM) {
 | 
						|
    showModalBottomSheet(
 | 
						|
      context: context,
 | 
						|
      isScrollControlled: true,
 | 
						|
      enableDrag: true,
 | 
						|
      builder: (BuildContext context) {
 | 
						|
        return AppointmentServicePickBottomSheet();
 | 
						|
      },
 | 
						|
    );
 | 
						|
  }
 | 
						|
 | 
						|
  void priceBreakDownClicked(BuildContext context, ServiceModel selectedService) {
 | 
						|
    showModalBottomSheet(
 | 
						|
        context: context,
 | 
						|
        isScrollControlled: true,
 | 
						|
        enableDrag: true,
 | 
						|
        builder: (BuildContext context) {
 | 
						|
          double totalKms = 15.3;
 | 
						|
          return InfoBottomSheet(
 | 
						|
              title: "Charges Breakdown".toText(fontSize: 24, isBold: true),
 | 
						|
              description: Column(
 | 
						|
                crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
                children: [
 | 
						|
                  "Services".toText(fontSize: 16, isBold: true),
 | 
						|
                  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),
 | 
						|
                        ],
 | 
						|
                      ),
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
                  Row(
 | 
						|
                    mainAxisAlignment: MainAxisAlignment.end,
 | 
						|
                    children: [
 | 
						|
                      "${selectedService.currentTotalServicePrice} SAR".toText(fontSize: 16, isBold: true),
 | 
						|
                    ],
 | 
						|
                  ),
 | 
						|
                  if (selectedService.isHomeSelected) ...[
 | 
						|
                    20.height,
 | 
						|
                    "Home Location".toText(fontSize: 16, isBold: true),
 | 
						|
                    Row(
 | 
						|
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
						|
                      children: [
 | 
						|
                        "${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),
 | 
						|
                      ],
 | 
						|
                    ),
 | 
						|
                  ],
 | 
						|
                  30.height,
 | 
						|
                  Row(
 | 
						|
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
						|
                    children: [
 | 
						|
                      "Total Amount ".toText(fontSize: 16, isBold: true),
 | 
						|
                      Row(
 | 
						|
                        crossAxisAlignment: CrossAxisAlignment.end,
 | 
						|
                        children: [
 | 
						|
                          (selectedService.isHomeSelected
 | 
						|
                                  ? "${(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),
 | 
						|
                        ],
 | 
						|
                      )
 | 
						|
                    ],
 | 
						|
                  ),
 | 
						|
                  30.height,
 | 
						|
                ],
 | 
						|
              ));
 | 
						|
        });
 | 
						|
  }
 | 
						|
 | 
						|
  void onReviewButtonPressed(BuildContext context) {
 | 
						|
    bool isValidated = false;
 | 
						|
 | 
						|
    for (int i = 0; i < serviceAppointmentScheduleList.length; i++) {
 | 
						|
      final schedule = serviceAppointmentScheduleList[i];
 | 
						|
      if (schedule.selectedCustomTimeDateSlotModel == null) {
 | 
						|
        isValidated = false;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      if (schedule.selectedCustomTimeDateSlotModel!.date == null || !schedule.selectedCustomTimeDateSlotModel!.date!.isSelected) {
 | 
						|
        isValidated = false;
 | 
						|
        break;
 | 
						|
      } else {
 | 
						|
        if (schedule.selectedCustomTimeDateSlotModel!.availableSlots == null) {
 | 
						|
          isValidated = false;
 | 
						|
          break;
 | 
						|
        } else {
 | 
						|
          TimeSlotModel slot = schedule.selectedCustomTimeDateSlotModel!.availableSlots!.firstWhere((element) => element.isSelected);
 | 
						|
          if (slot.date.isNotEmpty) {
 | 
						|
            isValidated = true;
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if (!isValidated) {
 | 
						|
      Utils.showToast("You must select appointment time for each schedule's appointment.");
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    navigateWithName(context, AppRoutes.reviewAppointmentView);
 | 
						|
  }
 | 
						|
 | 
						|
  void onServicesNextPressed(BuildContext context) async {
 | 
						|
    Utils.showLoading(context);
 | 
						|
 | 
						|
    List<String> serviceItemIdsForHome = [];
 | 
						|
    List<String> serviceItemIdsForWorkshop = [];
 | 
						|
    for (var serviceItem in allSelectedItemsInAppointments) {
 | 
						|
      if (serviceItem.isHomeSelected!) {
 | 
						|
        serviceItemIdsForHome.add(serviceItem.id!.toString());
 | 
						|
      } else {
 | 
						|
        serviceItemIdsForWorkshop.add(serviceItem.id!.toString());
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    serviceAppointmentScheduleList = await appointmentRepo.mergeServiceIntoAvailableSchedules(
 | 
						|
      serviceItemIdsForHome: serviceItemIdsForHome,
 | 
						|
      serviceItemIdsForWorkshop: serviceItemIdsForWorkshop,
 | 
						|
    );
 | 
						|
 | 
						|
    if (serviceAppointmentScheduleList.isEmpty) {
 | 
						|
      Utils.hideLoading(context);
 | 
						|
      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);
 | 
						|
      totalAmount = totalAmount + (schedule.amountTotal ?? 0.0);
 | 
						|
    }
 | 
						|
    Utils.hideLoading(context);
 | 
						|
 | 
						|
    navigateWithName(context, AppRoutes.bookAppointmenSchedulesView, arguments: ScreenArgumentsForAppointmentDetailPage(routeFlag: 1, appointmentId: 0)); // 1 For Creating an Appointment
 | 
						|
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> onRescheduleAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async {
 | 
						|
    Utils.showLoading(context);
 | 
						|
 | 
						|
    List<String> serviceItemIdsForHome = [];
 | 
						|
    List<String> serviceItemIdsForWorkshop = [];
 | 
						|
    for (var service in appointmentListModel.appointmentServicesList!) {
 | 
						|
      for (var serviceItem in service.serviceItems!) {
 | 
						|
        serviceItemIdsForWorkshop.add(serviceItem.id!.toString());
 | 
						|
 | 
						|
        // if (serviceItem.isHomeSelected ?? false) {
 | 
						|
        //   serviceItemIdsForHome.add(serviceItem.id!.toString());
 | 
						|
        // } else {
 | 
						|
        //   serviceItemIdsForWorkshop.add(serviceItem.id!.toString());
 | 
						|
        // }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    serviceAppointmentScheduleList = await appointmentRepo.mergeServiceIntoAvailableSchedules(
 | 
						|
      serviceItemIdsForHome: serviceItemIdsForHome,
 | 
						|
      serviceItemIdsForWorkshop: serviceItemIdsForWorkshop,
 | 
						|
    );
 | 
						|
 | 
						|
    if (serviceAppointmentScheduleList.isEmpty) {
 | 
						|
      Utils.hideLoading(context);
 | 
						|
      Utils.showToast("There are no available appointments for selected Items.");
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    Utils.hideLoading(context);
 | 
						|
 | 
						|
    navigateWithName(
 | 
						|
      context,
 | 
						|
      AppRoutes.bookAppointmenSchedulesView,
 | 
						|
      arguments: ScreenArgumentsForAppointmentDetailPage(routeFlag: 2, appointmentId: appointmentListModel.id ?? 0),
 | 
						|
    ); // 2 For Rescheduling an Appointment
 | 
						|
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> onRescheduleAppointmentConfirmPressed({required BuildContext context, required int appointmentId, required int selectedSlotId}) async {
 | 
						|
    Utils.showLoading(context);
 | 
						|
    try {
 | 
						|
      GenericRespModel genericRespModel = await appointmentRepo.cancelOrRescheduleServiceAppointment(
 | 
						|
        serviceAppointmentID: appointmentId,
 | 
						|
        serviceSlotID: selectedSlotId,
 | 
						|
        appointmentScheduleAction: 1, // 1 for Reschedule and 2 for Cancel
 | 
						|
      );
 | 
						|
 | 
						|
      if (genericRespModel.messageStatus == 2 || genericRespModel.data == null) {
 | 
						|
        Utils.hideLoading(context);
 | 
						|
        Utils.showToast("${genericRespModel.message.toString()}");
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (genericRespModel.messageStatus == 1) {
 | 
						|
        context.read<DashboardVmCustomer>().onNavbarTapped(1);
 | 
						|
        applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled);
 | 
						|
        Utils.showToast("${genericRespModel.message.toString()}");
 | 
						|
        getMyAppointments();
 | 
						|
        Utils.hideLoading(context);
 | 
						|
        navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      Utils.showToast("${e.toString()}");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // BRANCHES RELATED
 | 
						|
 | 
						|
  List<BranchDetailModel> nearbyBranches = [];
 | 
						|
  BranchDetailModel? selectedBranchModel;
 | 
						|
 | 
						|
  List<ServiceModel> branchServices = [];
 | 
						|
 | 
						|
  // populateBranchesFilterList() {
 | 
						|
  //   branchesFilterOptions.clear(); // TODO: THIS SHOULD BE DYNAMIC AND FILTERS SHOULD COME FORM API
 | 
						|
  //   branchesFilterOptions = [
 | 
						|
  //     FilterListModel(title: "All Branches", isSelected: true, id: 0),
 | 
						|
  //     FilterListModel(title: "Maintenance", isSelected: false, id: 1),
 | 
						|
  //     FilterListModel(title: "Oil Service", isSelected: false, id: 2),
 | 
						|
  //     FilterListModel(title: "Accessories", isSelected: false, id: 3),
 | 
						|
  //     FilterListModel(title: "Tire Service", isSelected: false, id: 4),
 | 
						|
  //     FilterListModel(title: "Dent and Paint", isSelected: false, id: 5),
 | 
						|
  //   ];
 | 
						|
  //   notifyListeners();
 | 
						|
  // }
 | 
						|
 | 
						|
  Future<void> populateBranchesFilterList() async {
 | 
						|
    if (branchesFilterOptions.isNotEmpty) return;
 | 
						|
    branchesFilterOptions.clear();
 | 
						|
    setOnlyState(ViewState.busy);
 | 
						|
    Category category = await branchRepo.fetchBranchCategory();
 | 
						|
    category.data?.forEach((element) {
 | 
						|
      branchesFilterOptions.add(FilterListModel(id: element.id ?? 0, isSelected: false, title: element.categoryName ?? "N/A"));
 | 
						|
    });
 | 
						|
    branchesFilterOptions.insert(0, FilterListModel(id: 0, isSelected: true, title: "All Branches"));
 | 
						|
    notifyListeners();
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> getAllNearBranches({bool isNeedToRebuild = false, bool isFromRefresh = false}) async {
 | 
						|
    nearbyBranches.clear();
 | 
						|
    if (isNeedToRebuild) setState(ViewState.busy);
 | 
						|
 | 
						|
    if (isFromRefresh) {
 | 
						|
      var selectedBranch = branchesFilterOptions.firstWhere((element) => element.isSelected);
 | 
						|
      nearbyBranches = await branchRepo.getBranchesByFilters(categoryIdsList: [selectedBranch.id]);
 | 
						|
      setState(ViewState.idle);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    nearbyBranches = await branchRepo.getAllNearBranchAndServices();
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  void getBranchCategories() async {
 | 
						|
    for (var value in selectedBranchModel!.branchServices!) {
 | 
						|
      if (!isCategoryAlreadyPresent(value.categoryId!)) {
 | 
						|
        branchCategories.add(DropValue(value.categoryId!, value.categoryName!, ""));
 | 
						|
      }
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  getBranchServices({required int categoryId}) async {
 | 
						|
    branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    isHomeTapped = false;
 | 
						|
    pickedHomeLocation = "";
 | 
						|
    pickHomeLocationError = "";
 | 
						|
    if (categoryId != -1) {
 | 
						|
      isFetchingServices = true;
 | 
						|
      branchServices = getFilteredBranchServices(categoryId: categoryId);
 | 
						|
      isFetchingServices = false;
 | 
						|
      notifyListeners();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  List<ServiceModel> getFilteredBranchServices({required int categoryId}) {
 | 
						|
    List<ServiceModel> filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList();
 | 
						|
    return filteredServices;
 | 
						|
  }
 | 
						|
 | 
						|
  getBranchAndServices(int providerId) async {
 | 
						|
    providerProfileModel = null;
 | 
						|
    providerProfileModel = await branchRepo.getBranchAndServicesByProviderId(providerId);
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  bool isCategoryAlreadyPresent(int id) {
 | 
						|
    final contain = branchCategories.where((element) => element.id == id);
 | 
						|
    if (contain.isEmpty) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  updateSelectedBranch(BranchDetailModel branchDetailModel) {
 | 
						|
    selectedBranchModel = branchDetailModel;
 | 
						|
    getBranchCategories();
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  int branchFiltersCounter = 0;
 | 
						|
 | 
						|
  updateBranchFiltersCounter(int value) {
 | 
						|
    branchFiltersCounter = value;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  double branchFilterCurrentDistance = 25.0;
 | 
						|
 | 
						|
  updateBranchFilterCurrentDistance(double value) {
 | 
						|
    branchFilterCurrentDistance = value;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  // Provider Filter
 | 
						|
  List<DropValue> branchFilterProviderSearchHistory = [];
 | 
						|
 | 
						|
  void removeBranchFilterProviderSearchHistory({bool isClear = false, required int index}) {
 | 
						|
    if (isClear) {
 | 
						|
      branchFilterProviderSearchHistory.clear();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    branchFilterProviderSearchHistory.removeAt(index);
 | 
						|
    if (branchFilterProviderSearchHistory.isEmpty) {
 | 
						|
      updateBranchFiltersCounter(branchFiltersCounter - 1);
 | 
						|
      // branchFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void addBranchFilterProviderSearchHistory({required DropValue value}) {
 | 
						|
    if (branchFilterProviderSearchHistory.isEmpty) {
 | 
						|
      updateBranchFiltersCounter(branchFiltersCounter + 1);
 | 
						|
    }
 | 
						|
    branchFilterProviderSearchHistory.add(value);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel branchFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateBranchFilterSelectedProviderId(SelectionModel id, {bool isForSearch = false}) async {
 | 
						|
    if (isForSearch) {
 | 
						|
      DropValue providerDrop = providersDropList.firstWhere((element) => element.id == id.selectedId);
 | 
						|
      if (!ifAlreadyExist(list: branchFilterProviderSearchHistory, value: providerDrop)) {
 | 
						|
        addBranchFilterProviderSearchHistory(value: providerDrop);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    branchFilterSelectedProviderId = id;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  // Category Filter
 | 
						|
  List<DropValue> branchFilterCategorySearchHistory = [];
 | 
						|
 | 
						|
  void removeBranchFilterCategorySearchHistory({bool isClear = false, required int index}) {
 | 
						|
    if (isClear) {
 | 
						|
      branchFilterCategorySearchHistory.clear();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    branchFilterCategorySearchHistory.removeAt(index);
 | 
						|
    if (branchFilterCategorySearchHistory.isEmpty) {
 | 
						|
      updateBranchFiltersCounter(branchFiltersCounter - 1);
 | 
						|
      // branchFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void addBranchFilterCategorySearchHistory({required DropValue value}) {
 | 
						|
    if (branchFilterCategorySearchHistory.isEmpty) {
 | 
						|
      updateBranchFiltersCounter(branchFiltersCounter + 1);
 | 
						|
    }
 | 
						|
    branchFilterCategorySearchHistory.add(value);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel branchFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateBranchFilterSelectedCategoryId(SelectionModel id, {bool isForSearch = false}) async {
 | 
						|
    if (isForSearch) {
 | 
						|
      DropValue categoryDrop = categoryDropList.firstWhere((element) => element.id == id.selectedId);
 | 
						|
      if (!ifAlreadyExist(list: branchFilterCategorySearchHistory, value: categoryDrop)) {
 | 
						|
        addBranchFilterCategorySearchHistory(value: categoryDrop);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    branchFilterSelectedCategoryId = id;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  // Services Filter
 | 
						|
  List<DropValue> branchFilterServicesSearchHistory = [];
 | 
						|
 | 
						|
  void removeBranchFilterServicesSearchHistory({bool isClear = false, required int index}) {
 | 
						|
    if (isClear) {
 | 
						|
      branchFilterServicesSearchHistory.clear();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    branchFilterServicesSearchHistory.removeAt(index);
 | 
						|
    if (branchFilterServicesSearchHistory.isEmpty) {
 | 
						|
      updateBranchFiltersCounter(branchFiltersCounter - 1);
 | 
						|
      // branchFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void addBranchFilterServicesSearchHistory({required DropValue value}) {
 | 
						|
    if (branchFilterServicesSearchHistory.isEmpty) {
 | 
						|
      updateBranchFiltersCounter(branchFiltersCounter + 1);
 | 
						|
    }
 | 
						|
    branchFilterServicesSearchHistory.add(value);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel branchFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateBranchFilterSelectedServiceId(SelectionModel id, {bool isForSearch = false}) async {
 | 
						|
    if (isForSearch) {
 | 
						|
      DropValue serviceDrop = servicesDropList.firstWhere((element) => element.id == id.selectedId);
 | 
						|
      if (!ifAlreadyExist(list: branchFilterServicesSearchHistory, value: serviceDrop)) {
 | 
						|
        addBranchFilterServicesSearchHistory(value: serviceDrop);
 | 
						|
      }
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    branchFilterSelectedServiceId = id;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  ifAlreadyExist({required List<DropValue> list, required DropValue value}) {
 | 
						|
    int index = list.indexWhere((element) {
 | 
						|
      return element.id == value.id;
 | 
						|
    });
 | 
						|
 | 
						|
    if (index != -1) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Rating filter
 | 
						|
 | 
						|
  double branchFilterByRating = 4.0;
 | 
						|
 | 
						|
  updateBranchFilterByRating(double value) {
 | 
						|
    branchFilterByRating = value;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  List<DropValue> categoryDropList = [];
 | 
						|
  List<DropValue> servicesDropList = [];
 | 
						|
  List<DropValue> providersDropList = [];
 | 
						|
 | 
						|
  Future<void> fetchAllProviders() async {
 | 
						|
    if (providersDropList.isNotEmpty) return;
 | 
						|
 | 
						|
    providersDropList.clear();
 | 
						|
    setOnlyState(ViewState.busy);
 | 
						|
    List<ProviderBasicDataModel> providers = await branchRepo.getAllProvidersWitheBasicData();
 | 
						|
    for (var element in providers) {
 | 
						|
      providersDropList.add(
 | 
						|
        DropValue(element.id ?? 0, element.providerName ?? "N/A", ""),
 | 
						|
      );
 | 
						|
    }
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> fetchAllCategories(String countryCode) async {
 | 
						|
    if (categoryDropList.isNotEmpty) return;
 | 
						|
    categoryDropList.clear();
 | 
						|
    setOnlyState(ViewState.busy);
 | 
						|
    Category category = await branchRepo.fetchBranchCategory();
 | 
						|
    category.data?.forEach((element) {
 | 
						|
      categoryDropList.add(
 | 
						|
        DropValue(
 | 
						|
            element.id ?? 0,
 | 
						|
            ((element.categoryName!.isEmpty
 | 
						|
                    ? "N/A"
 | 
						|
                    : countryCode == "SA"
 | 
						|
                        ? element.categoryNameN
 | 
						|
                        : element.categoryName) ??
 | 
						|
                "N/A"),
 | 
						|
            ""),
 | 
						|
      );
 | 
						|
    });
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> fetchAllServices() async {
 | 
						|
    if (servicesDropList.isNotEmpty) return;
 | 
						|
    servicesDropList.clear();
 | 
						|
    setState(ViewState.busy);
 | 
						|
    Services services = await branchRepo.fetchServicesByCategoryId(serviceCategoryId: -1); // to get all services
 | 
						|
 | 
						|
    for (var element in services.data!) {
 | 
						|
      servicesDropList.add(
 | 
						|
        DropValue(
 | 
						|
          element.id ?? 0,
 | 
						|
          element.description ?? "N/A",
 | 
						|
          "",
 | 
						|
        ),
 | 
						|
      );
 | 
						|
    }
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> populateDataForBranchesFilter() async {
 | 
						|
    await fetchAllProviders(); // saudi arabia
 | 
						|
    await fetchAllCategories("SA"); // saudi arabia
 | 
						|
    await fetchAllServices(); // saudi arabia
 | 
						|
    updateBranchFilterCurrentDistance(25.0);
 | 
						|
  }
 | 
						|
 | 
						|
  void clearBranchFilters() {
 | 
						|
    branchFilterServicesSearchHistory.clear();
 | 
						|
    branchFilterCategorySearchHistory.clear();
 | 
						|
    branchFilterProviderSearchHistory.clear();
 | 
						|
    branchFilterByRating = 4.0;
 | 
						|
    branchFilterCurrentDistance = 25.0;
 | 
						|
    branchFiltersCounter = 0;
 | 
						|
    clearBranchFilterSelections();
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void clearBranchFilterSelections() {
 | 
						|
    branchFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    branchFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    branchFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> getBranchesBasedOnFilters() async {
 | 
						|
    nearbyBranches.clear();
 | 
						|
    setState(ViewState.busy);
 | 
						|
    List<int> providersIdsList = [];
 | 
						|
    if (branchFilterProviderSearchHistory.isNotEmpty) {
 | 
						|
      for (var element in branchFilterProviderSearchHistory) {
 | 
						|
        providersIdsList.add(element.id);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    List<int> categoryIdsList = [];
 | 
						|
    if (branchFilterCategorySearchHistory.isNotEmpty) {
 | 
						|
      for (var element in branchFilterCategorySearchHistory) {
 | 
						|
        categoryIdsList.add(element.id);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    List<int> servicesIdsList = [];
 | 
						|
    if (branchFilterServicesSearchHistory.isNotEmpty) {
 | 
						|
      for (var element in branchFilterServicesSearchHistory) {
 | 
						|
        servicesIdsList.add(element.id);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    nearbyBranches = await branchRepo.getBranchesByFilters(
 | 
						|
      providerIdsList: providersIdsList.isNotEmpty ? providersIdsList : null,
 | 
						|
      categoryIdsList: categoryIdsList.isNotEmpty ? categoryIdsList : null,
 | 
						|
      serviceIdsList: servicesIdsList.isNotEmpty ? servicesIdsList : null,
 | 
						|
      distanceKm: branchFilterCurrentDistance.toInt(),
 | 
						|
      rating: branchFilterByRating.toInt(),
 | 
						|
      latitude: 24.694969,
 | 
						|
      longitude: 46.724129,
 | 
						|
    );
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> getBranchesBasedOnCategoryFilters({required int categoryId}) async {
 | 
						|
    if (categoryId == 0) {
 | 
						|
      await getAllNearBranches();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    setState(ViewState.busy);
 | 
						|
    nearbyBranches.clear();
 | 
						|
    nearbyBranches = await branchRepo.getBranchesByFilters(categoryIdsList: [categoryId]);
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
 | 
						|
  // Appointments Filter Screen
 | 
						|
 | 
						|
  List<DropValue> branchesDropList = [];
 | 
						|
 | 
						|
  Future<void> fetchAllBranchesBySelectedProviderId({required List<int> providersIdsList}) async {
 | 
						|
    branchesDropList.clear();
 | 
						|
    setOnlyState(ViewState.busy);
 | 
						|
    List<BranchDetailModel> providers = await branchRepo.getBranchesByFilters(providerIdsList: providersIdsList);
 | 
						|
    for (var element in providers) {
 | 
						|
      branchesDropList.add(DropValue(element.id ?? 0, element.branchName ?? "N/A", ""));
 | 
						|
    }
 | 
						|
    setState(ViewState.idle);
 | 
						|
 | 
						|
    log("branchesDropList: ${branchesDropList.length}");
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> populateDataForAppointmentsFilter() async {
 | 
						|
    await fetchAllProviders(); // saudi arabia
 | 
						|
    await fetchAllCategories("SA"); // saudi arabia
 | 
						|
    await fetchAllServices(); // saudi arabia
 | 
						|
  }
 | 
						|
 | 
						|
  int appointmentFiltersCounter = 0;
 | 
						|
 | 
						|
  updateAppointmentFiltersCounter(int value) {
 | 
						|
    appointmentFiltersCounter = value;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  // Provider Filter For Appointments
 | 
						|
  List<DropValue> appointmentFilterProviderSearchHistory = [];
 | 
						|
 | 
						|
  void removeAppointmentFilterProviderSearchHistory({bool isClear = false, required int index}) {
 | 
						|
    if (isClear) {
 | 
						|
      appointmentFilterProviderSearchHistory.clear();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    appointmentFilterProviderSearchHistory.removeAt(index);
 | 
						|
    if (appointmentFilterProviderSearchHistory.isNotEmpty) {
 | 
						|
      List<int> providerIdsSelected = [];
 | 
						|
      for (var element in appointmentFilterProviderSearchHistory) {
 | 
						|
        providerIdsSelected.add(element.id);
 | 
						|
      }
 | 
						|
      fetchAllBranchesBySelectedProviderId(providersIdsList: providerIdsSelected);
 | 
						|
    }
 | 
						|
 | 
						|
    if (appointmentFilterProviderSearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
 | 
						|
      // appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void addAppointmentFilterProviderSearchHistory({required DropValue value}) {
 | 
						|
    if (appointmentFilterProviderSearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
 | 
						|
    }
 | 
						|
    List<int> providerIdsSelected = [];
 | 
						|
    for (var element in appointmentFilterProviderSearchHistory) {
 | 
						|
      providerIdsSelected.add(element.id);
 | 
						|
    }
 | 
						|
    fetchAllBranchesBySelectedProviderId(providersIdsList: providerIdsSelected);
 | 
						|
    appointmentFilterProviderSearchHistory.add(value);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateAppointmentFilterSelectedProviderId(SelectionModel id, {bool isForSearch = false}) async {
 | 
						|
    if (isForSearch) {
 | 
						|
      DropValue providerDrop = providersDropList.firstWhere((element) => element.id == id.selectedId);
 | 
						|
      if (!ifAlreadyExist(list: appointmentFilterProviderSearchHistory, value: providerDrop)) {
 | 
						|
        addAppointmentFilterProviderSearchHistory(value: providerDrop);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // appointmentFilterSelectedProviderId = id;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  // Branches Filter For Appointments
 | 
						|
 | 
						|
  List<DropValue> appointmentFilterBranchSearchHistory = [];
 | 
						|
 | 
						|
  void removeAppointmentFilterBranchSearchHistory({bool isClear = false, required int index}) {
 | 
						|
    if (isClear) {
 | 
						|
      appointmentFilterBranchSearchHistory.clear();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    appointmentFilterBranchSearchHistory.removeAt(index);
 | 
						|
    if (appointmentFilterBranchSearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
 | 
						|
      // appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void addAppointmentFilterBranchSearchHistory({required DropValue value}) {
 | 
						|
    if (appointmentFilterBranchSearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
 | 
						|
    }
 | 
						|
    appointmentFilterBranchSearchHistory.add(value);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateAppointmentFilterSelectedBranchId(SelectionModel id, {bool isForSearch = false}) async {
 | 
						|
    if (isForSearch) {
 | 
						|
      DropValue branchesDrop = branchesDropList.firstWhere((element) => element.id == id.selectedId);
 | 
						|
      if (!ifAlreadyExist(list: appointmentFilterBranchSearchHistory, value: branchesDrop)) {
 | 
						|
        addAppointmentFilterBranchSearchHistory(value: branchesDrop);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // appointmentFilterSelectedBranchId = id;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  // Category Filter For Appointments
 | 
						|
 | 
						|
  List<DropValue> appointmentFilterCategorySearchHistory = [];
 | 
						|
 | 
						|
  void removeAppointmentFilterCategorySearchHistory({bool isClear = false, required int index}) {
 | 
						|
    if (isClear) {
 | 
						|
      appointmentFilterCategorySearchHistory.clear();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    appointmentFilterCategorySearchHistory.removeAt(index);
 | 
						|
    if (appointmentFilterCategorySearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
 | 
						|
      // appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void addAppointmentFilterCategorySearchHistory({required DropValue value}) {
 | 
						|
    if (appointmentFilterCategorySearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
 | 
						|
    }
 | 
						|
    appointmentFilterCategorySearchHistory.add(value);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateAppointmentFilterSelectedCategoryId(SelectionModel id, {bool isForSearch = false}) async {
 | 
						|
    if (isForSearch) {
 | 
						|
      DropValue categoryDrop = categoryDropList.firstWhere((element) => element.id == id.selectedId);
 | 
						|
      if (!ifAlreadyExist(list: appointmentFilterCategorySearchHistory, value: categoryDrop)) {
 | 
						|
        addAppointmentFilterCategorySearchHistory(value: categoryDrop);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // appointmentFilterSelectedCategoryId = id;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  List<DropValue> appointmentFilterServicesSearchHistory = [];
 | 
						|
 | 
						|
  void removeAppointmentFilterServicesSearchHistory({bool isClear = false, required int index}) {
 | 
						|
    if (isClear) {
 | 
						|
      appointmentFilterServicesSearchHistory.clear();
 | 
						|
      notifyListeners();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    appointmentFilterServicesSearchHistory.removeAt(index);
 | 
						|
    if (appointmentFilterServicesSearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
 | 
						|
      // appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    }
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void addAppointmentFilterServicesSearchHistory({required DropValue value}) {
 | 
						|
    if (appointmentFilterServicesSearchHistory.isEmpty) {
 | 
						|
      updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
 | 
						|
    }
 | 
						|
    appointmentFilterServicesSearchHistory.add(value);
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  SelectionModel appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
 | 
						|
  void updateAppointmentFilterSelectedServiceId(SelectionModel id, {bool isForSearch = false}) async {
 | 
						|
    if (isForSearch) {
 | 
						|
      DropValue servicesDrop = servicesDropList.firstWhere((element) => element.id == id.selectedId);
 | 
						|
      if (!ifAlreadyExist(list: appointmentFilterServicesSearchHistory, value: servicesDrop)) {
 | 
						|
        addAppointmentFilterServicesSearchHistory(value: servicesDrop);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    // appointmentFilterSelectedServiceId = id;
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  void clearAppointmentFilterSelections() {
 | 
						|
    appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
    appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
 | 
						|
  }
 | 
						|
 | 
						|
  void clearAppointmentFilters() {
 | 
						|
    appointmentFilterServicesSearchHistory.clear();
 | 
						|
    appointmentFilterCategorySearchHistory.clear();
 | 
						|
    appointmentFilterProviderSearchHistory.clear();
 | 
						|
    appointmentFilterBranchSearchHistory.clear();
 | 
						|
    appointmentFiltersCounter = 0;
 | 
						|
    clearAppointmentFilterSelections();
 | 
						|
    notifyListeners();
 | 
						|
  }
 | 
						|
 | 
						|
  Future<void> getAppointmentsBasedOnFilters() async {
 | 
						|
    nearbyBranches.clear();
 | 
						|
    setState(ViewState.busy);
 | 
						|
    List<int> providersIdsList = [];
 | 
						|
    if (appointmentFilterProviderSearchHistory.isNotEmpty) {
 | 
						|
      for (var element in appointmentFilterProviderSearchHistory) {
 | 
						|
        providersIdsList.add(element.id);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    List<int> categoryIdsList = [];
 | 
						|
    if (appointmentFilterCategorySearchHistory.isNotEmpty) {
 | 
						|
      for (var element in appointmentFilterCategorySearchHistory) {
 | 
						|
        categoryIdsList.add(element.id);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    List<int> servicesIdsList = [];
 | 
						|
    if (appointmentFilterServicesSearchHistory.isNotEmpty) {
 | 
						|
      for (var element in appointmentFilterServicesSearchHistory) {
 | 
						|
        servicesIdsList.add(element.id);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    List<int> branchesIdsList = [];
 | 
						|
    if (appointmentFilterBranchSearchHistory.isNotEmpty) {
 | 
						|
      for (var element in appointmentFilterBranchSearchHistory) {
 | 
						|
        branchesIdsList.add(element.id);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters(
 | 
						|
      providerIdsList: providersIdsList.isNotEmpty ? providersIdsList : null,
 | 
						|
      categoryIdsList: categoryIdsList.isNotEmpty ? categoryIdsList : null,
 | 
						|
      serviceIdsList: servicesIdsList.isNotEmpty ? servicesIdsList : null,
 | 
						|
      branchIdsList: branchesIdsList.isNotEmpty ? branchesIdsList : null,
 | 
						|
    );
 | 
						|
    applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
 | 
						|
    setState(ViewState.idle);
 | 
						|
  }
 | 
						|
}
 |