import 'package:car_customer_app/repositories/provider_repo.dart'; import 'package:car_customer_app/repositories/schedule_repo.dart'; import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.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/service_schedule_model.dart'; import 'package:mc_common_app/models/services/item_model.dart'; import 'package:mc_common_app/models/services/service_model.dart'; import 'package:mc_common_app/models/widgets_models.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; import 'package:mc_common_app/services/common_services.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/widgets/dropdown/dropdow_field.dart'; class AppointmentsVM extends BaseVM { final CommonRepo commonRepo; final CommonAppServices commonServices; final ProviderRepo providerRepo; final ScheduleRepo scheduleRepo; AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo}); bool isFetchingLists = false; List myAppointments = []; List appointmentsFilterOptions = []; // List availableSchedules = []; bool isFetchingServices = false; List branchCategories = []; bool isHomeTapped = false; List serviceAppointmentScheduleList = []; // Future getSchedulesByBranchId() async { // availableSchedules = await scheduleRepo.getSchedules(selectedBranchModel!.id!.toString()); // log("schedules: ${availableSchedules.toString()}"); // notifyListeners(); // } List servicesInSchedule = []; Future mergeServiceIntoAvailableSchedules() async { List serviceItemIds = []; currentServiceSelection!.serviceItems!.forEach((serviceItem) { if (serviceItem.isUpdateOrSelected!) { serviceItemIds.add(serviceItem.id!.toString()); } }); servicesInCurrentAppointment.add(currentServiceSelection!); serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules( serviceItemIds: serviceItemIds, appointmentType: isHomeTapped ? 2 : 1, // AppointmentType 1 for workshop and 2 for Home based schedule. ); servicesInSchedule.clear(); if (serviceAppointmentScheduleList.isEmpty) { Utils.showToast("There are no available appointments for selected Items."); return; } serviceAppointmentScheduleList.forEach( (schedule) { amountToPayForAppointment = amountToPayForAppointment + (schedule.amountToPay ?? 0.0); schedule.serviceItemList!.forEach((item) { if (!ifItemAlreadyThere(item.serviceProviderServiceId!)) { servicesInSchedule.add(DropValue(item.serviceProviderServiceId!, item.description!, "")); } }); }, ); notifyListeners(); } Future onItemsSelectedInService() async { if (currentServiceSelection != null) { servicesInCurrentAppointment.add(currentServiceSelection!); } } Future onBookAppointmentPressed(BuildContext context) async { Utils.showLoading(context); try { serviceAppointmentScheduleList.forEach((schedule) async { List serviceItemIds = []; schedule.serviceItemList!.forEach((serviceItem) { serviceItemIds.add(serviceItem.id.toString()); }); await scheduleRepo.createServiceAppointment(serviceItemIds: serviceItemIds, serviceSlotID: schedule.selectedCustomTimeDateSlotModel!.date!.slotId); }); } catch (e) { Utils.showToast("${e.toString()}"); } } bool ifItemAlreadyThere(int id) { int index = servicesInSchedule.indexWhere((element) => element.id == id); if (index == -1) { return false; } return true; } void updateIsHomeTapped(bool value) { isHomeTapped = value; notifyListeners(); } String pickedHomeLocation = ""; void updatePickedHomeLocation(String value) { pickedHomeLocation = value; pickHomeLocationError = ""; notifyListeners(); } SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); void updateProviderCategoryId(SelectionModel id) { branchSelectedCategoryId = id; getBranchServices(categoryId: branchSelectedCategoryId.selectedId); notifyListeners(); } List providersFilterOptions = []; List nearbyBranches = []; BranchDetailModel? selectedBranchModel; List branchServices = []; List servicesInCurrentAppointment = []; ServiceModel? currentServiceSelection; void updateBranchServiceId(SelectionModel id) async { branchSelectedServiceId = id; currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId); notifyListeners(); } resetCategorySelectionBottomSheet() { selectedSubServicesCounter = 0; branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); isHomeTapped = false; branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); currentServiceSelection = null; } populateAppointmentsFilterList() { appointmentsFilterOptions.clear(); appointmentsFilterOptions = [ FilterListModel(title: "All Appointments", isSelected: true, id: -1), FilterListModel(title: "Booked", isSelected: false, id: 1), FilterListModel(title: "Confirmed", isSelected: false, id: 2), FilterListModel(title: "Arrived", isSelected: false, id: 3), FilterListModel(title: "Cancelled", isSelected: false, id: 4), ]; notifyListeners(); } applyFilterOnAppointmentsVM({required int index}) { if (appointmentsFilterOptions.isEmpty) return; for (var value in appointmentsFilterOptions) { value.isSelected = false; } appointmentsFilterOptions[index].isSelected = true; notifyListeners(); } Future getMyAppointments() async { isFetchingLists = true; myAppointments = await commonRepo.getMyAppointments(); isFetchingLists = false; notifyListeners(); } updateSelectedBranch(BranchDetailModel branchDetailModel) { selectedBranchModel = branchDetailModel; getBranchCategories(); notifyListeners(); } updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) { serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!.forEach((element) { 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}) { serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList!.forEach((element) { element.availableSlots!.forEach((element) => 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!; print("here: ${serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![index].availableSlots![slotIndex].slotId}"); notifyListeners(); } double amountToPayForAppointment = 0.0; double totalAmount = 0.0; 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 = true; 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); } List serviceItemsFromApi = []; ProviderProfileModel? providerProfileModel; int selectedSubServicesCounter = 0; updateSelectedSubServicesCounter(int value) { selectedSubServicesCounter = value; notifyListeners(); } onItemUpdateOrSelected(int index, bool selected, int itemId) { serviceItemsFromApi[index].isUpdateOrSelected = selected; if (selected) { selectedSubServicesCounter = selectedSubServicesCounter + 1; updateSelectedSubServicesCounter(selectedSubServicesCounter); selectSubServicesError = ""; currentServiceSelection!.serviceItems!.add(serviceItemsFromApi[index]); } if (!selected) { selectedSubServicesCounter = selectedSubServicesCounter - 1; updateSelectedSubServicesCounter(selectedSubServicesCounter); currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId); } notifyListeners(); } populateProvidersFilterList() { providersFilterOptions.clear(); providersFilterOptions = [ FilterListModel(title: "All Providers", isSelected: true, id: -1), FilterListModel(title: "Maintenance", isSelected: false, id: 0), FilterListModel(title: "Oil Service", isSelected: false, id: 1), FilterListModel(title: "Accessories", isSelected: false, id: 2), FilterListModel(title: "Tire Service", isSelected: false, id: 3), FilterListModel(title: "Dent and Paint", isSelected: false, id: 4), ]; notifyListeners(); } applyFilterOnProviders({required int index}) { if (providersFilterOptions.isEmpty) return; for (var value in providersFilterOptions) { value.isSelected = false; } providersFilterOptions[index].isSelected = true; notifyListeners(); } getAllNearBranches({bool isNeedToRebuild = false}) async { //TODO: needs to lat,long into API nearbyBranches.clear(); if (isNeedToRebuild) setState(ViewState.busy); nearbyBranches = await providerRepo.getAllNearBranchAndServices(); setState(ViewState.idle); } Future> getServiceItems(int serviceId) async { serviceItemsFromApi.clear(); serviceItemsFromApi = await providerRepo.getServiceItems(serviceId); setState(ViewState.idle); return serviceItemsFromApi; } getBranchAndServices(int providerId) async { providerProfileModel = null; providerProfileModel = await providerRepo.getBranchAndServices(providerId); setState(ViewState.idle); } String pickHomeLocationError = ""; String selectSubServicesError = ""; SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); bool isCategoryAlreadyPresent(int id) { final contain = branchCategories.where((element) => element.id == id); if (contain.isEmpty) { return false; } return true; } 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; // notifyListeners(); branchServices = getFilteredBranchServices(categoryId: categoryId); isFetchingServices = false; notifyListeners(); } } List getFilteredBranchServices({required int categoryId}) { List filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList(); return filteredServices; } 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; } // void mergeServiceInAvailableSchedule() { // log("schedules: ${availableSchedules}"); // for (var schedule in availableSchedules) { // for (var service in schedule.scheduleServices!) { // if (branchSelectedServiceId.selectedId == service.serviceId) { // log("ID matched: ${service.serviceId}"); // log("SelectedServices: ${schedule.selectedServices}"); // // // int isAlreadyThereIndex = schedule.selectedServices!.indexWhere((element) => element.serviceProviderServiceId == branchSelectedServiceId.selectedId); // if (isAlreadyThereIndex != -1) { // log("removing: ${service.serviceId}"); // schedule.selectedServices!.removeAt(isAlreadyThereIndex); // } // schedule.selectedServices!.add(currentServiceSelection!); // notifyListeners(); // return; // } // } // } // notifyListeners(); // } }