From 342d9b267276867ea8fc6a875b133d7c3ba42a0f Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Wed, 8 May 2024 18:11:31 +0300 Subject: [PATCH 1/3] Added Branch FilterView --- lib/config/dependencies.dart | 2 + lib/config/routes.dart | 1 + lib/repositories/ads_repo.dart | 219 +----------- lib/repositories/branch_repo.dart | 233 +++++++++++++ lib/repositories/common_repo.dart | 288 +++++++++++----- lib/repositories/items_repo.dart | 46 +++ lib/repositories/schedule_repo.dart | 61 ++++ lib/view_models/ad_view_model.dart | 20 +- lib/view_models/appointments_view_model.dart | 315 ++++++++++++++---- lib/views/branches/branches_filter_view.dart | 153 +++++++++ lib/widgets/common_widgets/slider_widget.dart | 47 +++ pubspec.lock | 54 ++- 12 files changed, 1023 insertions(+), 416 deletions(-) create mode 100644 lib/repositories/branch_repo.dart create mode 100644 lib/repositories/items_repo.dart create mode 100644 lib/repositories/schedule_repo.dart create mode 100644 lib/views/branches/branches_filter_view.dart create mode 100644 lib/widgets/common_widgets/slider_widget.dart diff --git a/lib/config/dependencies.dart b/lib/config/dependencies.dart index 2d7b1f8..8d13281 100644 --- a/lib/config/dependencies.dart +++ b/lib/config/dependencies.dart @@ -6,6 +6,7 @@ import 'package:mc_common_app/api/api_client.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/repositories/ads_repo.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/chat_repo.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; import 'package:mc_common_app/repositories/payments_repo.dart'; @@ -35,5 +36,6 @@ class AppDependencies { injector.registerSingleton(() => ProviderRepoImp()); injector.registerSingleton(() => AppointmentRepoImp()); injector.registerSingleton(() => ChatRepoImp()); + injector.registerSingleton(() => BranchRepoImp()); } } diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 8d500e4..36e8503 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -66,6 +66,7 @@ class AppRoutes { //Customer APP: Provider & Services static const String branchDetailPage = "/branchDetailPage"; + static const String branchSearchFilterPage = "/branchSearchFilterPage"; static const String providerProfilePage = "/providerProfilePage"; // Subscriptions diff --git a/lib/repositories/ads_repo.dart b/lib/repositories/ads_repo.dart index f22d5ad..246641a 100644 --- a/lib/repositories/ads_repo.dart +++ b/lib/repositories/ads_repo.dart @@ -16,33 +16,7 @@ import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/utils/enums.dart'; abstract class AdsRepo { - Future> getVehicleTypes(); - Future> getVehicleBrands({required int vehicleTypeId}); - - Future> getVehicleModels({required int vehicleTypeId}); - - Future> getVehicleModelYears({required int vehicleTypeId}); - - Future> getVehicleColors({required int vehicleTypeId}); - - Future> getVehicleConditions({required int vehicleTypeId}); - - Future> getVehicleCategories({required int vehicleTypeId}); - - Future> getVehicleMileages({required int vehicleTypeId}); - - Future> getVehicleTransmission({required int vehicleTypeId}); - - Future> getVehicleSellerTypes({required int vehicleTypeId}); - - Future> getVehicleCountries(); - - Future> getVehicleCities({required int countryId}); - - Future> getVehicleDamageParts(); - - Future getVehicleDetails({required int vehicleTypeId, required int vehicleBrandId}); Future> getAdsDuration(); @@ -75,200 +49,11 @@ class AdsRepoImp implements AdsRepo { ApiClient apiClient = injector.get(); AppState appState = injector.get(); - @override - Future> getVehicleTypes() async { - GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleTypeGet); - List vehicleTypes = List.generate(adsGenericModel.data.length, (index) => VehicleTypeModel.fromJson(adsGenericModel.data[index])); - return vehicleTypes; - } - - @override - Future> getVehicleCategories({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = - await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCategoryGet, queryParameters: postParams); - List vehicleCategories = List.generate(adsGenericModel.data.length, (index) => VehicleCategoryModel.fromJson(adsGenericModel.data[index])); - return vehicleCategories; - } - - @override - Future> getVehicleCities({required int countryId}) async { - var postParams = { - "CountryID": countryId.toString(), - }; - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCityGet, queryParameters: countryId != -1 ? postParams : null); - List vehicleCities = List.generate(adsGenericModel.data.length, (index) => VehicleCityModel.fromJson(adsGenericModel.data[index])); - return vehicleCities; - } - - @override - Future> getVehicleColors({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = - await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleColorGet, queryParameters: postParams); - List vehicleColors = List.generate(adsGenericModel.data.length, (index) => VehicleColorModel.fromJson(adsGenericModel.data[index])); - return vehicleColors; - } - - @override - Future> getVehicleConditions({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = - await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleConditionGet, queryParameters: postParams); - List vehicleConditions = List.generate(adsGenericModel.data.length, (index) => VehicleConditionModel.fromJson(adsGenericModel.data[index])); - return vehicleConditions; - } - - @override - Future> getVehicleCountries() async { - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleCountryGet, - ); - List vehicleConditions = List.generate(adsGenericModel.data.length, (index) => VehicleCountryModel.fromJson(adsGenericModel.data[index])); - return vehicleConditions; - } - - @override - Future> getVehicleMileages({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = - await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleMileageGet, queryParameters: postParams); - List vehicleMileages = List.generate(adsGenericModel.data.length, (index) => VehicleMileageModel.fromJson(adsGenericModel.data[index])); - return vehicleMileages; - } - - @override - Future> getVehicleModelYears({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleModelYearGet, - queryParameters: vehicleTypeId != -1 ? postParams : null, - ); - List vehicleModelYears = List.generate(adsGenericModel.data.length, (index) => VehicleYearModel.fromJson(adsGenericModel.data[index])); - return vehicleModelYears; - } - - @override - Future> getVehicleModels({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleModelGet, - queryParameters: postParams, - ); - List vehicleModels = List.generate(adsGenericModel.data.length, (index) => VehicleModel.fromJson(adsGenericModel.data[index])); - return vehicleModels; - } - - @override - Future> getVehicleBrands({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleBrandGet, - queryParameters: vehicleTypeId != -1 ? postParams : null, - ); - List vehicleBrands = List.generate(adsGenericModel.data.length, (index) => VehicleBrandsModel.fromJson(adsGenericModel.data[index])); - return vehicleBrands; - } - - @override - Future> getVehicleSellerTypes({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleSellerTypeGet, - queryParameters: postParams, - ); - List vehicleSellerTypes = List.generate(adsGenericModel.data.length, (index) => VehicleSellerTypeModel.fromJson(adsGenericModel.data[index])); - return vehicleSellerTypes; - } - - @override - Future> getVehicleTransmission({required int vehicleTypeId}) async { - var postParams = { - "VehicleType": vehicleTypeId.toString(), - }; - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleTransmissionGet, - queryParameters: postParams, - ); - List vehicleTransmissions = List.generate(adsGenericModel.data.length, (index) => VehicleTransmissionModel.fromJson(adsGenericModel.data[index])); - return vehicleTransmissions; - } - - @override - Future getVehicleDetails({required int vehicleTypeId, required int vehicleBrandId}) async { - var postParams = { - "vehicleType": vehicleTypeId.toString(), - "isVehicleBrand": "true", - "vehicleBrand": vehicleBrandId.toString(), - "isVehicleCategory": "true", - "isVehicleColor": "true", - "isVehicleCondition": "true", - "isVehicleMileage": "true", - "isVehicleModel": "true", - "isVehicleModelYear": "true", - "isVehiclePriceRange": "true", - "isVehiclePricingMethod": "true", - "isVehcileSellerType": "true", - "isVehicleTransmission": "true", - "isCountry": "true" - }; - - String token = appState.getUser.data!.accessToken ?? ""; - GenericRespModel adsGenericModel = await apiClient.postJsonForObject( - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleDetailsMaster, - postParams, - token: token, - ); - VehicleDetailsModel vehicleDetails = VehicleDetailsModel.fromJson(adsGenericModel.data); - return vehicleDetails; - } - - @override - Future> getVehicleDamageParts() async { - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleDamagePartGet, - ); - List vehicleParts = List.generate(adsGenericModel.data.length, (index) => VehiclePartModel.fromJson(adsGenericModel.data[index])); - return vehicleParts; - } - @override Future> getAdsDuration() async { GenericRespModel adsGenericModel = await apiClient.getJsonForObject( token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), + (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsDurationGet, ); List vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => AdsDurationModel.fromJson(adsGenericModel.data[index])); @@ -281,7 +66,7 @@ class AdsRepoImp implements AdsRepo { "SpecialServiceType": specialServiceId.toString(), }; GenericRespModel adsGenericModel = - await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params); + await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params); List vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index])); return vehicleAdsDuration; } diff --git a/lib/repositories/branch_repo.dart b/lib/repositories/branch_repo.dart new file mode 100644 index 0000000..c14408d --- /dev/null +++ b/lib/repositories/branch_repo.dart @@ -0,0 +1,233 @@ +import 'dart:async'; +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/general_models/m_response.dart'; + +import 'package:flutter/cupertino.dart'; +import 'package:mc_common_app/models/provider_branches_models/profile/branch.dart'; +import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; +import 'package:mc_common_app/models/provider_branches_models/profile/document.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'; + +abstract class BranchRepo { + Future createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude); + + Future updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true}); + + Future fetchAllBranches(); + + Future fetchBranchCategory(); + + Future fetchServicesByCategoryId({required int serviceCategoryId}); + + Future fetchProviderServices(String branchID, String serviceCategoryId); + + Future createNewService(List> map); + + Future getServiceProviderDocument(dynamic userId); + + Future serviceProviderDocumentsUpdate(List? documents); + + Future getBranchAndServices(); + + Future createService(List> map); + + Future updateService(List> map); + + Future getMatchedServices(int oldBranchId, int newBranchId, int categoryId); + + Future duplicateItems(Map map); + + Future getAllProviderDealers(Map map); + + Future getBranchUsers(Map map); + + Future assignDealerToBranch(Map map); + + Future removeDealerFromBranch(Map map); + + Future addNewServicesInAppointment(Map map); +} + +class BranchRepoImp implements BranchRepo { + @override + Future createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async { + var postParams = { + "serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "", + "branchName": branchName, + "branchDescription": branchDescription, + "cityID": cityId, + "address": address, + "latitude": latitude, + "longitude": longitude, + "isActive": true + }; + String t = AppState().getUser.data!.accessToken ?? ""; + debugPrint("token " + t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createProviderBranch, postParams, token: t); + } + + @override + Future fetchAllBranches() async { + var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => Branch.fromJson(json), ApiConsts.ServiceProviderBranchGet, queryParameters: postParams, token: t); + } + + @override + Future fetchBranchCategory() async { + var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => Category.fromJson(json), ApiConsts.ServiceCategory_Get, queryParameters: postParams, token: t); + } + + @override + Future fetchServicesByCategoryId({required int serviceCategoryId}) async { + var postParams = {"ServiceCategoryID": serviceCategoryId}; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => Services.fromJson(json), ApiConsts.Services_Get, queryParameters: serviceCategoryId != -1 ? postParams : null, token: t); + } + + @override + Future createNewService(List> map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t); + } + + @override + Future getServiceProviderDocument(dynamic userId) async { + var queryParameters = { + "ServiceProviderID": userId.toString(), + }; + String? token = AppState().getUser.data?.accessToken; + debugPrint(token); + return await injector + .get() + .getJsonForObject((json) => Document.fromJson(json), ApiConsts.GetProviderDocument, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? ""); + } + + @override + Future serviceProviderDocumentsUpdate(List? documents) async { + List> map = []; + for (int i = 0; i < documents!.length; i++) { + if (documents[i].document != null) { + var postParams = { + "id": documents[i].id, + "serviceProviderID": documents[i].serviceProviderId, + "documentID": documents[i].documentId, + "documentExt": documents[i].fileExt, + "documentImage": documents[i].document, + "isActive": true + }; + map.add(postParams); + } + } + String t = AppState().getUser.data!.accessToken ?? ""; + debugPrint("token " + t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderDocument_Update, map, token: t); + } + + @override + Future getBranchAndServices() async { + var postParams = {"serviceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; + String t = AppState().getUser.data!.accessToken ?? ""; + print("tokeen121 " + t); + return await injector.get().getJsonForObject((json) => ProviderModel.fromJson(json), ApiConsts.BranchesAndServices, queryParameters: postParams, token: t); + } + + @override + Future updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true}) async { + String lat = "0", long = "0"; + try { + lat = latitude.substring(0, 9); + long = longitude.substring(0, 9); + } catch (e) {} + var postParams = { + "id": id, + "serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "", + "branchName": branchName, + "branchDescription": branchDescription, + "cityID": cityId, + "address": address, + "latitude": lat, + "longitude": long, + "isActive": isNeedToDelete + }; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t); + } + + @override + Future createService(List> map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t); + } + + @override + Future updateService(List> map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Update, map, token: t); + } + + @override + Future getMatchedServices(int oldBranchId, int newBranchId, int categoryId) async { + var postParams = { + "ProviderBranchIDExisted": oldBranchId.toString(), + "ProviderBranchIDNew": newBranchId.toString(), + "CategoryID": categoryId.toString(), + }; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getMatchedServices, queryParameters: postParams, token: t); + } + + @override + Future duplicateItems(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.duplicateItems, map, token: t); + } + + @override + Future getAllProviderDealers(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getAllProviderDealers, queryParameters: map, token: t); + } + + @override + Future getBranchUsers(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getBranchUser, queryParameters: map, token: t); + } + + @override + Future assignDealerToBranch(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.assignDealerToBranch, map, token: t); + } + + @override + Future removeDealerFromBranch(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.removeDealerFromBranch, map, token: t); + } + + @override + Future fetchProviderServices(String branchID, String serviceCategoryId) async { + var postParams = { + "ServiceCategoryID": serviceCategoryId, + "ProviderBranchID": branchID, + }; + String t = AppState().getUser.data!.accessToken ?? ""; + debugPrint("token " + t); + return await injector.get().getJsonForObject((json) => Services.fromJson(json), ApiConsts.GetProviderServices, queryParameters: postParams, token: t); + } + + @override + Future addNewServicesInAppointment(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.AddNewServicesInAppointment, map, token: t); + } +} diff --git a/lib/repositories/common_repo.dart b/lib/repositories/common_repo.dart index 0ec703d..d26ee5e 100644 --- a/lib/repositories/common_repo.dart +++ b/lib/repositories/common_repo.dart @@ -15,34 +15,46 @@ import 'package:mc_common_app/models/user_models/role.dart'; abstract class CommonRepo { Future getAllCountries(); - Future getAllCites(String countryId); + Future> getVehicleTypes(); - //TODO: Needs to remove cities method one of them - Future> getVehicleCities({required int countryId}); + Future> getVehicleBrands({required int vehicleTypeId}); - Future getRoles(); + Future> getVehicleModels({required int vehicleTypeId}); - Future> getMyAppointments(); + Future> getVehicleModelYears({required int vehicleTypeId}); - Future getCarCheckServiceScheduleDetails( - {required double lat, required double long}); + Future> getVehicleColors({required int vehicleTypeId}); - Future> - getPhotographyServiceScheduleListByOffices( - {required double lat, required double long}); + Future> getVehicleConditions({required int vehicleTypeId}); - // Future> getProviderServiceCategories(); + Future> getVehicleCategories({required int vehicleTypeId}); -// Future> getProviderServices({required int categoryId}); + Future> getVehicleMileages({required int vehicleTypeId}); - Future> getVehicleTypes(); + Future> getVehicleTransmission({required int vehicleTypeId}); + + Future> getVehicleSellerTypes({required int vehicleTypeId}); + + Future> getVehicleCountries(); + + Future> getVehicleCities({required int countryId}); + + Future> getVehicleDamageParts(); + + Future getAllCites(String countryId); + + Future getRoles(); + + Future> getMyAppointments(); + + Future getCarCheckServiceScheduleDetails({required double lat, required double long}); + + Future> getPhotographyServiceScheduleListByOffices({required double lat, required double long}); //TODO: Needs to remove common methods from AD's repo and delete all repeated methods. - Future getVehicleDetails( - {int? vehicleTypeId, int? vehicleBrandId}); + Future getVehicleDetails({int? vehicleTypeId, int? vehicleBrandId}); - Future> getEnumTypeValues( - {int? enumTypeID, String? enumTypeName}); + Future> getEnumTypeValues({int? enumTypeID, String? enumTypeName}); } class CommonRepoImp implements CommonRepo { @@ -51,8 +63,7 @@ class CommonRepoImp implements CommonRepo { @override Future getAllCountries() async { - return await apiClient.getJsonForObject( - (json) => Country.fromJson(json), ApiConsts.GetAllCountry); + return await apiClient.getJsonForObject((json) => Country.fromJson(json), ApiConsts.GetAllCountry); } @override @@ -60,22 +71,18 @@ class CommonRepoImp implements CommonRepo { var postParams = { "CountryID": countryId, }; - return await apiClient.getJsonForObject( - (json) => Cities.fromJson(json), ApiConsts.GetAllCities, - queryParameters: postParams); + return await apiClient.getJsonForObject((json) => Cities.fromJson(json), ApiConsts.GetAllCities, queryParameters: postParams); } @override Future getRoles() async { - return await apiClient.getJsonForObject( - (json) => Role.fromJson(json), ApiConsts.GetProviderRoles); + return await apiClient.getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles); } @override Future> getMyAppointments() async { var params = { - "customerID": - appState.getUser.data!.userInfo!.customerId.toString() ?? "", + "customerID": appState.getUser.data!.userInfo!.customerId.toString() ?? "", }; GenericRespModel genericRespModel = await apiClient.getJsonForObject( token: appState.getUser.data!.accessToken, @@ -83,15 +90,12 @@ class CommonRepoImp implements CommonRepo { queryParameters: params, ApiConsts.serviceProvidersAppointmentGet, ); - List appointmentList = List.generate( - genericRespModel.data.length, - (index) => AppointmentListModel.fromJson(genericRespModel.data[index])); + 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 { + Future getCarCheckServiceScheduleDetails({required double lat, required double long}) async { var params = { "Latitude": lat.toString(), "Longitude": long.toString(), @@ -102,15 +106,12 @@ class CommonRepoImp implements CommonRepo { queryParameters: params, ApiConsts.adsCarCheckupSPBranchScheduleSlotGet, ); - SSCarCheckScheduleModel ssCarCheckScheduleModel = - SSCarCheckScheduleModel.fromJson(genericRespModel.data[0]); + SSCarCheckScheduleModel ssCarCheckScheduleModel = SSCarCheckScheduleModel.fromJson(genericRespModel.data[0]); return ssCarCheckScheduleModel; } @override - Future> - getPhotographyServiceScheduleListByOffices( - {required double lat, required double long}) async { + Future> getPhotographyServiceScheduleListByOffices({required double lat, required double long}) async { var params = { "Latitude": lat.toString(), "Longitude": long.toString(), @@ -124,32 +125,178 @@ class CommonRepoImp implements CommonRepo { if (genericRespModel.data == null) { return []; } - List ssPhotoScheduleModel = List.generate( - genericRespModel.data.length, - (index) => - SSPhotoOfficeScheduleModel.fromJson(genericRespModel.data[index])); + List ssPhotoScheduleModel = List.generate(genericRespModel.data.length, (index) => SSPhotoOfficeScheduleModel.fromJson(genericRespModel.data[index])); return ssPhotoScheduleModel ?? []; } @override Future> getVehicleTypes() async { - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleTypeGet); - List vehicleTypes = List.generate( - adsGenericModel.data.length, - (index) => VehicleTypeModel.fromJson(adsGenericModel.data[index])); + GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleTypeGet); + List vehicleTypes = List.generate(adsGenericModel.data.length, (index) => VehicleTypeModel.fromJson(adsGenericModel.data[index])); return vehicleTypes; } @override - Future getVehicleDetails( - {int? vehicleTypeId, int? vehicleBrandId}) async { + Future> getEnumTypeValues({int? enumTypeID, String? enumTypeName}) async { + var postParams = {"enumTypeID": (enumTypeID ?? 0).toString(), "enumTypeName": enumTypeName ?? ""}; + GenericRespModel enumGenericModel = await apiClient.postJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.getEnumTypeValues, + postParams, + token: appState.getUser.data!.accessToken, + ); + + List vehicleCities = List.generate(enumGenericModel.data.length, (index) => EnumsModel.fromJson(enumGenericModel.data[index])); + return vehicleCities; + } + + @override + Future> getVehicleCategories({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = + await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCategoryGet, queryParameters: postParams); + List vehicleCategories = List.generate(adsGenericModel.data.length, (index) => VehicleCategoryModel.fromJson(adsGenericModel.data[index])); + return vehicleCategories; + } + + @override + Future> getVehicleCities({required int countryId}) async { + var postParams = { + "CountryID": countryId.toString(), + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleCityGet, queryParameters: countryId != -1 ? postParams : null); + List vehicleCities = List.generate(adsGenericModel.data.length, (index) => VehicleCityModel.fromJson(adsGenericModel.data[index])); + return vehicleCities; + } + + @override + Future> getVehicleColors({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = + await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleColorGet, queryParameters: postParams); + List vehicleColors = List.generate(adsGenericModel.data.length, (index) => VehicleColorModel.fromJson(adsGenericModel.data[index])); + return vehicleColors; + } + + @override + Future> getVehicleConditions({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = + await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleConditionGet, queryParameters: postParams); + List vehicleConditions = List.generate(adsGenericModel.data.length, (index) => VehicleConditionModel.fromJson(adsGenericModel.data[index])); + return vehicleConditions; + } + + @override + Future> getVehicleCountries() async { + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.vehicleCountryGet, + ); + List vehicleConditions = List.generate(adsGenericModel.data.length, (index) => VehicleCountryModel.fromJson(adsGenericModel.data[index])); + return vehicleConditions; + } + + @override + Future> getVehicleMileages({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = + await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleMileageGet, queryParameters: postParams); + List vehicleMileages = List.generate(adsGenericModel.data.length, (index) => VehicleMileageModel.fromJson(adsGenericModel.data[index])); + return vehicleMileages; + } + + @override + Future> getVehicleModelYears({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.vehicleModelYearGet, + queryParameters: vehicleTypeId != -1 ? postParams : null, + ); + List vehicleModelYears = List.generate(adsGenericModel.data.length, (index) => VehicleYearModel.fromJson(adsGenericModel.data[index])); + return vehicleModelYears; + } + + @override + Future> getVehicleModels({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.vehicleModelGet, + queryParameters: postParams, + ); + List vehicleModels = List.generate(adsGenericModel.data.length, (index) => VehicleModel.fromJson(adsGenericModel.data[index])); + return vehicleModels; + } + + @override + Future> getVehicleBrands({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.vehicleBrandGet, + queryParameters: vehicleTypeId != -1 ? postParams : null, + ); + List vehicleBrands = List.generate(adsGenericModel.data.length, (index) => VehicleBrandsModel.fromJson(adsGenericModel.data[index])); + return vehicleBrands; + } + + @override + Future> getVehicleSellerTypes({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.vehicleSellerTypeGet, + queryParameters: postParams, + ); + List vehicleSellerTypes = List.generate(adsGenericModel.data.length, (index) => VehicleSellerTypeModel.fromJson(adsGenericModel.data[index])); + return vehicleSellerTypes; + } + + @override + Future> getVehicleTransmission({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.vehicleTransmissionGet, + queryParameters: postParams, + ); + List vehicleTransmissions = List.generate(adsGenericModel.data.length, (index) => VehicleTransmissionModel.fromJson(adsGenericModel.data[index])); + return vehicleTransmissions; + } + + @override + Future getVehicleDetails({int? vehicleTypeId, int? vehicleBrandId}) async { var postParams = { - "vehicleType": vehicleTypeId ?? 0, + "vehicleType": vehicleTypeId == null ? 0 : vehicleTypeId.toString(), "isVehicleBrand": "true", - "vehicleBrand": vehicleBrandId ?? 0, + "vehicleBrand": vehicleBrandId == null ? 0 : vehicleBrandId.toString(), "isVehicleCategory": "true", "isVehicleColor": "true", "isVehicleCondition": "true", @@ -170,46 +317,21 @@ class CommonRepoImp implements CommonRepo { postParams, token: token, ); - VehicleDetailsModel vehicleDetails = - VehicleDetailsModel.fromJson(adsGenericModel.data); + VehicleDetailsModel vehicleDetails = VehicleDetailsModel.fromJson(adsGenericModel.data); return vehicleDetails; } @override - Future> getVehicleCities( - {required int countryId}) async { - var postParams = { - "CountryID": countryId.toString(), - }; + Future> getVehicleDamageParts() async { GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - token: appState.getUser.data!.accessToken, - (json) => GenericRespModel.fromJson(json), - ApiConsts.vehicleCityGet, - queryParameters: postParams); - List vehicleCities = List.generate( - adsGenericModel.data.length, - (index) => VehicleCityModel.fromJson(adsGenericModel.data[index])); - return vehicleCities; - } - - @override - Future> getEnumTypeValues( - {int? enumTypeID, String? enumTypeName}) async { - var postParams = { - "enumTypeID": (enumTypeID ?? 0).toString(), - "enumTypeName": enumTypeName ?? "" - }; - GenericRespModel enumGenericModel = await apiClient.postJsonForObject( - (json) => GenericRespModel.fromJson(json), - ApiConsts.getEnumTypeValues, - postParams, token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.vehicleDamagePartGet, ); - - List vehicleCities = List.generate(enumGenericModel.data.length, - (index) => EnumsModel.fromJson(enumGenericModel.data[index])); - return vehicleCities; + List vehicleParts = List.generate(adsGenericModel.data.length, (index) => VehiclePartModel.fromJson(adsGenericModel.data[index])); + return vehicleParts; } + // // @override // Future> getProviderServiceCategories() async { diff --git a/lib/repositories/items_repo.dart b/lib/repositories/items_repo.dart new file mode 100644 index 0000000..fc8faee --- /dev/null +++ b/lib/repositories/items_repo.dart @@ -0,0 +1,46 @@ + +import 'package:flutter/material.dart'; +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/general_models/m_response.dart'; +import 'package:mc_common_app/models/services_models/item_model.dart'; + + +abstract class ItemsRepo { + Future createServiceItems(Map map); + + Future getServiceItems(int serviceId); + + Future updateServiceItem(Map map); +} + +class ItemsRepoImp implements ItemsRepo { + @override + Future createServiceItems(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + debugPrint(t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createItems, map, token: t); + } + + @override + Future getServiceItems(int serviceId) async { + var queryParameters = { + "ServiceProviderServiceID": serviceId.toString(), + }; + String? token = AppState().getUser.data?.accessToken; + debugPrint(token); + return await injector + .get() + .getJsonForObject((json) => ItemModel.fromJson(json), ApiConsts.getServiceItems, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? ""); + } + + @override + Future updateServiceItem(Map map) async { + String t = AppState().getUser.data!.accessToken ?? ""; + debugPrint(t); + return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateServiceItem, map, token: t); + + } +} diff --git a/lib/repositories/schedule_repo.dart b/lib/repositories/schedule_repo.dart new file mode 100644 index 0000000..e906cda --- /dev/null +++ b/lib/repositories/schedule_repo.dart @@ -0,0 +1,61 @@ +import 'package:mc_common_app/models/appointments_models/schedule_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 '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'; + +abstract class ScheduleRepo { + Future getAllServices(String branchId); + + Future createSchedule(Map map); + + Future addServicesInSchedule(Map map); + + Future updateSchedule(Map map); + + Future getSchedules(String branchId); + + Future updateServicesInSchedule(Map map); +} + +class ScheduleRepoImp implements ScheduleRepo { + @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); + } + + @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); + } + + @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); + } + + @override + Future getSchedules(String branchId) async { + Map map = {"ServiceProviderBranchID": branchId}; + String t = AppState().getUser.data!.accessToken ?? ""; + return await injector.get().getJsonForObject((json) => Schedule.fromJson(json), ApiConsts.getSchedule, token: t, queryParameters: map); + } + + @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); + } + + @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); + } +} diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index a35df39..3e6838c 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -1,7 +1,5 @@ import 'dart:convert'; -import 'dart:developer'; import 'dart:io'; - import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; @@ -11,7 +9,6 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/models/advertisment_models/ads_bank_details_model.dart'; import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart'; -import 'package:mc_common_app/models/advertisment_models/reserved_ads_models.dart'; import 'package:mc_common_app/models/advertisment_models/special_service_model.dart'; import 'package:mc_common_app/models/advertisment_models/ss_car_check_schedule_model.dart'; import 'package:mc_common_app/models/advertisment_models/ss_photo_schedule_model.dart'; @@ -137,7 +134,6 @@ class AdVM extends BaseVM { notifyListeners(); } - } } @@ -271,7 +267,7 @@ class AdVM extends BaseVM { } Future getVehicleTypes() async { - vehicleTypes = await adsRepo.getVehicleTypes(); + vehicleTypes = await commonRepo.getVehicleTypes(); notifyListeners(); } @@ -387,7 +383,7 @@ class AdVM extends BaseVM { if (vehicleTypeId.selectedId == -1 || vehicleBrands.isNotEmpty) { return; } - vehicleBrands = await adsRepo.getVehicleBrands(vehicleTypeId: vehicleTypeId.selectedId); + vehicleBrands = await commonRepo.getVehicleBrands(vehicleTypeId: vehicleTypeId.selectedId); notifyListeners(); } @@ -397,7 +393,7 @@ class AdVM extends BaseVM { } isFetchingLists = true; notifyListeners(); - vehicleDetails = await adsRepo.getVehicleDetails(vehicleTypeId: vehicleTypeId.selectedId, vehicleBrandId: vehicleBrandId.selectedId); + vehicleDetails = await commonRepo.getVehicleDetails(vehicleTypeId: vehicleTypeId.selectedId, vehicleBrandId: vehicleBrandId.selectedId); if (vehicleDetails != null) { vehicleModels = vehicleDetails!.vehicleModels!; @@ -605,7 +601,7 @@ class AdVM extends BaseVM { vehicleCountryId = id; isCountryFetching = true; notifyListeners(); - vehicleCities = await adsRepo.getVehicleCities(countryId: vehicleCountryId.selectedId); + vehicleCities = await commonRepo.getVehicleCities(countryId: vehicleCountryId.selectedId); isCountryFetching = false; notifyListeners(); } @@ -1186,7 +1182,7 @@ class AdVM extends BaseVM { } Future getVehicleDamagePartsList() async { - vehicleDamageParts = await adsRepo.getVehicleDamageParts(); + vehicleDamageParts = await commonRepo.getVehicleDamageParts(); notifyListeners(); } @@ -1404,12 +1400,12 @@ class AdVM extends BaseVM { Future populateDataForAdFilter() async { if (vehicleBrands.isEmpty) { - vehicleBrands = await adsRepo.getVehicleBrands(vehicleTypeId: -1); + vehicleBrands = await commonRepo.getVehicleBrands(vehicleTypeId: -1); } if (vehicleModelYears.isEmpty) { - vehicleModelYears = await adsRepo.getVehicleModelYears(vehicleTypeId: -1); + vehicleModelYears = await commonRepo.getVehicleModelYears(vehicleTypeId: -1); } - vehicleCities = await adsRepo.getVehicleCities(countryId: -1); // fetch all the cities + vehicleCities = await commonRepo.getVehicleCities(countryId: -1); // fetch all the cities } ifAlreadyExist({required List list, required DropValue value}) { diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart index e7c1c58..4e3d246 100644 --- a/lib/view_models/appointments_view_model.dart +++ b/lib/view_models/appointments_view_model.dart @@ -10,10 +10,13 @@ import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/m_response.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; +import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; +import 'package:mc_common_app/models/provider_branches_models/profile/services.dart'; import 'package:mc_common_app/models/provider_branches_models/provider_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/repositories/provider_repo.dart'; import 'package:mc_common_app/services/common_services.dart'; @@ -37,9 +40,10 @@ class AppointmentsVM extends BaseVM { final CommonRepo commonRepo; final CommonAppServices commonServices; final ProviderRepo providerRepo; + final BranchRepo branchRepo; final AppointmentRepo scheduleRepo; - AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo}); + AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo, required this.branchRepo}); bool isUpcommingEnabled = true; bool isFetchingLists = false; @@ -218,10 +222,6 @@ class AppointmentsVM extends BaseVM { } List providersFilterOptions = []; - List nearbyBranches = []; - BranchDetailModel? selectedBranchModel; - - List branchServices = []; List servicesInCurrentAppointment = []; ServiceModel? currentServiceSelection; @@ -369,12 +369,6 @@ class AppointmentsVM extends BaseVM { setState(ViewState.idle); } - updateSelectedBranch(BranchDetailModel branchDetailModel) { - selectedBranchModel = branchDetailModel; - getBranchCategories(); - notifyListeners(); - } - updateAppointmentStatus(Map map, {bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { @@ -501,19 +495,6 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - populateBranchesFilterList() { - providersFilterOptions.clear(); // TODO: THIS SHOULD BE DYNAMIC AND FILTERS SHOULD COME FORM API - providersFilterOptions = [ - FilterListModel(title: "All Providers", isSelected: true, id: 0), - FilterListModel(title: "Maintenance", isSelected: false, id: 1), - FilterListModel(title: "Oil Service", isSelected: false, id: 2), - FilterListModel(title: "Accessories", isSelected: false, id: 3), - FilterListModel(title: "Tire Service", isSelected: false, id: 4), - FilterListModel(title: "Dent and Paint", isSelected: false, id: 5), - ]; - notifyListeners(); - } - applyFilterOnProviders({required int index}) { if (providersFilterOptions.isEmpty) return; for (var value in providersFilterOptions) { @@ -523,14 +504,6 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - getAllNearBranches({bool isNeedToRebuild = false}) async { - //TODO: needs to lat,long into API - nearbyBranches.clear(); - if (isNeedToRebuild) setState(ViewState.busy); - nearbyBranches = await providerRepo.getAllNearBranchAndServices(); - setState(ViewState.idle); - } - Future> getServiceItems(int serviceId) async { serviceItemsFromApi.clear(); serviceItemsFromApi = await providerRepo.getServiceItems(serviceId); @@ -543,52 +516,11 @@ class AppointmentsVM extends BaseVM { return serviceItemsFromApi; } - getBranchAndServices(int providerId) async { - providerProfileModel = null; - providerProfileModel = await providerRepo.getBranchAndServices(providerId); - setState(ViewState.idle); - } - String pickHomeLocationError = ""; String selectSubServicesError = ""; SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); - bool isCategoryAlreadyPresent(int id) { - final contain = branchCategories.where((element) => element.id == id); - if (contain.isEmpty) { - return false; - } - return true; - } - - void getBranchCategories() async { - for (var value in selectedBranchModel!.branchServices!) { - if (!isCategoryAlreadyPresent(value.categoryId!)) { - branchCategories.add(DropValue(value.categoryId!, value.categoryName!, "")); - } - } - notifyListeners(); - } - - getBranchServices({required int categoryId}) async { - branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); - isHomeTapped = false; - pickedHomeLocation = ""; - pickHomeLocationError = ""; - if (categoryId != -1) { - isFetchingServices = true; - branchServices = getFilteredBranchServices(categoryId: categoryId); - isFetchingServices = false; - notifyListeners(); - } - } - - List getFilteredBranchServices({required int categoryId}) { - List filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList(); - return filteredServices; - } - void updatePickHomeLocationError(String value) { pickHomeLocationError = value; // notifyListeners(); @@ -843,4 +775,241 @@ class AppointmentsVM extends BaseVM { Utils.showToast("${e.toString()}"); } } + + // BRANCHES RELATED + + List nearbyBranches = []; + BranchDetailModel? selectedBranchModel; + + List branchServices = []; + + populateBranchesFilterList() { + providersFilterOptions.clear(); // TODO: THIS SHOULD BE DYNAMIC AND FILTERS SHOULD COME FORM API + providersFilterOptions = [ + FilterListModel(title: "All Providers", isSelected: true, id: 0), + FilterListModel(title: "Maintenance", isSelected: false, id: 1), + FilterListModel(title: "Oil Service", isSelected: false, id: 2), + FilterListModel(title: "Accessories", isSelected: false, id: 3), + FilterListModel(title: "Tire Service", isSelected: false, id: 4), + FilterListModel(title: "Dent and Paint", isSelected: false, id: 5), + ]; + notifyListeners(); + } + + getAllNearBranches({bool isNeedToRebuild = false}) async { + //TODO: needs to lat,long into API + nearbyBranches.clear(); + if (isNeedToRebuild) setState(ViewState.busy); + nearbyBranches = await providerRepo.getAllNearBranchAndServices(); + setState(ViewState.idle); + } + + void getBranchCategories() async { + for (var value in selectedBranchModel!.branchServices!) { + if (!isCategoryAlreadyPresent(value.categoryId!)) { + branchCategories.add(DropValue(value.categoryId!, value.categoryName!, "")); + } + } + notifyListeners(); + } + + getBranchServices({required int categoryId}) async { + branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + isHomeTapped = false; + pickedHomeLocation = ""; + pickHomeLocationError = ""; + if (categoryId != -1) { + isFetchingServices = true; + branchServices = getFilteredBranchServices(categoryId: categoryId); + isFetchingServices = false; + notifyListeners(); + } + } + + List getFilteredBranchServices({required int categoryId}) { + List filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList(); + return filteredServices; + } + + getBranchAndServices(int providerId) async { + providerProfileModel = null; + providerProfileModel = await providerRepo.getBranchAndServices(providerId); + setState(ViewState.idle); + } + + bool isCategoryAlreadyPresent(int id) { + final contain = branchCategories.where((element) => element.id == id); + if (contain.isEmpty) { + return false; + } + return true; + } + + updateSelectedBranch(BranchDetailModel branchDetailModel) { + selectedBranchModel = branchDetailModel; + getBranchCategories(); + notifyListeners(); + } + + double branchFilterCurrentDistance = 25.0; + + updateBranchFilterCurrentDistance(double value) { + branchFilterCurrentDistance = value; + notifyListeners(); + } + + // Provider Filter + List branchFilterProviderSearchHistory = []; + + void removeBranchFilterProviderSearchHistory({bool isClear = false, required int index}) { + if (isClear) { + branchFilterProviderSearchHistory.clear(); + notifyListeners(); + return; + } + branchFilterProviderSearchHistory.removeAt(index); + notifyListeners(); + } + + void addBranchFilterProviderSearchHistory({required DropValue value}) { + branchFilterProviderSearchHistory.add(value); + notifyListeners(); + } + + SelectionModel branchFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + + void updateBranchFilterSelectedProviderId(SelectionModel id, {bool isForSearch = false}) async {} + + // Category Filter + List branchFilterCategorySearchHistory = []; + + void removeFilterCategorySearchHistory({bool isClear = false, required int index}) { + if (isClear) { + branchFilterCategorySearchHistory.clear(); + notifyListeners(); + return; + } + branchFilterCategorySearchHistory.removeAt(index); + notifyListeners(); + } + + void addBranchFilterCategorySearchHistory({required DropValue value}) { + 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 branchFilterServicesSearchHistory = []; + + void removeBranchFilterServicesSearchHistory({bool isClear = false, required int index}) { + if (isClear) { + branchFilterServicesSearchHistory.clear(); + notifyListeners(); + return; + } + branchFilterServicesSearchHistory.removeAt(index); + notifyListeners(); + } + + void addBranchFilterServicesSearchHistory({required DropValue value}) { + branchFilterServicesSearchHistory.add(value); + notifyListeners(); + } + + SelectionModel branchFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + + void updateBranchFilterSelectedServiceId(SelectionModel id, {bool isForSearch = false}) async { + if (isForSearch) { + DropValue serviceDrop = categoryDropList.firstWhere((element) => element.id == id.selectedId); + if (!ifAlreadyExist(list: branchFilterServicesSearchHistory, value: serviceDrop)) { + addBranchFilterServicesSearchHistory(value: serviceDrop); + } + } + + branchFilterSelectedServiceId = id; + notifyListeners(); + + } + + ifAlreadyExist({required List list, required DropValue value}) { + int index = list.indexWhere((element) { + return element.id == value.id; + }); + + if (index != -1) { + return true; + } + + return false; + } + + List categoryDropList = []; + List servicesDropList = []; + List providersDropList = []; + + Future fetchAllProviders() async { + setOnlyState(ViewState.busy); + providersDropList.clear(); // IN PROGRESS + setState(ViewState.idle); + } + + Future fetchAllCategories(String countryCode) async { + categoryDropList.clear(); + setOnlyState(ViewState.busy); + Category category = await branchRepo.fetchBranchCategory(); + category.data?.forEach((element) { + categoryDropList.add( + DropValue( + element.id ?? 0, + ((element.categoryName!.isEmpty + ? "N/A" + : countryCode == "SA" + ? element.categoryNameN + : element.categoryName) ?? + "N/A"), + "", + ), + ); + }); + setState(ViewState.idle); + } + + Future fetchAllServices() async { + servicesDropList = []; + 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 populateDataForBranchesFilter() async { + await fetchAllCategories("SA"); // saudi arabia + await fetchAllServices(); // saudi arabia + updateBranchFilterCurrentDistance(25.0); + } } diff --git a/lib/views/branches/branches_filter_view.dart b/lib/views/branches/branches_filter_view.dart new file mode 100644 index 0000000..38fa55f --- /dev/null +++ b/lib/views/branches/branches_filter_view.dart @@ -0,0 +1,153 @@ +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'; +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'; + +class BranchesFilterView extends StatelessWidget { + const BranchesFilterView({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + title: "Branches 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 Name", + actionWidget: Builder( + builder: (context) { + return DropdownField( + (DropValue value) => appointmentsVM.updateBranchFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: appointmentsVM.providersDropList, + dropdownValue: appointmentsVM.branchFilterSelectedProviderId.selectedId != -1 + ? DropValue(appointmentsVM.branchFilterSelectedProviderId.selectedId, appointmentsVM.branchFilterSelectedProviderId.selectedOption, "") + : null, + hint: "Select Provider", + ); + }, + ), + historyContent: appointmentsVM.branchFilterProviderSearchHistory, + onHistoryItemDeleted: (index) { + appointmentsVM.removeBranchFilterProviderSearchHistory(index: index); + }, + onHistoryItemTapped: (DropValue value) => + appointmentsVM.updateBranchFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + ), + const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), + Row( + children: [ + "0 KM".toText(fontSize: 12, isBold: true), + Expanded( + child: SliderWidget( + minValue: 0, + maxValue: 100, + value: appointmentsVM.branchFilterCurrentDistance, + onChanged: appointmentsVM.updateBranchFilterCurrentDistance, + ), + ), + "${appointmentsVM.branchFilterCurrentDistance.toInt()} KM".toText(fontSize: 12, isBold: true), + ], + ), + const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), + SearchEntityWidget( + title: "Search By Category", + actionWidget: Builder( + builder: (context) { + return DropdownField( + (DropValue value) => appointmentsVM.updateBranchFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: appointmentsVM.categoryDropList, + dropdownValue: appointmentsVM.branchFilterSelectedCategoryId.selectedId != -1 + ? DropValue(appointmentsVM.branchFilterSelectedCategoryId.selectedId, appointmentsVM.branchFilterSelectedCategoryId.selectedOption, "") + : null, + hint: "Select Category", + ); + }, + ), + historyContent: appointmentsVM.branchFilterCategorySearchHistory, + onHistoryItemDeleted: (index) { + appointmentsVM.removeFilterCategorySearchHistory(index: index); + }, + onHistoryItemTapped: (DropValue value) => + appointmentsVM.updateBranchFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + ), + const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), + SearchEntityWidget( + title: "Search By Services", + actionWidget: Builder(builder: (context) { + return DropdownField( + (DropValue value) => appointmentsVM.updateBranchFilterSelectedServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + list: appointmentsVM.servicesDropList, + dropdownValue: appointmentsVM.branchFilterSelectedServiceId.selectedId != -1 + ? DropValue(appointmentsVM.branchFilterSelectedServiceId.selectedId, appointmentsVM.branchFilterSelectedServiceId.selectedOption, "") + : null, + hint: "Select Services", + ); + }), + historyContent: appointmentsVM.branchFilterServicesSearchHistory, + onHistoryItemDeleted: (index) => appointmentsVM.removeBranchFilterServicesSearchHistory(index: index), + onHistoryItemTapped: (DropValue value) => + appointmentsVM.updateBranchFilterSelectedServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + ) + ], + ).expand(), + Container( + color: MyColors.white, + child: Column( + children: [ + 5.height, + Row( + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Search", + onPressed: () {}, + backgroundColor: MyColors.darkPrimaryColor, + txtColor: MyColors.white, + fontSize: 18, + ), + ) + ], + ), + 10.height, + ], + ), + ), + ], + ).horPaddingMain(), + ); + }, + ), + ); + } +} diff --git a/lib/widgets/common_widgets/slider_widget.dart b/lib/widgets/common_widgets/slider_widget.dart new file mode 100644 index 0000000..4819861 --- /dev/null +++ b/lib/widgets/common_widgets/slider_widget.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; + +class SliderWidget extends StatelessWidget { + final double minValue; + final double maxValue; + final double value; + final Function(double) onChanged; + + const SliderWidget({super.key, required this.minValue, required this.maxValue, required this.value, required this.onChanged}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: SliderTheme( + data: const SliderThemeData( + trackShape: CustomSliderTrackShape(), + ), + child: Slider( + min: minValue, + max: maxValue, + value: value, + onChanged: onChanged, + ), + ), + ); + } +} + +class CustomSliderTrackShape extends RoundedRectSliderTrackShape { + const CustomSliderTrackShape(); + + @override + Rect getPreferredRect({ + required RenderBox parentBox, + Offset offset = Offset.zero, + required SliderThemeData sliderTheme, + bool isEnabled = false, + bool isDiscrete = false, + }) { + final trackHeight = sliderTheme.trackHeight; + final trackLeft = offset.dx; + final trackTop = offset.dy + (parentBox.size.height - trackHeight!) / 2; + final trackWidth = parentBox.size.width; + return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight); + } +} diff --git a/pubspec.lock b/pubspec.lock index 8bc6900..be6d778 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.1" country_code_picker: dependency: "direct main" description: @@ -561,10 +561,10 @@ packages: dependency: "direct main" description: name: intl - sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.18.1" + version: "0.18.0" js: dependency: transitive description: @@ -649,26 +649,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.2.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" mime: dependency: transitive description: @@ -958,10 +958,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" sqflite: dependency: transitive description: @@ -990,18 +990,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" stream_transform: dependency: transitive description: @@ -1046,10 +1046,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.5.1" tuple: dependency: transitive description: @@ -1154,14 +1154,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - web: - dependency: transitive - description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 - url: "https://pub.dev" - source: hosted - version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1174,18 +1166,18 @@ packages: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.0.9" win32_registry: dependency: transitive description: name: win32_registry - sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" + sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.1" xdg_directories: dependency: transitive description: @@ -1203,5 +1195,5 @@ packages: source: hosted version: "6.3.0" sdks: - dart: ">=3.2.0 <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.10.0" From 55c3af05405077d06878cafefc3a976194d04835 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Sun, 12 May 2024 18:13:39 +0300 Subject: [PATCH 2/3] Added Branch FilterView and their API integrations --- lib/classes/consts.dart | 3 +- lib/config/dependencies.dart | 2 - .../provider_model.dart | 33 ++- lib/repositories/branch_repo.dart | 157 +++++++++++-- lib/repositories/common_repo.dart | 4 +- lib/repositories/provider_repo.dart | 55 ----- lib/view_models/appointments_view_model.dart | 221 ++++++++++++++---- .../ad_duration_container.dart | 3 +- .../ad_review_containers.dart | 14 +- lib/views/branches/branches_filter_view.dart | 102 ++++++-- 10 files changed, 435 insertions(+), 159 deletions(-) delete mode 100644 lib/repositories/provider_repo.dart diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index b137e2a..7ce2de6 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -50,6 +50,7 @@ class ApiConsts { static String ServiceProviderService_Get = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get"; static String BranchesAndServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderDetail_Get"; + static String serviceProviderDDLGet = "${baseUrlServices}api/ServiceProviders/ServiceProviderDDL_Get"; static String GetAllNearBranches = "${baseUrlServices}api/ServiceProviders/ServiceProviderBranchDetail_Get"; //Appointment APIs @@ -100,7 +101,7 @@ class ApiConsts { static String vehicleDetailsMaster = "${baseUrlServices}api/Master"; static String vehicleAdsDurationGet = "${baseUrlServices}api/Advertisement/AdsDuration_Get"; static String vehicleAdsSpecialServicesGet = "${baseUrlServices}api/Common/SpecialService_Get"; - static String vehicleAdsSingleStepCreate = "${baseUrlServices}api/Advertisement/AdsSingl`eStep_Create"; + static String vehicleAdsSingleStepCreate = "${baseUrlServices}api/Advertisement/AdsSingleStep_Create"; static String vehicleAdsGet = "${baseUrlServices}api/Advertisement/Ads_Get"; static String myAdsReserveGet = "${baseUrlServices}api/Advertisement/AdsReserve_Get"; static String reserveAdsBankDetailsGet = "${baseUrlServices}api/Advertisement/MCBankAccountAd_Get"; diff --git a/lib/config/dependencies.dart b/lib/config/dependencies.dart index 8d13281..a16b30b 100644 --- a/lib/config/dependencies.dart +++ b/lib/config/dependencies.dart @@ -10,7 +10,6 @@ import 'package:mc_common_app/repositories/branch_repo.dart'; import 'package:mc_common_app/repositories/chat_repo.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; import 'package:mc_common_app/repositories/payments_repo.dart'; -import 'package:mc_common_app/repositories/provider_repo.dart'; import 'package:mc_common_app/repositories/user_repo.dart'; import 'package:mc_common_app/services/common_services.dart'; import 'package:mc_common_app/services/payments_service.dart'; @@ -33,7 +32,6 @@ class AppDependencies { injector.registerSingleton(() => AdsRepoImp()); injector.registerSingleton(() => PaymentsRepoImp()); injector.registerSingleton(() => RequestRepoImp()); - injector.registerSingleton(() => ProviderRepoImp()); injector.registerSingleton(() => AppointmentRepoImp()); injector.registerSingleton(() => ChatRepoImp()); injector.registerSingleton(() => BranchRepoImp()); diff --git a/lib/models/provider_branches_models/provider_model.dart b/lib/models/provider_branches_models/provider_model.dart index 256b281..f7a8c96 100644 --- a/lib/models/provider_branches_models/provider_model.dart +++ b/lib/models/provider_branches_models/provider_model.dart @@ -23,16 +23,14 @@ class ProviderModel { final ProviderModelData? data; final String? message; - factory ProviderModel.fromJson(Map json) => - ProviderModel( + factory ProviderModel.fromJson(Map json) => ProviderModel( messageStatus: json["messageStatus"], totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : ProviderModelData.fromJson(json["data"]), message: json["message"], ); - Map toJson() => - { + Map toJson() => { "messageStatus": messageStatus, "totalItemsCount": totalItemsCount, "data": data == null ? null : data!.toJson(), @@ -63,8 +61,7 @@ class ProviderModelData { final String? userId; final List? serviceProviderBranch; - factory ProviderModelData.fromJson(Map json) => - ProviderModelData( + factory ProviderModelData.fromJson(Map json) => ProviderModelData( id: json["id"], companyName: json["companyName"], countryName: json["countryName"], @@ -76,8 +73,7 @@ class ProviderModelData { serviceProviderBranch: json["serviceProviderBranch"] == null ? null : List.from(json["serviceProviderBranch"].map((x) => BranchDetailModel.fromJson(x))), ); - Map toJson() => - { + Map toJson() => { "id": id, "companyName": companyName, "companyDescription": companyDescription, @@ -88,3 +84,24 @@ class ProviderModelData { }; } +class ProviderBasicDataModel { + int? id; + String? providerName; + String? providerDescription; + + ProviderBasicDataModel({this.id, this.providerName, this.providerDescription}); + + ProviderBasicDataModel.fromJson(Map json) { + id = json['id']; + providerName = json['providerName']; + providerDescription = json['providerDescription']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['providerName'] = providerName; + data['providerDescription'] = providerDescription; + return data; + } +} diff --git a/lib/repositories/branch_repo.dart b/lib/repositories/branch_repo.dart index c14408d..46ad07a 100644 --- a/lib/repositories/branch_repo.dart +++ b/lib/repositories/branch_repo.dart @@ -4,14 +4,18 @@ 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/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/general_models/m_response.dart'; import 'package:flutter/cupertino.dart'; +import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/branch.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/document.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'; abstract class BranchRepo { Future createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude); @@ -34,6 +38,8 @@ abstract class BranchRepo { Future getBranchAndServices(); + Future> getAllProvidersWitheBasicData(); + Future createService(List> map); Future updateService(List> map); @@ -51,9 +57,28 @@ abstract class BranchRepo { Future removeDealerFromBranch(Map map); Future addNewServicesInAppointment(Map map); + + Future> getAllNearBranchAndServices(); + + Future> getServiceItems(int serviceId); + + Future getBranchAndServicesByProviderId(int providerId); + + Future> getBranchesByFilters({ + List? providerIdsList, + List? categoryIdsList, + List? serviceIdsList, + int? distanceKm, + int? rating, + double? latitude, + double? longitude, + }); } class BranchRepoImp implements BranchRepo { + ApiClient apiClient = injector.get(); + AppState appState = injector.get(); + @override Future createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async { var postParams = { @@ -67,35 +92,34 @@ class BranchRepoImp implements BranchRepo { "isActive": true }; String t = AppState().getUser.data!.accessToken ?? ""; - debugPrint("token " + t); - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createProviderBranch, postParams, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createProviderBranch, postParams, token: t); } @override Future fetchAllBranches() async { var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => Branch.fromJson(json), ApiConsts.ServiceProviderBranchGet, queryParameters: postParams, token: t); + return await apiClient.getJsonForObject((json) => Branch.fromJson(json), ApiConsts.ServiceProviderBranchGet, queryParameters: postParams, token: t); } @override Future fetchBranchCategory() async { var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => Category.fromJson(json), ApiConsts.ServiceCategory_Get, queryParameters: postParams, token: t); + return await apiClient.getJsonForObject((json) => Category.fromJson(json), ApiConsts.ServiceCategory_Get, queryParameters: postParams, token: t); } @override Future fetchServicesByCategoryId({required int serviceCategoryId}) async { var postParams = {"ServiceCategoryID": serviceCategoryId}; String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => Services.fromJson(json), ApiConsts.Services_Get, queryParameters: serviceCategoryId != -1 ? postParams : null, token: t); + return await apiClient.getJsonForObject((json) => Services.fromJson(json), ApiConsts.Services_Get, queryParameters: serviceCategoryId != -1 ? postParams : null, token: t); } @override Future createNewService(List> map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t); } @override @@ -127,16 +151,27 @@ class BranchRepoImp implements BranchRepo { } } String t = AppState().getUser.data!.accessToken ?? ""; - debugPrint("token " + t); - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderDocument_Update, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderDocument_Update, map, token: t); } @override Future getBranchAndServices() async { var postParams = {"serviceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; String t = AppState().getUser.data!.accessToken ?? ""; - print("tokeen121 " + t); - return await injector.get().getJsonForObject((json) => ProviderModel.fromJson(json), ApiConsts.BranchesAndServices, queryParameters: postParams, token: t); + return await apiClient.getJsonForObject((json) => ProviderModel.fromJson(json), ApiConsts.BranchesAndServices, queryParameters: postParams, token: t); + } + + @override + Future> getAllProvidersWitheBasicData() async { + String t = AppState().getUser.data!.accessToken ?? ""; + + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: t, + (json) => GenericRespModel.fromJson(json), + ApiConsts.serviceProviderDDLGet, + ); + List providersList = List.generate(adsGenericModel.data.length, (index) => ProviderBasicDataModel.fromJson(adsGenericModel.data[index])); + return providersList; } @override @@ -158,19 +193,19 @@ class BranchRepoImp implements BranchRepo { "isActive": isNeedToDelete }; String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t); } @override Future createService(List> map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t); } @override Future updateService(List> map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Update, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Update, map, token: t); } @override @@ -181,37 +216,37 @@ class BranchRepoImp implements BranchRepo { "CategoryID": categoryId.toString(), }; String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getMatchedServices, queryParameters: postParams, token: t); + return await apiClient.getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getMatchedServices, queryParameters: postParams, token: t); } @override Future duplicateItems(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.duplicateItems, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.duplicateItems, map, token: t); } @override Future getAllProviderDealers(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getAllProviderDealers, queryParameters: map, token: t); + return await apiClient.getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getAllProviderDealers, queryParameters: map, token: t); } @override Future getBranchUsers(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getBranchUser, queryParameters: map, token: t); + return await apiClient.getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getBranchUser, queryParameters: map, token: t); } @override Future assignDealerToBranch(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.assignDealerToBranch, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.assignDealerToBranch, map, token: t); } @override Future removeDealerFromBranch(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.removeDealerFromBranch, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.removeDealerFromBranch, map, token: t); } @override @@ -222,12 +257,92 @@ class BranchRepoImp implements BranchRepo { }; String t = AppState().getUser.data!.accessToken ?? ""; debugPrint("token " + t); - return await injector.get().getJsonForObject((json) => Services.fromJson(json), ApiConsts.GetProviderServices, queryParameters: postParams, token: t); + return await apiClient.getJsonForObject((json) => Services.fromJson(json), ApiConsts.GetProviderServices, queryParameters: postParams, token: t); } @override Future addNewServicesInAppointment(Map map) async { String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.AddNewServicesInAppointment, map, token: t); + return await apiClient.postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.AddNewServicesInAppointment, map, token: t); + } + + @override + Future> getAllNearBranchAndServices() async { + GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.GetAllNearBranches, token: appState.getUser.data!.accessToken); + List nearBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index])); + return nearBranches; + } + + @override + Future> getServiceItems(int serviceId) async { + var queryParameters = { + "ServiceProviderServiceID": serviceId.toString(), + }; + + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.getServiceItems, + token: appState.getUser.data!.accessToken, + queryParameters: queryParameters, + ); + List serviceItems = List.generate(adsGenericModel.data.length, (index) => ItemData.fromJson(adsGenericModel.data[index])); + return serviceItems; + } + + @override + Future getBranchAndServicesByProviderId(int providerId) async { + var postParams = {"serviceProviderID": providerId.toString()}; + GenericRespModel adsGenericModel = + await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.BranchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams); + + return ProviderProfileModel.fromJson(adsGenericModel.data); + } + + @override + Future> getBranchesByFilters({ + List? providerIdsList, + List? categoryIdsList, + List? serviceIdsList, + int? distanceKm, + int? rating, + double? latitude, + double? longitude, + }) 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()); + } + } + var postParams = { + "ServiceProviderIDs": providerIds, + "ServiceCategoryIDs": categoryIds, + "ServiceIDs": serviceIds, + "DistanceByKM": "${distanceKm ?? 0}", + "Rating": "${rating ?? 0}", + "Latitude": latitude.toString(), + "Longitude": longitude.toString(), + }; + + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.GetAllNearBranches, + token: appState.getUser.data!.accessToken, + queryParameters: postParams, + ); + List nearBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index])); + return nearBranches; } } diff --git a/lib/repositories/common_repo.dart b/lib/repositories/common_repo.dart index d26ee5e..80e6099 100644 --- a/lib/repositories/common_repo.dart +++ b/lib/repositories/common_repo.dart @@ -146,8 +146,8 @@ class CommonRepoImp implements CommonRepo { token: appState.getUser.data!.accessToken, ); - List vehicleCities = List.generate(enumGenericModel.data.length, (index) => EnumsModel.fromJson(enumGenericModel.data[index])); - return vehicleCities; + List enums = List.generate(enumGenericModel.data.length, (index) => EnumsModel.fromJson(enumGenericModel.data[index])); + return enums; } @override diff --git a/lib/repositories/provider_repo.dart b/lib/repositories/provider_repo.dart deleted file mode 100644 index b327a17..0000000 --- a/lib/repositories/provider_repo.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'dart:async'; - -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/general_models/generic_resp_model.dart'; -import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; -import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart'; -import 'package:mc_common_app/models/services_models/item_model.dart'; - -abstract class ProviderRepo { - Future> getAllNearBranchAndServices(); - - Future> getServiceItems(int serviceId); - - Future getBranchAndServices(int providerId); -} - -class ProviderRepoImp implements ProviderRepo { - ApiClient apiClient = injector.get(); - AppState appState = injector.get(); - - @override - Future> getAllNearBranchAndServices() async { - GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.GetAllNearBranches, token: appState.getUser.data!.accessToken); - List nearBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index])); - return nearBranches; - } - - @override - Future> getServiceItems(int serviceId) async { - var queryParameters = { - "ServiceProviderServiceID": serviceId.toString(), - }; - - GenericRespModel adsGenericModel = await apiClient.getJsonForObject( - (json) => GenericRespModel.fromJson(json), - ApiConsts.getServiceItems, - token: appState.getUser.data!.accessToken, - queryParameters: queryParameters, - ); - List serviceItems = List.generate(adsGenericModel.data.length, (index) => ItemData.fromJson(adsGenericModel.data[index])); - return serviceItems; - } - - @override - Future getBranchAndServices(int providerId) async { - var postParams = {"serviceProviderID": providerId.toString()}; - GenericRespModel adsGenericModel = - await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.BranchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams); - - return ProviderProfileModel.fromJson(adsGenericModel.data); - } -} diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart index 4e3d246..fe229f3 100644 --- a/lib/view_models/appointments_view_model.dart +++ b/lib/view_models/appointments_view_model.dart @@ -1,9 +1,12 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; +import 'package:mc_common_app/models/appointments_models/appointment_slots.dart'; import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/models/general_models/enums_model.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; @@ -12,13 +15,13 @@ import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/services.dart'; +import 'package:mc_common_app/models/provider_branches_models/provider_model.dart'; import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart'; import 'package:mc_common_app/models/services_models/item_model.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; import 'package:mc_common_app/repositories/appointment_repo.dart'; import 'package:mc_common_app/repositories/branch_repo.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; -import 'package:mc_common_app/repositories/provider_repo.dart'; import 'package:mc_common_app/services/common_services.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; @@ -34,16 +37,13 @@ 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 '../models/appointments_models/appointment_slots.dart'; - class AppointmentsVM extends BaseVM { final CommonRepo commonRepo; final CommonAppServices commonServices; - final ProviderRepo providerRepo; final BranchRepo branchRepo; final AppointmentRepo scheduleRepo; - AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo, required this.branchRepo}); + AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.commonRepo, required this.branchRepo}); bool isUpcommingEnabled = true; bool isFetchingLists = false; @@ -221,7 +221,7 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - List providersFilterOptions = []; + List branchesFilterOptions = []; List servicesInCurrentAppointment = []; ServiceModel? currentServiceSelection; @@ -279,11 +279,11 @@ class AppointmentsVM extends BaseVM { value.isSelected = false; } - appointmentsFilterOptions.forEach((element) { + for (var element in appointmentsFilterOptions) { if (element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()) { element.isSelected = true; } - }); + } // appointmentsFilterOptions[ // appointmentStatusEnum.getIdFromAppointmentStatusEnum()] // .isSelected = true; @@ -495,18 +495,20 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - applyFilterOnProviders({required int index}) { - if (providersFilterOptions.isEmpty) return; - for (var value in providersFilterOptions) { + applyFilterOnBranches({required int index}) async { + if (branchesFilterOptions.isEmpty) return; + for (var value in branchesFilterOptions) { value.isSelected = false; } - providersFilterOptions[index].isSelected = true; + branchesFilterOptions[index].isSelected = true; + + await getBranchesBasedOnCategoryFilters(categoryId: branchesFilterOptions[index].id); notifyListeners(); } Future> getServiceItems(int serviceId) async { serviceItemsFromApi.clear(); - serviceItemsFromApi = await providerRepo.getServiceItems(serviceId); + serviceItemsFromApi = await branchRepo.getServiceItems(serviceId); for (var item in serviceItemsFromApi) { if (ifItemAlreadySelected(item.id!)) { item.isUpdateOrSelected = true; @@ -783,24 +785,43 @@ class AppointmentsVM extends BaseVM { List branchServices = []; - populateBranchesFilterList() { - providersFilterOptions.clear(); // TODO: THIS SHOULD BE DYNAMIC AND FILTERS SHOULD COME FORM API - providersFilterOptions = [ - FilterListModel(title: "All Providers", isSelected: true, id: 0), - FilterListModel(title: "Maintenance", isSelected: false, id: 1), - FilterListModel(title: "Oil Service", isSelected: false, id: 2), - FilterListModel(title: "Accessories", isSelected: false, id: 3), - FilterListModel(title: "Tire Service", isSelected: false, id: 4), - FilterListModel(title: "Dent and Paint", isSelected: false, id: 5), - ]; + // populateBranchesFilterList() { + // branchesFilterOptions.clear(); // TODO: THIS SHOULD BE DYNAMIC AND FILTERS SHOULD COME FORM API + // branchesFilterOptions = [ + // FilterListModel(title: "All Branches", isSelected: true, id: 0), + // FilterListModel(title: "Maintenance", isSelected: false, id: 1), + // FilterListModel(title: "Oil Service", isSelected: false, id: 2), + // FilterListModel(title: "Accessories", isSelected: false, id: 3), + // FilterListModel(title: "Tire Service", isSelected: false, id: 4), + // FilterListModel(title: "Dent and Paint", isSelected: false, id: 5), + // ]; + // notifyListeners(); + // } + + Future populateBranchesFilterList() async { + if (branchesFilterOptions.isNotEmpty) return; + branchesFilterOptions.clear(); + setOnlyState(ViewState.busy); + Category category = await branchRepo.fetchBranchCategory(); + category.data?.forEach((element) { + branchesFilterOptions.add(FilterListModel(id: element.id ?? 0, isSelected: false, title: element.categoryName ?? "N/A")); + }); + branchesFilterOptions.insert(0, FilterListModel(id: 0, isSelected: true, title: "All Branches")); notifyListeners(); + setState(ViewState.idle); } - getAllNearBranches({bool isNeedToRebuild = false}) async { - //TODO: needs to lat,long into API + getAllNearBranches({bool isNeedToRebuild = false, bool isFromRefresh = false}) async { nearbyBranches.clear(); if (isNeedToRebuild) setState(ViewState.busy); - nearbyBranches = await providerRepo.getAllNearBranchAndServices(); + + if (isFromRefresh) { + var selectedBranch = branchesFilterOptions.firstWhere((element) => element.isSelected); + nearbyBranches = await branchRepo.getBranchesByFilters(categoryIdsList: [selectedBranch.id]); + setState(ViewState.idle); + return; + } + nearbyBranches = await branchRepo.getAllNearBranchAndServices(); setState(ViewState.idle); } @@ -833,7 +854,7 @@ class AppointmentsVM extends BaseVM { getBranchAndServices(int providerId) async { providerProfileModel = null; - providerProfileModel = await providerRepo.getBranchAndServices(providerId); + providerProfileModel = await branchRepo.getBranchAndServicesByProviderId(providerId); setState(ViewState.idle); } @@ -851,6 +872,13 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } + int branchFiltersCounter = 0; + + updateBranchFiltersCounter(int value) { + branchFiltersCounter = value; + notifyListeners(); + } + double branchFilterCurrentDistance = 25.0; updateBranchFilterCurrentDistance(double value) { @@ -868,17 +896,33 @@ class AppointmentsVM extends BaseVM { return; } branchFilterProviderSearchHistory.removeAt(index); + if (branchFilterProviderSearchHistory.isEmpty) { + updateBranchFiltersCounter(branchFiltersCounter - 1); + } 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 {} + 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 branchFilterCategorySearchHistory = []; @@ -890,10 +934,16 @@ class AppointmentsVM extends BaseVM { return; } branchFilterCategorySearchHistory.removeAt(index); + if (branchFilterCategorySearchHistory.isEmpty) { + updateBranchFiltersCounter(branchFiltersCounter - 1); + } notifyListeners(); } void addBranchFilterCategorySearchHistory({required DropValue value}) { + if (branchFilterCategorySearchHistory.isEmpty) { + updateBranchFiltersCounter(branchFiltersCounter + 1); + } branchFilterCategorySearchHistory.add(value); notifyListeners(); } @@ -912,8 +962,6 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - - // Services Filter List branchFilterServicesSearchHistory = []; @@ -924,10 +972,16 @@ class AppointmentsVM extends BaseVM { return; } branchFilterServicesSearchHistory.removeAt(index); + if (branchFilterServicesSearchHistory.isEmpty) { + updateBranchFiltersCounter(branchFiltersCounter - 1); + } notifyListeners(); } void addBranchFilterServicesSearchHistory({required DropValue value}) { + if (branchFilterServicesSearchHistory.isEmpty) { + updateBranchFiltersCounter(branchFiltersCounter + 1); + } branchFilterServicesSearchHistory.add(value); notifyListeners(); } @@ -936,7 +990,7 @@ class AppointmentsVM extends BaseVM { void updateBranchFilterSelectedServiceId(SelectionModel id, {bool isForSearch = false}) async { if (isForSearch) { - DropValue serviceDrop = categoryDropList.firstWhere((element) => element.id == id.selectedId); + DropValue serviceDrop = servicesDropList.firstWhere((element) => element.id == id.selectedId); if (!ifAlreadyExist(list: branchFilterServicesSearchHistory, value: serviceDrop)) { addBranchFilterServicesSearchHistory(value: serviceDrop); } @@ -944,7 +998,6 @@ class AppointmentsVM extends BaseVM { branchFilterSelectedServiceId = id; notifyListeners(); - } ifAlreadyExist({required List list, required DropValue value}) { @@ -959,39 +1012,57 @@ class AppointmentsVM extends BaseVM { return false; } + // Rating filter + + double branchFilterByRating = 4.0; + + updateBranchFilterByRating(double value) { + branchFilterByRating = value; + notifyListeners(); + } + List categoryDropList = []; List servicesDropList = []; List providersDropList = []; Future fetchAllProviders() async { + if (providersDropList.isNotEmpty) return; + + providersDropList.clear(); setOnlyState(ViewState.busy); - providersDropList.clear(); // IN PROGRESS + List providers = await branchRepo.getAllProvidersWitheBasicData(); + for (var element in providers) { + providersDropList.add( + DropValue(element.id ?? 0, element.providerName ?? "N/A", ""), + ); + } setState(ViewState.idle); } Future fetchAllCategories(String countryCode) async { + if (categoryDropList.isNotEmpty) return; categoryDropList.clear(); setOnlyState(ViewState.busy); Category category = await branchRepo.fetchBranchCategory(); category.data?.forEach((element) { categoryDropList.add( DropValue( - element.id ?? 0, - ((element.categoryName!.isEmpty - ? "N/A" - : countryCode == "SA" - ? element.categoryNameN - : element.categoryName) ?? - "N/A"), - "", - ), + element.id ?? 0, + ((element.categoryName!.isEmpty + ? "N/A" + : countryCode == "SA" + ? element.categoryNameN + : element.categoryName) ?? + "N/A"), + ""), ); }); setState(ViewState.idle); } Future fetchAllServices() async { - servicesDropList = []; + if (servicesDropList.isNotEmpty) return; + servicesDropList.clear(); setState(ViewState.busy); Services services = await branchRepo.fetchServicesByCategoryId(serviceCategoryId: -1); // to get all services @@ -1008,8 +1079,72 @@ class AppointmentsVM extends BaseVM { } Future populateDataForBranchesFilter() async { + await fetchAllProviders(); // saudi arabia await fetchAllCategories("SA"); // saudi arabia await fetchAllServices(); // saudi arabia updateBranchFilterCurrentDistance(25.0); } + + void clearBranchFilters() { + branchFilterServicesSearchHistory.clear(); + branchFilterCategorySearchHistory.clear(); + branchFilterProviderSearchHistory.clear(); + branchFilterByRating = 4.0; + branchFilterCurrentDistance = 25.0; + branchFiltersCounter = 0; + clearBranchFilterSelections(); + notifyListeners(); + } + + void clearBranchFilterSelections() { + branchFilterSelectedProviderId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + branchFilterSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + branchFilterSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + } + + Future getBranchesBasedOnFilters() async { + nearbyBranches.clear(); + setState(ViewState.busy); + List providersIdsList = []; + if (branchFilterProviderSearchHistory.isNotEmpty) { + for (var element in branchFilterProviderSearchHistory) { + providersIdsList.add(element.id); + } + } + List categoryIdsList = []; + if (branchFilterCategorySearchHistory.isNotEmpty) { + for (var element in branchFilterCategorySearchHistory) { + categoryIdsList.add(element.id); + } + } + List servicesIdsList = []; + if (branchFilterServicesSearchHistory.isNotEmpty) { + for (var element in branchFilterServicesSearchHistory) { + servicesIdsList.add(element.id); + } + } + + nearbyBranches = await branchRepo.getBranchesByFilters( + providerIdsList: providersIdsList.isNotEmpty ? providersIdsList : null, + categoryIdsList: categoryIdsList.isNotEmpty ? categoryIdsList : null, + serviceIdsList: servicesIdsList.isNotEmpty ? servicesIdsList : null, + distanceKm: branchFilterCurrentDistance.toInt(), + rating: branchFilterByRating.toInt(), + latitude: 24.694969, + longitude: 46.724129, + ); + setState(ViewState.idle); + } + + Future getBranchesBasedOnCategoryFilters({required int categoryId}) async { + if (categoryId == 0) { + await getAllNearBranches(); + return; + } + setState(ViewState.busy); + + nearbyBranches.clear(); + nearbyBranches = await branchRepo.getBranchesByFilters(categoryIdsList: [categoryId]); + setState(ViewState.idle); + } } diff --git a/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart index ba0ef7b..ce9854e 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart @@ -154,7 +154,7 @@ class AdDuration extends StatelessWidget { child: CupertinoSwitch( activeColor: MyColors.darkPrimaryColor, trackColor: MyColors.white, - thumbColor: MyColors.grey98Color, + thumbColor: MyColors.greyButtonColor, value: adVM.isPhoneNumberShown, onChanged: (value) { adVM.updateIsPhoneNumberShownStatus(value); @@ -190,6 +190,7 @@ class AdDuration extends StatelessWidget { ), errorValue: adVM.adPhoneNumberError, hint: '123456789', + keyboardType: TextInputType.number, value: adVM.adPhoneNumber, onChanged: (v) => adVM.updateAdPhoneNumber(v), ), diff --git a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart index a939613..9eb84bc 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart @@ -15,10 +15,10 @@ class ReviewAd extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - VehicleDetailsReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), - DamagePartsReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), - AdDurationReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), - AdContactDetailsReview(), + const VehicleDetailsReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), + const DamagePartsReview(), + const AdDurationReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), + const AdContactDetailsReview(), ], ); } @@ -160,14 +160,16 @@ class DamagePartsReview extends StatelessWidget { @override Widget build(BuildContext context) { AdVM adVM = context.read(); - + if (adVM.vehicleDamageCards.isEmpty) { + return const SizedBox.shrink(); + } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Vehicle Damage Part".toText(fontSize: 18, isBold: true), buildDamagePartList(adVM), ], - ); + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)); } } diff --git a/lib/views/branches/branches_filter_view.dart b/lib/views/branches/branches_filter_view.dart index 38fa55f..321358d 100644 --- a/lib/views/branches/branches_filter_view.dart +++ b/lib/views/branches/branches_filter_view.dart @@ -1,3 +1,5 @@ +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'; @@ -14,9 +16,31 @@ import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; -class BranchesFilterView extends StatelessWidget { +class BranchesFilterView extends StatefulWidget { const BranchesFilterView({super.key}); + @override + State createState() => _BranchesFilterViewState(); +} + +class _BranchesFilterViewState 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( @@ -43,7 +67,7 @@ class BranchesFilterView extends StatelessWidget { children: [ 20.height, SearchEntityWidget( - title: "Search By Provider Name", + title: "Search By Provider", actionWidget: Builder( builder: (context) { return DropdownField( @@ -63,22 +87,28 @@ class BranchesFilterView extends StatelessWidget { onHistoryItemTapped: (DropValue value) => appointmentsVM.updateBranchFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), ), - const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), - Row( + const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - "0 KM".toText(fontSize: 12, isBold: true), - Expanded( - child: SliderWidget( - minValue: 0, - maxValue: 100, - value: appointmentsVM.branchFilterCurrentDistance, - onChanged: appointmentsVM.updateBranchFilterCurrentDistance, - ), + "Search By Distance".toText(fontSize: 16, isBold: true), + Row( + children: [ + "0 KM".toText(fontSize: 12, isBold: true), + Expanded( + child: SliderWidget( + minValue: 0, + maxValue: 100, + value: appointmentsVM.branchFilterCurrentDistance, + onChanged: appointmentsVM.updateBranchFilterCurrentDistance, + ), + ), + "${appointmentsVM.branchFilterCurrentDistance.toInt()} KM".toText(fontSize: 12, isBold: true), + ], ), - "${appointmentsVM.branchFilterCurrentDistance.toInt()} KM".toText(fontSize: 12, isBold: true), ], ), - const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), + const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), SearchEntityWidget( title: "Search By Category", actionWidget: Builder( @@ -100,9 +130,9 @@ class BranchesFilterView extends StatelessWidget { onHistoryItemTapped: (DropValue value) => appointmentsVM.updateBranchFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), ), - const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7), + const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), SearchEntityWidget( - title: "Search By Services", + title: "Search By Service", actionWidget: Builder(builder: (context) { return DropdownField( (DropValue value) => appointmentsVM.updateBranchFilterSelectedServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), @@ -115,9 +145,29 @@ class BranchesFilterView extends StatelessWidget { }), historyContent: appointmentsVM.branchFilterServicesSearchHistory, onHistoryItemDeleted: (index) => appointmentsVM.removeBranchFilterServicesSearchHistory(index: index), - onHistoryItemTapped: (DropValue value) => - appointmentsVM.updateBranchFilterSelectedServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), - ) + onHistoryItemTapped: (DropValue value) => null, + ), + const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Search By Minimum Ratings".toText(fontSize: 16, isBold: true), + Row( + children: [ + "1 Star".toText(fontSize: 12, isBold: true), + Expanded( + child: SliderWidget( + minValue: 0, + maxValue: 5, + value: appointmentsVM.branchFilterByRating, + onChanged: appointmentsVM.updateBranchFilterByRating, + ), + ), + "${appointmentsVM.branchFilterByRating.toInt()} Star".toText(fontSize: 12, isBold: true), + ], + ), + ], + ), ], ).expand(), Container( @@ -131,7 +181,10 @@ class BranchesFilterView extends StatelessWidget { child: ShowFillButton( maxHeight: 55, title: "Search", - onPressed: () {}, + onPressed: () { + Navigator.pop(context); + appointmentsVM.getBranchesBasedOnFilters(); + }, backgroundColor: MyColors.darkPrimaryColor, txtColor: MyColors.white, fontSize: 18, @@ -139,6 +192,15 @@ class BranchesFilterView extends StatelessWidget { ) ], ), + 8.height, + InkWell( + onTap: () => appointmentsVM.clearBranchFilters(), + child: "Clear Filters".toText( + fontSize: 14, + isBold: true, + color: MyColors.darkPrimaryColor, + ), + ), 10.height, ], ), From 69fc3346c6d86f9b27fd3b6fea797955170bda84 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Tue, 14 May 2024 18:12:03 +0300 Subject: [PATCH 3/3] 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(