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.
2041 lines
77 KiB
Dart
2041 lines
77 KiB
Dart
import 'dart:developer';
|
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:mc_common_app/classes/app_state.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/generated/locale_keys.g.dart';
|
|
import 'package:mc_common_app/main.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/chat_models/chat_message_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/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/branch_review_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/date_helper.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/button/show_fill_button.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:mc_common_app/widgets/txt_field.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 isUpcomingEnabled = true;
|
|
bool isFetchingLists = false;
|
|
int selectedAppointmentIndex = 0;
|
|
int selectedAppointmentSubIndex = 0;
|
|
int selectedAppointmentId = 0;
|
|
int selectedBranchIdForAppointments = 0;
|
|
|
|
List<AppointmentListModel> myAppointments = [];
|
|
List<AppointmentListModel> myUpComingAppointments = [];
|
|
List<AppointmentListModel> myFilteredAppointments = [];
|
|
List<FilterListModel> appointmentsFilterOptions = [];
|
|
List<AppointmentListModel> myFilteredAppointments2 = [];
|
|
|
|
bool isFetchingServices = false;
|
|
|
|
List<DropValue> branchCategories = [];
|
|
|
|
bool isHomeTapped = false;
|
|
bool isShowEmptyMessage = false;
|
|
|
|
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleList = [];
|
|
|
|
List<ItemData> allSelectedItemsInAppointments = [];
|
|
|
|
bool ifItemAlreadySelected(int id) {
|
|
int indexFound = allSelectedItemsInAppointments.indexWhere((element) => element.id == id);
|
|
log("already selected at: $indexFound");
|
|
if (indexFound != -1) {
|
|
return true;
|
|
}
|
|
return 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(LocaleKeys.appointmentBookedSuccessfully.tr());
|
|
getMyAppointmentsForCustomer();
|
|
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);
|
|
}
|
|
|
|
OfferRequestCommentModel selectedCancelAppointmentReason = OfferRequestCommentModel(
|
|
index: 0,
|
|
isSelected: true,
|
|
title: LocaleKeys.changedMind.tr(),
|
|
);
|
|
|
|
List<OfferRequestCommentModel> cancelAppointmentReasonList = [
|
|
OfferRequestCommentModel(
|
|
index: 0,
|
|
isSelected: true,
|
|
title: LocaleKeys.wantToRescheduleAppointment.tr(),
|
|
),
|
|
OfferRequestCommentModel(
|
|
index: 1,
|
|
isSelected: false,
|
|
title: LocaleKeys.noNeedForService.tr(),
|
|
),
|
|
OfferRequestCommentModel(
|
|
index: 2,
|
|
isSelected: false,
|
|
title: LocaleKeys.testTheService.tr(),
|
|
),
|
|
OfferRequestCommentModel(
|
|
index: 3,
|
|
isSelected: false,
|
|
title: LocaleKeys.otherVar.tr(),
|
|
),
|
|
];
|
|
|
|
void updateSelectedCancelAppointmentReason(int index) {
|
|
for (var value in cancelAppointmentReasonList) {
|
|
value.isSelected = false;
|
|
}
|
|
selectedCancelAppointmentReason = cancelAppointmentReasonList[index];
|
|
cancelAppointmentReasonList[index].isSelected = true;
|
|
notifyListeners();
|
|
}
|
|
|
|
String cancelAppointmentDescription = "";
|
|
String cancelAppointmentDescriptionError = "";
|
|
|
|
void updateCancelAppointmentDescription(String value) {
|
|
cancelAppointmentDescription = value;
|
|
if (value.isNotEmpty) {
|
|
cancelAppointmentDescriptionError = "";
|
|
}
|
|
}
|
|
|
|
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 && AppState().currentAppType == AppType.customer) {
|
|
context.read<DashboardVmCustomer>().onNavbarTapped(1);
|
|
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled);
|
|
Utils.showToast(genericRespModel.message.toString());
|
|
await getMyAppointmentsForCustomer();
|
|
Utils.hideLoading(context);
|
|
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
|
|
}
|
|
} catch (e) {
|
|
logger.e(e.toString());
|
|
Utils.showToast(e.toString());
|
|
}
|
|
}
|
|
|
|
void updateIsHomeTapped(bool value) {
|
|
isHomeTapped = value;
|
|
if (currentServiceSelection != null) {
|
|
currentServiceSelection!.isHomeSelected = value;
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateProviderCategoryId(SelectionModel id) {
|
|
branchSelectedCategoryId = id;
|
|
getBranchServices(categoryId: branchSelectedCategoryId.selectedId);
|
|
notifyListeners();
|
|
}
|
|
|
|
List<FilterListModel> branchesCategoriesFilterOptions = [];
|
|
|
|
List<ServiceModel> servicesInCurrentAppointment = [];
|
|
ServiceModel? currentServiceSelection;
|
|
|
|
CurrentLocationInfoModel? currentLocationInfoModel;
|
|
|
|
void updateCurrentLocationInfoModel(CurrentLocationInfoModel? value) {
|
|
currentLocationInfoModel = value;
|
|
pickHomeLocationError = "";
|
|
if (currentServiceSelection != null && value != null) {
|
|
currentServiceSelection!.servicelocationInfo = value;
|
|
}
|
|
|
|
if (value != null) {
|
|
for (var service in servicesInCurrentAppointment) {
|
|
service.servicelocationInfo.address = value.address;
|
|
service.servicelocationInfo.latitude = value.latitude;
|
|
service.servicelocationInfo.longitude = value.longitude;
|
|
service.servicelocationInfo.distanceToBranch = value.distanceToBranch;
|
|
service.servicelocationInfo.homeChargesInCurrentService = double.parse(service.rangePricePerKm ?? "0.0");
|
|
}
|
|
}
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
void updateBranchServiceId(SelectionModel id) async {
|
|
branchSelectedServiceId = id;
|
|
currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId);
|
|
if (currentServiceSelection == null) {
|
|
return;
|
|
}
|
|
|
|
if (!(currentServiceSelection!.isAllowAppointmentHome ?? false)) {
|
|
updateIsHomeTapped(false);
|
|
return;
|
|
}
|
|
if (currentLocationInfoModel != null) {
|
|
currentLocationInfoModel!.homeChargesInCurrentService = double.parse(currentServiceSelection!.rangePricePerKm ?? "0.0");
|
|
currentServiceSelection!.servicelocationInfo = CurrentLocationInfoModel(
|
|
address: currentLocationInfoModel!.address,
|
|
latitude: currentLocationInfoModel!.latitude,
|
|
longitude: currentLocationInfoModel!.longitude,
|
|
distanceToBranch: currentLocationInfoModel!.distanceToBranch,
|
|
homeChargesInCurrentService: double.parse(currentServiceSelection!.rangePricePerKm ?? "0.0"),
|
|
);
|
|
}
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
void removeServiceInCurrentAppointment(int index) {
|
|
int serviceId = servicesInCurrentAppointment.elementAt(index).serviceProviderServiceId ?? -1;
|
|
allSelectedItemsInAppointments.removeWhere((element) => element.serviceProviderServiceId == serviceId);
|
|
servicesInCurrentAppointment[index].serviceItems!.clear();
|
|
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();
|
|
currentServiceSelection = null;
|
|
for (var element in servicesInCurrentAppointment) {
|
|
if (element.serviceItems != null) {
|
|
element.serviceItems!.clear();
|
|
element.serviceItems = [];
|
|
}
|
|
}
|
|
servicesInCurrentAppointment.clear();
|
|
servicesInCurrentAppointment = [];
|
|
currentLocationInfoModel = null;
|
|
log("here servicesInCurrentAppointment: ${servicesInCurrentAppointment.length}");
|
|
}
|
|
|
|
List<EnumsModel> myAppointmentsEnum = [];
|
|
|
|
Future<void> populateAppointmentsFilterList() async {
|
|
if (appointmentsFilterOptions.isNotEmpty) return;
|
|
|
|
myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.appointmentsFilterEnumId); // 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));
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) {
|
|
log("appointmentStatusEnum: $appointmentStatusEnum");
|
|
// 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 == AppointmentStatusEnum.allAppointments) {
|
|
myFilteredAppointments = myAppointments;
|
|
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(myFilteredAppointments);
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
|
|
myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList();
|
|
if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(myFilteredAppointments);
|
|
notifyListeners();
|
|
}
|
|
|
|
findAppointmentsBasedOnCustomers(List<AppointmentListModel> appointments) {
|
|
// Use a Set to ensure uniqueness of customerIDs
|
|
Set<int> uniqueCustomerIDs = <int>{};
|
|
|
|
// Extract unique customerIDs
|
|
for (var item in appointments) {
|
|
uniqueCustomerIDs.add(item.customerID ?? 0);
|
|
}
|
|
|
|
// Create a list of CustomerData instances
|
|
myFilteredAppointments2 = uniqueCustomerIDs.map((id) {
|
|
List<AppointmentListModel> list = appointments.where((item) => item.customerID == id).toList();
|
|
list.sort((a, b) => DateHelper.parseStringToDate(DateHelper.formatDateT(b.appointmentDate!))
|
|
.millisecondsSinceEpoch
|
|
.compareTo(DateHelper.parseStringToDate(DateHelper.formatDateT(a.appointmentDate!)).millisecondsSinceEpoch));
|
|
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() async {
|
|
// setState(ViewState.busy);
|
|
//
|
|
// myAppointments =
|
|
// await appointmentRepo.getMyAppointmentsForCustomersByFilters();
|
|
// myFilteredAppointments = myAppointments;
|
|
// myUpComingAppointments = myAppointments
|
|
// .where((element) =>
|
|
// element.appointmentStatusEnum == AppointmentStatusEnum.booked)
|
|
// .toList();
|
|
// applyFilterOnAppointmentsVM(
|
|
// appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
|
|
// if (myUpComingAppointments.isEmpty) {
|
|
// isShowEmptyMessage = true;
|
|
// }
|
|
// setState(ViewState.idle);
|
|
// notifyListeners();
|
|
// }
|
|
|
|
Future<void> getMyAppointmentsForCustomer({bool isNeedToRebuild = false}) async {
|
|
if (isNeedToRebuild) setState(ViewState.busy);
|
|
|
|
myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters();
|
|
// myFilteredAppointments = myAppointments;
|
|
|
|
setState(ViewState.idle);
|
|
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
|
|
|
|
myUpComingAppointments = myAppointments
|
|
.where((element) =>
|
|
(element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
|
|
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
|
|
.toList();
|
|
notifyListeners();
|
|
}
|
|
|
|
AppointmentSlots? appointmentSlots;
|
|
|
|
Future<void> getAppointmentSlotsInfo({required int branchID, required BuildContext context, bool isNeedToRebuild = false}) async {
|
|
if (isNeedToRebuild) setState(ViewState.busy);
|
|
try {
|
|
GenericRespModel genericRespModel = await appointmentRepo.getAppointmentSlots(branchID: branchID, fromDate: selectedDateForAppointments, toDate: selectedDateForAppointments);
|
|
if (genericRespModel.messageStatus == 1) {
|
|
appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data);
|
|
} else {
|
|
Utils.showToast(genericRespModel.message.toString());
|
|
}
|
|
} catch (e) {
|
|
Utils.showToast(e.toString());
|
|
}
|
|
}
|
|
|
|
Future<void> getMyAppointmentsForProvider({required int branchID}) async {
|
|
setState(ViewState.busy);
|
|
myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters(branchID: branchID);
|
|
myFilteredAppointments = myAppointments;
|
|
myUpComingAppointments = myAppointments
|
|
.where((element) =>
|
|
(element.appointmentStatusEnum == AppointmentStatusEnum.confirmed || element.appointmentStatusEnum == AppointmentStatusEnum.booked) &&
|
|
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
|
|
.toList();
|
|
notifyListeners();
|
|
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
Future<bool> updateAppointmentStatus({required int appointmentId, required AppointmentStatusEnum appointmentStatusEnum, bool isNeedToRebuild = false}) async {
|
|
if (isNeedToRebuild) setState(ViewState.busy);
|
|
try {
|
|
GenericRespModel genericRespModel = await appointmentRepo.updateAppointmentStatus(appointmentId: appointmentId, appointmentStatusEnum: appointmentStatusEnum);
|
|
|
|
if (genericRespModel.messageStatus == 1) {
|
|
Utils.showToast(LocaleKeys.appointmentStatusUpdated.tr());
|
|
return true;
|
|
} else {
|
|
Utils.showToast(genericRespModel.message.toString());
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
Utils.showToast(e.toString());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> updateAppointmentPaymentStatus(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
|
|
if (isNeedToRebuild) setState(ViewState.busy);
|
|
try {
|
|
GenericRespModel genericRespModel = await appointmentRepo.updateAppointmentPaymentStatus(map);
|
|
|
|
if (genericRespModel.messageStatus == 1) {
|
|
Utils.showToast(LocaleKeys.paymentStatusUpdated.tr());
|
|
return true;
|
|
} else {
|
|
Utils.showToast(genericRespModel.message.toString());
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
Utils.showToast(e.toString());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool isShowMergeButton() {
|
|
return myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList!.every((appointment) => appointment.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
|
|
myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList!.length > 1;
|
|
}
|
|
|
|
Future<GenericRespModel> createMergeAppointment(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
|
|
if (isNeedToRebuild) setState(ViewState.busy);
|
|
GenericRespModel genericRespModel = await appointmentRepo.createMergeAppointment(map);
|
|
|
|
return genericRespModel;
|
|
}
|
|
|
|
bool inNeedToEnableMergeButton = false;
|
|
|
|
void 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 dateIndex = serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!;
|
|
serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].availableSlots![slotIndex].isSelected = true;
|
|
serviceAppointmentScheduleList[scheduleIndex].selectedCustomTimeDateSlotModel!.availableSlots = serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![dateIndex].availableSlots!;
|
|
notifyListeners();
|
|
}
|
|
|
|
double amountToPayForAppointment = 0.0;
|
|
double totalAmount = 0.0;
|
|
|
|
List<ItemData> serviceItemsFromApi = [];
|
|
|
|
ProviderProfileModel? providerProfileModel;
|
|
|
|
int selectedSubServicesCounter = 0;
|
|
|
|
void onItemUpdateOrSelected(int index, bool selected, int itemId) {
|
|
int serviceIndex = servicesInCurrentAppointment.indexWhere((element) => element.serviceId == currentServiceSelection!.serviceId!);
|
|
|
|
serviceItemsFromApi[index].isUpdateOrSelected = selected;
|
|
serviceItemsFromApi[index].isHomeSelected = isHomeTapped;
|
|
log(" serviceIndex: $serviceIndex");
|
|
|
|
if (selected) {
|
|
selectedSubServicesCounter = selectedSubServicesCounter + 1;
|
|
selectSubServicesError = "";
|
|
|
|
if (!ifItemAlreadySelected(serviceItemsFromApi[index].id!)) {
|
|
currentServiceSelection!.serviceItems!.add(serviceItemsFromApi[index]);
|
|
allSelectedItemsInAppointments.add(serviceItemsFromApi[index]);
|
|
log("Here with: ${serviceItemsFromApi[index].description}");
|
|
if (serviceIndex != -1) {
|
|
// servicesInCurrentAppointment[serviceIndex].serviceItems!.add(serviceItemsFromApi[index]);
|
|
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
|
|
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice + double.parse((serviceItemsFromApi[index].price) ?? "0.0");
|
|
}
|
|
}
|
|
} else {
|
|
selectedSubServicesCounter = selectedSubServicesCounter - 1;
|
|
currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId);
|
|
allSelectedItemsInAppointments.removeWhere((element) => element.id == itemId);
|
|
if (serviceIndex != -1) {
|
|
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice =
|
|
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice - double.parse((serviceItemsFromApi[index].price) ?? "0.0");
|
|
if (servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice < 0.0) {
|
|
servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice = servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice * -1;
|
|
}
|
|
// servicesInCurrentAppointment[serviceIndex].serviceItems!.removeWhere((element) => element.id == itemId);
|
|
}
|
|
}
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> applyFilterOnBranches({required int index}) async {
|
|
if (branchesCategoriesFilterOptions.isEmpty) return;
|
|
for (var value in branchesCategoriesFilterOptions) {
|
|
value.isSelected = false;
|
|
}
|
|
branchesCategoriesFilterOptions[index].isSelected = true;
|
|
|
|
await getBranchesBasedOnCategoryFilters(serviceId: branchesCategoriesFilterOptions[index].id);
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<List<ItemData>> getServiceItems({required int serviceId}) async {
|
|
setState(ViewState.busy);
|
|
serviceItemsFromApi.clear();
|
|
serviceItemsFromApi = await branchRepo.getServiceItems(serviceId: serviceId);
|
|
selectedSubServicesCounter = 0;
|
|
for (var item in serviceItemsFromApi) {
|
|
if (ifItemAlreadySelected(item.id!)) {
|
|
item.isUpdateOrSelected = true;
|
|
selectedSubServicesCounter++;
|
|
}
|
|
}
|
|
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 (currentLocationInfoModel == null || currentLocationInfoModel!.address == "") {
|
|
updatePickHomeLocationError(GlobalConsts.homeLocationEmptyError);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool validateItemsSelection() {
|
|
for (var value in serviceItemsFromApi) {
|
|
if (value.isUpdateOrSelected!) {
|
|
return true;
|
|
}
|
|
}
|
|
selectSubServicesError = LocaleKeys.selectOneSubService.tr();
|
|
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 const AppointmentServicePickBottomSheet();
|
|
},
|
|
);
|
|
}
|
|
|
|
void priceBreakDownClicked(BuildContext context, ServiceModel selectedService) {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
enableDrag: true,
|
|
builder: (BuildContext context) {
|
|
double totalKms = double.parse(selectedService.servicelocationInfo.distanceToBranch.toStringAsFixed(2));
|
|
double pricePerKm = double.parse(selectedService.servicelocationInfo.homeChargesInCurrentService.toStringAsFixed(2));
|
|
return InfoBottomSheet(
|
|
title: LocaleKeys.chargesBreakdown.tr().toText(fontSize: 24, isBold: true),
|
|
description: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
LocaleKeys.services.tr().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} ${LocaleKeys.sar.tr()}".toText(fontSize: 12, isBold: true),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
"${selectedService.currentTotalServicePrice} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
|
|
],
|
|
),
|
|
if (selectedService.isHomeSelected) ...[
|
|
20.height,
|
|
LocaleKeys.homeLocation.tr().toText(fontSize: 16, isBold: true),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
"${totalKms}km ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
|
|
"$pricePerKm x $totalKms".toText(fontSize: 12, isBold: true),
|
|
],
|
|
),
|
|
8.height,
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
"${((pricePerKm) * totalKms).toStringAsFixed(2)} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
|
|
],
|
|
),
|
|
],
|
|
30.height,
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
LocaleKeys.totalAmount.tr().toText(fontSize: 16, isBold: true),
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
(selectedService.isHomeSelected ? ((selectedService.currentTotalServicePrice) + (pricePerKm * totalKms)).toStringAsFixed(2) : "${selectedService.currentTotalServicePrice}")
|
|
.toText(fontSize: 29, isBold: true),
|
|
2.width,
|
|
LocaleKeys.sar.tr().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(LocaleKeys.selectAppointmentTime.tr());
|
|
return;
|
|
}
|
|
navigateWithName(context, AppRoutes.reviewAppointmentView);
|
|
}
|
|
|
|
void onServicesNextPressed(BuildContext context) async {
|
|
if (allSelectedItemsInAppointments.isEmpty) {
|
|
Utils.showToast(LocaleKeys.pleaseSelectService.tr());
|
|
return;
|
|
}
|
|
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(LocaleKeys.noAppointmentAvailable.tr());
|
|
return;
|
|
}
|
|
totalAmount = 0.0;
|
|
amountToPayForAppointment = 0.0;
|
|
for (var schedule in serviceAppointmentScheduleList) {
|
|
amountToPayForAppointment = amountToPayForAppointment + (schedule.amountToPay ?? 0.0);
|
|
totalAmount = totalAmount + (schedule.amountTotal ?? 0.0);
|
|
for (var service in schedule.servicesListInAppointment!) {
|
|
int index = servicesInCurrentAppointment.indexWhere((element) => element.serviceProviderServiceId == service.serviceProviderServiceId);
|
|
if (index != -1) {
|
|
if (servicesInCurrentAppointment[index].isHomeSelected) {
|
|
service.servicelocationInfo = servicesInCurrentAppointment[index].servicelocationInfo;
|
|
schedule.locationInfoModel = servicesInCurrentAppointment[index].servicelocationInfo;
|
|
totalAmount =
|
|
totalAmount + ((servicesInCurrentAppointment[index].servicelocationInfo.distanceToBranch) * servicesInCurrentAppointment[index].servicelocationInfo.homeChargesInCurrentService);
|
|
schedule.totalLocationCharges = schedule.totalLocationCharges! +
|
|
(servicesInCurrentAppointment[index].servicelocationInfo.distanceToBranch * servicesInCurrentAppointment[index].servicelocationInfo.homeChargesInCurrentService);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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(LocaleKeys.noAppointmentAvailable.tr());
|
|
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());
|
|
getMyAppointmentsForCustomer();
|
|
Utils.hideLoading(context);
|
|
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
|
|
}
|
|
} catch (e) {
|
|
Utils.showToast(e.toString());
|
|
}
|
|
}
|
|
|
|
// REPORT A COMPLAINT
|
|
|
|
String complaintDescription = "";
|
|
String complaintDescriptionError = "";
|
|
|
|
void updateComplaintDescription(String value) {
|
|
complaintDescription = value;
|
|
if (value.isNotEmpty) {
|
|
complaintDescriptionError = "";
|
|
}
|
|
}
|
|
|
|
Future buildComplaintBottomSheet({required int customerID, required int complainType, required String customerName, required BuildContext context}) {
|
|
return showModalBottomSheet(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
enableDrag: true,
|
|
builder: (BuildContext context) {
|
|
return InfoBottomSheet(
|
|
title: LocaleKeys.reportComplaint.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
|
|
description: Padding(
|
|
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
if (customerName.isNotEmpty) ...[
|
|
("${LocaleKeys.customerName.tr()}: $customerName").toText(fontSize: 15, color: MyColors.lightTextColor),
|
|
],
|
|
10.height,
|
|
TxtField(
|
|
maxLines: 5,
|
|
value: complaintDescription,
|
|
errorValue: complaintDescriptionError,
|
|
keyboardType: TextInputType.text,
|
|
hint: LocaleKeys.description.tr(),
|
|
onChanged: (v) => updateComplaintDescription(v),
|
|
),
|
|
25.height,
|
|
ShowFillButton(
|
|
title: LocaleKeys.submit.tr(),
|
|
onPressed: () async {
|
|
if (complaintDescription.isEmpty) {
|
|
Utils.showToast(LocaleKeys.descriptionCannotBeEmpty.tr());
|
|
return;
|
|
}
|
|
final status = await reportComplaintAgainstCustomer(
|
|
customerID: customerID,
|
|
comment: complaintDescription,
|
|
complaintType: complainType, // 1 for Appointment and 2 for Requests
|
|
context: context,
|
|
);
|
|
|
|
if (status) {
|
|
updateComplaintDescription("");
|
|
pop(context);
|
|
}
|
|
},
|
|
maxWidth: double.infinity,
|
|
),
|
|
19.height,
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
Future<bool> reportComplaintAgainstCustomer({required int customerID, required String comment, required int complaintType, required BuildContext context}) async {
|
|
Utils.showLoading(context);
|
|
try {
|
|
GenericRespModel genericRespModel = await commonRepo.createComplainFromProvider(customerId: customerID, comment: comment, complainType: complaintType);
|
|
Utils.showToast(genericRespModel.message.toString());
|
|
Utils.hideLoading(context);
|
|
return genericRespModel.messageStatus == 1;
|
|
} catch (e, s) {
|
|
logger.e(s);
|
|
Utils.hideLoading(context);
|
|
Utils.showToast(e.toString());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// BRANCHES RELATED
|
|
|
|
List<BranchDetailModel> nearbyBranches = [];
|
|
List<BranchDetailModel> myRecentBranches = [];
|
|
BranchDetailModel? selectedBranchModel;
|
|
|
|
List<ServiceModel> branchServices = [];
|
|
|
|
Future<void> populateBranchesFilterList() async {
|
|
if (branchesCategoriesFilterOptions.isNotEmpty) return;
|
|
branchesCategoriesFilterOptions.clear();
|
|
setOnlyState(ViewState.busy);
|
|
Services services = await branchRepo.fetchServicesByCategoryId(serviceCategoryId: -1);
|
|
services.data?.forEach((element) {
|
|
branchesCategoriesFilterOptions.add(FilterListModel(id: element.id ?? 0, isSelected: false, iconUrl: element.serviceIconUrl ?? "", title: element.description ?? ""));
|
|
});
|
|
branchesCategoriesFilterOptions.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 selectedFilter = branchesCategoriesFilterOptions.firstWhere((element) => element.isSelected);
|
|
log("selectedFilter: ${selectedFilter.id}");
|
|
|
|
if (selectedFilter.id == 0) {
|
|
nearbyBranches = await branchRepo.getAllNearBranchAndServices(
|
|
latitude: AppState().currentLocation.latitude,
|
|
longitude: AppState().currentLocation.longitude,
|
|
);
|
|
} else {
|
|
nearbyBranches = await branchRepo.getBranchesByFilters(
|
|
categoryIdsList: [selectedFilter.id],
|
|
latitude: AppState().currentLocation.latitude,
|
|
longitude: AppState().currentLocation.longitude,
|
|
);
|
|
}
|
|
setState(ViewState.idle);
|
|
return;
|
|
}
|
|
nearbyBranches = await branchRepo.getAllNearBranchAndServices(
|
|
latitude: AppState().currentLocation.latitude,
|
|
longitude: AppState().currentLocation.longitude,
|
|
);
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
Future<void> getMyRecentBranches({bool isNeedToRebuild = false}) async {
|
|
myRecentBranches.clear();
|
|
if (isNeedToRebuild) setState(ViewState.busy);
|
|
myRecentBranches = await branchRepo.getMyRecentBranchesWithServices();
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
void getBranchCategories() async {
|
|
for (var value in selectedBranchModel!.branchServices!) {
|
|
if (!isCategoryAlreadyPresent(value.categoryId!)) {
|
|
branchCategories.add(DropValue(value.categoryId!, value.categoryName!, ""));
|
|
}
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> getBranchServices({required int categoryId}) async {
|
|
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
isHomeTapped = false;
|
|
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;
|
|
}
|
|
|
|
Future<void> getProviderProfileWithBranchesAndServices(int providerId) async {
|
|
double latitude = AppState().currentLocation.latitude;
|
|
double longitude = AppState().currentLocation.longitude;
|
|
setState(ViewState.busy);
|
|
try {
|
|
providerProfileModel = await branchRepo.getBranchAndServicesByProviderId(providerId, latitude: latitude, longitude: longitude);
|
|
} catch (e, s) {
|
|
logger.e(s);
|
|
setState(ViewState.idle);
|
|
Utils.showToast(e.toString());
|
|
}
|
|
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;
|
|
}
|
|
|
|
ifAlreadyExistForStringValue({required List<String> list, required String value}) {
|
|
int index = list.indexWhere((element) {
|
|
log("element: $element");
|
|
log("value: $value");
|
|
|
|
return element == value;
|
|
});
|
|
|
|
if (index != -1) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Rating filter
|
|
|
|
double branchFilterByRating = 4.0;
|
|
|
|
updateBranchFilterByRating(double value) {
|
|
branchFilterByRating = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
List<DropValue> categoryDropList = [];
|
|
List<DropValue> providersDropList = [];
|
|
List<DropValue> servicesDropList = [];
|
|
List<DropValue> itemsDropList = [];
|
|
List<DropValue> serviceDeliveryTypesDropList = [];
|
|
|
|
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() 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" : 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> fetchAllItems() async {
|
|
if (itemsDropList.isNotEmpty) return;
|
|
itemsDropList.clear();
|
|
setState(ViewState.busy);
|
|
List<ItemData> itemsList = await branchRepo.getServiceItems(serviceId: -1); // to get all services
|
|
|
|
for (ItemData element in itemsList) {
|
|
if (element.name != null && element.name!.isNotEmpty) {
|
|
itemsDropList.add(
|
|
DropValue(
|
|
element.id ?? 0,
|
|
element.name ?? "",
|
|
"",
|
|
),
|
|
);
|
|
}
|
|
}
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
Future<void> fetchAllServiceDeliveryTypes() async {
|
|
if (serviceDeliveryTypesDropList.isNotEmpty) return;
|
|
serviceDeliveryTypesDropList.clear();
|
|
setState(ViewState.busy);
|
|
|
|
List<EnumsModel> enums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.serviceDeliveryTypeEnumId);
|
|
|
|
for (EnumsModel element in enums) {
|
|
serviceDeliveryTypesDropList.add(
|
|
DropValue(
|
|
element.enumValue,
|
|
element.enumValueStr,
|
|
"",
|
|
),
|
|
);
|
|
}
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
Future<void> populateDataForBranchesFilter() async {
|
|
await fetchAllProviders();
|
|
await fetchAllCategories();
|
|
await fetchAllServices();
|
|
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: AppState().currentLocation.latitude,
|
|
longitude: AppState().currentLocation.longitude,
|
|
);
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
Future<void> getBranchesBasedOnCategoryFilters({required int serviceId}) async {
|
|
setState(ViewState.busy);
|
|
if (serviceId == 0) {
|
|
await getAllNearBranches();
|
|
return;
|
|
}
|
|
nearbyBranches.clear();
|
|
nearbyBranches = await branchRepo.getBranchesByFilters(
|
|
serviceIdsList: [serviceId],
|
|
latitude: AppState().currentLocation.latitude,
|
|
longitude: AppState().currentLocation.longitude,
|
|
);
|
|
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,
|
|
latitude: AppState().currentLocation.latitude,
|
|
longitude: AppState().currentLocation.longitude,
|
|
);
|
|
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();
|
|
await fetchAllCategories();
|
|
await fetchAllServices();
|
|
await fetchAllItems();
|
|
await fetchAllServiceDeliveryTypes();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
List<DropValue> appointmentFilterItemsSearchHistory = [];
|
|
|
|
void removeAppointmentFilterItemsSearchHistory({bool isClear = false, required int index}) {
|
|
if (isClear) {
|
|
appointmentFilterItemsSearchHistory.clear();
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
appointmentFilterItemsSearchHistory.removeAt(index);
|
|
if (appointmentFilterItemsSearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
|
|
// appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
void addAppointmentFilterItemsSearchHistory({required DropValue value}) {
|
|
if (appointmentFilterItemsSearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
|
|
}
|
|
appointmentFilterItemsSearchHistory.add(value);
|
|
notifyListeners();
|
|
}
|
|
|
|
SelectionModel appointmentFilterSelectedItemId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateAppointmentFilterSelectedItemId(SelectionModel id, {bool isForSearch = false}) async {
|
|
if (isForSearch) {
|
|
DropValue itemsDrop = itemsDropList.firstWhere((element) => element.id == id.selectedId);
|
|
if (!ifAlreadyExist(list: appointmentFilterItemsSearchHistory, value: itemsDrop)) {
|
|
addAppointmentFilterItemsSearchHistory(value: itemsDrop);
|
|
}
|
|
}
|
|
// appointmentFilterSelectedServiceId = id;
|
|
notifyListeners();
|
|
}
|
|
|
|
// Customer Name Filter for PROVIDER ONLY
|
|
|
|
List<String> appointmentFilterCustomerNameSearchHistory = [];
|
|
String currentCustomerNameFilter = '';
|
|
|
|
void onCurrentCustomerNameFilterChanged(var value) {
|
|
currentCustomerNameFilter = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
void removeAppointmentFilterCustomerNameSearchHistory({bool isClear = false, required int index}) {
|
|
if (isClear) {
|
|
appointmentFilterCustomerNameSearchHistory.clear();
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
appointmentFilterCustomerNameSearchHistory.removeAt(index);
|
|
if (appointmentFilterCustomerNameSearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
|
|
// appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
void addAppointmentFilterCustomerNameSearchHistory({required String value}) {
|
|
if (appointmentFilterCustomerNameSearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
|
|
}
|
|
|
|
if (!ifAlreadyExistForStringValue(list: appointmentFilterCustomerNameSearchHistory, value: value)) {
|
|
appointmentFilterCustomerNameSearchHistory.add(value);
|
|
currentCustomerNameFilter = "";
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
// MOBILE PHONE Filter for PROVIDER ONLY
|
|
|
|
String currentMobilePhoneFilter = '';
|
|
|
|
void onCurrentMobilePhoneFilterChanged(var value) {
|
|
currentMobilePhoneFilter = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
List<String> appointmentFilterMobilePhoneSearchHistory = [];
|
|
|
|
void removeAppointmentFilterMobilePhoneSearchHistory({bool isClear = false, required int index}) {
|
|
if (isClear) {
|
|
appointmentFilterMobilePhoneSearchHistory.clear();
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
appointmentFilterMobilePhoneSearchHistory.removeAt(index);
|
|
if (appointmentFilterMobilePhoneSearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
|
|
// appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
void addAppointmentFilterMobilePhoneSearchHistory({required String value}) {
|
|
if (appointmentFilterMobilePhoneSearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
|
|
}
|
|
|
|
if (!ifAlreadyExistForStringValue(list: appointmentFilterMobilePhoneSearchHistory, value: value)) {
|
|
appointmentFilterMobilePhoneSearchHistory.add(value);
|
|
currentMobilePhoneFilter = "";
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
// Service Delivery Types For PROVIDER ONLY
|
|
|
|
List<DropValue> appointmentFilterServiceDeliverySearchHistory = [];
|
|
|
|
void removeAppointmentFilterServiceDeliverySearchHistory({bool isClear = false, required int index}) {
|
|
if (isClear) {
|
|
appointmentFilterServiceDeliverySearchHistory.clear();
|
|
notifyListeners();
|
|
return;
|
|
}
|
|
appointmentFilterServiceDeliverySearchHistory.removeAt(index);
|
|
if (appointmentFilterServiceDeliverySearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter - 1);
|
|
// appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
void addAppointmentFilterServiceDeliverySearchHistory({required DropValue value}) {
|
|
if (appointmentFilterServiceDeliverySearchHistory.isEmpty) {
|
|
updateAppointmentFiltersCounter(appointmentFiltersCounter + 1);
|
|
}
|
|
|
|
appointmentFilterServiceDeliverySearchHistory.add(value);
|
|
notifyListeners();
|
|
}
|
|
|
|
SelectionModel appointmentFilterSelectedServiceDeliveryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateAppointmentFilterSelectedServiceDeliveryId(SelectionModel id, {bool isForSearch = false}) async {
|
|
if (isForSearch) {
|
|
DropValue itemsDrop = serviceDeliveryTypesDropList.firstWhere((element) => element.id == id.selectedId);
|
|
if (!ifAlreadyExist(list: appointmentFilterServiceDeliverySearchHistory, value: itemsDrop)) {
|
|
addAppointmentFilterServiceDeliverySearchHistory(value: itemsDrop);
|
|
}
|
|
}
|
|
// appointmentFilterSelectedServiceId = id;
|
|
notifyListeners();
|
|
}
|
|
|
|
void clearAppointmentFilterSelections() {
|
|
appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
appointmentFilterSelectedItemId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
appointmentFilterSelectedServiceDeliveryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
}
|
|
|
|
void clearAppointmentFilters() {
|
|
appointmentFilterServiceDeliverySearchHistory.clear();
|
|
appointmentFilterCustomerNameSearchHistory.clear();
|
|
appointmentFilterMobilePhoneSearchHistory.clear();
|
|
appointmentFilterItemsSearchHistory.clear();
|
|
appointmentFilterServicesSearchHistory.clear();
|
|
appointmentFilterCategorySearchHistory.clear();
|
|
appointmentFilterProviderSearchHistory.clear();
|
|
appointmentFilterBranchSearchHistory.clear();
|
|
appointmentFiltersCounter = 0;
|
|
clearAppointmentFilterSelections();
|
|
|
|
if (AppState().currentAppType == AppType.provider) {
|
|
getMyAppointmentsForProvider(branchID: selectedBranchIdForAppointments);
|
|
} else {
|
|
getMyAppointmentsForCustomer();
|
|
}
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> getAppointmentsBasedOnFiltersForCustomer() async {
|
|
setState(ViewState.busy);
|
|
List<String> providersIdsList = [];
|
|
if (appointmentFilterProviderSearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterProviderSearchHistory) {
|
|
providersIdsList.add(element.id.toString());
|
|
}
|
|
}
|
|
List<String> categoryIdsList = [];
|
|
if (appointmentFilterCategorySearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterCategorySearchHistory) {
|
|
categoryIdsList.add(element.id.toString());
|
|
}
|
|
}
|
|
List<String> servicesIdsList = [];
|
|
if (appointmentFilterServicesSearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterServicesSearchHistory) {
|
|
servicesIdsList.add(element.id.toString());
|
|
}
|
|
}
|
|
List<String> itemIdsList = [];
|
|
if (appointmentFilterItemsSearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterItemsSearchHistory) {
|
|
itemIdsList.add(element.id.toString());
|
|
}
|
|
}
|
|
List<String> branchesIdsList = [];
|
|
if (appointmentFilterBranchSearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterBranchSearchHistory) {
|
|
branchesIdsList.add(element.id.toString());
|
|
}
|
|
}
|
|
|
|
myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters(
|
|
providerIdsList: providersIdsList,
|
|
categoryIdsList: categoryIdsList,
|
|
serviceIdsList: servicesIdsList,
|
|
itemIdsList: itemIdsList,
|
|
branchIdsList: branchesIdsList,
|
|
);
|
|
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
String selectedDateForAppointments = "";
|
|
|
|
Future<void> getAppointmentsBasedOnFiltersForProviders({required int branchID}) async {
|
|
setState(ViewState.busy);
|
|
|
|
List<String> servicesIdsList = [];
|
|
if (appointmentFilterServicesSearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterServicesSearchHistory) {
|
|
servicesIdsList.add(element.id.toString());
|
|
}
|
|
}
|
|
|
|
List<String> customerNamesList = [];
|
|
if (appointmentFilterCustomerNameSearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterCustomerNameSearchHistory) {
|
|
customerNamesList.add(element.toString());
|
|
}
|
|
}
|
|
|
|
List<String> customerPhonesList = [];
|
|
if (appointmentFilterMobilePhoneSearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterMobilePhoneSearchHistory) {
|
|
customerPhonesList.add(element.toString());
|
|
}
|
|
}
|
|
List<String> customerDeliveryTypesList = [];
|
|
if (appointmentFilterServiceDeliverySearchHistory.isNotEmpty) {
|
|
for (var element in appointmentFilterServiceDeliverySearchHistory) {
|
|
customerDeliveryTypesList.add(element.id.toString());
|
|
}
|
|
}
|
|
|
|
log("customerNamesList: $customerNamesList");
|
|
log("customerPhonesList: $customerPhonesList");
|
|
log("customerDeliveryTypesList: $customerDeliveryTypesList");
|
|
log("servicesIdsList: $servicesIdsList");
|
|
myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters(
|
|
branchID: branchID,
|
|
customerNamesList: customerNamesList,
|
|
customerPhonesList: customerPhonesList,
|
|
deliveryTypeIdsList: customerDeliveryTypesList,
|
|
serviceProviderServiceIdsList: servicesIdsList,
|
|
fromDate: '',
|
|
toDate: '');
|
|
|
|
log(" myFilteredAppointments : ${myFilteredAppointments.length}");
|
|
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
Future<bool> addProviderToFavorite({required int serviceProviderID, required BuildContext context}) async {
|
|
Utils.showLoading(context);
|
|
try {
|
|
GenericRespModel genericRespModel = await branchRepo.addProviderToFavourite(providerID: serviceProviderID);
|
|
Utils.showToast(genericRespModel.message.toString());
|
|
Utils.hideLoading(context);
|
|
return genericRespModel.messageStatus == 1;
|
|
} catch (e, s) {
|
|
logger.e(s);
|
|
Utils.hideLoading(context);
|
|
Utils.showToast(e.toString());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<bool> removeProviderFromFavorite({required int serviceProviderID, required BuildContext context}) async {
|
|
Utils.showLoading(context);
|
|
|
|
try {
|
|
GenericRespModel genericRespModel = await branchRepo.removeProviderFromFavourite(providerID: serviceProviderID);
|
|
Utils.hideLoading(context);
|
|
Utils.showToast(genericRespModel.message.toString());
|
|
return genericRespModel.messageStatus == 1;
|
|
} catch (e, s) {
|
|
logger.e(s);
|
|
Utils.hideLoading(context);
|
|
Utils.showToast(e.toString());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
List<ProviderProfileModel> myFavProvidersList = [];
|
|
|
|
Future<void> getMyFavoriteProviders() async {
|
|
myFavProvidersList.clear();
|
|
setState(ViewState.busy);
|
|
try {
|
|
myFavProvidersList = await branchRepo.getMyFavoriteProviders();
|
|
setState(ViewState.idle);
|
|
} catch (e, s) {
|
|
logger.e(s);
|
|
setState(ViewState.idle);
|
|
Utils.showToast(e.toString());
|
|
}
|
|
}
|
|
|
|
List<BranchRatingModel> currentBranchReviews = [];
|
|
bool isReadMoreEnabled = false;
|
|
|
|
void resetCurrentBranchRatings() {
|
|
currentBranchReviews.clear();
|
|
isReadMoreEnabled = false;
|
|
}
|
|
|
|
updateIsReadMoreEnabled(var value) {
|
|
isReadMoreEnabled = value;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> getReviewsByBranchId({required int serviceProviderBranchID}) async {
|
|
setState(ViewState.busy);
|
|
try {
|
|
currentBranchReviews = await branchRepo.getBranchRatings(serviceProviderBranchID: serviceProviderBranchID);
|
|
} catch (e, s) {
|
|
logger.e(s);
|
|
setState(ViewState.idle);
|
|
Utils.showToast(e.toString());
|
|
}
|
|
setState(ViewState.idle);
|
|
}
|
|
|
|
// Chat Related
|
|
|
|
Future<void> getGeneralChatsListForProvider({required BuildContext context}) async {
|
|
try {
|
|
// Utils.showLoading(context);
|
|
// List<BuyersChatForAdzsModel> buyersChatList = await appointmentRepo.getChatBuyersForAds(adsID: adsID);
|
|
// Utils.hideLoading(context);
|
|
// buyersChatListForAds.clear();
|
|
// buyersChatListForAds = buyersChatList;
|
|
notifyListeners();
|
|
} catch (e) {
|
|
logger.i(e.toString());
|
|
Utils.showToast(e.toString());
|
|
Utils.hideLoading(context);
|
|
}
|
|
}
|
|
|
|
void onGeneralChatMessagesButtonPressed({required BuildContext context}) async {
|
|
final myUserID = AppState().getUser.data!.userInfo!.userId;
|
|
// if (adDetailsModel.isMyAd != null && adDetailsModel.isMyAd!) {
|
|
// await getGeneralChatsListForProvider(context: context);
|
|
// // navigateWithName(context, AppRoutes.generalChatsListForProvider, arguments: buyersChatListForAds);
|
|
// } else {
|
|
// ChatViewArgumentsForAd chatViewArgumentsForAd = ChatViewArgumentsForAd(receiverUserID: adDetailsModel.userID, adsID: adDetailsModel.id);
|
|
// ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.ads, chatViewArgumentsForAd: chatViewArgumentsForAd);
|
|
// final chatVM = context.read<ChatVM>();
|
|
// await chatVM
|
|
// .getUsersChatMessagesForAd(
|
|
// context: context,
|
|
// isForBuyer: true,
|
|
// adsChatBuyerId: 1,
|
|
// adID: adDetailsModel.id,
|
|
// userID: myUserID,
|
|
// senderName: adDetailsModel.adOwnerName,
|
|
// )
|
|
// .whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments));
|
|
// }
|
|
}
|
|
}
|