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));
// }
}
}