diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 5cb1115..ef14308 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -785,6 +785,10 @@ "tapToView": "انقر لعرض", "noServicesAvailableToCopy": "لا توجد خدمات متاحة في هذا الفرع لنسخها.", "copySelectedItems": "نسخ العناصر المحددة", - "companyNameMandatory": "اسم الشركة إلزامي" - + "companyNameMandatory": "اسم الشركة إلزامي", + "noOfInvites": "عدد الدعوات", + "noSpecialServicesAvailable": "لا توجد خدمات خاصة متاحة للمنطقة المحددة.", + "customService": "الخدمة المخصصة", + "selectServiceDetails": "اختر تفاصيل الخدمة", + "addServiceDetails": "أضف تفاصيل الخدمة" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 865ef94..0f5e483 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -783,5 +783,10 @@ "tapToView": "Tap to view", "noServicesAvailableToCopy": "There are no services available in this branch to copy.", "copySelectedItems": "Copy Selected Items", - "companyNameMandatory": "Company Name is mandatory" + "companyNameMandatory": "Company Name is mandatory", + "noOfInvites": "No of invites", + "noSpecialServicesAvailable": "There are no special services available for the selected region.", + "customService": "Custom Service", + "selectServiceDetails": "Select service details", + "addServiceDetails": "Add service details" } \ No newline at end of file diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 7f9ee48..f777be3 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -41,6 +41,7 @@ class ApiConsts { static String getUserImage = "${baseUrlServices}api/ProfileImage"; static String userUpdate = "${baseUrlServices}api/User_Update"; static String providerComplaintCreate = "${baseUrlServices}api/ServiceProviders/ProviderComplaint_Create"; + static String provideContactInfoGet = "${baseUrlServices}api/ServiceProviders/ServiceProviderContact_Get"; //Profile static String fetProviderDocument = "${baseUrlServices}api/ServiceProviders/ServiceProviderDocument_Get"; @@ -191,6 +192,7 @@ class ApiConsts { static String getContactInfo = "${baseUrlServices}api/Master/ContactInfo_Get"; static String getAppInfo = "${baseUrlServices}api/Master/AppInfo_Get"; static String getTermsAndConditions = "${baseUrlServices}api/Master/TermAndCondition_Get"; + static String getAppInvitationHistory = "${baseUrlServices}api/Common/AppInvitation_Get"; static List closingUrls = ["PayFortResponse"]; } @@ -234,6 +236,9 @@ class GlobalConsts { static String homeLocationEmptyError = "Home location cannot be empty"; static String fillAllFields = "Please fill out all the fields."; static String requestTypeCannotBeEmpty = "Request type cannot be empty."; + static String serviceNameError = "Service name cannot be empty."; + static String priceError = "Price cannot be empty."; + static String taxError = "Tax cannot be empty."; static String reserveAdPriceInfo = "Some dummy description to explain the following concept. This price will be for 24 hours and if a user cancels the reservations before 24 hours then the amount will be automatically refunded to the buyer."; static String appInvitationMessageEn = "🚗 Hey , check out MOWATER to book car services, buy/sell vehicles, and more—join here! [Invite Link]"; @@ -261,8 +266,8 @@ class GlobalConsts { static int maxFileCount = 7; static int maxFileSizeInBytes = 2 * 1024 * 1024; - static String allowedFileExtensions = "jpg,png - 2MB"; - static String allowedFileExtensionsPDF = "PDF 2MB"; + static String allowedFileExtensions = "jpg,jpeg,png - 2MB/file"; + static String allowedFileExtensionsPDF = "PDF 2MB/file"; static int providerDealerRoleTypeId = 6; static int providerIndividualRoleTypeId = 5; diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index 18d8869..eb64623 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -736,7 +736,7 @@ class CodegenLoader extends AssetLoader{ "ownerInformation": "معلومات المالك", "acceptedRequests": "الطلبات المقبولة", "specialRequestChat": "دردشة الطلب الخاص", - "companyName": "اسم الشركة *", + "companyName": "اسم الشركة", "noAvailableItems": "لا توجد عناصر متاحة.", "serviceDeliveryType": "نوع تقديم الخدمة", "noImagesToShow": "لا توجد صور للعرض", @@ -801,7 +801,12 @@ class CodegenLoader extends AssetLoader{ "tapToView": "انقر لعرض", "noServicesAvailableToCopy": "لا توجد خدمات متاحة في هذا الفرع لنسخها.", "copySelectedItems": "نسخ العناصر المحددة", - "companyNameMandatory": "اسم الشركة إلزامي" + "companyNameMandatory": "اسم الشركة إلزامي", + "noOfInvites": "عدد الدعوات", + "noSpecialServicesAvailable": "لا توجد خدمات خاصة متاحة للمنطقة المحددة.", + "customService": "الخدمة المخصصة", + "selectServiceDetails": "اختر تفاصيل الخدمة", + "addServiceDetails": "أضف تفاصيل الخدمة" }; static const Map en_US = { "firstTimeLogIn": "First Time Log In", @@ -1519,7 +1524,7 @@ static const Map en_US = { "noItemsToShow": "There are no Items no show.", "acceptedRequests": "Accepted Requests", "specialRequestChat": "Special Request Chat", - "companyName": "Company Name *", + "companyName": "Company Name", "noAvailableItems": "There are no available items.", "serviceDeliveryType": "Service Delivery Type", "noImagesToShow": "No Images to Show", @@ -1588,7 +1593,12 @@ static const Map en_US = { "tapToView": "Tap to view", "noServicesAvailableToCopy": "There are no services available in this branch to copy.", "copySelectedItems": "Copy Selected Items", - "companyNameMandatory": "Company Name is mandatory" + "companyNameMandatory": "Company Name is mandatory", + "noOfInvites": "No of invites", + "noSpecialServicesAvailable": "There are no special services available for the selected region.", + "customService": "Custom Service", + "selectServiceDetails": "Select service details", + "addServiceDetails": "Add service details" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 16d573f..1dc7365 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1,6 +1,6 @@ // DO NOT EDIT. This is code generated via package:easy_localization/generate.dart -abstract class LocaleKeys { +abstract class LocaleKeys { static const firstTimeLogIn = 'firstTimeLogIn'; static const signUp = 'signUp'; static const changeMobile = 'changeMobile'; @@ -47,7 +47,7 @@ abstract class LocaleKeys { static const emailChangedSuccessfully = 'emailChangedSuccessfully'; static const passwordIsUpdated = 'passwordIsUpdated'; static const passwordShouldContains = 'passwordShouldContains'; - static const successfullyRegistered = ' successfullyRegistered'; + static const successfullyRegistered = ' successfullyRegistered'; static const pleaseEnterSamePassword = 'pleaseEnterSamePassword'; static const firstNameMandatory = 'firstNameMandatory'; static const surnameNameMandatory = 'surnameNameMandatory'; @@ -765,5 +765,10 @@ abstract class LocaleKeys { static const noServicesAvailableToCopy = 'noServicesAvailableToCopy'; static const copySelectedItems = 'copySelectedItems'; static const companyNameMandatory = 'companyNameMandatory'; + static const noOfInvites = 'noOfInvites'; + static const noSpecialServicesAvailable = 'noSpecialServicesAvailable'; + static const customService = 'customService'; + static const selectServiceDetails = 'selectServiceDetails'; + static const addServiceDetails = 'addServiceDetails'; } diff --git a/lib/models/provider_branches_models/provider_contact_info_model.dart b/lib/models/provider_branches_models/provider_contact_info_model.dart new file mode 100644 index 0000000..2b3febf --- /dev/null +++ b/lib/models/provider_branches_models/provider_contact_info_model.dart @@ -0,0 +1,47 @@ +class ProviderContactInfoModel { + int? id; + int? providerID; + String? name; + int? allDocStatus; + String? companyName; + String? companyDescription; + int? countryID; + String? countryName; + String? userID; + String? memberSince; + String? mobile; + String? whatsApp; + String? email; + + ProviderContactInfoModel({ + this.id, + this.providerID, + this.name, + this.allDocStatus, + this.companyName, + this.companyDescription, + this.countryID, + this.countryName, + this.userID, + this.memberSince, + this.mobile, + this.whatsApp, + this.email, + }); + + ProviderContactInfoModel.fromJson(Map json) { + id = json['id']; + providerID = json['providerID']; + name = json['name']; + allDocStatus = json['allDocStatus']; + companyName = json['companyName']; + companyDescription = json['companyDescription']; + countryID = json['countryID']; + countryName = json['countryName']; + userID = json['userID']; + memberSince = json['memberSince']; + mobile = json['mobile']; + whatsApp = json['whatsApp']; + email = json['email']; + } +} diff --git a/lib/models/provider_branches_models/provider_profile_model.dart b/lib/models/provider_branches_models/provider_profile_model.dart index 0ad6d75..d40dc76 100644 --- a/lib/models/provider_branches_models/provider_profile_model.dart +++ b/lib/models/provider_branches_models/provider_profile_model.dart @@ -4,6 +4,7 @@ class ProviderProfileModel { ProviderProfileModel({ this.id, this.companyName, + this.profileImage, this.name, this.countryName, this.companyDescription, @@ -20,6 +21,7 @@ class ProviderProfileModel { }); final int? id; + final String? profileImage; final String? companyName; final String? companyDescription; int? countryID; @@ -38,6 +40,7 @@ class ProviderProfileModel { factory ProviderProfileModel.fromJson(Map json) => ProviderProfileModel( id: json["id"], companyName: json["companyName"], + profileImage: json["profileImage"] ?? "", name: json["name"], countryName: json["countryName"], countryID: json["countryID"], diff --git a/lib/models/setting_utils_models/app_invitation_history_model.dart b/lib/models/setting_utils_models/app_invitation_history_model.dart new file mode 100644 index 0000000..2bd75d5 --- /dev/null +++ b/lib/models/setting_utils_models/app_invitation_history_model.dart @@ -0,0 +1,26 @@ +class AppInvitationHistoryModel { + int? id; + int? customerID; + int? channelID; + int? appInvitationEnumID; + int? noOfInvites; + String? comments; + + AppInvitationHistoryModel({ + this.id, + this.customerID, + this.channelID, + this.appInvitationEnumID, + this.noOfInvites, + this.comments, + }); + + AppInvitationHistoryModel.fromJson(Map json) { + id = json['id']; + customerID = json['customerID']; + channelID = json['channelID']; + appInvitationEnumID = json['appInvitationEnumID']; + noOfInvites = json['noofInvites']; + comments = json['comments']; + } +} diff --git a/lib/models/user_models/role.dart b/lib/models/user_models/role.dart index 2ea0054..4b8a3ff 100644 --- a/lib/models/user_models/role.dart +++ b/lib/models/user_models/role.dart @@ -22,17 +22,17 @@ class Role { String? message; factory Role.fromJson(Map json) => Role( - totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : List.from(json["data"].map((x) => RoleData.fromJson(x))), - messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], - message: json["message"] == null ? null : json["message"], + messageStatus: json["messageStatus"], + message: json["message"], ); Map toJson() => { - "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "totalItemsCount": totalItemsCount, "data": data == null ? null : List.from(data!.map((x) => x.toJson())), - "messageStatus": messageStatus == null ? null : messageStatus, - "message": message == null ? null : message, + "messageStatus": messageStatus, + "message": message, }; } @@ -50,16 +50,16 @@ class RoleData { bool? isActive; factory RoleData.fromJson(Map json) => RoleData( - id: json["id"] == null ? null : json["id"], - roleName: json["roleName"] == null ? null : json["roleName"], - roleNameN: json["roleNameN"] == null ? null : json["roleNameN"], - isActive: json["isActive"] == null ? null : json["isActive"], + id: json["id"], + roleName: json["roleName"], + roleNameN: json["roleNameN"], + isActive: json["isActive"], ); Map toJson() => { - "id": id == null ? null : id, - "roleName": roleName == null ? null : roleName, - "roleNameN": roleNameN == null ? null : roleNameN, - "isActive": isActive == null ? null : isActive, + "id": id, + "roleName": roleName, + "roleNameN": roleNameN, + "isActive": isActive, }; } diff --git a/lib/repositories/ads_repo.dart b/lib/repositories/ads_repo.dart index 8a48c49..0a2a7fd 100644 --- a/lib/repositories/ads_repo.dart +++ b/lib/repositories/ads_repo.dart @@ -137,6 +137,9 @@ class AdsRepoImp implements AdsRepo { }); List vehiclePostingDamageParts = []; + + int sellerTypeID = AppState().getUser.data!.userInfo!.roleId ?? 0; + adsCreationPayloadModel.vehiclePosting!.vehiclePostingDamageParts?.forEach((element) { log("comment: ${element.comment}"); var imageMap = { @@ -169,7 +172,7 @@ class AdsRepoImp implements AdsRepo { "vehicleConditionID": adsCreationPayloadModel.vehiclePosting!.vehicleConditionID, "vehicleMileageID": adsCreationPayloadModel.vehiclePosting!.vehicleMileageID, "vehicleTransmissionID": adsCreationPayloadModel.vehiclePosting!.vehicleTransmissionID, - "vehicleSellerTypeID": adsCreationPayloadModel.vehiclePosting!.vehicleSellerTypeID, + "vehicleSellerTypeID": sellerTypeID, "cityID": adsCreationPayloadModel.vehiclePosting!.cityID, "price": adsCreationPayloadModel.vehiclePosting!.price, "vehicleVIN": adsCreationPayloadModel.vehiclePosting!.vehicleVIN, @@ -534,7 +537,7 @@ class AdsRepoImp implements AdsRepo { String token = appState.getUser.data!.accessToken ?? ""; GenericRespModel adsGenericModel = await apiClient.postJsonForObject( (json) => GenericRespModel.fromJson(json), - ApiConsts.adsPhotoOfficeAppointmentCreate, + "", postParams, token: token, ); diff --git a/lib/repositories/appointment_repo.dart b/lib/repositories/appointment_repo.dart index 9a25aeb..2a26f98 100644 --- a/lib/repositories/appointment_repo.dart +++ b/lib/repositories/appointment_repo.dart @@ -21,6 +21,7 @@ abstract class AppointmentRepo { List? customerNamesList, List? customerPhonesList, List? deliveryTypeIdsList, + AppointmentStatusEnum? appointmentStatusEnum, String? fromDate, String? toDate, }); @@ -31,6 +32,7 @@ abstract class AppointmentRepo { List? serviceIdsList, List? itemIdsList, List? branchIdsList, + AppointmentStatusEnum? appointmentStatusEnum, }); Future updateAppointmentStatus({required int appointmentId, required AppointmentStatusEnum appointmentStatusEnum}); @@ -170,7 +172,6 @@ class AppointmentRepoImp implements AppointmentRepo { index = 0; } - slotId = schedule.selectedCustomTimeDateSlotModel!.availableSlots![index].slotId; mapList.add({ @@ -237,6 +238,7 @@ class AppointmentRepoImp implements AppointmentRepo { List? customerNamesList, List? customerPhonesList, List? deliveryTypeIdsList, + AppointmentStatusEnum? appointmentStatusEnum, String? fromDate, String? toDate, }) async { @@ -254,6 +256,9 @@ class AppointmentRepoImp implements AppointmentRepo { "DateTo": toDate ?? "", }; + if (appointmentStatusEnum != null) { + params.addAll({"AppointmentStatusID": appointmentStatusEnum.getIdFromAppointmentStatusEnum().toString()}); + } GenericRespModel genericRespModel = await apiClient.getJsonForObject( token: t, (json) => GenericRespModel.fromJson(json), @@ -271,6 +276,7 @@ class AppointmentRepoImp implements AppointmentRepo { List? serviceIdsList, List? itemIdsList, List? branchIdsList, + AppointmentStatusEnum? appointmentStatusEnum, }) async { var params = { "customerID": appState.getUser.data!.userInfo!.customerId.toString(), @@ -280,6 +286,10 @@ class AppointmentRepoImp implements AppointmentRepo { "ServiceItemIDs": itemIdsList ?? [], "CategoryIDs": categoryIdsList ?? [], }; + + if (appointmentStatusEnum != null) { + params.addAll({"AppointmentStatusID": appointmentStatusEnum.getIdFromAppointmentStatusEnum().toString()}); + } GenericRespModel genericRespModel = await apiClient.getJsonForObject( token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), diff --git a/lib/repositories/branch_repo.dart b/lib/repositories/branch_repo.dart index eb0e352..dc12110 100644 --- a/lib/repositories/branch_repo.dart +++ b/lib/repositories/branch_repo.dart @@ -77,7 +77,7 @@ abstract class BranchRepo { Future updateCategoryStatus({required int branchId, required int categoryId, required ServiceStatusEnum serviceStatusEnum}); - Future> getAppointmentsByCategoryOrService({required int branchId, required int serviceId}); + Future> getAppointmentsByCategoryOrService({required int branchId, required int categoryId, required int serviceId}); Future getMatchedServices(int oldBranchId, int newBranchId, int categoryId); @@ -217,7 +217,7 @@ class BranchRepoImp implements BranchRepo { "documentExt": documents[i].fileExt, "documentImage": documents[i].document, "isActive": true, - "dateExpire":documents[i].dateExpire, + "dateExpire": documents[i].dateExpire, }; map.add(postParams); } @@ -348,12 +348,22 @@ class BranchRepoImp implements BranchRepo { } @override - Future> getAppointmentsByCategoryOrService({required int branchId, required int serviceId}) async { + Future> getAppointmentsByCategoryOrService({required int branchId, required int categoryId, required int serviceId}) async { var map = { "ProviderBranchID": branchId.toString(), - "ServiceProviderServiceID": serviceId.toString(), }; + if (serviceId != -1) { + map.addAll({ + "ServiceProviderServiceID": serviceId.toString(), + }); + } + if (categoryId != -1) { + map.addAll({ + "ServiceProviderServiceID": serviceId.toString(), + }); + } + String t = AppState().getUser.data!.accessToken ?? ""; GenericRespModel genericRespModel = await apiClient.getJsonForObject( (json) => GenericRespModel.fromJson(json), diff --git a/lib/repositories/common_repo.dart b/lib/repositories/common_repo.dart index d823a16..4169dba 100644 --- a/lib/repositories/common_repo.dart +++ b/lib/repositories/common_repo.dart @@ -8,6 +8,7 @@ import 'package:mc_common_app/models/advertisment_models/vehicle_details_models. import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; import 'package:mc_common_app/models/general_models/enums_model.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; +import 'package:mc_common_app/models/provider_branches_models/provider_contact_info_model.dart'; import 'package:mc_common_app/models/user_models/cities.dart'; import 'package:mc_common_app/models/user_models/country.dart'; import 'package:mc_common_app/models/user_models/role.dart'; @@ -56,6 +57,8 @@ abstract class CommonRepo { Future> getEnumTypeValues({int? enumTypeID, String? enumTypeName}); Future createComplainFromProvider({required int customerId, required String comment, required int complainType}); + + Future getProvidersContactInfo({required int providerId}); } class CommonRepoImp implements CommonRepo { @@ -363,4 +366,19 @@ class CommonRepoImp implements CommonRepo { ); return adsGenericModel; } + + @override + Future getProvidersContactInfo({required int providerId}) async { + final parameters = { + "ProviderID": providerId.toString(), + }; + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.provideContactInfoGet, + queryParameters: parameters, + ); + ProviderContactInfoModel contactInfoModel = ProviderContactInfoModel.fromJson(adsGenericModel.data); + return contactInfoModel; + } } diff --git a/lib/repositories/setting_options_repo.dart b/lib/repositories/setting_options_repo.dart index b2c2888..dda9f2e 100644 --- a/lib/repositories/setting_options_repo.dart +++ b/lib/repositories/setting_options_repo.dart @@ -6,6 +6,7 @@ import 'package:mc_common_app/config/dependency_injection.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/setting_utils_models/app_info_model.dart'; +import 'package:mc_common_app/models/setting_utils_models/app_invitation_history_model.dart'; import 'package:mc_common_app/models/setting_utils_models/contact_infos_model.dart'; import 'package:mc_common_app/models/setting_utils_models/faqs_model.dart'; import 'package:mc_common_app/utils/enums.dart'; @@ -21,6 +22,8 @@ abstract class SettingOptionsRepo { Future> getTermsAndConditions(); Future appInvitationCreate({required int channelId, required String message}); + + Future> getAppInvitationsHistory(); } class SettingOptionsRepoImp extends SettingOptionsRepo { @@ -158,17 +161,19 @@ class SettingOptionsRepoImp extends SettingOptionsRepo { String token = appState.getUser.data!.accessToken ?? ""; final params = { - "channelID": channelId.toString(), + "appInvitationEnumID": channelId.toString(), "comments": message, }; if (AppState().currentAppType == AppType.customer) { params.addAll({ "customerID": (appState.getUser.data!.userInfo!.customerId ?? "0").toString(), + "channelID": "3", }); } else { params.addAll({ "providerID": (appState.getUser.data!.userInfo!.providerId ?? "0").toString(), + "channelID": "2", }); } @@ -180,4 +185,30 @@ class SettingOptionsRepoImp extends SettingOptionsRepo { ); return genericRespModel; } + + @override + Future> getAppInvitationsHistory() async { + final params = { + "CustomerID": (appState.getUser.data!.userInfo!.customerId ?? "0").toString(), + "ChannelID": "3", + }; + + String token = appState.getUser.data!.accessToken ?? ""; + + GenericRespModel genericRespModel = await injector.get().getJsonForObject( + (json) => GenericRespModel.fromJson(json), + ApiConsts.getAppInvitationHistory, + queryParameters: params, + token: token, + ); + + if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) { + Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr()); + return []; + } + + List list = List.generate(genericRespModel.data.length, (index) => AppInvitationHistoryModel.fromJson(genericRespModel.data[index])); + + return list; + } } diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index b47916a..a2bb7c1 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -379,7 +379,14 @@ class AdVM extends BaseVM { } Future getVehicleAdsSpecialServices({required int cityId, required int countryId, required int specialServiceType}) async { + log("cityId: $cityId"); + vehicleAdsSpecialServices = await adsRepo.getSpecialServices(specialServiceType: specialServiceType, countryId: countryId, cityId: cityId); + vehicleAdsSpecialServices = vehicleAdsSpecialServices.where((ad) { + bool matchesCityInDetails = ad.details?.any((detail) => detail.fromcity == cityId || detail.tocity == cityId) ?? false; + bool matchesCityInOffice = ad.office?.any((office) => office.cityID == cityId) ?? false; + return matchesCityInDetails || matchesCityInOffice; + }).toList(); notifyListeners(); } @@ -1472,12 +1479,11 @@ class AdVM extends BaseVM { List photoSSSchedulesByOffices = []; SSPhotoOfficeScheduleModel selectedPhotoSSSchedulesByOffice = SSPhotoOfficeScheduleModel(); - Future getPhotographyServiceScheduleListByOffices({required double latitude, required double longitude, bool isNeedToRebuild = false}) async { + Future getPhotographyServiceScheduleListByOffices({required int cityId, required double latitude, required double longitude, bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); - int cityID = AppState().getUser.data!.userInfo!.cityId ?? 1; try { - photoSSSchedulesByOffices = await commonRepo.getPhotographyServiceScheduleListByOffices(lat: latitude, long: longitude, cityID: cityID); + photoSSSchedulesByOffices = await commonRepo.getPhotographyServiceScheduleListByOffices(lat: latitude, long: longitude, cityID: cityId); if (isNeedToRebuild) setState(ViewState.idle); } catch (e) { if (isNeedToRebuild) setState(ViewState.idle); @@ -2118,7 +2124,8 @@ class AdVM extends BaseVM { } } - selectionDurationStartDate = DateHelper.formatDateT(previousAdDetails!.startdate ?? ""); + // selectionDurationStartDate = DateHelper.formatDateT(previousAdDetails!.startdate ?? ""); + selectionDurationStartDate = ""; isPhoneNumberShown = previousAdDetails!.phoneNo != null; if (isPhoneNumberShown) { adPhoneNumber = previousAdDetails!.phoneNo ?? ""; diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart index 5897b6f..b7be248 100644 --- a/lib/view_models/appointments_view_model.dart +++ b/lib/view_models/appointments_view_model.dart @@ -20,6 +20,7 @@ import 'package:mc_common_app/models/provider_branches_models/branch_detail_mode import 'package:mc_common_app/models/provider_branches_models/branch_review_model.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/services.dart'; +import 'package:mc_common_app/models/provider_branches_models/provider_contact_info_model.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'; @@ -62,9 +63,9 @@ class AppointmentsVM extends BaseVM { List myAppointments = []; List myUpComingAppointments = []; - List myFilteredAppointments = []; + List myFilteredAppointmentsForCustomers = []; List appointmentsFilterOptions = []; - List myFilteredAppointments2 = []; + List myFilteredAppointmentsForProvider = []; bool isFetchingServices = false; @@ -140,7 +141,7 @@ class AppointmentsVM extends BaseVM { } context.read().onNavbarTapped(1); - applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.booked); + applyFilterOnAppointmentsVMForCustomers(appointmentStatusEnum: AppointmentStatusEnum.booked); Utils.hideLoading(context); resetAfterBookingAppointment(); if (isSuccess) { @@ -149,7 +150,6 @@ class AppointmentsVM extends BaseVM { navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment); } else { Utils.showToast(LocaleKeys.appointmentBookedSuccessfully.tr()); - getMyAppointmentsForCustomer(); navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard); } } @@ -227,9 +227,8 @@ class AppointmentsVM extends BaseVM { } if (genericRespModel.messageStatus == 1 && AppState().currentAppType == AppType.customer) { context.read().onNavbarTapped(1); - applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); + applyFilterOnAppointmentsVMForCustomers(appointmentStatusEnum: AppointmentStatusEnum.cancelled); Utils.showToast(genericRespModel.message.toString()); - await getMyAppointmentsForCustomer(); Utils.hideLoading(context); navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard); } @@ -353,46 +352,69 @@ class AppointmentsVM extends BaseVM { notifyListeners(); } - applyFilterOnAppointmentsVM({required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false}) { - log("appointmentStatusEnum: $appointmentStatusEnum"); - // isNeedCustomerFilter IS ONLY FOR THE PROVIDER APP + bool isAppointmentLoading = false; + + applyFilterOnAppointmentsVMForProviders({int? branchID, required AppointmentStatusEnum appointmentStatusEnum, bool isNeedCustomerFilter = false, bool shouldPopulateUpcoming = false}) async { if (appointmentsFilterOptions.isEmpty) return; for (var value in appointmentsFilterOptions) { value.isSelected = false; } + int index = appointmentsFilterOptions.indexWhere((element) => element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()); + appointmentsFilterOptions[index].isSelected = true; - for (var element in appointmentsFilterOptions) { - if (element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()) { - element.isSelected = true; - } + isAppointmentLoading = true; + notifyListeners(); + myFilteredAppointmentsForProvider = await getAppointmentsBasedOnFiltersForProviders(branchID: branchID ?? selectedBranchIdForAppointments, appointmentStatus: appointmentStatusEnum); + isAppointmentLoading = false; + + if (shouldPopulateUpcoming) { + myUpComingAppointments = myFilteredAppointmentsForProvider + .where((element) => + (element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) && + (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now()))) + .toList(); } - // appointmentsFilterOptions[ - // appointmentStatusEnum.getIdFromAppointmentStatusEnum()] - // .isSelected = true; - if (appointmentStatusEnum == AppointmentStatusEnum.allAppointments) { - myFilteredAppointments = myAppointments; - if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(myFilteredAppointments); - notifyListeners(); - return; + log("myUpComingAppointments: ${myUpComingAppointments.length}"); + + if (isNeedCustomerFilter) { + myFilteredAppointmentsForProvider = findAppointmentsBasedOnCustomers(myFilteredAppointmentsForProvider); + } + notifyListeners(); + } + + applyFilterOnAppointmentsVMForCustomers({required AppointmentStatusEnum appointmentStatusEnum, bool shouldPopulateUpcoming = false}) async { + log("appointmentsFilterOptions: ${appointmentsFilterOptions.isEmpty}"); + if (appointmentsFilterOptions.isEmpty) return; + for (var value in appointmentsFilterOptions) { + value.isSelected = false; + } + int index = appointmentsFilterOptions.indexWhere((element) => element.id == appointmentStatusEnum.getIdFromAppointmentStatusEnum()); + appointmentsFilterOptions[index].isSelected = true; + + isAppointmentLoading = true; + notifyListeners(); + myFilteredAppointmentsForCustomers = await getAppointmentsBasedOnFiltersForCustomer(); + isAppointmentLoading = false; + + if (shouldPopulateUpcoming) { + myUpComingAppointments = myFilteredAppointmentsForCustomers + .where((element) => + (element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) && + (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now()))) + .toList(); } - myFilteredAppointments = myAppointments.where((element) => element.appointmentStatusID! == appointmentStatusEnum.getIdFromAppointmentStatusEnum()).toList(); - if (isNeedCustomerFilter) findAppointmentsBasedOnCustomers(myFilteredAppointments); notifyListeners(); } - findAppointmentsBasedOnCustomers(List appointments) { - // Use a Set to ensure uniqueness of customerIDs + List findAppointmentsBasedOnCustomers(List appointments) { Set uniqueCustomerIDs = {}; - - // Extract unique customerIDs for (var item in appointments) { uniqueCustomerIDs.add(item.customerID ?? 0); } - // Create a list of CustomerData instances - myFilteredAppointments2 = uniqueCustomerIDs.map((id) { + List groupedList = uniqueCustomerIDs.map((id) { List list = appointments.where((item) => item.customerID == id).toList(); list.sort((a, b) => DateHelper.parseStringToDate(DateHelper.formatDateT(b.appointmentDate!)) .millisecondsSinceEpoch @@ -402,61 +424,16 @@ class AppointmentsVM extends BaseVM { return model; }).toList(); - // customersAppointments = uniqueCustomerIDs.map((id) { - // List list = myFilteredAppointments - // .where((item) => item.customerID == id) - // .toList(); - // var customerItem = - // myFilteredAppointments.firstWhere((item) => item.customerID == id); - // - // return CustomerData( - // customerID: id, - // customerName: customerItem.customerName ?? "", - // appointmentList: list, - // ); - // }).toList(); - } - - // Future getMyAppointments() async { - // setState(ViewState.busy); - // - // myAppointments = - // await appointmentRepo.getMyAppointmentsForCustomersByFilters(); - // myFilteredAppointments = myAppointments; - // myUpComingAppointments = myAppointments - // .where((element) => - // element.appointmentStatusEnum == AppointmentStatusEnum.booked) - // .toList(); - // applyFilterOnAppointmentsVM( - // appointmentStatusEnum: AppointmentStatusEnum.allAppointments); - // if (myUpComingAppointments.isEmpty) { - // isShowEmptyMessage = true; - // } - // setState(ViewState.idle); - // notifyListeners(); - // } - - Future getMyAppointmentsForCustomer({bool isNeedToRebuild = false}) async { - if (isNeedToRebuild) setState(ViewState.busy); - - myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters(); - // myFilteredAppointments = myAppointments; - - setState(ViewState.idle); - applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); - - myUpComingAppointments = myAppointments - .where((element) => - (element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) && - (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now()))) - .toList(); - notifyListeners(); + return groupedList; } AppointmentSlots? appointmentSlots; - Future getAppointmentSlotsInfo({required int branchID, required BuildContext context, bool isNeedToRebuild = false}) async { - if (isNeedToRebuild) setState(ViewState.busy); + bool isSlotsLoading = true; + + Future getAppointmentSlotsInfo({required int branchID}) async { + isSlotsLoading = true; + notifyListeners(); try { GenericRespModel genericRespModel = await appointmentRepo.getAppointmentSlots(branchID: branchID, fromDate: selectedDateForAppointments, toDate: selectedDateForAppointments); if (genericRespModel.messageStatus == 1) { @@ -464,25 +441,15 @@ class AppointmentsVM extends BaseVM { } else { Utils.showToast(genericRespModel.message.toString()); } + isSlotsLoading = false; + notifyListeners(); } catch (e) { + isSlotsLoading = false; + notifyListeners(); Utils.showToast(e.toString()); } } - Future getMyAppointmentsForProvider({required int branchID}) async { - setState(ViewState.busy); - myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters(branchID: branchID); - myFilteredAppointments = myAppointments; - myUpComingAppointments = myAppointments - .where((element) => - (element.appointmentStatusEnum == AppointmentStatusEnum.confirmed || element.appointmentStatusEnum == AppointmentStatusEnum.booked) && - (DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now()))) - .toList(); - notifyListeners(); - applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true); - setState(ViewState.idle); - } - Future updateAppointmentStatus({required int appointmentId, required AppointmentStatusEnum appointmentStatusEnum, bool isNeedToRebuild = false}) async { if (isNeedToRebuild) setState(ViewState.busy); try { @@ -520,8 +487,8 @@ class AppointmentsVM extends BaseVM { } bool isShowMergeButton() { - return myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList!.every((appointment) => appointment.appointmentStatusEnum == AppointmentStatusEnum.confirmed) && - myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList!.length > 1; + return myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList!.every((appointment) => appointment.appointmentStatusEnum == AppointmentStatusEnum.confirmed) && + myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList!.length > 1; } Future createMergeAppointment(Map map, {bool isNeedToRebuild = false}) async { @@ -534,10 +501,10 @@ class AppointmentsVM extends BaseVM { bool inNeedToEnableMergeButton = false; void updateCheckBoxInMergeRequest(int currentIndex) { - myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected = - !(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false); + myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected = + !(myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false); - int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []); + int count = countSelected(myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList ?? []); if (count > 1) { inNeedToEnableMergeButton = true; } else { @@ -917,9 +884,8 @@ class AppointmentsVM extends BaseVM { } if (genericRespModel.messageStatus == 1) { context.read().onNavbarTapped(1); - applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.cancelled); Utils.showToast(genericRespModel.message.toString()); - getMyAppointmentsForCustomer(); + applyFilterOnAppointmentsVMForCustomers(appointmentStatusEnum: AppointmentStatusEnum.cancelled); Utils.hideLoading(context); navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard); } @@ -1011,6 +977,20 @@ class AppointmentsVM extends BaseVM { } } + Future getProvidersContactInfo({required int providerId, required BuildContext context}) async { + Utils.showLoading(context); + try { + ProviderContactInfoModel contactInfoModel = await commonRepo.getProvidersContactInfo(providerId: providerId); + Utils.hideLoading(context); + return contactInfoModel; + } catch (e, s) { + logger.e(s); + Utils.hideLoading(context); + Utils.showToast(e.toString()); + return null; + } + } + // BRANCHES RELATED List nearbyBranches = []; @@ -1827,105 +1807,120 @@ class AppointmentsVM extends BaseVM { clearAppointmentFilterSelections(); if (AppState().currentAppType == AppType.provider) { - getMyAppointmentsForProvider(branchID: selectedBranchIdForAppointments); + applyFilterOnAppointmentsVMForProviders(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true); } else { - getMyAppointmentsForCustomer(); + applyFilterOnAppointmentsVMForCustomers(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); } notifyListeners(); } - Future getAppointmentsBasedOnFiltersForCustomer() async { - setState(ViewState.busy); - List providersIdsList = []; - if (appointmentFilterProviderSearchHistory.isNotEmpty) { - for (var element in appointmentFilterProviderSearchHistory) { - providersIdsList.add(element.id.toString()); + Future> getAppointmentsBasedOnFiltersForCustomer() async { + try { + setState(ViewState.busy); + List providersIdsList = []; + if (appointmentFilterProviderSearchHistory.isNotEmpty) { + for (var element in appointmentFilterProviderSearchHistory) { + providersIdsList.add(element.id.toString()); + } } - } - List categoryIdsList = []; - if (appointmentFilterCategorySearchHistory.isNotEmpty) { - for (var element in appointmentFilterCategorySearchHistory) { - categoryIdsList.add(element.id.toString()); + List categoryIdsList = []; + if (appointmentFilterCategorySearchHistory.isNotEmpty) { + for (var element in appointmentFilterCategorySearchHistory) { + categoryIdsList.add(element.id.toString()); + } } - } - List servicesIdsList = []; - if (appointmentFilterServicesSearchHistory.isNotEmpty) { - for (var element in appointmentFilterServicesSearchHistory) { - servicesIdsList.add(element.id.toString()); + List servicesIdsList = []; + if (appointmentFilterServicesSearchHistory.isNotEmpty) { + for (var element in appointmentFilterServicesSearchHistory) { + servicesIdsList.add(element.id.toString()); + } } - } - List itemIdsList = []; - if (appointmentFilterItemsSearchHistory.isNotEmpty) { - for (var element in appointmentFilterItemsSearchHistory) { - itemIdsList.add(element.id.toString()); + List itemIdsList = []; + if (appointmentFilterItemsSearchHistory.isNotEmpty) { + for (var element in appointmentFilterItemsSearchHistory) { + itemIdsList.add(element.id.toString()); + } } - } - List branchesIdsList = []; - if (appointmentFilterBranchSearchHistory.isNotEmpty) { - for (var element in appointmentFilterBranchSearchHistory) { - branchesIdsList.add(element.id.toString()); + List branchesIdsList = []; + if (appointmentFilterBranchSearchHistory.isNotEmpty) { + for (var element in appointmentFilterBranchSearchHistory) { + branchesIdsList.add(element.id.toString()); + } } - } - myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters( - providerIdsList: providersIdsList, - categoryIdsList: categoryIdsList, - serviceIdsList: servicesIdsList, - itemIdsList: itemIdsList, - branchIdsList: branchesIdsList, - ); - applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); - setState(ViewState.idle); + List myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters( + providerIdsList: providersIdsList, + categoryIdsList: categoryIdsList, + serviceIdsList: servicesIdsList, + itemIdsList: itemIdsList, + branchIdsList: branchesIdsList, + ); + setState(ViewState.idle); + + return myAppointments; + } catch (e) { + logger.e(e); + setState(ViewState.idle); + Utils.showToast(e.toString()); + return []; + } } String selectedDateForAppointments = ""; - Future getAppointmentsBasedOnFiltersForProviders({required int branchID}) async { - setState(ViewState.busy); - - List servicesIdsList = []; - if (appointmentFilterServicesSearchHistory.isNotEmpty) { - for (var element in appointmentFilterServicesSearchHistory) { - servicesIdsList.add(element.id.toString()); + Future> getAppointmentsBasedOnFiltersForProviders({required int branchID, AppointmentStatusEnum? appointmentStatus}) async { + try { + setState(ViewState.busy); + List servicesIdsList = []; + if (appointmentFilterServicesSearchHistory.isNotEmpty) { + for (var element in appointmentFilterServicesSearchHistory) { + servicesIdsList.add(element.id.toString()); + } } - } - List customerNamesList = []; - if (appointmentFilterCustomerNameSearchHistory.isNotEmpty) { - for (var element in appointmentFilterCustomerNameSearchHistory) { - customerNamesList.add(element.toString()); + List customerNamesList = []; + if (appointmentFilterCustomerNameSearchHistory.isNotEmpty) { + for (var element in appointmentFilterCustomerNameSearchHistory) { + customerNamesList.add(element.toString()); + } } - } - List customerPhonesList = []; - if (appointmentFilterMobilePhoneSearchHistory.isNotEmpty) { - for (var element in appointmentFilterMobilePhoneSearchHistory) { - customerPhonesList.add(element.toString()); + List customerPhonesList = []; + if (appointmentFilterMobilePhoneSearchHistory.isNotEmpty) { + for (var element in appointmentFilterMobilePhoneSearchHistory) { + customerPhonesList.add(element.toString()); + } } - } - List customerDeliveryTypesList = []; - if (appointmentFilterServiceDeliverySearchHistory.isNotEmpty) { - for (var element in appointmentFilterServiceDeliverySearchHistory) { - customerDeliveryTypesList.add(element.id.toString()); + List customerDeliveryTypesList = []; + if (appointmentFilterServiceDeliverySearchHistory.isNotEmpty) { + for (var element in appointmentFilterServiceDeliverySearchHistory) { + customerDeliveryTypesList.add(element.id.toString()); + } } - } - log("customerNamesList: $customerNamesList"); - log("customerPhonesList: $customerPhonesList"); - log("customerDeliveryTypesList: $customerDeliveryTypesList"); - log("servicesIdsList: $servicesIdsList"); - myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters( - branchID: branchID, - customerNamesList: customerNamesList, - customerPhonesList: customerPhonesList, - deliveryTypeIdsList: customerDeliveryTypesList, - serviceProviderServiceIdsList: servicesIdsList, - fromDate: '', - toDate: ''); - - log(" myFilteredAppointments : ${myFilteredAppointments.length}"); - applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true); - setState(ViewState.idle); + log("customerNamesList: $customerNamesList"); + log("customerPhonesList: $customerPhonesList"); + log("customerDeliveryTypesList: $customerDeliveryTypesList"); + log("servicesIdsList: $servicesIdsList"); + List myAppointments = await appointmentRepo.getMyAppointmentsForProvidersByFilters( + branchID: branchID, + customerNamesList: customerNamesList, + customerPhonesList: customerPhonesList, + deliveryTypeIdsList: customerDeliveryTypesList, + serviceProviderServiceIdsList: servicesIdsList, + appointmentStatusEnum: appointmentStatus, + fromDate: '', + toDate: ''); + + setState(ViewState.idle); + + return myAppointments ?? []; + } catch (e) { + logger.e(e); + setState(ViewState.idle); + Utils.showToast(e.toString()); + return []; + } } Future addProviderToFavorite({required int serviceProviderID, required BuildContext context}) async { diff --git a/lib/view_models/dashboard_view_model_customer.dart b/lib/view_models/dashboard_view_model_customer.dart index 2f4b7fc..8786043 100644 --- a/lib/view_models/dashboard_view_model_customer.dart +++ b/lib/view_models/dashboard_view_model_customer.dart @@ -67,7 +67,7 @@ class DashboardVmCustomer extends BaseVM { appointmentsVM.populateAppointmentsFilterList(); adVM.populateAdsFilterList(); requestsVM.populateDataForRequestsFilter(); - await appointmentsVM.getMyAppointmentsForCustomer(); + await appointmentsVM.applyFilterOnAppointmentsVMForCustomers(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, shouldPopulateUpcoming: true); await appointmentsVM.applyFilterOnBranches(index: 0); // to get all branches! await appointmentsVM.getMyRecentBranches(); // to get my recent branches diff --git a/lib/view_models/dashboard_view_model_provider.dart b/lib/view_models/dashboard_view_model_provider.dart index f0433c6..2247ab8 100644 --- a/lib/view_models/dashboard_view_model_provider.dart +++ b/lib/view_models/dashboard_view_model_provider.dart @@ -82,14 +82,13 @@ class DashboardVMProvider extends BaseVM { appointmentVM.populateAppointmentsFilterList(); shippingManagementVM.populateShippingRequestFilterList(); await serviceVM.populateBranchServiceFilters(); - await serviceVM.getBranchAndServices(); if (dashboardRouteEnum != DashboardRouteEnum.fromAdsPayment && dashboardRouteEnum != DashboardRouteEnum.fromAdsSubmit) { await adVM.getMyAds(); await adVM.getExploreAds(); } - await appointmentVM.getMyAppointmentsForProvider(branchID: appointmentVM.selectedBranchIdForAppointments); + await appointmentVM.applyFilterOnAppointmentsVMForProviders(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, shouldPopulateUpcoming: true); adVM.populateAdsFilterList(); await requestsVM.getRequests(); await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true); @@ -130,7 +129,7 @@ class DashboardVMProvider extends BaseVM { void performCheckOnUsers(BuildContext context, Function() callBack) async { if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.subUsersRemaining! > 0) { - showMyBottomSheet(context, isDismissible: false, isScrollControlled: true, child: AddPhoneNumWidget(), callBackFunc: callBack); + showMyBottomSheet(context, isDismissible: false, isScrollControlled: true, child: AddPhoneNumWidget(), callBackFunc: callBack); } else { Utils.showToast(LocaleKeys.upgradeSubUsers.tr()); } diff --git a/lib/view_models/service_view_model.dart b/lib/view_models/service_view_model.dart index c29faec..be89fe7 100644 --- a/lib/view_models/service_view_model.dart +++ b/lib/view_models/service_view_model.dart @@ -275,7 +275,11 @@ class ServiceVM extends BaseVM { context, allowMultiple: false, ); - if (files != null && files.any((element) => element.path.split('.').last.toLowerCase() != 'pdf')) { + if (files != null && files.any((element) => + element.path + .split('.') + .last + .toLowerCase() != 'pdf')) { Utils.showToast("Only PDF Files are allowed"); return; } @@ -339,6 +343,67 @@ class ServiceVM extends BaseVM { return await branchRepo.serviceProviderDocumentsUpdate(data); } + bool customServiceEnabledStatus = false; + + void updateCustomServiceEnabledStatus(bool status) { + customServiceEnabledStatus = status; + notifyListeners(); + } + + String customServiceTitle = ""; + + void updateCustomServiceTitle(String title) { + customServiceTitle = title; + } + + String customServicePrice = ""; + + void updateCustomServicePrice(String title) { + customServicePrice = title; + } + + String customerServiceTax = "15"; + + void updateCustomerServiceTax(String title) { + customerServiceTax = title; + } + + resetCustomServiceForm() { + customServiceTitle = ""; + customServicePrice = ""; + customerServiceTax = "15"; + } + + String customServiceTitleError = ""; + String customServicePriceError = ""; + String customerServiceTaxError = ""; + + bool isCustomServiceDetailValidated() { + bool isValidated = true; + if (customServiceTitle.isEmpty) { + customServiceTitleError = GlobalConsts.serviceNameError; + isValidated = false; + notifyListeners(); + return isValidated; + } else { + customServiceTitleError = ""; + } + if (customServicePrice.isEmpty) { + customServicePriceError = GlobalConsts.priceError; + isValidated = false; + } else { + customServicePriceError = ""; + } + if (customerServiceTax.isEmpty) { + customerServiceTaxError = GlobalConsts.taxError; + isValidated = false; + } else { + customerServiceTaxError = ""; + } + notifyListeners(); + return isValidated; + } + // Create new branch Future getBranchAndServices() async { setState(ViewState.busy); @@ -466,10 +531,10 @@ class ServiceVM extends BaseVM { DropValue( element.id ?? 0, ((element.categoryName!.isEmpty - ? "N/A" - : countryCode == "SA" - ? element.categoryNameN - : element.categoryName) ?? + ? "N/A" + : countryCode == "SA" + ? element.categoryNameN + : element.categoryName) ?? "N/A"), "", ), @@ -527,18 +592,23 @@ class ServiceVM extends BaseVM { Future createService(List> map) async { setState(ViewState.busy); - return await branchRepo.createService(map); + GenericRespModel response = await branchRepo.createService(map); setState(ViewState.idle); + return response; } Future updateServices(List> map) async { return await branchRepo.updateService(map); } - Future> getAppointmentsByServiceID({required BuildContext context, required int branchId, required int serviceId}) async { + Future> getAppointmentsByCategoryOrService({required BuildContext context, required int branchId, required int categoryId, required int serviceId}) async { try { Utils.showLoading(context); - List appointmentList = await branchRepo.getAppointmentsByCategoryOrService(branchId: branchId, serviceId: serviceId); + List appointmentList = await branchRepo.getAppointmentsByCategoryOrService( + branchId: branchId, + serviceId: serviceId, + categoryId: categoryId, + ); // log("list: ${mResponse.}"); Utils.hideLoading(context); @@ -585,7 +655,8 @@ class ServiceVM extends BaseVM { } } - Future buildDealNotCompletedBottomSheetOptions({required BuildContext mainContext, required List appointments, required String branchName}) async { + Future cannotDeactivateServiceOrCategoryBottomSheet( + {required BuildContext mainContext, required List appointments, required String branchName, required bool isService}) async { return actionConfirmationBottomSheet( isOnlyOneButton: true, context: mainContext, @@ -770,7 +841,9 @@ class ServiceVM extends BaseVM { File file = File(imageModel.filePath!); List imageBytes = await file.readAsBytes(); String image = base64Encode(imageBytes); - String fileName = file.path.split('/').last; + String fileName = file.path + .split('/') + .last; branchPostingImages = BranchPostingImages( imageName: fileName, imageStr: image, diff --git a/lib/view_models/setting_options_view_model.dart b/lib/view_models/setting_options_view_model.dart index 4ce8e7e..add6955 100644 --- a/lib/view_models/setting_options_view_model.dart +++ b/lib/view_models/setting_options_view_model.dart @@ -4,6 +4,7 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/main.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/models/setting_utils_models/app_info_model.dart'; +import 'package:mc_common_app/models/setting_utils_models/app_invitation_history_model.dart'; import 'package:mc_common_app/models/setting_utils_models/contact_infos_model.dart'; import 'package:mc_common_app/models/setting_utils_models/faqs_model.dart'; import 'package:mc_common_app/repositories/setting_options_repo.dart'; @@ -82,11 +83,20 @@ class SettingOptionsVM extends BaseVM { try { GenericRespModel respModel = await settingOptionsRepo.appInvitationCreate(channelId: inviteTypeEnum.toIntFromEnum(), message: GlobalConsts.getAppInvitationLink()); await Utils.inviteFriend(inviteTypeEnum: inviteTypeEnum, message: GlobalConsts.getAppInvitationLink()); - Utils.hideLoading(context); } catch (e) { logger.i(e.toString()); Utils.hideLoading(context); } } + + List appInvitationHistoryList = []; + + Future getAppInvitationHistoryList() async { + try { + appInvitationHistoryList = await settingOptionsRepo.getAppInvitationsHistory(); + } catch (e) { + logger.i(e.toString()); + } + } } diff --git a/lib/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart b/lib/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart index 93e66ec..879b9d4 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart @@ -10,7 +10,7 @@ class DottedRoundedCard extends StatelessWidget { final String text; final Widget icon; - const DottedRoundedCard({Key? key, required this.onTap, required this.text, required this.icon}) : super(key: key); + const DottedRoundedCard({super.key, required this.onTap, required this.text, required this.icon}); @override Widget build(BuildContext context) { @@ -48,44 +48,47 @@ class DottedRectContainer extends StatelessWidget { final Widget icon; final String extensions; - const DottedRectContainer({Key? key, required this.onTap, required this.text, required this.icon, required this.extensions}) : super(key: key); + const DottedRectContainer({super.key, required this.onTap, required this.text, required this.icon, required this.extensions}); @override Widget build(BuildContext context) { return InkWell( onTap: onTap, - child: Column( - children: [ - DashedRect( - color: MyColors.lightIconColor, - strokeWidth: 2.0, - gap: 4.0, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, + child: Container( + constraints: const BoxConstraints(minHeight: 60), + child: Column( + children: [ + DashedRect( + color: MyColors.lightIconColor, + strokeWidth: 2.0, + gap: 4.0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + icon, + const SizedBox(width: 8), + text + .toText( + fontSize: 15, + isBold: true, + color: MyColors.darkPrimaryColor, + ) + .paddingAll(10), + ], + ), + ), + 8.height, + Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ - icon, - const SizedBox(width: 8), - text - .toText( - fontSize: 15, - isBold: true, - color: MyColors.darkPrimaryColor, - ) - .paddingAll(6), + "( $extensions )".toText( + fontSize: 8, + color: MyColors.lightTextColor, + ), ], - ), - ), - 8.height, - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - "( $extensions )".toText( - fontSize: 8, - color: MyColors.lightTextColor, - ), - ], - ) - ], + ) + ], + ), ), ); } 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 20a17fe..89c22db 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart @@ -6,6 +6,7 @@ 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/generated/locale_keys.g.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/utils/utils.dart'; @@ -22,6 +23,7 @@ class AdDuration extends StatelessWidget { const AdDuration({super.key}); void onAddSpecialServiceButtonTapped(BuildContext context, AdVM adVM) { + adVM.updateSelectedVehicleAdsSpecialServicesId(SelectionModel(selectedOption: "", selectedId: -1, errorValue: "")); showModalBottomSheet( context: context, isScrollControlled: true, @@ -72,10 +74,7 @@ class AdDuration extends StatelessWidget { value: adVM.vehicleAdDurationId.selectedOption, isNeedClickAll: true, postFixDataColor: MyColors.darkTextColor, - onTap: () async { - final formattedDate = await Utils.pickDateFromDatePicker(context); - adVM.updateSelectionDurationStartDate(formattedDate); - }, + onTap: () {}, ), ], // Builder(builder: (context) { diff --git a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart index ac6ea39..1b64231 100644 --- a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart +++ b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart @@ -26,10 +26,31 @@ class VehicleDetails extends StatelessWidget { @override Widget build(BuildContext context) { return Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { + String roleAppState = ""; + String roleName = ""; + + if (AppState().getUser.data!.userInfo != null) { + roleAppState = AppState().getUser.data!.userInfo!.roleName ?? ""; + List list = roleAppState.split('_'); + if (list.length > 1) { + roleName = list[1]; + } + } + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.vehicleDetail.tr().toText(fontSize: 18, isBold: true), + if (AppState().currentAppType == AppType.provider && roleName.isNotEmpty) ...[ + 8.height, + TxtField( + value: roleName, + isBackgroundEnabled: true, + isNeedClickAll: true, + hint: '', + onTap: () {}, + ), + ], 8.height, Builder( builder: (context) { @@ -56,40 +77,32 @@ class VehicleDetails extends StatelessWidget { ).paddingAll(10), ] else ...[ 8.height, - if (AppState().currentAppType == AppType.provider) ...[ - Builder(builder: (context) { - List vehicleSellerTypesDrop = []; - for (var element in adVM.vehicleSellerTypes) { - log("${element.id} : ${element.sellerType}"); - vehicleSellerTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.sellerType ?? "", "")); - } - - DropValue? model; - int index = -1; - if (AppState().userType == UserType.providerDealer) { - index = vehicleSellerTypesDrop.indexWhere((element) => element.id == GlobalConsts.providerDealerRoleTypeId); - } else { - index = vehicleSellerTypesDrop.indexWhere((element) => element.id == GlobalConsts.providerIndividualRoleTypeId); - } - - if (index == -1) { - model = vehicleSellerTypesDrop.first; - } else { - model = vehicleSellerTypesDrop[index]; - } - adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: model.id, selectedOption: model.value), needRefresh: false); - - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - isSelectAble: false, - list: vehicleSellerTypesDrop, - dropdownValue: adVM.vehicleSellerTypeId.selectedId != -1 ? DropValue(adVM.vehicleSellerTypeId.selectedId, adVM.vehicleSellerTypeId.selectedOption, "") : null, - hint: LocaleKeys.vehicleSellerType.tr(), - errorValue: adVM.vehicleSellerTypeId.errorValue, - ); - }), - 8.height, - ], + // if (AppState().currentAppType == AppType.provider) ...[ + // Builder(builder: (context) { + // List vehicleSellerTypesDrop = []; + // for (var element in adVM.vehicleSellerTypes) { + // log("${element.id} : ${element.sellerType}"); + // vehicleSellerTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.sellerType ?? "", "")); + // } + // + // adVM.updateSelectionVehicleSellerTypeId( + // SelectionModel( + // selectedId: AppState().getUser.data!.userInfo!.roleId ?? GlobalConsts.providerIndividualRoleTypeId, + // selectedOption: AppState().getUser.data!.userInfo!.roleName ?? "", + // ), + // needRefresh: false); + // + // return DropdownField( + // (DropValue value) => adVM.updateSelectionVehicleSellerTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + // isSelectAble: false, + // list: vehicleSellerTypesDrop, + // dropdownValue: adVM.vehicleSellerTypeId.selectedId != -1 ? DropValue(adVM.vehicleSellerTypeId.selectedId, adVM.vehicleSellerTypeId.selectedOption, "") : null, + // hint: LocaleKeys.vehicleSellerType.tr(), + // errorValue: adVM.vehicleSellerTypeId.errorValue, + // ); + // }), + // 8.height, + // ], Builder(builder: (context) { List vehicleModelsDrop = []; for (var element in adVM.vehicleModels) { diff --git a/lib/views/advertisement/ads_detail_view/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view/ads_detail_view.dart index 99afa00..c5a6ee6 100644 --- a/lib/views/advertisement/ads_detail_view/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view/ads_detail_view.dart @@ -364,7 +364,9 @@ class _AdsDetailViewState extends State { endDate.isNotEmpty ? endDate.toText(fontSize: 10) : const SizedBox(), ], ), - (LocaleKeys.extendAd.tr()).toText(fontSize: 12, color: MyColors.darkPrimaryColor, isUnderLine: true).onPress(() async => await onExtendAdPressed()), + if (widget.adDetails.adPostStatus == AdPostStatus.active || widget.adDetails.adPostStatus == AdPostStatus.expired) ...[ + (LocaleKeys.extendAd.tr()).toText(fontSize: 12, color: MyColors.darkPrimaryColor, isUnderLine: true).onPress(() async => await onExtendAdPressed()), + ], ], ), ], diff --git a/lib/views/advertisement/ads_detail_view/components.dart b/lib/views/advertisement/ads_detail_view/components.dart index dc379f6..2227047 100644 --- a/lib/views/advertisement/ads_detail_view/components.dart +++ b/lib/views/advertisement/ads_detail_view/components.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; @@ -275,8 +276,13 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { void onBookPhotographyServiceClicked(BuildContext context, {required AdDetailsModel adDetailsModel}) async { AdVM adVM = context.read(); + log("adDetailsModel.vehicle!.cityID: ${adDetailsModel.vehicle!.cityID}"); if (adVM.photoOfficeSelectedId.selectedId == -1) { - adVM.getPhotographyServiceScheduleListByOffices(latitude: AppState().currentLocation.latitude, longitude: AppState().currentLocation.longitude, isNeedToRebuild: true); + adVM.getPhotographyServiceScheduleListByOffices( + cityId: adDetailsModel.vehicle!.cityID ?? AppState().getUser.data!.userInfo!.cityId ?? 0, + latitude: AppState().currentLocation.latitude, + longitude: AppState().currentLocation.longitude, + isNeedToRebuild: true); } return showModalBottomSheet( @@ -716,7 +722,11 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { title: LocaleKeys.yes.tr(), fontSize: 15, onPressed: () { - adVM.deactivateTheAd(context, adId: adDetailsModel.id!, comment: comments); + if (adVM.selectedDeActivateAdCommentModel.index == 0) { + adVM.markAdAsSold(context, adId: adDetailsModel.id!); + } else { + adVM.deactivateTheAd(context, adId: adDetailsModel.id!, comment: comments); + } }, ), ), diff --git a/lib/views/advertisement/bottom_sheets/ad_special_service_sheet.dart b/lib/views/advertisement/bottom_sheets/ad_special_service_sheet.dart index 8f5f81d..0a21a84 100644 --- a/lib/views/advertisement/bottom_sheets/ad_special_service_sheet.dart +++ b/lib/views/advertisement/bottom_sheets/ad_special_service_sheet.dart @@ -1,4 +1,7 @@ +import 'dart:developer'; + 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/generated/locale_keys.g.dart'; @@ -10,6 +13,7 @@ import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/time_slots.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; +import 'package:mc_common_app/widgets/empty_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:provider/provider.dart'; @@ -177,170 +181,186 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { builder: (BuildContext context, AdVM adVM, Widget? child) { return SizedBox( height: MediaQuery.of(context).size.height * 0.7, - child: Column( - children: [ - Container( - margin: const EdgeInsets.all(8), - height: 8, - width: 60, - decoration: const BoxDecoration(color: MyColors.lightTextColor, borderRadius: BorderRadius.all(Radius.circular(20))), - ), - 12.height, - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: adVM.vehicleAdsSpecialServices.isEmpty + ? Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - LocaleKeys.addSpecialService.tr().toText(fontSize: 24, isBold: true), - 8.height, - Builder( - builder: (context) { - List vehicleAdsSpecialServices = []; - for (var element in adVM.vehicleAdsSpecialServices) { - if (!element.isSelected!) { - vehicleAdsSpecialServices.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", element.price == null ? "" : element.price!.toInt().toString())); - } - } - return DropdownField( - (DropValue value) => adVM.updateSelectedVehicleAdsSpecialServicesId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)), - list: vehicleAdsSpecialServices, - hint: LocaleKeys.selectService.tr(), - dropdownValue: adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1 ? DropValue(adVM.selectedVehicleAdsSpecialServicesId.selectedId, adVM.selectedVehicleAdsSpecialServicesId.selectedOption, "") : null, - ); - }, + Container( + margin: const EdgeInsets.all(8), + height: 8, + width: 60, + decoration: const BoxDecoration(color: MyColors.lightTextColor, borderRadius: BorderRadius.all(Radius.circular(20))), ), - if (adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1) ...[ - if (adVM.isFetchingLists) ...[ - Center(child: const CircularProgressIndicator().paddingAll(20)), - ] else ...[ - 8.height, - if ((adVM.selectedVehicleAdsSpecialServicesId.selectedId == 1 && adVM.ssPhotoScheduleModel != null)) ...[ - // Builder( - // builder: (context) { - // List vehicleAdsSpecialServiceDates = adVM.populateScheduleDatesForAdPhotoService(); - // - // return DropdownField( - // (DropValue value) => adVM.updateVehicleVehicleAdsPhotoServiceDate(SelectionModel( - // selectedId: value.id, - // selectedOption: value.value, - // )), - // list: vehicleAdsSpecialServiceDates, - // hint: "Select Date", - // dropdownValue: adVM.vehicleAdsPhotoServiceDate.selectedId != -1 - // ? DropValue( - // adVM.vehicleAdsPhotoServiceDate.selectedId, - // adVM.vehicleAdsPhotoServiceDate.selectedOption, - // "", - // ) - // : null, - // ); - // }, - // ), - // 22.height, - ] else if ((adVM.selectedVehicleAdsSpecialServicesId.selectedId == 3 && adVM.ssCarCheckScheduleModel != null)) ...[ - // Builder( - // builder: (context) { - // List vehicleAdsSpecialServiceDates = adVM.populateScheduleDatesForAdCarCheckService(); - // - // return DropdownField( - // (DropValue value) => adVM.updateVehicleAdsCarCheckServicesDate(SelectionModel( - // selectedId: value.id, - // selectedOption: value.value, - // )), - // list: vehicleAdsSpecialServiceDates, - // hint: "Select Date", - // dropdownValue: adVM.vehicleAdsCarCheckServicesDate.selectedId != -1 - // ? DropValue( - // adVM.vehicleAdsCarCheckServicesDate.selectedId, - // adVM.vehicleAdsCarCheckServicesDate.selectedOption, - // "", - // ) - // : null, - // ); - // }, - // ), - // 22.height, - ], - if (adVM.selectedVehicleAdsSpecialServicesId.selectedId != 3 && adVM.selectedVehicleAdsSpecialServicesId.selectedId != 1) ...[ - descriptionCard( - description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.selectedVehicleAdsSpecialServicesId.selectedId).description ?? "", - ), - ], - if (adVM.adSSTimeSlots.isNotEmpty) ...[ - LocaleKeys.availableSlots.tr().toText(fontSize: 15, isBold: true), + Center(child: LocaleKeys.noSpecialServicesAvailable.tr().toText(fontSize: 18, color: MyColors.lightTextColor, fontWeight: MyFonts.Medium)).paddingAll(30), + const SizedBox(), + ], + ) + : Column( + children: [ + Container( + margin: const EdgeInsets.all(8), + height: 8, + width: 60, + decoration: const BoxDecoration(color: MyColors.lightTextColor, borderRadius: BorderRadius.all(Radius.circular(20))), + ), + 12.height, + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocaleKeys.addSpecialService.tr().toText(fontSize: 24, isBold: true), 8.height, - BuildTimeSlots( - timeSlots: adVM.adSSTimeSlots, - onPressed: (index) => adVM.updateIsSelectedInSlots(index), + Builder( + builder: (context) { + List vehicleAdsSpecialServices = []; + for (var element in adVM.vehicleAdsSpecialServices) { + if (!element.isSelected!) { + vehicleAdsSpecialServices.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", element.price == null ? "" : element.price!.toInt().toString())); + } + } + return DropdownField( + (DropValue value) => adVM.updateSelectedVehicleAdsSpecialServicesId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)), + list: vehicleAdsSpecialServices, + hint: LocaleKeys.selectService.tr(), + dropdownValue: adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1 + ? DropValue(adVM.selectedVehicleAdsSpecialServicesId.selectedId, adVM.selectedVehicleAdsSpecialServicesId.selectedOption, "") + : null, + ); + }, ), - ], - 22.height, - LocaleKeys.serviceAmount.tr().toText(fontSize: 16, isBold: true, color: MyColors.lightTextColor), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - adVM.selectedVehicleAdsSpecialServicesId.itemPrice.toText(fontSize: 20, isBold: true), - SizedBox(width: 1.w), - LocaleKeys.sar.tr().toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 2), + if (adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1) ...[ + if (adVM.isFetchingLists) ...[ + Center(child: const CircularProgressIndicator().paddingAll(20)), + ] else ...[ + 8.height, + if ((adVM.selectedVehicleAdsSpecialServicesId.selectedId == 1 && adVM.ssPhotoScheduleModel != null)) ...[ + // Builder( + // builder: (context) { + // List vehicleAdsSpecialServiceDates = adVM.populateScheduleDatesForAdPhotoService(); + // + // return DropdownField( + // (DropValue value) => adVM.updateVehicleVehicleAdsPhotoServiceDate(SelectionModel( + // selectedId: value.id, + // selectedOption: value.value, + // )), + // list: vehicleAdsSpecialServiceDates, + // hint: "Select Date", + // dropdownValue: adVM.vehicleAdsPhotoServiceDate.selectedId != -1 + // ? DropValue( + // adVM.vehicleAdsPhotoServiceDate.selectedId, + // adVM.vehicleAdsPhotoServiceDate.selectedOption, + // "", + // ) + // : null, + // ); + // }, + // ), + // 22.height, + ] else if ((adVM.selectedVehicleAdsSpecialServicesId.selectedId == 3 && adVM.ssCarCheckScheduleModel != null)) ...[ + // Builder( + // builder: (context) { + // List vehicleAdsSpecialServiceDates = adVM.populateScheduleDatesForAdCarCheckService(); + // + // return DropdownField( + // (DropValue value) => adVM.updateVehicleAdsCarCheckServicesDate(SelectionModel( + // selectedId: value.id, + // selectedOption: value.value, + // )), + // list: vehicleAdsSpecialServiceDates, + // hint: "Select Date", + // dropdownValue: adVM.vehicleAdsCarCheckServicesDate.selectedId != -1 + // ? DropValue( + // adVM.vehicleAdsCarCheckServicesDate.selectedId, + // adVM.vehicleAdsCarCheckServicesDate.selectedOption, + // "", + // ) + // : null, + // ); + // }, + // ), + // 22.height, + ], + if (adVM.selectedVehicleAdsSpecialServicesId.selectedId != 3 && adVM.selectedVehicleAdsSpecialServicesId.selectedId != 1) ...[ + descriptionCard( + description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.selectedVehicleAdsSpecialServicesId.selectedId).description ?? "", + ), + ], + if (adVM.adSSTimeSlots.isNotEmpty) ...[ + LocaleKeys.availableSlots.tr().toText(fontSize: 15, isBold: true), + 8.height, + BuildTimeSlots( + timeSlots: adVM.adSSTimeSlots, + onPressed: (index) => adVM.updateIsSelectedInSlots(index), + ), + ], + 22.height, + LocaleKeys.serviceAmount.tr().toText(fontSize: 16, isBold: true, color: MyColors.lightTextColor), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + adVM.selectedVehicleAdsSpecialServicesId.itemPrice.toText(fontSize: 20, isBold: true), + SizedBox(width: 1.w), + LocaleKeys.sar.tr().toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 2), + ], + ), + ], ], - ), - ], - ], - ], - ), - ), - SizedBox( - width: double.infinity, - child: ShowFillButton( - backgroundColor: !isButtonTappable(adVM) ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.darkPrimaryColor, - title: LocaleKeys.addService.tr(), - onPressed: () { - if (!isButtonTappable(adVM)) { - return; - } - Navigator.pop(context); - - adVM.addNewSpecialServiceCard( - specialServiceCard: SpecialServiceCard( - serviceSelectedId: adVM.selectedVehicleAdsSpecialServicesId, - description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.selectedVehicleAdsSpecialServicesId.selectedId).description ?? "", - duration: "", - serviceDate: "", - serviceDateError: "", - serviceTimeError: "", - address: "", - serviceTime: "", + ], ), - ); + ), + SizedBox( + width: double.infinity, + child: ShowFillButton( + backgroundColor: !isButtonTappable(adVM) ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.darkPrimaryColor, + title: LocaleKeys.addService.tr(), + onPressed: () { + if (!isButtonTappable(adVM)) { + return; + } + Navigator.pop(context); - // adVM.addNewSpecialServiceCard( - // specialServiceCard: SpecialServiceCard( - // serviceDate: adVM.vehicleAdsSpecialServicesId.selectedId == 1 - // ? adVM.vehicleAdsPhotoServiceDate.selectedOption - // : adVM.vehicleAdsSpecialServicesId.selectedId == 3 - // ? adVM.vehicleAdsCarCheckServicesDate.selectedOption - // : "", - // serviceDateError: "", - // serviceSelectedId: adVM.vehicleAdsSpecialServicesId, - // serviceTimeError: "", - // description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "", - // duration: adVM.vehicleAdsSpecialServicesId.selectedId == 1 - // ? adVM.ssPhotoScheduleModel!.distanceKM.toString() - // : adVM.vehicleAdsSpecialServicesId.selectedId == 3 - // ? adVM.ssCarCheckScheduleModel!.distanceKM.toString() - // : "", - // address: adVM.vehicleAdsSpecialServicesId.selectedId == 1 - // ? "${adVM.ssPhotoScheduleModel!.photoOfficeName} - ${adVM.ssPhotoScheduleModel!.areaName}" - // : adVM.vehicleAdsSpecialServicesId.selectedId == 3 - // ? adVM.ssCarCheckScheduleModel!.address - // : "", - // serviceTime: adVM.slotSelectedIndex == null || adVM.adSSTimeSlots.isEmpty ? "" : adVM.adSSTimeSlots[adVM.slotSelectedIndex!].slot, - // ), - // ); - }, - ).paddingOnly(bottom: 10), - ), - ], - ).horPaddingMain(), + adVM.addNewSpecialServiceCard( + specialServiceCard: SpecialServiceCard( + serviceSelectedId: adVM.selectedVehicleAdsSpecialServicesId, + description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.selectedVehicleAdsSpecialServicesId.selectedId).description ?? "", + duration: "", + serviceDate: "", + serviceDateError: "", + serviceTimeError: "", + address: "", + serviceTime: "", + ), + ); + + // adVM.addNewSpecialServiceCard( + // specialServiceCard: SpecialServiceCard( + // serviceDate: adVM.vehicleAdsSpecialServicesId.selectedId == 1 + // ? adVM.vehicleAdsPhotoServiceDate.selectedOption + // : adVM.vehicleAdsSpecialServicesId.selectedId == 3 + // ? adVM.vehicleAdsCarCheckServicesDate.selectedOption + // : "", + // serviceDateError: "", + // serviceSelectedId: adVM.vehicleAdsSpecialServicesId, + // serviceTimeError: "", + // description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "", + // duration: adVM.vehicleAdsSpecialServicesId.selectedId == 1 + // ? adVM.ssPhotoScheduleModel!.distanceKM.toString() + // : adVM.vehicleAdsSpecialServicesId.selectedId == 3 + // ? adVM.ssCarCheckScheduleModel!.distanceKM.toString() + // : "", + // address: adVM.vehicleAdsSpecialServicesId.selectedId == 1 + // ? "${adVM.ssPhotoScheduleModel!.photoOfficeName} - ${adVM.ssPhotoScheduleModel!.areaName}" + // : adVM.vehicleAdsSpecialServicesId.selectedId == 3 + // ? adVM.ssCarCheckScheduleModel!.address + // : "", + // serviceTime: adVM.slotSelectedIndex == null || adVM.adSSTimeSlots.isEmpty ? "" : adVM.adSSTimeSlots[adVM.slotSelectedIndex!].slot, + // ), + // ); + }, + ).paddingOnly(bottom: 10), + ), + ], + ).horPaddingMain(), ); }, ); diff --git a/lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart b/lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart index af3352d..799a05b 100644 --- a/lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart +++ b/lib/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart @@ -37,7 +37,6 @@ class _AdDamagePartPicturesSheetState extends State { void populateDamagePartPictures() { for (var element in widget.adDamageReportList) { ImageModel imageModel = ImageModel(id: element.id!, filePath: element.imageUrl!, isFromNetwork: true); - VehicleDamageCard vehicleDamageCard = VehicleDamageCard( partSelectedId: SelectionModel( selectedId: element.vehicleDamagePartID!, @@ -46,7 +45,16 @@ class _AdDamagePartPicturesSheetState extends State { damagePartDescription: element.comment ?? "", partImages: [imageModel], ); - vehicleDamageCards.add(vehicleDamageCard); + + int index = vehicleDamageCards.indexWhere((card) => card.partSelectedId!.selectedId == element.vehicleDamagePartID!); + + if (index == -1) { + vehicleDamageCards.add(vehicleDamageCard); + } else { + if (vehicleDamageCards[index].partImages != null) { + vehicleDamageCards[index].partImages!.add(imageModel); + } + } } setState(() {}); } @@ -56,7 +64,6 @@ class _AdDamagePartPicturesSheetState extends State { return SizedBox( height: MediaQuery.of(context).size.height / 1.2, child: ListView.builder( - physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: vehicleDamageCards.length, itemBuilder: (BuildContext context, int index) { diff --git a/lib/views/advertisement/select_ad_type_view.dart b/lib/views/advertisement/select_ad_type_view.dart index 07076c9..ed64799 100644 --- a/lib/views/advertisement/select_ad_type_view.dart +++ b/lib/views/advertisement/select_ad_type_view.dart @@ -80,7 +80,7 @@ class SelectAdTypeView extends StatelessWidget { if (adVM.isAdEditEnabled) { adVM.autoFillSelectedVehicleAdsDetails(); } - if (AppState().currentAppType == AppType.provider && AppState().userType == UserType.providerDealer) { + if (AppState().currentAppType == AppType.provider) { if (isFromExtendAd && !adVM.isAdEditEnabled) { bool status = await adVM.createAdExtensionOrder(context, adId: adsId, adsDurationId: adVM.vehicleAdDurationId.selectedId); log("hereStatus: $status"); diff --git a/lib/views/appointments/appointments_filter_view.dart b/lib/views/appointments/appointments_filter_view.dart index 3ac7b7c..bb421c1 100644 --- a/lib/views/appointments/appointments_filter_view.dart +++ b/lib/views/appointments/appointments_filter_view.dart @@ -293,11 +293,10 @@ class _AppointmentsFilterViewState extends State { title: LocaleKeys.search.tr(), onPressed: () { Navigator.pop(context); - if (AppState().currentAppType == AppType.provider) { - appointmentsVM.getAppointmentsBasedOnFiltersForProviders(branchID: appointmentsVM.selectedBranchIdForAppointments); + appointmentsVM.applyFilterOnAppointmentsVMForProviders(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true); } else { - appointmentsVM.getAppointmentsBasedOnFiltersForCustomer(); + appointmentsVM.applyFilterOnAppointmentsVMForCustomers(appointmentStatusEnum: AppointmentStatusEnum.allAppointments); } }, backgroundColor: MyColors.darkPrimaryColor, diff --git a/lib/views/appointments/review_appointment_view.dart b/lib/views/appointments/review_appointment_view.dart index 122ec25..39d830e 100644 --- a/lib/views/appointments/review_appointment_view.dart +++ b/lib/views/appointments/review_appointment_view.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/app_state.dart'; @@ -6,6 +8,7 @@ import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; +import 'package:mc_common_app/models/provider_branches_models/provider_contact_info_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/theme/colors.dart'; @@ -372,6 +375,7 @@ class ReviewAppointment extends StatelessWidget { @override Widget build(BuildContext context) { + log("state: ${AppState().getUser.data!.userInfo!.customerId}"); return Scaffold( appBar: CustomAppBar( title: LocaleKeys.reviewAppointment.tr(), @@ -380,8 +384,12 @@ class ReviewAppointment extends StatelessWidget { onBackButtonTapped: () => Navigator.pop(context), actions: [ IconButton( - onPressed: () { - // Utils.buildProviderContactInfoBottomSheet(context: context, email:, mobileNo:); + onPressed: () async { + final appointmentsVM = context.read(); + ProviderContactInfoModel? contact = await appointmentsVM.getProvidersContactInfo(providerId: appointmentsVM.selectedBranchModel!.serviceProviderId ?? 0, context: context); + if (contact != null) { + Utils.buildProviderContactInfoBottomSheet(context: context, email: contact.email, mobileNo: contact.mobile); + } }, icon: const Icon(Icons.help_outline_outlined).paddingOnly(right: 21), ), diff --git a/lib/views/requests/review_request_offer.dart b/lib/views/requests/review_request_offer.dart index b6e5df5..ac250e9 100644 --- a/lib/views/requests/review_request_offer.dart +++ b/lib/views/requests/review_request_offer.dart @@ -287,6 +287,7 @@ class _ReviewRequestOfferState extends State { IconButton( onPressed: () { final requestVM = context.read(); + Utils.buildProviderContactInfoBottomSheet( context: context, email: requestVM.currentSelectedOffer!.email, diff --git a/lib/views/setting_options/setting_options_invite_friends.dart b/lib/views/setting_options/setting_options_invite_friends.dart index 76c4117..41d8926 100644 --- a/lib/views/setting_options/setting_options_invite_friends.dart +++ b/lib/views/setting_options/setting_options_invite_friends.dart @@ -5,6 +5,7 @@ import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/setting_utils_models/app_invitation_history_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; @@ -25,52 +26,82 @@ class SettingOptionsInviteFriends extends StatelessWidget { isScrollControlled: true, enableDrag: true, builder: (BuildContext context) { - return InfoBottomSheet( - title: LocaleKeys.inviteFriends.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), - description: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - CustomSettingOptionsTile( - leadingWidget: MyAssets.whatsAppIcon.buildSvg( - height: 20, - width: 20, - color: MyColors.greyColor, - ), - titleText: LocaleKeys.inviteFriendsByWhatsApp.tr(), - needBorderBelow: true, - showTrailingArrow: false, - onTap: () async { - await context.read().appInvitationCreate(context: context, inviteTypeEnum: InviteTypeEnum.whatsapp); - }, - ), - CustomSettingOptionsTile( - leadingWidget: const Icon( - Icons.sms_outlined, - size: 20, - color: MyColors.greyColor, + return Consumer( + builder: (BuildContext context, SettingOptionsVM settingsOptionsVM, Widget? child) { + List list = settingsOptionsVM.appInvitationHistoryList; + int whatsAppInvites = 0; + int smsAppInvites = 0; + int emailAppInvites = 0; + for (var invite in list) { + switch (invite.appInvitationEnumID) { + case 1: // Assume 1 is WhatsApp channel + whatsAppInvites += invite.noOfInvites ?? 0; + break; + case 2: // Assume 2 is SMS channel + smsAppInvites += invite.noOfInvites ?? 0; + break; + case 3: // Assume 3 is Email channel + emailAppInvites += invite.noOfInvites ?? 0; + break; + default: + break; + } + } + + return InfoBottomSheet( + title: LocaleKeys.inviteFriends.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44), + description: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CustomSettingOptionsTile( + leadingWidget: MyAssets.whatsAppIcon.buildSvg( + height: 20, + width: 20, + color: MyColors.greyColor, + ), + titleText: LocaleKeys.inviteFriendsByWhatsApp.tr(), + subTitle: " ${LocaleKeys.noOfInvites.tr()}: $whatsAppInvites", + subtitleTextColor: MyColors.lightTextColor, + needBorderBelow: true, + showTrailingArrow: false, + onTap: () async { + await settingsOptionsVM.appInvitationCreate(context: context, inviteTypeEnum: InviteTypeEnum.whatsapp); + }, ), - titleText: LocaleKeys.inviteFriendsBySMS.tr(), - needBorderBelow: true, - showTrailingArrow: false, - onTap: () async { - await context.read().appInvitationCreate(context: context, inviteTypeEnum: InviteTypeEnum.sms); - }), - CustomSettingOptionsTile( - leadingWidget: const Icon( - Icons.email_outlined, - size: 20, - color: MyColors.greyColor, - ), - titleText: LocaleKeys.inviteFriendsByEmail.tr(), - needBorderBelow: false, - showTrailingArrow: false, - onTap: () async { - await context.read().appInvitationCreate(context: context, inviteTypeEnum: InviteTypeEnum.email); - }, + CustomSettingOptionsTile( + leadingWidget: const Icon( + Icons.sms_outlined, + size: 20, + color: MyColors.greyColor, + ), + titleText: LocaleKeys.inviteFriendsBySMS.tr(), + subTitle: " ${LocaleKeys.noOfInvites.tr()}: $smsAppInvites", + subtitleTextColor: MyColors.lightTextColor, + needBorderBelow: true, + showTrailingArrow: false, + onTap: () async { + await settingsOptionsVM.appInvitationCreate(context: context, inviteTypeEnum: InviteTypeEnum.sms); + }), + CustomSettingOptionsTile( + leadingWidget: const Icon( + Icons.email_outlined, + size: 20, + color: MyColors.greyColor, + ), + titleText: LocaleKeys.inviteFriendsByEmail.tr(), + subTitle: " ${LocaleKeys.noOfInvites.tr()}: $emailAppInvites", + subtitleTextColor: MyColors.lightTextColor, + needBorderBelow: false, + showTrailingArrow: false, + onTap: () async { + await settingsOptionsVM.appInvitationCreate(context: context, inviteTypeEnum: InviteTypeEnum.email); + }, + ), + 30.height, + ], ), - 30.height, - ], - ), + ); + }, ); }, ); diff --git a/lib/views/setting_options/setting_options_more.dart b/lib/views/setting_options/setting_options_more.dart index 0907b63..5c1ec77 100644 --- a/lib/views/setting_options/setting_options_more.dart +++ b/lib/views/setting_options/setting_options_more.dart @@ -12,6 +12,7 @@ import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/view_models/setting_options_view_model.dart'; import 'package:mc_common_app/view_models/user_view_model.dart'; import 'package:mc_common_app/views/setting_options/widgets/custom_setting_options_tile.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; @@ -110,11 +111,13 @@ class _SettingOptionsMoreState extends State { ), ], CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.settings, size: 20), - titleText: LocaleKeys.settings.tr(), - needBorderBelow: false, - onTap: () => navigateWithName(context, AppRoutes.settingOptionsInviteFriends), - ), + leadingWidget: const Icon(Icons.settings, size: 20), + titleText: LocaleKeys.settings.tr(), + needBorderBelow: false, + onTap: () { + context.read().getAppInvitationHistoryList(); + navigateWithName(context, AppRoutes.settingOptionsInviteFriends); + }), ], ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0), 10.height, diff --git a/lib/views/shipping_management/shipping_management_view.dart b/lib/views/shipping_management/shipping_management_view.dart index e134c93..3e7d766 100644 --- a/lib/views/shipping_management/shipping_management_view.dart +++ b/lib/views/shipping_management/shipping_management_view.dart @@ -184,7 +184,7 @@ class _ShippingManagementViewState extends State { text: Utils.getNameByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated), chipColor: Utils.getChipColorByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated), ), - ("${shippingRequest.request!.brand} ${shippingRequest.request!.model} | ${shippingRequest.id.toString()}").toText(fontSize: 16), + ("${shippingRequest.request!.brand} ${shippingRequest.request!.model} | ${shippingRequest.requestID.toString()}").toText(fontSize: 16), (shippingRequest.request!.description ?? "").toText(color: MyColors.lightTextColor, fontSize: 12, fontWeight: MyFonts.Medium), if (shippingRequest.comment != null && shippingRequest.comment!.isNotEmpty) ...[ ("${LocaleKeys.comment.tr()}: ${shippingRequest.comment ?? ""}").toText(color: MyColors.lightTextColor, fontSize: 12, fontWeight: MyFonts.Medium), diff --git a/lib/widgets/common_widgets/provider_details_card.dart b/lib/widgets/common_widgets/provider_details_card.dart index 8954fa5..1167613 100644 --- a/lib/widgets/common_widgets/provider_details_card.dart +++ b/lib/widgets/common_widgets/provider_details_card.dart @@ -33,27 +33,14 @@ class ProviderDetailCard extends StatelessWidget { @override Widget build(BuildContext context) { - String nameInitials = ""; - if (title.isNotEmpty) { - nameInitials = title[0]; - } return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (isFromFavoriteList) ...[ - CircleAvatar( - radius: 22, - backgroundColor: MyColors.darkPrimaryColor, - child: nameInitials.toText(fontSize: 25, isBold: true), - ), - ] else ...[ - Image.asset( - providerImageUrl, - width: 80, - height: 85, - fit: BoxFit.cover, - ), - ], + providerImageUrl.buildNetworkImage( + width: 80, + height: 85, + fit: BoxFit.cover, + ), 12.width, Expanded( child: Column( diff --git a/lib/widgets/dropdown/dropdow_field.dart b/lib/widgets/dropdown/dropdow_field.dart index c8c75ce..7e4bbff 100644 --- a/lib/widgets/dropdown/dropdow_field.dart +++ b/lib/widgets/dropdown/dropdow_field.dart @@ -33,7 +33,8 @@ class DropdownField extends StatefulWidget { final TextStyle? textStyle; final bool isSelectAble; - const DropdownField(this.onSelect, {super.key, this.hint, this.list, this.dropdownValue, this.errorValue = "", this.showAppointmentPickerVariant = false, this.textStyle, this.isSelectAble = true}); + const DropdownField(this.onSelect, + {super.key, this.hint, this.list, this.dropdownValue, this.onTap, this.errorValue = "", this.showAppointmentPickerVariant = false, this.textStyle, this.isSelectAble = true}); @override State createState() => _DropdownFieldState(); @@ -51,7 +52,6 @@ class _DropdownFieldState extends State { super.initState(); } - @override Widget build(BuildContext context) { dropdownValue = widget.dropdownValue; @@ -72,7 +72,6 @@ class _DropdownFieldState extends State { color: !widget.isSelectAble ? Colors.transparent : null, size: 21, ), - elevation: 16, iconSize: widget.showAppointmentPickerVariant ? 26 : 16, iconEnabledColor: borderColor, @@ -91,7 +90,6 @@ class _DropdownFieldState extends State { }); }, onTap: widget.onTap, - items: (widget.list ?? defaultV).map>( (DropValue value) { return DropdownMenuItem(