From 69fc3346c6d86f9b27fd3b6fea797955170bda84 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Tue, 14 May 2024 18:12:03 +0300 Subject: [PATCH] Added Ads Filter and Appointments Filter --- lib/classes/consts.dart | 1 + lib/config/routes.dart | 29 +- lib/repositories/appointment_repo.dart | 188 +++++++---- lib/repositories/common_repo.dart | 16 +- lib/view_models/ad_view_model.dart | 100 ++++++ lib/view_models/appointments_view_model.dart | 319 ++++++++++++++++-- lib/views/advertisement/ads_filter_view.dart | 46 ++- .../appointments_filter_view.dart | 210 ++++++++++++ lib/views/branches/branches_filter_view.dart | 2 +- lib/views/user/register_selection_page.dart | 24 +- 10 files changed, 797 insertions(+), 138 deletions(-) create mode 100644 lib/views/appointments/appointments_filter_view.dart diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 7ce2de6..31e27dc 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -55,6 +55,7 @@ class ApiConsts { //Appointment APIs static String serviceProvidersAppointmentGet = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointment_Get"; + static String customersAppointmentGetByFilters = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointmentSearchFiltersByCustomer_Get"; static String serviceCategoryGet = "${baseUrlServices}api/Master/ServiceCategory_Get"; static String serviceItemsGet = "${baseUrlServices}api/ServiceProviders/ServiceItem_Get"; static String GetServiceItemAppointmentScheduleSlots = "${baseUrlServices}api/ServiceProviders/ServiceItemAppointmentScheduleSlots_GetByAppointmentType"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 36e8503..6ea75a3 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -47,13 +47,18 @@ class AppRoutes { static const String changeEmailPage = "/changeEmailPage"; static const String editAccountPage = "/editAccoundPage"; + static const String dashboard = "/dashboard"; static const String bookProviderAppView = "/bookProviderAppView"; + + + // Appoinments static const String appointmentDetailView = "/appointmentDetailView"; static const String bookAppointmenServicesView = "/bookAppointmenServicesView"; static const String bookAppointmenSchedulesView = "/bookAppointmenSchedulesView"; static const String bookAppointmentsItemView = "/bookAppointmentsItemView"; static const String reviewAppointmentView = "/reviewAppointmentView"; + static const String appoinmentSearchFilterPage = "/appoinmentSearchFilterPage"; //Advertisement static const String selectAdTypeView = "/selectAdTypeView"; @@ -104,12 +109,28 @@ class AppRoutes { forgetPassword: (context) => const ForgetPasswordPage(), loginVerification: (context) => const LoginVerificationPage(), loginWithPassword: (context) => const LoginWithPassword(), - loginMethodSelection: (context) => LoginMethodSelectionPage(ModalRoute.of(context)!.settings.arguments as String), - completeProfile: (context) => CompleteProfilePage(ModalRoute.of(context)!.settings.arguments as RegisterUserRespModel), + loginMethodSelection: (context) => + LoginMethodSelectionPage(ModalRoute + .of(context)! + .settings + .arguments as String), + completeProfile: (context) => + CompleteProfilePage(ModalRoute + .of(context)! + .settings + .arguments as RegisterUserRespModel), verifyPassword: (context) => VerifyPasswordPage(), - confirmNewPasswordPage: (context) => ConfirmNewPasswordPage(ModalRoute.of(context)!.settings.arguments as String), + confirmNewPasswordPage: (context) => + ConfirmNewPasswordPage(ModalRoute + .of(context)! + .settings + .arguments as String), changePassword: (context) => const ChangePasswordPage(), - forgetPasswordMethodPage: (context) => ForgetPasswordMethodPage(ModalRoute.of(context)!.settings.arguments as String), + forgetPasswordMethodPage: (context) => + ForgetPasswordMethodPage(ModalRoute + .of(context)! + .settings + .arguments as String), changeMobilePage: (context) => ChangeMobilePage(), changeEmailPage: (context) => const ChangeEmailPage(), editAccountPage: (context) => const EditAccountPage(), diff --git a/lib/repositories/appointment_repo.dart b/lib/repositories/appointment_repo.dart index 126bc6e..24eebc1 100644 --- a/lib/repositories/appointment_repo.dart +++ b/lib/repositories/appointment_repo.dart @@ -4,16 +4,22 @@ import 'package:mc_common_app/api/api_client.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/dependencies.dart'; +import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; import 'package:mc_common_app/models/appointments_models/schedule_model.dart'; import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/m_response.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/services.dart'; -import '../models/appointments_models/appointment_list_model.dart'; - abstract class AppointmentRepo { - Future> getMyAppointments(Map map); + Future> getMyAppointmentsForProvider(Map map); + + Future> getMyAppointmentsForCustomersByFilters({ + List? providerIdsList, + List? categoryIdsList, + List? serviceIdsList, + List? branchIdsList, + }); Future updateAppointmentStatus(Map map); @@ -46,57 +52,60 @@ abstract class AppointmentRepo { } class AppointmentRepoImp implements AppointmentRepo { + ApiClient apiClient = injector.get(); + AppState appState = injector.get(); + @override Future getAllServices(String branchId) async { Map map = {"ProviderBranchID": branchId}; - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, token: t, queryParameters: map); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.getJsonForObject((json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, token: t, queryParameters: map); } @override Future createSchedule(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, token: t); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, token: t); } @override Future addServicesInSchedule(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createGroup, map, token: t); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createGroup, map, token: t); } @override Future> getSchedules(String branchId) async { Map map = {"ServiceProviderBranchID": branchId}; - String t = AppState().getUser.data!.accessToken ?? ""; + String t = appState.getUser.data!.accessToken ?? ""; - GenericRespModel adsGenericModel = await injector.get().getJsonForObject( - (json) => GenericRespModel.fromJson(json), - ApiConsts.getSchedule, - token: t, - queryParameters: map, - ); + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.getSchedule, + token: t, + queryParameters: map, + ); return List.generate(adsGenericModel.data.length, (index) => ScheduleData.fromJson(adsGenericModel.data[index])); } @override Future updateSchedule(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, token: t); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, token: t); } @override Future updateServicesInSchedule(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, token: t); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, token: t); } Future> mergeServiceIntoAvailableSchedules({ required List serviceItemIdsForHome, required List serviceItemIdsForWorkshop, }) async { - String t = AppState().getUser.data!.accessToken ?? ""; + String t = appState.getUser.data!.accessToken ?? ""; var queryParameters = [ { "appointmentType": 2, @@ -107,12 +116,12 @@ class AppointmentRepoImp implements AppointmentRepo { "ServiceItemIDs": serviceItemIdsForWorkshop, } ]; - GenericRespModel adsGenericModel = await injector.get().postJsonForObject( - (json) => GenericRespModel.fromJson(json), - ApiConsts.GetServiceItemAppointmentScheduleSlots, - queryParameters, - token: t, - ); + GenericRespModel adsGenericModel = await apiClient.postJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.GetServiceItemAppointmentScheduleSlots, + queryParameters, + token: t, + ); if (adsGenericModel.data == null) { return []; } @@ -122,8 +131,8 @@ class AppointmentRepoImp implements AppointmentRepo { } Future createServiceAppointment({required List schedules, required int serviceProviderID}) async { - String t = AppState().getUser.data!.accessToken ?? ""; - int customerId = AppState().getUser.data!.userInfo!.customerId ?? 0; + String t = appState.getUser.data!.accessToken ?? ""; + int customerId = appState.getUser.data!.userInfo!.customerId ?? 0; List> mapList = []; schedules.forEach((schedule) { @@ -140,21 +149,21 @@ class AppointmentRepoImp implements AppointmentRepo { "serviceItemID": serviceItemIds, }); }); - log("maplist: ${mapList.toString() }"); + log("maplist: ${mapList.toString()}"); - GenericRespModel adsGenericModel = await injector.get().postJsonForObject( - (json) => GenericRespModel.fromJson(json), - ApiConsts.ServiceProvidersAppointmentCreate, - mapList, - token: t, - ); + GenericRespModel adsGenericModel = await apiClient.postJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.ServiceProvidersAppointmentCreate, + mapList, + token: t, + ); return adsGenericModel; } @override Future cancelOrRescheduleServiceAppointment({required int serviceAppointmentID, required int serviceSlotID, required int appointmentScheduleAction}) async { - String t = AppState().getUser.data!.accessToken ?? ""; + String t = appState.getUser.data!.accessToken ?? ""; final payload = { "serviceAppointmentID": serviceAppointmentID, @@ -162,59 +171,108 @@ class AppointmentRepoImp implements AppointmentRepo { "appointmentScheduleAction": appointmentScheduleAction, }; - GenericRespModel adsGenericModel = await injector.get().postJsonForObject( - (json) => GenericRespModel.fromJson(json), - ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment, - payload, - token: t, - ); + GenericRespModel adsGenericModel = await apiClient.postJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.ServiceProviderAppointmentRescheduleCancelAppointment, + payload, + token: t, + ); return adsGenericModel; } @override - Future> getMyAppointments(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - - GenericRespModel genericRespModel = await injector.get().getJsonForObject( - token: t, - (json) => GenericRespModel.fromJson(json), - queryParameters: map, - ApiConsts.serviceProvidersAppointmentGet, - ); + Future> getMyAppointmentsForProvider(Map map) async { + String t = appState.getUser.data!.accessToken ?? ""; + + GenericRespModel genericRespModel = await apiClient.getJsonForObject( + token: t, + (json) => GenericRespModel.fromJson(json), + queryParameters: map, + ApiConsts.serviceProvidersAppointmentGet, + ); + List appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index])); + return appointmentList; + } + + @override + Future> getMyAppointmentsForCustomersByFilters({ + List? providerIdsList, + List? categoryIdsList, + List? serviceIdsList, + List? branchIdsList, + }) async { + List providerIds = []; + if (providerIdsList != null) { + for (var element in providerIdsList) { + providerIds.add(element.toString()); + } + } + List categoryIds = []; + if (categoryIdsList != null) { + for (var element in categoryIdsList) { + categoryIds.add(element.toString()); + } + } + List serviceIds = []; + if (serviceIdsList != null) { + for (var element in serviceIdsList) { + serviceIds.add(element.toString()); + } + } + List branchIds = []; + if (branchIdsList != null) { + for (var element in branchIdsList) { + branchIds.add(element.toString()); + } + } + + var params = { + "customerID": appState.getUser.data!.userInfo!.customerId.toString(), + "ServiceProviderIDs": providerIds, + "ProviderBranchIDs": categoryIds, + "ServiceIDs": serviceIds, + "CategoryIDs": categoryIds, + }; + GenericRespModel genericRespModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + queryParameters: params, + ApiConsts.customersAppointmentGetByFilters, + ); List appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index])); return appointmentList; } @override Future getAppointmentSlots(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; + String t = appState.getUser.data!.accessToken ?? ""; - MResponse adsGenericModel = await injector.get().getJsonForObject( - (json) => MResponse.fromJson(json), - ApiConsts.getAppointmentSlots, - token: t, - queryParameters: map, - ); + MResponse adsGenericModel = await apiClient.getJsonForObject( + (json) => MResponse.fromJson(json), + ApiConsts.getAppointmentSlots, + token: t, + queryParameters: map, + ); return adsGenericModel; } @override Future updateAppointmentPaymentStatus(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateAppointmentPaymentStatus, map, token: t); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateAppointmentPaymentStatus, map, token: t); } @override Future updateAppointmentStatus(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateAppointmentStatus, map, token: t); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateAppointmentStatus, map, token: t); } @override Future createMergeAppointment(Map map) async { - String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createMergeAppointment, map, token: t); + String t = appState.getUser.data!.accessToken ?? ""; + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createMergeAppointment, map, token: t); } } diff --git a/lib/repositories/common_repo.dart b/lib/repositories/common_repo.dart index 80e6099..0e7a8df 100644 --- a/lib/repositories/common_repo.dart +++ b/lib/repositories/common_repo.dart @@ -45,7 +45,6 @@ abstract class CommonRepo { Future getRoles(); - Future> getMyAppointments(); Future getCarCheckServiceScheduleDetails({required double lat, required double long}); @@ -79,20 +78,7 @@ class CommonRepoImp implements CommonRepo { return await apiClient.getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles); } - @override - Future> getMyAppointments() async { - var params = { - "customerID": appState.getUser.data!.userInfo!.customerId.toString() ?? "", - }; - GenericRespModel genericRespModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - queryParameters: params, - ApiConsts.serviceProvidersAppointmentGet, - ); - List appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index])); - return appointmentList; - } + @override Future getCarCheckServiceScheduleDetails({required double lat, required double long}) async { diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index 3e6838c..6ac7603 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -468,6 +468,8 @@ class AdVM extends BaseVM { if (!ifAlreadyExist(list: vehicleBrandsAdSearchHistory, value: brandValue)) { addToVehicleBrandsAdSearchHistory(value: brandValue); } + notifyListeners(); + return; } vehicleBrandId = id; getVehicleDetailsByVehicleBrandId(); @@ -491,6 +493,8 @@ class AdVM extends BaseVM { if (!ifAlreadyExist(list: vehicleYearAdSearchHistory, value: yearValue)) { addToVehicleYearAdSearchHistory(value: yearValue); } + notifyListeners(); + return; } vehicleModelYearId = id; notifyListeners(); @@ -615,6 +619,8 @@ class AdVM extends BaseVM { if (!ifAlreadyExist(list: vehicleLocationAdSearchHistory, value: cityValue)) { addToVehicleLocationAdSearchHistory(value: cityValue); } + notifyListeners(); + return; } vehicleCityId = id; notifyListeners(); @@ -1430,10 +1436,16 @@ class AdVM extends BaseVM { return; } vehicleBrandsAdSearchHistory.removeAt(index); + if (vehicleBrandsAdSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter - 1); + } notifyListeners(); } void addToVehicleBrandsAdSearchHistory({required DropValue value}) { + if (vehicleBrandsAdSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter + 1); + } vehicleBrandsAdSearchHistory.add(value); notifyListeners(); } @@ -1448,15 +1460,38 @@ class AdVM extends BaseVM { return; } vehicleLocationAdSearchHistory.removeAt(index); + if (vehicleLocationAdSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter - 1); + } notifyListeners(); } void addToVehicleLocationAdSearchHistory({required DropValue value}) { + if (vehicleLocationAdSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter + 1); + } vehicleLocationAdSearchHistory.add(value); notifyListeners(); } // OWNER + + SelectionModel vehicleOwnerId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + + void updateSelectionVehicleAdOwnerId(SelectionModel id, {bool isForSearch = false}) { + if (isForSearch) { + EnumsModel owner = exploreAdsEnums.firstWhere((element) => element.id == id.selectedId); + DropValue ownerValue = DropValue(owner.id, "${owner.enumValueStr} Ads", ""); + if (!ifAlreadyExist(list: vehicleYearAdSearchHistory, value: ownerValue)) { + addToVehicleAdOwnerSearchHistory(value: ownerValue); + } + notifyListeners(); + return; + } + vehicleOwnerId = id; + notifyListeners(); + } + List vehicleAdOwnerSearchHistory = []; void removeVehicleAdOwnerSearchHistory({bool isClear = false, required int index}) { @@ -1466,10 +1501,16 @@ class AdVM extends BaseVM { return; } vehicleAdOwnerSearchHistory.removeAt(index); + if (vehicleAdOwnerSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter - 1); + } notifyListeners(); } void addToVehicleAdOwnerSearchHistory({required DropValue value}) { + if (vehicleAdOwnerSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter + 1); + } vehicleAdOwnerSearchHistory.add(value); notifyListeners(); } @@ -1484,13 +1525,72 @@ class AdVM extends BaseVM { return; } vehicleYearAdSearchHistory.removeAt(index); + if (vehicleYearAdSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter - 1); + } notifyListeners(); } void addToVehicleYearAdSearchHistory({required DropValue value}) { + if (vehicleYearAdSearchHistory.isEmpty) { + updateAdsFiltersCounter(adsFiltersCounter + 1); + } vehicleYearAdSearchHistory.add(value); notifyListeners(); } + + int adsFiltersCounter = 0; + + updateAdsFiltersCounter(int value) { + adsFiltersCounter = value; + notifyListeners(); + } + + void clearAdsFilters() { + vehicleBrandsAdSearchHistory.clear(); + vehicleAdOwnerSearchHistory.clear(); + vehicleLocationAdSearchHistory.clear(); + vehicleYearAdSearchHistory.clear(); + notifyListeners(); + } + + Future getAdsBasedOnFilters() async { + exploreAds.clear(); + setState(ViewState.busy); + List cityIdsList = []; + if (vehicleLocationAdSearchHistory.isNotEmpty) { + for (var element in vehicleLocationAdSearchHistory) { + cityIdsList.add(element.id); + } + } + List brandsIdsList = []; + if (vehicleBrandsAdSearchHistory.isNotEmpty) { + for (var element in vehicleBrandsAdSearchHistory) { + brandsIdsList.add(element.id); + } + } + List vehicleYearIdsList = []; + if (vehicleYearAdSearchHistory.isNotEmpty) { + for (var element in vehicleYearAdSearchHistory) { + vehicleYearIdsList.add(element.id); + } + } + List adOwnerIdsList = []; + if (vehicleAdOwnerSearchHistory.isNotEmpty) { + for (var element in vehicleAdOwnerSearchHistory) { + adOwnerIdsList.add(element.id); + } + } + // + // myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters( + // providerIdsList: providersIdsList.isNotEmpty ? providersIdsList : null, + // categoryIdsList: categoryIdsList.isNotEmpty ? categoryIdsList : null, + // serviceIdsList: servicesIdsList.isNotEmpty ? servicesIdsList : null, + // branchIdsList: branchesIdsList.isNotEmpty ? branchesIdsList : null, + // ); + applyFilterOnExploreAds(createdByRoleFilter: CreatedByRoleEnum.allAds); + setState(ViewState.idle); + } } class VehicleDamageCard { diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart index fe229f3..e685c9d 100644 --- a/lib/view_models/appointments_view_model.dart +++ b/lib/view_models/appointments_view_model.dart @@ -41,9 +41,9 @@ class AppointmentsVM extends BaseVM { final CommonRepo commonRepo; final CommonAppServices commonServices; final BranchRepo branchRepo; - final AppointmentRepo scheduleRepo; + final AppointmentRepo appointmentRepo; - AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.commonRepo, required this.branchRepo}); + AppointmentsVM({required this.commonServices, required this.appointmentRepo, required this.commonRepo, required this.branchRepo}); bool isUpcommingEnabled = true; bool isFetchingLists = false; @@ -79,15 +79,15 @@ class AppointmentsVM extends BaseVM { List allSelectedItemsInAppointments = []; - setupProviderAppointmentFilter() { - appointmentsFilterOptions.clear(); - appointmentsFilterOptions.add(FilterListModel(id: 0, title: "All Appointments", isSelected: true)); - appointmentsFilterOptions.add(FilterListModel(id: 2, title: "Confirmed", isSelected: false)); - appointmentsFilterOptions.add(FilterListModel(id: 3, title: "Arrived", isSelected: false)); - appointmentsFilterOptions.add(FilterListModel(id: 7, title: "Work In Progress", isSelected: false)); - appointmentsFilterOptions.add(FilterListModel(id: 8, title: "Completed", isSelected: false)); - appointmentsFilterOptions.add(FilterListModel(id: 4, title: "Canceled", isSelected: false)); - } + // setupProviderAppointmentFilter() { + // appointmentsFilterOptions.clear(); + // appointmentsFilterOptions.add(FilterListModel(id: 0, title: "All Appointments", isSelected: true)); + // appointmentsFilterOptions.add(FilterListModel(id: 2, title: "Confirmed", isSelected: false)); + // appointmentsFilterOptions.add(FilterListModel(id: 3, title: "Arrived", isSelected: false)); + // appointmentsFilterOptions.add(FilterListModel(id: 7, title: "Work In Progress", isSelected: false)); + // appointmentsFilterOptions.add(FilterListModel(id: 8, title: "Completed", isSelected: false)); + // appointmentsFilterOptions.add(FilterListModel(id: 4, title: "Canceled", isSelected: false)); + // } Future onItemsSelectedInService() async { if (currentServiceSelection != null) { @@ -117,7 +117,7 @@ class AppointmentsVM extends BaseVM { bool isSuccess = false; List appointmentIdsList = []; try { - GenericRespModel genericRespModel = await scheduleRepo.createServiceAppointment( + GenericRespModel genericRespModel = await appointmentRepo.createServiceAppointment( schedules: serviceAppointmentScheduleList, serviceProviderID: selectedBranchModel!.serviceProviderId ?? 0, ); @@ -169,7 +169,7 @@ class AppointmentsVM extends BaseVM { Future onCancelAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async { Utils.showLoading(context); try { - GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment( + GenericRespModel genericRespModel = await appointmentRepo.cancelOrRescheduleServiceAppointment( serviceAppointmentID: appointmentListModel.id ?? 0, serviceSlotID: appointmentListModel.serviceSlotID ?? 0, appointmentScheduleAction: 2, // 1 for Reschedule and 2 for Cancel @@ -256,10 +256,10 @@ class AppointmentsVM extends BaseVM { List myAppointmentsEnum = []; - populateAppointmentsFilterList() async { + Future populateAppointmentsFilterList() async { if (appointmentsFilterOptions.isNotEmpty) return; - myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: 13); //TODO: 13 is to get Appointments Filter Enums + myAppointmentsEnum = await commonRepo.getEnumTypeValues(enumTypeID: 13); // 13 is to get Appointments Filter Enums for (int i = 0; i < myAppointmentsEnum.length; i++) { appointmentsFilterOptions.add(FilterListModel(title: myAppointmentsEnum[i].enumValueStr, isSelected: false, id: myAppointmentsEnum[i].enumValue)); @@ -274,6 +274,7 @@ class AppointmentsVM extends BaseVM { } applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) { + // isNeedCustomerFilter IS ONLY FOR THE PROVIDER APP if (appointmentsFilterOptions.isEmpty) return; for (var value in appointmentsFilterOptions) { value.isSelected = false; @@ -302,7 +303,7 @@ class AppointmentsVM extends BaseVM { findAppointmentsBasedOnCustomers() { // Use a Set to ensure uniqueness of customerIDs - Set uniqueCustomerIDs = Set(); + Set uniqueCustomerIDs = {}; // Extract unique customerIDs for (var item in myFilteredAppointments) { @@ -334,11 +335,11 @@ class AppointmentsVM extends BaseVM { Future getMyAppointments({bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); - myAppointments = await commonRepo.getMyAppointments(); - myFilteredAppointments = myAppointments; + myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters(); + // myFilteredAppointments = myAppointments; myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList(); setState(ViewState.idle); - // applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); notifyListeners(); } @@ -347,7 +348,7 @@ class AppointmentsVM extends BaseVM { Future getAppointmentSlotsInfo({required Map map, required BuildContext context, bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { - MResponse genericRespModel = await scheduleRepo.getAppointmentSlots(map); + MResponse genericRespModel = await appointmentRepo.getAppointmentSlots(map); if (genericRespModel.messageStatus == 1) { appointmentSlots = AppointmentSlots.fromJson(genericRespModel.data); } else { @@ -358,10 +359,10 @@ class AppointmentsVM extends BaseVM { } } - Future getProviderMyAppointments(Map map, {bool isNeedToRebuild = false}) async { + Future getMyAppointmentsForProvider(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); - myAppointments = await scheduleRepo.getMyAppointments(map); + myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map); myFilteredAppointments = myAppointments; myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked).toList(); @@ -372,7 +373,7 @@ class AppointmentsVM extends BaseVM { updateAppointmentStatus(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { - MResponse genericRespModel = await scheduleRepo.updateAppointmentStatus(map); + MResponse genericRespModel = await appointmentRepo.updateAppointmentStatus(map); if (genericRespModel.messageStatus == 1) { Utils.showToast("appointment status updated"); @@ -387,7 +388,7 @@ class AppointmentsVM extends BaseVM { updateAppointmentPaymentStatus(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { - MResponse genericRespModel = await scheduleRepo.updateAppointmentPaymentStatus(map); + MResponse genericRespModel = await appointmentRepo.updateAppointmentPaymentStatus(map); if (genericRespModel.messageStatus == 1) { Utils.showToast("payment status updated"); @@ -401,7 +402,7 @@ class AppointmentsVM extends BaseVM { Future createMergeAppointment(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); - MResponse genericRespModel = await scheduleRepo.createMergeAppointment(map); + MResponse genericRespModel = await appointmentRepo.createMergeAppointment(map); return genericRespModel; } @@ -495,7 +496,7 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - applyFilterOnBranches({required int index}) async { + Future applyFilterOnBranches({required int index}) async { if (branchesFilterOptions.isEmpty) return; for (var value in branchesFilterOptions) { value.isSelected = false; @@ -690,7 +691,7 @@ class AppointmentsVM extends BaseVM { } } - serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules( + serviceAppointmentScheduleList = await appointmentRepo.mergeServiceIntoAvailableSchedules( serviceItemIdsForHome: serviceItemIdsForHome, serviceItemIdsForWorkshop: serviceItemIdsForWorkshop, ); @@ -730,7 +731,7 @@ class AppointmentsVM extends BaseVM { } } - serviceAppointmentScheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules( + serviceAppointmentScheduleList = await appointmentRepo.mergeServiceIntoAvailableSchedules( serviceItemIdsForHome: serviceItemIdsForHome, serviceItemIdsForWorkshop: serviceItemIdsForWorkshop, ); @@ -754,7 +755,7 @@ class AppointmentsVM extends BaseVM { Future onRescheduleAppointmentConfirmPressed({required BuildContext context, required int appointmentId, required int selectedSlotId}) async { Utils.showLoading(context); try { - GenericRespModel genericRespModel = await scheduleRepo.cancelOrRescheduleServiceAppointment( + GenericRespModel genericRespModel = await appointmentRepo.cancelOrRescheduleServiceAppointment( serviceAppointmentID: appointmentId, serviceSlotID: selectedSlotId, appointmentScheduleAction: 1, // 1 for Reschedule and 2 for Cancel @@ -811,7 +812,7 @@ class AppointmentsVM extends BaseVM { setState(ViewState.idle); } - getAllNearBranches({bool isNeedToRebuild = false, bool isFromRefresh = false}) async { + Future getAllNearBranches({bool isNeedToRebuild = false, bool isFromRefresh = false}) async { nearbyBranches.clear(); if (isNeedToRebuild) setState(ViewState.busy); @@ -898,6 +899,7 @@ class AppointmentsVM extends BaseVM { branchFilterProviderSearchHistory.removeAt(index); if (branchFilterProviderSearchHistory.isEmpty) { updateBranchFiltersCounter(branchFiltersCounter - 1); + // branchFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); } notifyListeners(); } @@ -927,7 +929,7 @@ class AppointmentsVM extends BaseVM { // Category Filter List branchFilterCategorySearchHistory = []; - void removeFilterCategorySearchHistory({bool isClear = false, required int index}) { + void removeBranchFilterCategorySearchHistory({bool isClear = false, required int index}) { if (isClear) { branchFilterCategorySearchHistory.clear(); notifyListeners(); @@ -936,6 +938,7 @@ class AppointmentsVM extends BaseVM { branchFilterCategorySearchHistory.removeAt(index); if (branchFilterCategorySearchHistory.isEmpty) { updateBranchFiltersCounter(branchFiltersCounter - 1); + // branchFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); } notifyListeners(); } @@ -974,6 +977,7 @@ class AppointmentsVM extends BaseVM { branchFilterServicesSearchHistory.removeAt(index); if (branchFilterServicesSearchHistory.isEmpty) { updateBranchFiltersCounter(branchFiltersCounter - 1); + // branchFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); } notifyListeners(); } @@ -994,6 +998,8 @@ class AppointmentsVM extends BaseVM { if (!ifAlreadyExist(list: branchFilterServicesSearchHistory, value: serviceDrop)) { addBranchFilterServicesSearchHistory(value: serviceDrop); } + notifyListeners(); + return; } branchFilterSelectedServiceId = id; @@ -1142,9 +1148,258 @@ class AppointmentsVM extends BaseVM { return; } setState(ViewState.busy); - nearbyBranches.clear(); nearbyBranches = await branchRepo.getBranchesByFilters(categoryIdsList: [categoryId]); setState(ViewState.idle); } + + // Appointments Filter Screen + + List branchesDropList = []; + + Future fetchAllBranchesBySelectedProviderId({required List providersIdsList}) async { + branchesDropList.clear(); + setOnlyState(ViewState.busy); + List providers = await branchRepo.getBranchesByFilters(providerIdsList: providersIdsList); + for (var element in providers) { + branchesDropList.add(DropValue(element.id ?? 0, element.branchName ?? "N/A", "")); + } + setState(ViewState.idle); + + log("branchesDropList: ${branchesDropList.length}"); + } + + Future populateDataForAppointmentsFilter() async { + await fetchAllProviders(); // saudi arabia + await fetchAllCategories("SA"); // saudi arabia + await fetchAllServices(); // saudi arabia + } + + int appointmentFiltersCounter = 0; + + updateAppointmentFiltersCounter(int value) { + appointmentFiltersCounter = value; + notifyListeners(); + } + + // Provider Filter For Appointments + List appointmentFilterProviderSearchHistory = []; + + void removeAppointmentFilterProviderSearchHistory({bool isClear = false, required int index}) { + if (isClear) { + appointmentFilterProviderSearchHistory.clear(); + notifyListeners(); + return; + } + appointmentFilterProviderSearchHistory.removeAt(index); + if (appointmentFilterProviderSearchHistory.isNotEmpty) { + List 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 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 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 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 appointmentFilterServicesSearchHistory = []; + + void removeAppointmentFilterServicesSearchHistory({bool isClear = false, required int index}) { + if (isClear) { + appointmentFilterServicesSearchHistory.clear(); + notifyListeners(); + return; + } + appointmentFilterServicesSearchHistory.removeAt(index); + if (appointmentFilterServicesSearchHistory.isEmpty) { + updateAppointmentFiltersCounter(appointmentFiltersCounter - 1); + // appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + } + notifyListeners(); + } + + void addAppointmentFilterServicesSearchHistory({required DropValue value}) { + if (appointmentFilterServicesSearchHistory.isEmpty) { + updateAppointmentFiltersCounter(appointmentFiltersCounter + 1); + } + appointmentFilterServicesSearchHistory.add(value); + notifyListeners(); + } + + SelectionModel appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + + void updateAppointmentFilterSelectedServiceId(SelectionModel id, {bool isForSearch = false}) async { + if (isForSearch) { + DropValue servicesDrop = servicesDropList.firstWhere((element) => element.id == id.selectedId); + if (!ifAlreadyExist(list: appointmentFilterServicesSearchHistory, value: servicesDrop)) { + addAppointmentFilterServicesSearchHistory(value: servicesDrop); + } + } + // appointmentFilterSelectedServiceId = id; + notifyListeners(); + } + + void clearAppointmentFilterSelections() { + appointmentFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + appointmentFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + appointmentFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + appointmentFilterSelectedBranchId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + } + + void clearAppointmentFilters() { + appointmentFilterServicesSearchHistory.clear(); + appointmentFilterCategorySearchHistory.clear(); + appointmentFilterProviderSearchHistory.clear(); + appointmentFilterBranchSearchHistory.clear(); + appointmentFiltersCounter = 0; + clearAppointmentFilterSelections(); + notifyListeners(); + } + + Future getAppointmentsBasedOnFilters() async { + nearbyBranches.clear(); + setState(ViewState.busy); + List providersIdsList = []; + if (appointmentFilterProviderSearchHistory.isNotEmpty) { + for (var element in appointmentFilterProviderSearchHistory) { + providersIdsList.add(element.id); + } + } + List categoryIdsList = []; + if (appointmentFilterCategorySearchHistory.isNotEmpty) { + for (var element in appointmentFilterCategorySearchHistory) { + categoryIdsList.add(element.id); + } + } + List servicesIdsList = []; + if (appointmentFilterServicesSearchHistory.isNotEmpty) { + for (var element in appointmentFilterServicesSearchHistory) { + servicesIdsList.add(element.id); + } + } + List branchesIdsList = []; + if (appointmentFilterBranchSearchHistory.isNotEmpty) { + for (var element in appointmentFilterBranchSearchHistory) { + branchesIdsList.add(element.id); + } + } + + myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters( + providerIdsList: providersIdsList.isNotEmpty ? providersIdsList : null, + categoryIdsList: categoryIdsList.isNotEmpty ? categoryIdsList : null, + serviceIdsList: servicesIdsList.isNotEmpty ? servicesIdsList : null, + branchIdsList: branchesIdsList.isNotEmpty ? branchesIdsList : null, + ); + applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); + setState(ViewState.idle); + } } diff --git a/lib/views/advertisement/ads_filter_view.dart b/lib/views/advertisement/ads_filter_view.dart index dd1247a..c7cf7a5 100644 --- a/lib/views/advertisement/ads_filter_view.dart +++ b/lib/views/advertisement/ads_filter_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; @@ -40,7 +41,7 @@ class AdsFilterView extends StatelessWidget { children: [ 20.height, SearchEntityWidget( - title: "Search By Location", + title: "Search By City", actionWidget: Builder(builder: (context) { List vehicleBrandsDrop = []; for (var element in adVM.vehicleCities) { @@ -50,15 +51,13 @@ class AdsFilterView extends StatelessWidget { (DropValue value) => adVM.updateSelectionVehicleCityId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), list: vehicleBrandsDrop, dropdownValue: adVM.vehicleCityId.selectedId != -1 ? DropValue(adVM.vehicleCityId.selectedId, adVM.vehicleCityId.selectedOption, "") : null, - hint: "Select Location", + hint: "Select City", errorValue: adVM.vehicleCityId.errorValue, ); }), historyContent: adVM.vehicleLocationAdSearchHistory, - onHistoryItemDeleted: (index) { - adVM.removeVehicleLocationAdSearchHistory(index: index); - }, - onHistoryItemTapped: (DropValue value) => adVM.updateSelectionVehicleCityId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + onHistoryItemDeleted: (index) => adVM.removeVehicleLocationAdSearchHistory(index: index), + onHistoryItemTapped: (DropValue value) => null, ), const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), SearchEntityWidget( @@ -78,11 +77,11 @@ class AdsFilterView extends StatelessWidget { }), historyContent: adVM.vehicleBrandsAdSearchHistory, onHistoryItemDeleted: (index) => adVM.removeVehicleBrandsAdSearchHistory(index: index), - onHistoryItemTapped: (DropValue value) => adVM.updateSelectionVehicleBrandId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + onHistoryItemTapped: (DropValue value) => null, ), const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), SearchEntityWidget( - title: "Search By Year", + title: "Search By Vehicle Year", actionWidget: Builder(builder: (context) { List vehicleBrandsDrop = []; for (var element in adVM.vehicleModelYears) { @@ -98,7 +97,27 @@ class AdsFilterView extends StatelessWidget { }), historyContent: adVM.vehicleYearAdSearchHistory, onHistoryItemDeleted: (index) => adVM.removeVehicleYearAdSearchHistory(index: index), - onHistoryItemTapped: (DropValue value) => adVM.updateSelectionVehicleModelYearId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + onHistoryItemTapped: (DropValue value) => null, + ), + const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), + SearchEntityWidget( + title: "Search By Ad Owner", + actionWidget: Builder(builder: (context) { + List vehicleOwnerDrop = []; + for (var element in adVM.exploreAdsEnums) { + vehicleOwnerDrop.add(DropValue(element.id.toInt(), "${element.enumValueStr} Ads", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleAdOwnerId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: vehicleOwnerDrop, + dropdownValue: adVM.vehicleOwnerId.selectedId != -1 ? DropValue(adVM.vehicleOwnerId.selectedId, adVM.vehicleOwnerId.selectedOption, "") : null, + hint: "Select Owner", + errorValue: adVM.vehicleOwnerId.errorValue, + ); + }), + historyContent: adVM.vehicleAdOwnerSearchHistory, + onHistoryItemDeleted: (index) => adVM.removeVehicleAdOwnerSearchHistory(index: index), + onHistoryItemTapped: (DropValue value) => null, ) ], ).expand(), @@ -121,6 +140,15 @@ class AdsFilterView extends StatelessWidget { ) ], ), + 8.height, + InkWell( + onTap: () => adVM.clearAdsFilters(), + child: "Clear Filters".toText( + fontSize: 14, + isBold: true, + color: MyColors.darkPrimaryColor, + ), + ), 10.height, ], ), diff --git a/lib/views/appointments/appointments_filter_view.dart b/lib/views/appointments/appointments_filter_view.dart new file mode 100644 index 0000000..59101fd --- /dev/null +++ b/lib/views/appointments/appointments_filter_view.dart @@ -0,0 +1,210 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/general_models/widgets_models.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/view_models/ad_view_model.dart'; +import 'package:mc_common_app/view_models/appointments_view_model.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/common_widgets/search_entity_widget.dart'; +import 'package:mc_common_app/widgets/common_widgets/slider_widget.dart'; +import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; + +class AppointmentsFilterView extends StatefulWidget { + const AppointmentsFilterView({super.key}); + + @override + State createState() => _AppointmentsFilterViewState(); +} + +class _AppointmentsFilterViewState extends State { + late AppointmentsVM appointmentsVM; + + @override + void initState() { + appointmentsVM = context.read(); + scheduleMicrotask(() async { + await appointmentsVM.populateDataForBranchesFilter(); + }); + super.initState(); + } + + @override + void dispose() { + appointmentsVM.clearBranchFilterSelections(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + title: "Appointments Filter", + profileImageUrl: MyAssets.bnCar, + isRemoveBackButton: false, + isDrawerEnabled: false, + onBackButtonTapped: () { + context.read().resetValues(); + Navigator.pop(context); + }, + ), + body: Consumer( + builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { + return WillPopScope( + onWillPop: () async { + context.read().resetValues(); + return true; + }, + child: Column( + children: [ + ListView( + children: [ + 20.height, + SearchEntityWidget( + title: "Search By Provider", + actionWidget: Builder( + builder: (context) { + return DropdownField( + (DropValue value) => appointmentsVM.updateAppointmentFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: appointmentsVM.providersDropList, + dropdownValue: appointmentsVM.appointmentFilterSelectedProviderId.selectedId != -1 + ? DropValue(appointmentsVM.appointmentFilterSelectedProviderId.selectedId, appointmentsVM.appointmentFilterSelectedProviderId.selectedOption, "") + : null, + hint: "Select Provider", + ); + }, + ), + historyContent: appointmentsVM.appointmentFilterProviderSearchHistory, + onHistoryItemDeleted: (index) { + appointmentsVM.removeAppointmentFilterProviderSearchHistory(index: index); + }, + onHistoryItemTapped: (DropValue value) => + appointmentsVM.updateAppointmentFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + ), + if (appointmentsVM.state == ViewState.busy) ...[ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + height: 5.h, + child: const CircularProgressIndicator(), + ), + ], + ), + ], + if (appointmentsVM.appointmentFilterProviderSearchHistory.isNotEmpty) ...[ + const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + SearchEntityWidget( + title: "Search By Branch", + actionWidget: Builder( + builder: (context) { + return DropdownField( + (DropValue value) => appointmentsVM.updateAppointmentFilterSelectedBranchId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: appointmentsVM.branchesDropList, + dropdownValue: appointmentsVM.appointmentFilterSelectedBranchId.selectedId != -1 + ? DropValue(appointmentsVM.appointmentFilterSelectedBranchId.selectedId, appointmentsVM.appointmentFilterSelectedBranchId.selectedOption, "") + : null, + hint: "Select Branch", + ); + }, + ), + historyContent: appointmentsVM.appointmentFilterBranchSearchHistory, + onHistoryItemDeleted: (index) { + appointmentsVM.removeAppointmentFilterBranchSearchHistory(index: index); + }, + onHistoryItemTapped: (DropValue value) => + appointmentsVM.updateAppointmentFilterSelectedBranchId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + ), + ], + const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + SearchEntityWidget( + title: "Search By Category", + actionWidget: Builder( + builder: (context) { + return DropdownField( + (DropValue value) => appointmentsVM.updateAppointmentFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: appointmentsVM.categoryDropList, + dropdownValue: appointmentsVM.appointmentFilterSelectedCategoryId.selectedId != -1 + ? DropValue(appointmentsVM.appointmentFilterSelectedCategoryId.selectedId, appointmentsVM.appointmentFilterSelectedCategoryId.selectedOption, "") + : null, + hint: "Select Category", + ); + }, + ), + historyContent: appointmentsVM.appointmentFilterCategorySearchHistory, + onHistoryItemDeleted: (index) { + appointmentsVM.removeAppointmentFilterCategorySearchHistory(index: index); + }, + onHistoryItemTapped: (DropValue value) => + appointmentsVM.updateAppointmentFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + ), + const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + SearchEntityWidget( + title: "Search By Service", + actionWidget: Builder(builder: (context) { + return DropdownField( + (DropValue value) => appointmentsVM.updateAppointmentFilterSelectedServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: appointmentsVM.servicesDropList, + dropdownValue: appointmentsVM.appointmentFilterSelectedServiceId.selectedId != -1 + ? DropValue(appointmentsVM.appointmentFilterSelectedServiceId.selectedId, appointmentsVM.appointmentFilterSelectedServiceId.selectedOption, "") + : null, + hint: "Select Services", + ); + }), + historyContent: appointmentsVM.appointmentFilterServicesSearchHistory, + onHistoryItemDeleted: (index) => appointmentsVM.removeAppointmentFilterServicesSearchHistory(index: index), + onHistoryItemTapped: (DropValue value) => null, + ), + ], + ).expand(), + Container( + color: MyColors.white, + child: Column( + children: [ + 5.height, + Row( + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Search", + onPressed: () { + Navigator.pop(context); + appointmentsVM.getAppointmentsBasedOnFilters(); + }, + backgroundColor: MyColors.darkPrimaryColor, + txtColor: MyColors.white, + fontSize: 18, + ), + ) + ], + ), + 8.height, + InkWell( + onTap: () => appointmentsVM.clearAppointmentFilters(), + child: "Clear Filters".toText( + fontSize: 14, + isBold: true, + color: MyColors.darkPrimaryColor, + ), + ), + 10.height, + ], + ), + ), + ], + ).horPaddingMain(), + ); + }, + ), + ); + } +} diff --git a/lib/views/branches/branches_filter_view.dart b/lib/views/branches/branches_filter_view.dart index 321358d..9adbc7d 100644 --- a/lib/views/branches/branches_filter_view.dart +++ b/lib/views/branches/branches_filter_view.dart @@ -125,7 +125,7 @@ class _BranchesFilterViewState extends State { ), historyContent: appointmentsVM.branchFilterCategorySearchHistory, onHistoryItemDeleted: (index) { - appointmentsVM.removeFilterCategorySearchHistory(index: index); + appointmentsVM.removeBranchFilterCategorySearchHistory(index: index); }, onHistoryItemTapped: (DropValue value) => appointmentsVM.updateBranchFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), diff --git a/lib/views/user/register_selection_page.dart b/lib/views/user/register_selection_page.dart index 0926b8f..e1e8011 100644 --- a/lib/views/user/register_selection_page.dart +++ b/lib/views/user/register_selection_page.dart @@ -72,18 +72,18 @@ class RegisterSelectionPage extends StatelessWidget { ), 10.height, Utils.mFlex(3), - TextButton( - onPressed: () {}, - child: const Text( - "Continue as Guest", - style: TextStyle( - color: MyColors.darkPrimaryColor, - fontWeight: FontWeight.bold, - decoration: TextDecoration.underline, - ), - ), - ), - 10.height, + // TextButton( + // onPressed: () {}, + // child: const Text( + // "Continue as Guest", + // style: TextStyle( + // color: MyColors.darkPrimaryColor, + // fontWeight: FontWeight.bold, + // decoration: TextDecoration.underline, + // ), + // ), + // ), + // 10.height, TextButton( onPressed: () {}, child: Text(