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, ], ),