diff --git a/assets/icons/vehicle_type_buggy.svg b/assets/icons/vehicle_type_buggy.svg new file mode 100644 index 0000000..fa95ab0 --- /dev/null +++ b/assets/icons/vehicle_type_buggy.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/vehicle_type_car.svg b/assets/icons/vehicle_type_car.svg new file mode 100644 index 0000000..008545c --- /dev/null +++ b/assets/icons/vehicle_type_car.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/icons/vehicle_type_golf_cart.svg b/assets/icons/vehicle_type_golf_cart.svg new file mode 100644 index 0000000..18a1fd9 --- /dev/null +++ b/assets/icons/vehicle_type_golf_cart.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/vehicle_type_motorcycle.svg b/assets/icons/vehicle_type_motorcycle.svg new file mode 100644 index 0000000..c63fffd --- /dev/null +++ b/assets/icons/vehicle_type_motorcycle.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 7623f20..707b7cc 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -50,6 +50,7 @@ class ApiConsts { static String ServiceProviderService_Get = "${baseUrlServices}api/ServiceProviders/ServiceProviderService_Get"; static String BranchesAndServices = "${baseUrlServices}api/ServiceProviders/ServiceProviderDetail_Get"; static String GetAllNearBranches = "${baseUrlServices}api/ServiceProviders/ServiceProviderBranchDetail_Get"; + static String GetServiceItemAppointmentScheduleSlots = "${baseUrlServices}api/ServiceProviders/ServiceItemAppointmentScheduleSlots_Get"; //Appointment APIs static String serviceProvidersAppointmentGet = "${baseUrlServices}api/ServiceProviders/ServiceProvidersAppointment_Get"; @@ -76,6 +77,7 @@ class ApiConsts { //Advertisement APIs static String vehicleTypeGet = "${baseUrlServices}api/ServiceProviders/VehicleType_Get"; static String vehicleModelGet = "${baseUrlServices}api/Master/VehicleModel_Get"; + static String vehicleBrandGet = "${baseUrlServices}api/Master/VehicleBrand_Get"; static String vehicleModelYearGet = "${baseUrlServices}api/Master/VehicleModelYear_Get"; static String vehicleColorGet = "${baseUrlServices}api/Master/VehicleColor_Get"; static String vehicleConditionGet = "${baseUrlServices}api/Master/VehicleCondition_Get"; @@ -91,6 +93,7 @@ class ApiConsts { static String vehicleAdsSpecialServicesGet = "${baseUrlServices}api/Common/SpecialService_Get"; static String vehicleAdsSingleStepCreate = "${baseUrlServices}api/Advertisement/AdsSingleStep_Create"; static String vehicleAdsGet = "${baseUrlServices}api/Advertisement/Ads_Get"; + static String myAdsReserveGet = "${baseUrlServices}api/Advertisement/AdsReserve_Get"; static String adsCarCheckupSPBranchScheduleSlotGet = "${baseUrlServices}api/Advertisement/AdsCarCheckupSPBranchScheduleSlot_Get"; static String adsPhotoOfficeAppointmentScheduleSlotGet = "${baseUrlServices}api/Advertisement/PhotoOfficeAppointmentScheduleSlot_Get"; @@ -124,7 +127,9 @@ class GlobalConsts { static String attachImageError = "You must add at least 3 images"; static String attachDamagePartImage = "Please add part image"; static String adDurationDateError = "Ad Duration start date cannot be empty"; + static String adDurationPhoneNumberError = "Phone number cannot be empty"; static String adReservablePriceErrorConst = "Ad Reservable price cannot be empty"; + static String homeLocationEmptyError = "Home location 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."; } @@ -194,6 +199,11 @@ class MyAssets { static String icPhoneNumber = "${assetPath}icons/ic_phone_number.svg"; static String icStar = "${assetPath}icons/ic_star.svg"; + static String vehicleTypeBuggy = "${assetPath}icons/vehicle_type_buggy.svg"; + static String vehicleTypeCar = "${assetPath}icons/vehicle_type_car.svg"; + static String vehicleTypeGolfCart = "${assetPath}icons/vehicle_type_golf_cart.svg"; + static String vehicleTypeMotorcycle = "${assetPath}icons/vehicle_type_motorcycle.svg"; + //PNG static String icWorldPng = "${assetPath}images/ic_world.png"; static String bnIntroPng = "${assetPath}images/bn_Intro.png"; diff --git a/lib/config/routes.dart b/lib/config/routes.dart index cb9aee9..c852ecc 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,9 +1,5 @@ import 'package:mc_common_app/models/user/register_user.dart'; -// import 'package:mc_common_app/views/settings/create_services_page.dart'; -// import 'package:mc_common_app/views/settings/dealership_page.dart'; -// import 'package:mc_common_app/views/settings/define_branch_page.dart'; -// import 'package:mc_common_app/views/settings/define_license_page.dart'; import 'package:mc_common_app/views/user/change_email_page.dart'; import 'package:mc_common_app/views/user/change_mobile_page.dart'; import 'package:mc_common_app/views/user/change_password_page.dart'; @@ -16,10 +12,6 @@ import 'package:mc_common_app/views/user/login_method_selection_page.dart'; import 'package:mc_common_app/views/user/login_verification_page.dart'; import 'package:mc_common_app/views/user/login_verify_account_page.dart'; import 'package:mc_common_app/views/user/login_with_password_page.dart'; - -// import 'package:mc_common_app/views/user/profile/profile_1_page.dart'; -// import 'package:mc_common_app/views/user/profile/profile_2_page.dart'; -// import 'package:mc_common_app/views/user/profile/profile_3_page.dart'; import 'package:mc_common_app/views/user/register_page.dart'; import 'package:mc_common_app/views/user/register_provider_page.dart'; import 'package:mc_common_app/views/user/register_selection_page.dart'; @@ -33,7 +25,7 @@ class AppRoutes { static const String registerSelection = "/registerSelection"; static const String loginVerifyAccount = "/loginVerifyAccount"; static const String registerCustomer = "/registerCustomer"; - static const String registerProvider= "/registerProvider"; + static const String registerProvider = "/registerProvider"; static const String forgetPassword = "/forgetPassword"; static const String loginVerification = "/loginVerification"; static const String loginWithPassword = "/loginWithPassword"; @@ -53,40 +45,47 @@ class AppRoutes { static const String dashboard = "/dashboard"; static const String bookProviderAppView = "/bookProviderAppView"; static const String appointmentDetailView = "/appointmentDetailView"; + static const String bookAppointmenServicesView = "/bookAppointmenServicesView"; + static const String bookAppointmentsItemView = "/bookAppointmentsItemView"; + static const String reviewAppointmentView = "/reviewAppointmentView"; + + //Advertisement + static const String selectAdTypeView = "/selectAdTypeView"; static const String adsDetailView = "/adsDetailView"; static const String createAdView = "/createAdView"; - static const String bookAppointmenServicesView = "/bookAppointmenServicesView"; + static const String adsSearchFilterScreen = "/adsSearchFilterScreen"; + + // Payments static const String paymentMethodsView = "/paymentMethodsView"; //Customer APP: Provider & Services static const String branchDetailPage = "/branchDetailPage"; static const String providerProfilePage = "/providerProfilePage"; - - //Subcriptions - static final String mySubscriptionsPage = "/mySubscriptionsPage"; - static final String subscriptionsPage = "/subscriptionsPage"; + // Subscriptions + static const String mySubscriptionsPage = "/mySubscriptionsPage"; + static const String subscriptionsPage = "/subscriptionsPage"; static const String initialRoute = splash; static final Map routes = { //User splash: (context) => const SplashPage(), - registerSelection: (context) => RegisterSelectionPage(), + registerSelection: (context) => const RegisterSelectionPage(), loginVerifyAccount: (context) => LoginVerifyAccountPage(), - registerCustomer: (context) => RegisterCustomerPage(), - registerProvider: (context) => RegisterProviderPage(), - forgetPassword: (context) => ForgetPasswordPage(), + registerCustomer: (context) => const RegisterCustomerPage(), + registerProvider: (context) => const RegisterProviderPage(), + forgetPassword: (context) => const ForgetPasswordPage(), loginVerification: (context) => const LoginVerificationPage(), - loginWithPassword: (context) => LoginWithPassword(), + loginWithPassword: (context) => const LoginWithPassword(), loginMethodSelection: (context) => LoginMethodSelectionPage(ModalRoute.of(context)!.settings.arguments as String), completeProfile: (context) => CompleteProfilePage(ModalRoute.of(context)!.settings.arguments as RegisterUserRespModel), verifyPassword: (context) => VerifyPasswordPage(), confirmNewPasswordPage: (context) => ConfirmNewPasswordPage(ModalRoute.of(context)!.settings.arguments as String), - changePassword: (context) => ChangePasswordPage(), + changePassword: (context) => const ChangePasswordPage(), forgetPasswordMethodPage: (context) => ForgetPasswordMethodPage(ModalRoute.of(context)!.settings.arguments as String), changeMobilePage: (context) => ChangeMobilePage(), changeEmailPage: (context) => const ChangeEmailPage(), - editAccountPage: (context) => EditAccountPage(), + editAccountPage: (context) => const EditAccountPage(), }; } diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index b72d532..2f07f17 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -3,6 +3,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/enums.dart'; extension EmailValidator on String { Widget toText( @@ -14,6 +15,7 @@ extension EmailValidator on String { TextDecoration? textDecoration, double letterSpacing = -0.4, TextAlign? textAlign, + FontWeight? fontWeight, double? height, int? maxLines}) => AutoSizeText( @@ -25,7 +27,7 @@ extension EmailValidator on String { height: height, decoration: isUnderLine ? TextDecoration.underline : textDecoration ?? TextDecoration.none, fontSize: fontSize ?? 10, - fontWeight: isBold ? FontWeight.bold : FontWeight.w600, + fontWeight: isBold ? FontWeight.bold : fontWeight ?? FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: letterSpacing, ), @@ -180,6 +182,94 @@ extension AdPostEnum on int { } } +extension AdPostStatusToInt on AdPostStatus { + int getIdFromAdPostStatusEnum() { + switch (this) { + case AdPostStatus.pendingForReview: + return 1; + case AdPostStatus.pendingForPayment: + return 2; + + case AdPostStatus.rejected: + return 3; + + case AdPostStatus.cancelled: + return 4; + + case AdPostStatus.pendingForPost: + return 5; + + case AdPostStatus.active: + return 6; + + case AdPostStatus.expired: + return 7; + + case AdPostStatus.sold: + return 8; + + case AdPostStatus.reserved: + return 9; + + case AdPostStatus.buyingService: + return 10; + + case AdPostStatus.reserveCancel: + return 11; + default: + return -1; + } + } +} + +extension CreatedByRoleEnumToInt on CreatedByRoleEnum { + int getIdFromCreatedByRoleEnum() { + switch (this) { + case CreatedByRoleEnum.admin: + return 1; + case CreatedByRoleEnum.customer: + return 2; + case CreatedByRoleEnum.provider: + return 3; + case CreatedByRoleEnum.allAds: + return -1; + default: + return 1; + } + } +} + +extension AdReserveStatusEnum on int { + AdReserveStatus toAdRserveStatusEnum() { + if (this == 0) { + return AdReserveStatus.defaultStatus; + } else if (this == 1) { + return AdReserveStatus.reserved; + } else if (this == 2) { + return AdReserveStatus.cancelledByOwner; + } else if (this == 3) { + return AdReserveStatus.cancelledByAdmin; + } else { + return AdReserveStatus.defaultStatus; + } + } +} + +extension AdOwnerEnum on int { + CreatedByRoleEnum toCreatedByRoleEnum() { + if (this == -1) { + return CreatedByRoleEnum.allAds; + } else if (this == 1) { + return CreatedByRoleEnum.admin; + } else if (this == 2) { + return CreatedByRoleEnum.customer; + } else if (this == 3) { + return CreatedByRoleEnum.provider; + } + return CreatedByRoleEnum.customer; + } +} + extension BranchsEnum on int { BranchStatusEnum toBranchStatusEnum() { if (this == 1) { @@ -246,3 +336,19 @@ extension DateTimeConversions on DateTime { } } } + +extension VehicleAdTypeEnum on int { + VehicleTypeEnum getVehicleTypeEnum() { + if (this == 1) { + return VehicleTypeEnum.car; + } else if (this == 2) { + return VehicleTypeEnum.motorCycle; + } else if (this == 3) { + return VehicleTypeEnum.golfCart; + } else if (this == 4) { + return VehicleTypeEnum.buggy; + } else { + return VehicleTypeEnum.car; + } + } +} diff --git a/lib/main.dart b/lib/main.dart index f2d9ecf..7ea71be 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,8 @@ import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; import 'package:sizer/sizer.dart'; + +//testing push final navigatorKey = GlobalKey(); Logger logger = Logger( diff --git a/lib/models/advertisment_models/ad_details_model.dart b/lib/models/advertisment_models/ad_details_model.dart index d27b578..4c7f85f 100644 --- a/lib/models/advertisment_models/ad_details_model.dart +++ b/lib/models/advertisment_models/ad_details_model.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/advertisment_models/special_service_model.dart'; import 'package:mc_common_app/utils/enums.dart'; @@ -36,6 +38,11 @@ class AdDetailsModel { bool? isMCHandled; String? modifiedOn; AdPostStatus? adPostStatus; + AdReserveStatus? adReserveStatus; + bool? isMyAd; + String? phoneNo; + String? whatsAppNo; + CreatedByRoleEnum? createdByRoleEnum; AdDetailsModel( {this.id, @@ -69,9 +76,20 @@ class AdDetailsModel { this.reservePrice, this.isMCHandled, this.adPostStatus, + this.adReserveStatus, + this.isMyAd, + this.phoneNo, + this.whatsAppNo, + this.createdByRoleEnum, this.modifiedOn}); - AdDetailsModel.fromJson(Map json) { + int getRandomValue({required int min, required int max}) { + Random random = Random(); + int randomNumber = random.nextInt(max - min); + return randomNumber; + } + + AdDetailsModel.fromJson(Map json, bool isMyAds) { id = json['id']; startdate = json['startdate']; enddate = json['enddate']; @@ -82,12 +100,6 @@ class AdDetailsModel { specialservice!.add(SpecialServiceModel.fromJson(v)); }); } - // if (json['reserved'] != null) { - // reserved = []; - // json['reserved'].forEach((v) { - // reserved!.add(Null.fromJson(v)); - // }); - // } statusID = json['statusID']; statuslabel = json['statuslabel']; adsDurationPrice = json['adsDurationPrice']; @@ -113,7 +125,14 @@ class AdDetailsModel { reservePrice = json['reservePrice']; isMCHandled = json['isMCHandled']; modifiedOn = json['modifiedOn']; + whatsAppNo = json['phoneNo']; + modifiedOn = json['whatsAppNo']; adPostStatus = (json['statusID'] as int).toAdPostEnum(); + //TODO: THIS ID SHOULD BE UPDATED! + adReserveStatus = AdReserveStatus.defaultStatus; + createdByRoleEnum = CreatedByRoleEnum.admin; + // createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum(); + isMyAd = isMyAds; } Map toJson() { diff --git a/lib/models/advertisment_models/reserved_ads_models.dart b/lib/models/advertisment_models/reserved_ads_models.dart new file mode 100644 index 0000000..83c793f --- /dev/null +++ b/lib/models/advertisment_models/reserved_ads_models.dart @@ -0,0 +1,36 @@ +class MyReservedAdsRespModel { + int? id; + int? adsID; + int? customerID; + int? paymentStatus; + int? reservationTimeID; + double? reservationBasePrice; + double? refundAmount; + String? refundDate; + + MyReservedAdsRespModel({this.id, this.adsID, this.customerID, this.paymentStatus, this.reservationTimeID, this.reservationBasePrice, this.refundAmount, this.refundDate}); + + MyReservedAdsRespModel.fromJson(Map json) { + id = json['id']; + adsID = json['adsID']; + customerID = json['customerID']; + paymentStatus = json['paymentStatus']; + reservationTimeID = json['reservationTimeID']; + reservationBasePrice = json['reservationBasePrice']; + refundAmount = json['refundAmount']; + refundDate = json['refundDate']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['adsID'] = adsID; + data['customerID'] = customerID; + data['paymentStatus'] = paymentStatus; + data['reservationTimeID'] = reservationTimeID; + data['reservationBasePrice'] = reservationBasePrice; + data['refundAmount'] = refundAmount; + data['refundDate'] = refundDate; + return data; + } +} diff --git a/lib/models/advertisment_models/vehicle_details_models.dart b/lib/models/advertisment_models/vehicle_details_models.dart index 60ff707..905e43b 100644 --- a/lib/models/advertisment_models/vehicle_details_models.dart +++ b/lib/models/advertisment_models/vehicle_details_models.dart @@ -1,5 +1,8 @@ import 'dart:developer'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/utils/enums.dart'; + class VehicleDetailsModel { List? vehicleBrands; List? vehicleCategories; @@ -56,14 +59,22 @@ class VehicleTypeModel { String? vehicleTypeName; String? vehicleTypeNameN; bool? isActive; - - VehicleTypeModel({this.id, this.vehicleTypeName, this.vehicleTypeNameN, this.isActive}); + VehicleTypeEnum? vehicleTypeEnum; + + VehicleTypeModel({ + this.id, + this.vehicleTypeName, + this.vehicleTypeNameN, + this.isActive, + this.vehicleTypeEnum = VehicleTypeEnum.car, + }); VehicleTypeModel.fromJson(Map json) { id = json['id']; vehicleTypeName = json['vehicleTypeName']; vehicleTypeNameN = json['vehicleTypeNameN']; isActive = json['isActive']; + vehicleTypeEnum = (json['id'] as int).getVehicleTypeEnum(); } Map toJson() { diff --git a/lib/models/generic_resp_model.dart b/lib/models/generic_resp_model.dart index 7b476d7..89d935d 100644 --- a/lib/models/generic_resp_model.dart +++ b/lib/models/generic_resp_model.dart @@ -23,16 +23,7 @@ class GenericRespModel { } var json = { - "ads": { - "id": 0, - "adsDurationID": 1, - "startDate": "2023-04-12T10:10:20.905Z", - "countryId": 1, - "specialServiceIDs": [ - - ], - "isMCHandled": false - }, + "ads": {"id": 0, "adsDurationID": 1, "startDate": "2023-04-12T10:10:20.905Z", "countryId": 1, "specialServiceIDs": [], "isMCHandled": false}, "vehiclePosting": { "id": 0, "userID": "1A1597B3-D5A0-433A-098B-08DB189E51EC", @@ -56,24 +47,10 @@ var json = { "demandAmount": 34, "adStatus": 1, "vehiclePostingImages": [ - { - "id": 0, - "imageName": "onon", - "imageUrl": "string", - "imageStr": null, - "vehiclePostingID": 0, - "vehiclePosting": null - } + {"id": 0, "imageName": "onon", "imageUrl": "string", "imageStr": null, "vehiclePostingID": 0, "vehiclePosting": null} ], "vehiclePostingDamageParts": [ - { - "id": 0, - "comment": "hhsa", - "vehicleImageBase64": null, - "vehicleDamagePartID": 1, - "vehiclePostingID": 0, - "isActive": true - } + {"id": 0, "comment": "hhsa", "vehicleImageBase64": null, "vehicleDamagePartID": 1, "vehiclePostingID": 0, "isActive": true} ] } }; @@ -86,9 +63,7 @@ class AdsCreationPayloadModel { AdsCreationPayloadModel.fromJson(Map json) { ads = json['ads'] != null ? Ads.fromJson(json['ads']) : null; - vehiclePosting = json['vehiclePosting'] != null - ? VehiclePosting.fromJson(json['vehiclePosting']) - : null; + vehiclePosting = json['vehiclePosting'] != null ? VehiclePosting.fromJson(json['vehiclePosting']) : null; } Map toJson() { @@ -111,13 +86,7 @@ class Ads { List? specialServiceIDs; bool? isMCHandled; - Ads( - {this.id, - this.adsDurationID, - this.startDate, - this.countryId, - this.specialServiceIDs, - this.isMCHandled}); + Ads({this.id, this.adsDurationID, this.startDate, this.countryId, this.specialServiceIDs, this.isMCHandled}); Ads.fromJson(Map json) { id = json['id']; @@ -164,31 +133,35 @@ class VehiclePosting { int? adStatus; List? vehiclePostingImages; List? vehiclePostingDamageParts; + String? phoneNo; + String? whatsAppNo; VehiclePosting( {this.id, - this.userID, - this.vehicleType, - this.vehicleModelID, - this.vehicleModelYearID, - this.vehicleColorID, - this.vehicleCategoryID, - this.vehicleConditionID, - this.vehicleMileageID, - this.vehicleTransmissionID, - this.vehicleSellerTypeID, - this.cityID, - this.price, - this.vehicleVIN, - this.vehicleDescription, - this.vehicleTitle, - this.vehicleDescriptionN, - this.isFinanceAvailable, - this.warantyYears, - this.demandAmount, - this.adStatus, - this.vehiclePostingImages, - this.vehiclePostingDamageParts}); + this.userID, + this.vehicleType, + this.vehicleModelID, + this.vehicleModelYearID, + this.vehicleColorID, + this.vehicleCategoryID, + this.vehicleConditionID, + this.vehicleMileageID, + this.vehicleTransmissionID, + this.vehicleSellerTypeID, + this.cityID, + this.price, + this.vehicleVIN, + this.vehicleDescription, + this.vehicleTitle, + this.vehicleDescriptionN, + this.isFinanceAvailable, + this.warantyYears, + this.demandAmount, + this.adStatus, + this.phoneNo, + this.whatsAppNo, + this.vehiclePostingImages, + this.vehiclePostingDamageParts}); VehiclePosting.fromJson(Map json) { id = json['id']; @@ -212,6 +185,8 @@ class VehiclePosting { warantyYears = json['warantyYears']; demandAmount = json['demandAmount']; adStatus = json['adStatus']; + phoneNo = json['phoneNo']; + whatsAppNo = json['whatsAppNo']; if (json['vehiclePostingImages'] != null) { vehiclePostingImages = []; json['vehiclePostingImages'].forEach((v) { @@ -221,8 +196,7 @@ class VehiclePosting { if (json['vehiclePostingDamageParts'] != null) { vehiclePostingDamageParts = []; json['vehiclePostingDamageParts'].forEach((v) { - vehiclePostingDamageParts! - .add(VehiclePostingDamageParts.fromJson(v)); + vehiclePostingDamageParts!.add(VehiclePostingDamageParts.fromJson(v)); }); } } @@ -250,16 +224,21 @@ class VehiclePosting { data['warantyYears'] = warantyYears; data['demandAmount'] = demandAmount; data['adStatus'] = adStatus; + data['phoneNo'] = phoneNo; + data['whatsAppNo'] = whatsAppNo; if (vehiclePostingImages != null) { - data['vehiclePostingImages'] = - vehiclePostingImages!.map((v) => v.toJson()).toList(); + data['vehiclePostingImages'] = vehiclePostingImages!.map((v) => v.toJson()).toList(); } if (vehiclePostingDamageParts != null) { - data['vehiclePostingDamageParts'] = - vehiclePostingDamageParts!.map((v) => v.toJson()).toList(); + data['vehiclePostingDamageParts'] = vehiclePostingDamageParts!.map((v) => v.toJson()).toList(); } return data; } + + @override + String toString() { + return 'VehiclePosting{id: $id, userID: $userID, vehicleType: $vehicleType, vehicleModelID: $vehicleModelID, vehicleModelYearID: $vehicleModelYearID, vehicleColorID: $vehicleColorID, vehicleCategoryID: $vehicleCategoryID, vehicleConditionID: $vehicleConditionID, vehicleMileageID: $vehicleMileageID, vehicleTransmissionID: $vehicleTransmissionID, vehicleSellerTypeID: $vehicleSellerTypeID, cityID: $cityID, price: $price, vehicleVIN: $vehicleVIN, vehicleDescription: $vehicleDescription, vehicleTitle: $vehicleTitle, vehicleDescriptionN: $vehicleDescriptionN, isFinanceAvailable: $isFinanceAvailable, warantyYears: $warantyYears, demandAmount: $demandAmount, adStatus: $adStatus, vehiclePostingImages: $vehiclePostingImages, vehiclePostingDamageParts: $vehiclePostingDamageParts, phoneNo: $phoneNo, whatsAppNo: $whatsAppNo}'; + } } class VehiclePostingImages { @@ -270,13 +249,7 @@ class VehiclePostingImages { int? vehiclePostingID; String? vehiclePosting; - VehiclePostingImages( - {this.id, - this.imageName, - this.imageUrl, - this.imageStr, - this.vehiclePostingID, - this.vehiclePosting}); + VehiclePostingImages({this.id, this.imageName, this.imageUrl, this.imageStr, this.vehiclePostingID, this.vehiclePosting}); VehiclePostingImages.fromJson(Map json) { id = json['id']; @@ -307,13 +280,7 @@ class VehiclePostingDamageParts { int? vehiclePostingID; bool? isActive; - VehiclePostingDamageParts( - {this.id, - this.comment, - this.vehicleImageBase64, - this.vehicleDamagePartID, - this.vehiclePostingID, - this.isActive}); + VehiclePostingDamageParts({this.id, this.comment, this.vehicleImageBase64, this.vehicleDamagePartID, this.vehiclePostingID, this.isActive}); VehiclePostingDamageParts.fromJson(Map json) { id = json['id']; diff --git a/lib/models/model/provider_model.dart b/lib/models/model/provider_model.dart index 97ce37e..256b281 100644 --- a/lib/models/model/provider_model.dart +++ b/lib/models/model/provider_model.dart @@ -4,8 +4,7 @@ import 'dart:convert'; -import 'package:mc_common_app/models/profile/categroy.dart'; -import 'package:mc_common_app/models/services/branch_model.dart'; +import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; ProviderModel branch2FromJson(String str) => ProviderModel.fromJson(json.decode(str)); @@ -26,18 +25,18 @@ class ProviderModel { factory ProviderModel.fromJson(Map json) => ProviderModel( - messageStatus: json["messageStatus"] == null ? null : json["messageStatus"], - totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + messageStatus: json["messageStatus"], + totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : ProviderModelData.fromJson(json["data"]), - message: json["message"] == null ? null : json["message"], + message: json["message"], ); Map toJson() => { - "messageStatus": messageStatus == null ? null : messageStatus, - "totalItemsCount": totalItemsCount == null ? null : totalItemsCount, + "messageStatus": messageStatus, + "totalItemsCount": totalItemsCount, "data": data == null ? null : data!.toJson(), - "message": message == null ? null : message, + "message": message, }; } @@ -62,29 +61,29 @@ class ProviderModelData { final int? allDocStatus; final bool? isValidSubscription; final String? userId; - final List? serviceProviderBranch; + final List? serviceProviderBranch; factory ProviderModelData.fromJson(Map json) => ProviderModelData( - id: json["id"] == null ? null : json["id"], - companyName: json["companyName"] == null ? null : json["companyName"], - countryName: json["countryName"] == null ? null : json["countryName"], - countryID: json["countryID"] == null ? null : json["countryID"], - companyDescription: json["companyDescription"] == null ? null : json["companyDescription"], - allDocStatus: json["allDocStatus"] == null ? null : json["allDocStatus"], - isValidSubscription: json["isValidSubscription"] == null ? null : json["isValidSubscription"], - userId: json["userID"] == null ? null : json["userID"], - serviceProviderBranch: json["serviceProviderBranch"] == null ? null : List.from(json["serviceProviderBranch"].map((x) => BranchModel.fromJson(x))), + id: json["id"], + companyName: json["companyName"], + countryName: json["countryName"], + countryID: json["countryID"], + companyDescription: json["companyDescription"], + allDocStatus: json["allDocStatus"], + isValidSubscription: json["isValidSubscription"], + userId: json["userID"], + serviceProviderBranch: json["serviceProviderBranch"] == null ? null : List.from(json["serviceProviderBranch"].map((x) => BranchDetailModel.fromJson(x))), ); Map toJson() => { - "id": id == null ? null : id, - "companyName": companyName == null ? null : companyName, - "companyDescription": companyDescription == null ? null : companyDescription, - "allDocStatus": allDocStatus == null ? null : allDocStatus, - "isValidSubscription": isValidSubscription == null ? null : isValidSubscription, - "userID": userId == null ? null : userId, + "id": id, + "companyName": companyName, + "companyDescription": companyDescription, + "allDocStatus": allDocStatus, + "isValidSubscription": isValidSubscription, + "userID": userId, "serviceProviderBranch": serviceProviderBranch == null ? null : List.from(serviceProviderBranch!.map((x) => x.toJson())), }; } diff --git a/lib/models/payment_models/pay_order_detail_resp_model.dart b/lib/models/payment_models/pay_order_detail_resp_model.dart index ca54aeb..7ed268c 100644 --- a/lib/models/payment_models/pay_order_detail_resp_model.dart +++ b/lib/models/payment_models/pay_order_detail_resp_model.dart @@ -30,6 +30,11 @@ class PayOrderDetailRespModel { this.serviceAppointmentID, this.providerSubscriptionID}); + @override + String toString() { + return 'PayOrderDetailRespModel{id: $id, userFullName: $userFullName, userMobile: $userMobile, userEmail: $userEmail, userID: $userID, amount: $amount, currency: $currency, payFortProjectID: $payFortProjectID, payFortServiceID: $payFortServiceID, description: $description, isPaid: $isPaid, language: $language, serviceAppointmentID: $serviceAppointmentID, providerSubscriptionID: $providerSubscriptionID}'; + } + PayOrderDetailRespModel.fromJson(Map json) { id = json['id']; userFullName = json['userFullName']; diff --git a/lib/models/services/branch_model.dart b/lib/models/provider_branches_models/branch_detail_model.dart similarity index 92% rename from lib/models/services/branch_model.dart rename to lib/models/provider_branches_models/branch_detail_model.dart index dfc56ca..70768c3 100644 --- a/lib/models/services/branch_model.dart +++ b/lib/models/provider_branches_models/branch_detail_model.dart @@ -1,9 +1,9 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; -import 'package:mc_common_app/models/profile/categroy.dart'; +import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/services/service_model.dart'; import 'package:mc_common_app/utils/enums.dart'; -class BranchModel { +class BranchDetailModel { final int? id; final int? serviceProviderId; final String? serviceProviderName; @@ -25,7 +25,7 @@ class BranchModel { String? countryName; bool isExpanded; - BranchModel({ + BranchDetailModel({ this.id, this.serviceProviderId, this.serviceProviderName, @@ -48,7 +48,7 @@ class BranchModel { required this.isExpanded, }); - factory BranchModel.fromJson(Map json) => BranchModel( + factory BranchDetailModel.fromJson(Map json) => BranchDetailModel( id: json["id"], serviceProviderId: json["serviceProviderID"], serviceProviderName: json["serviceProviderName"], diff --git a/lib/models/profile/branch.dart b/lib/models/provider_branches_models/profile/branch.dart similarity index 100% rename from lib/models/profile/branch.dart rename to lib/models/provider_branches_models/profile/branch.dart diff --git a/lib/models/profile/categroy.dart b/lib/models/provider_branches_models/profile/categroy.dart similarity index 96% rename from lib/models/profile/categroy.dart rename to lib/models/provider_branches_models/profile/categroy.dart index 0c7bf26..33feaae 100644 --- a/lib/models/profile/categroy.dart +++ b/lib/models/provider_branches_models/profile/categroy.dart @@ -5,7 +5,7 @@ import 'dart:convert'; import 'package:equatable/equatable.dart'; -import 'package:mc_common_app/models/model/provider_model.dart'; +import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart'; import 'package:mc_common_app/models/services/service_model.dart'; Category categoryFromJson(String str) => Category.fromJson(json.decode(str)); diff --git a/lib/models/profile/document.dart b/lib/models/provider_branches_models/profile/document.dart similarity index 100% rename from lib/models/profile/document.dart rename to lib/models/provider_branches_models/profile/document.dart diff --git a/lib/models/profile/services.dart b/lib/models/provider_branches_models/profile/services.dart similarity index 52% rename from lib/models/profile/services.dart rename to lib/models/provider_branches_models/profile/services.dart index 1d3d7ec..d457b4d 100644 --- a/lib/models/profile/services.dart +++ b/lib/models/provider_branches_models/profile/services.dart @@ -23,18 +23,18 @@ class Services { factory Services.fromJson(Map json) => Services( - totalItemsCount: json["totalItemsCount"] == null ? null : json["totalItemsCount"], + totalItemsCount: json["totalItemsCount"], data: json["data"] == null ? null : List.from(json["data"].map((x) => ServicesData.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, }; } @@ -61,24 +61,24 @@ class ServicesData { factory ServicesData.fromJson(Map json) => ServicesData( - id: json["id"] == null ? null : json["id"], - description: json["description"] == null ? (json["serviceDescription"] == null ? null : json["serviceDescription"]) : json["description"], - descriptionN: json["descriptionN"] == null ? (json["serviceDescriptionN"] == null ? null : json["serviceDescriptionN"]) : json["descriptionN"], - serviceIconUrl: json["serviceIconUrl"] == null ? null : json["serviceIconUrl"], - serviceImageUrl: json["serviceImageUrl"] == null ? null : json["serviceImageUrl"], - serviceCategoryId: json["serviceCategoryID"] == null ? null : json["serviceCategoryID"], - categoryName: json["categoryName"] == null ? null : json["categoryName"], + id: json["id"], + description: json["description"] ?? (json["serviceDescription"]), + descriptionN: json["descriptionN"] ?? (json["serviceDescriptionN"]), + serviceIconUrl: json["serviceIconUrl"], + serviceImageUrl: json["serviceImageUrl"], + serviceCategoryId: json["serviceCategoryID"], + categoryName: json["categoryName"], isSelected: false, ); Map toJson() => { - "id": id == null ? null : id, - "description": description == null ? null : description, - "descriptionN": descriptionN == null ? null : descriptionN, + "id": id, + "description": description, + "descriptionN": descriptionN, "serviceIconUrl": serviceIconUrl, "serviceImageUrl": serviceImageUrl, - "serviceCategoryID": serviceCategoryId == null ? null : serviceCategoryId, + "serviceCategoryID": serviceCategoryId, "categoryName": categoryName, }; } diff --git a/lib/models/provider_branches_models/provider_profile_model.dart b/lib/models/provider_branches_models/provider_profile_model.dart new file mode 100644 index 0000000..10a845f --- /dev/null +++ b/lib/models/provider_branches_models/provider_profile_model.dart @@ -0,0 +1,53 @@ +// To parse this JSON data, do +// +// final branch2 = branch2FromJson(jsonString); + +import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; + + +class ProviderProfileModel { + ProviderProfileModel({ + this.id, + this.companyName, + this.countryName, + this.companyDescription, + this.allDocStatus, + this.isValidSubscription, + this.userId, + this.serviceProviderBranch, + this.countryID, + }); + + final int? id; + final String? companyName; + final String? countryName; + int? countryID; + final String? companyDescription; + final int? allDocStatus; + final bool? isValidSubscription; + final String? userId; + final List? serviceProviderBranch; + + factory ProviderProfileModel.fromJson(Map json) => ProviderProfileModel( + id: json["id"], + companyName: json["companyName"], + countryName: json["countryName"], + countryID: json["countryID"], + companyDescription: json["companyDescription"], + allDocStatus: json["allDocStatus"], + isValidSubscription: json["isValidSubscription"], + userId: json["userID"], + serviceProviderBranch: json["serviceProviderBranch"] == null ? null : List.from(json["serviceProviderBranch"].map((x) => BranchDetailModel.fromJson(x))), + ); + + Map toJson() => { + "id": id, + "companyName": companyName, + "companyDescription": companyDescription, + "allDocStatus": allDocStatus, + "isValidSubscription": isValidSubscription, + "userID": userId, + "serviceProviderBranch": serviceProviderBranch == null ? null : List.from(serviceProviderBranch!.map((x) => x.toJson())), + }; +} + diff --git a/lib/models/provider_category_model.dart b/lib/models/provider_category_model.dart index 2c6ae13..18c8dda 100644 --- a/lib/models/provider_category_model.dart +++ b/lib/models/provider_category_model.dart @@ -1,32 +1,32 @@ -class ProviderCategoryModel { - int? id; - String? categoryName; - String? categoryNameN; - String? serviceCategoryIconUrl; - String? serviceCategoryImageUrl; - bool? isActive; - bool? isSelected; - - ProviderCategoryModel({this.id, this.categoryName, this.categoryNameN, this.serviceCategoryIconUrl, this.serviceCategoryImageUrl, this.isActive, this.isSelected = false}); - - ProviderCategoryModel.fromJson(Map json) { - id = json['id']; - categoryName = json['categoryName']; - categoryNameN = json['categoryNameN']; - serviceCategoryIconUrl = json['serviceCategoryIconUrl']; - serviceCategoryImageUrl = json['serviceCategoryImageUrl']; - isActive = json['isActive']; - isSelected = false; - } - - Map toJson() { - final Map data = {}; - data['id'] = id; - data['categoryName'] = categoryName; - data['categoryNameN'] = categoryNameN; - data['serviceCategoryIconUrl'] = serviceCategoryIconUrl; - data['serviceCategoryImageUrl'] = serviceCategoryImageUrl; - data['isActive'] = isActive; - return data; - } -} +// class ProviderCategoryModel { +// int? id; +// String? categoryName; +// String? categoryNameN; +// String? serviceCategoryIconUrl; +// String? serviceCategoryImageUrl; +// bool? isActive; +// bool? isSelected; +// +// ProviderCategoryModel({this.id, this.categoryName, this.categoryNameN, this.serviceCategoryIconUrl, this.serviceCategoryImageUrl, this.isActive, this.isSelected = false}); +// +// ProviderCategoryModel.fromJson(Map json) { +// id = json['id']; +// categoryName = json['categoryName']; +// categoryNameN = json['categoryNameN']; +// serviceCategoryIconUrl = json['serviceCategoryIconUrl']; +// serviceCategoryImageUrl = json['serviceCategoryImageUrl']; +// isActive = json['isActive']; +// isSelected = false; +// } +// +// Map toJson() { +// final Map data = {}; +// data['id'] = id; +// data['categoryName'] = categoryName; +// data['categoryNameN'] = categoryNameN; +// data['serviceCategoryIconUrl'] = serviceCategoryIconUrl; +// data['serviceCategoryImageUrl'] = serviceCategoryImageUrl; +// data['isActive'] = isActive; +// return data; +// } +// } diff --git a/lib/models/provider_service_model.dart b/lib/models/provider_service_model.dart index 4875675..914ce65 100644 --- a/lib/models/provider_service_model.dart +++ b/lib/models/provider_service_model.dart @@ -1,65 +1,65 @@ -class ProviderServiceModel { - int? id; - String? description; - String? descriptionN; - String? serviceIconUrl; - String? serviceImageUrl; - int? serviceCategoryID; - bool? isActive; - String? categoryName; - bool? ispartial; - int? appointmentPricePercentage; - int? refundAmountPercentage; - bool? isSelected; - - ProviderServiceModel( - {this.id, - this.description, - this.descriptionN, - this.serviceIconUrl, - this.serviceImageUrl, - this.serviceCategoryID, - this.isActive, - this.categoryName, - this.ispartial, - this.appointmentPricePercentage, - this.refundAmountPercentage, - this.isSelected = false, - }); - - ProviderServiceModel.fromJson(Map json) { - id = json['id']; - description = json['description']; - descriptionN = json['descriptionN']; - serviceIconUrl = json['serviceIconUrl']; - serviceImageUrl = json['serviceImageUrl']; - serviceCategoryID = json['serviceCategoryID']; - isActive = json['isActive']; - categoryName = json['categoryName']; - ispartial = json['ispartial']; - appointmentPricePercentage = json['appointmentPricePercentage']; - refundAmountPercentage = json['refundAmountPercentage']; - isSelected = false; - } - - Map toJson() { - final Map data = {}; - data['id'] = id; - data['description'] = description; - data['descriptionN'] = descriptionN; - data['serviceIconUrl'] = serviceIconUrl; - data['serviceImageUrl'] = serviceImageUrl; - data['serviceCategoryID'] = serviceCategoryID; - data['isActive'] = isActive; - data['categoryName'] = categoryName; - data['ispartial'] = ispartial; - data['appointmentPricePercentage'] = appointmentPricePercentage; - data['refundAmountPercentage'] = refundAmountPercentage; - return data; - } - - @override - String toString() { - return 'ProviderServiceModel{id: $id, description: $description, descriptionN: $descriptionN, serviceIconUrl: $serviceIconUrl, serviceImageUrl: $serviceImageUrl, serviceCategoryID: $serviceCategoryID, isActive: $isActive, categoryName: $categoryName, ispartial: $ispartial, appointmentPricePercentage: $appointmentPricePercentage, refundAmountPercentage: $refundAmountPercentage, isSelected: $isSelected}'; - } -} +// class ProviderServiceModel { +// int? id; +// String? description; +// String? descriptionN; +// String? serviceIconUrl; +// String? serviceImageUrl; +// int? serviceCategoryID; +// bool? isActive; +// String? categoryName; +// bool? ispartial; +// int? appointmentPricePercentage; +// int? refundAmountPercentage; +// bool? isSelected; +// +// ProviderServiceModel( +// {this.id, +// this.description, +// this.descriptionN, +// this.serviceIconUrl, +// this.serviceImageUrl, +// this.serviceCategoryID, +// this.isActive, +// this.categoryName, +// this.ispartial, +// this.appointmentPricePercentage, +// this.refundAmountPercentage, +// this.isSelected = false, +// }); +// +// ProviderServiceModel.fromJson(Map json) { +// id = json['id']; +// description = json['description']; +// descriptionN = json['descriptionN']; +// serviceIconUrl = json['serviceIconUrl']; +// serviceImageUrl = json['serviceImageUrl']; +// serviceCategoryID = json['serviceCategoryID']; +// isActive = json['isActive']; +// categoryName = json['categoryName']; +// ispartial = json['ispartial']; +// appointmentPricePercentage = json['appointmentPricePercentage']; +// refundAmountPercentage = json['refundAmountPercentage']; +// isSelected = false; +// } +// +// Map toJson() { +// final Map data = {}; +// data['id'] = id; +// data['description'] = description; +// data['descriptionN'] = descriptionN; +// data['serviceIconUrl'] = serviceIconUrl; +// data['serviceImageUrl'] = serviceImageUrl; +// data['serviceCategoryID'] = serviceCategoryID; +// data['isActive'] = isActive; +// data['categoryName'] = categoryName; +// data['ispartial'] = ispartial; +// data['appointmentPricePercentage'] = appointmentPricePercentage; +// data['refundAmountPercentage'] = refundAmountPercentage; +// return data; +// } +// +// @override +// String toString() { +// return 'ProviderServiceModel{id: $id, description: $description, descriptionN: $descriptionN, serviceIconUrl: $serviceIconUrl, serviceImageUrl: $serviceImageUrl, serviceCategoryID: $serviceCategoryID, isActive: $isActive, categoryName: $categoryName, ispartial: $ispartial, appointmentPricePercentage: $appointmentPricePercentage, refundAmountPercentage: $refundAmountPercentage, isSelected: $isSelected}'; +// } +// } diff --git a/lib/models/schedule_model.dart b/lib/models/schedule_model.dart index 6676083..47c13e6 100644 --- a/lib/models/schedule_model.dart +++ b/lib/models/schedule_model.dart @@ -4,6 +4,8 @@ import 'dart:convert'; +import 'package:mc_common_app/models/services/service_model.dart'; + Schedule scheduleFromJson(String str) => Schedule.fromJson(json.decode(str)); String scheduleToJson(Schedule data) => json.encode(data.toJson()); @@ -53,7 +55,8 @@ class ScheduleData { final String? latitude; final String? longitude; final List? weeklyOffDays; - final List? scheduleServices; + final List? scheduleServices; + final List? selectedServices; String branchId; ScheduleData({ @@ -72,6 +75,7 @@ class ScheduleData { this.longitude, this.weeklyOffDays, this.scheduleServices, + this.selectedServices, this.branchId = "", }); @@ -91,7 +95,8 @@ class ScheduleData { latitude: json["latitude"], longitude: json["longitude"], weeklyOffDays: json["weeklyOffDays"] == null ? [] : List.from(json["weeklyOffDays"]!.map((x) => WeeklyOffDay.fromJson(x))), - scheduleServices: json["scheduleServices"] == null ? [] : List.from(json["scheduleServices"]!.map((x) => ScheduleService.fromJson(x))), + scheduleServices: json["scheduleServices"] == null ? [] : List.from(json["scheduleServices"]!.map((x) => ServiceModel.fromJson(x))), + selectedServices: [], ); Map toJson() => @@ -111,33 +116,14 @@ class ScheduleData { "longitude": longitude, "scheduleServices": scheduleServices == null ? [] : List.from(scheduleServices!.map((x) => x.toJson())), }; -} - -class ScheduleService { - final int? providerServiceId; - // final int? branchScheduleGroupServiceID; - final String? providerServiceName; - ScheduleService({ - this.providerServiceId, - // this.branchScheduleGroupServiceID, - this.providerServiceName, - }); - - factory ScheduleService.fromJson(Map json) => - ScheduleService( - providerServiceId: json["providerServiceID"], - // branchScheduleGroupServiceID: json["branchScheduleGroupServiceID"], - providerServiceName: json["providerServiceName"], - ); - - Map toJson() => - { - "providerServiceID": providerServiceId, - "providerServiceName": providerServiceName, - }; + @override + String toString() { + return 'ScheduleData{id: $id, scheduleName: $scheduleName, serviceProviderBranchId: $serviceProviderBranchId, fromDate: $fromDate, toDate: $toDate, startTime: $startTime, endTime: $endTime, slotDurationMinute: $slotDurationMinute, perSlotAppointment: $perSlotAppointment, branchName: $branchName, address: $address, latitude: $latitude, longitude: $longitude, weeklyOffDays: $weeklyOffDays, scheduleServices: $scheduleServices, branchId: $branchId}'; + } } + class WeeklyOffDay { final int? id; final int? dayNumber; diff --git a/lib/models/service_schedule_model.dart b/lib/models/service_schedule_model.dart new file mode 100644 index 0000000..b8081f5 --- /dev/null +++ b/lib/models/service_schedule_model.dart @@ -0,0 +1,180 @@ +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/services/item_model.dart'; +import 'package:mc_common_app/models/widgets_models.dart'; + +class ServiceAppointmentScheduleModel { + List? serviceSlotList; + List? serviceItemList; + String? selectedDate; + String? selectedTimeSlot; + List? availableDates; + List? availableTimeSlots; + double? amountToPay; + double? amountTotal; + double? amountRem; + + ServiceAppointmentScheduleModel({ + this.serviceSlotList, + this.serviceItemList, + this.selectedDate, + this.selectedTimeSlot, + this.availableDates, + this.availableTimeSlots, + this.amountToPay, + this.amountTotal, + this.amountRem, + }); + + List getFormattedSlotTimes() { + var seenSlots = {}; + + var slotTimeData = serviceSlotList! + .where((slot) => seenSlots.add(TimeSlotModel( + slot: slot.startTime!, + slotId: slot.id!, + isSelected: false, + ))) + .toList(); + List slotTime = []; + for (var element in slotTimeData) { + slotTime.add(TimeSlotModel(isSelected: false, slotId: element.id!, slot: element.slotDate ?? "")); + } + + return slotTime; + } + + List getFormattedSlotDates() { + var seenDates = {}; + + var slotDatesData = serviceSlotList! + .where((slot) => seenDates.add(TimeSlotModel( + slot: slot.slotDate!, + slotId: slot.id!, + isSelected: false, + ))) + .toList(); + List slotDates = []; + for (var element in slotDatesData) { + slotDates.add(TimeSlotModel(isSelected: false, slotId: element.id!, slot: element.slotDate!.toFormattedDateWithoutTime() ?? "")); + } + + return slotDates; + } + + //TODO: I WILL START FROM HERE; I NEED TO ONLY PICK THE DISTINCT DATES FROM THE RESPONSE AND THEN BASED ON THE DATE SELECTION I WILL PICK THEIR SLOTS. + //TODO: AFTER THAT, I WILL + + ServiceAppointmentScheduleModel.fromJson(Map json) { + if (json['serviceSlotList'] != null) { + serviceSlotList = []; + json['serviceSlotList'].forEach((v) { + serviceSlotList!.add(ServiceSlotList.fromJson(v)); + }); + } + if (json['serviceItemList'] != null) { + serviceItemList = []; + json['serviceItemList'].forEach((v) { + serviceItemList!.add(ItemData.fromJson(v)); + }); + } + + amountToPay = json['amountToPay']; + selectedDate = ''; + selectedTimeSlot = ''; + availableDates = getFormattedSlotDates(); + availableTimeSlots = getFormattedSlotTimes(); + amountTotal = json['amountTotal']; + amountRem = json['amountRem']; + } + + Map toJson() { + final Map data = {}; + if (serviceSlotList != null) { + data['serviceSlotList'] = serviceSlotList!.map((v) => v.toJson()).toList(); + } + if (serviceItemList != null) { + data['serviceItemList'] = serviceItemList!.map((v) => v.toJson()).toList(); + } + data['amountToPay'] = amountToPay; + data['amountTotal'] = amountTotal; + data['amountRem'] = amountRem; + return data; + } +} + +class ServiceSlotList { + int? id; + int? branchAppointmentScheduleID; + String? branchAppointmentSchedule; + int? serviceProviderID; + String? slotDate; + String? startTime; + String? endTime; + int? bookAppointment; + int? allowAppointment; + int? slotDurationMinute; + int? appointmentType; + bool? isActive; + int? createdBy; + String? createdOn; + int? modifiedBy; + String? modifiedOn; + + ServiceSlotList( + {this.id, + this.branchAppointmentScheduleID, + this.branchAppointmentSchedule, + this.serviceProviderID, + this.slotDate, + this.startTime, + this.endTime, + this.bookAppointment, + this.allowAppointment, + this.slotDurationMinute, + this.appointmentType, + this.isActive, + this.createdBy, + this.createdOn, + this.modifiedBy, + this.modifiedOn}); + + ServiceSlotList.fromJson(Map json) { + id = json['id']; + branchAppointmentScheduleID = json['branchAppointmentScheduleID']; + branchAppointmentSchedule = json['branchAppointmentSchedule']; + serviceProviderID = json['serviceProviderID']; + slotDate = json['slotDate']; + startTime = json['startTime']; + endTime = json['endTime']; + bookAppointment = json['bookAppointment']; + allowAppointment = json['allowAppointment']; + slotDurationMinute = json['slotDurationMinute']; + appointmentType = json['appointmentType']; + isActive = json['isActive']; + createdBy = json['createdBy']; + createdOn = json['createdOn']; + modifiedBy = json['modifiedBy']; + modifiedOn = json['modifiedOn']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['branchAppointmentScheduleID'] = branchAppointmentScheduleID; + data['branchAppointmentSchedule'] = branchAppointmentSchedule; + data['serviceProviderID'] = serviceProviderID; + data['slotDate'] = slotDate; + data['startTime'] = startTime; + data['endTime'] = endTime; + data['bookAppointment'] = bookAppointment; + data['allowAppointment'] = allowAppointment; + data['slotDurationMinute'] = slotDurationMinute; + data['appointmentType'] = appointmentType; + data['isActive'] = isActive; + data['createdBy'] = createdBy; + data['createdOn'] = createdOn; + data['modifiedBy'] = modifiedBy; + data['modifiedOn'] = modifiedOn; + return data; + } +} diff --git a/lib/models/services/item_model.dart b/lib/models/services/item_model.dart index 9925e29..2ea572c 100644 --- a/lib/models/services/item_model.dart +++ b/lib/models/services/item_model.dart @@ -22,18 +22,18 @@ class ItemModel { }); factory ItemModel.fromJson(Map json) => ItemModel( - messageStatus: json["messageStatus"], - totalItemsCount: json["totalItemsCount"], - data: json["data"] == null ? [] : List.from(json["data"]!.map((x) => ItemData.fromJson(x))), - message: json["message"], - ); + messageStatus: json["messageStatus"], + totalItemsCount: json["totalItemsCount"], + data: json["data"] == null ? [] : List.from(json["data"]!.map((x) => ItemData.fromJson(x))), + message: json["message"], + ); Map toJson() => { - "messageStatus": messageStatus, - "totalItemsCount": totalItemsCount, - "data": data == null ? [] : List.from(data!.map((x) => x.toJson())), - "message": message, - }; + "messageStatus": messageStatus, + "totalItemsCount": totalItemsCount, + "data": data == null ? [] : List.from(data!.map((x) => x.toJson())), + "message": message, + }; } class ItemData { @@ -49,6 +49,7 @@ class ItemData { final bool? isAllowAppointment; final bool? isAppointmentCompanyLoc; final bool? isAppointmentCustomerLoc; + final double? appointmentPricePercentage; bool? isUpdateOrSelected; ItemData({ @@ -64,37 +65,38 @@ class ItemData { this.isAllowAppointment, this.isAppointmentCompanyLoc, this.isAppointmentCustomerLoc, + this.appointmentPricePercentage, this.isUpdateOrSelected, }); factory ItemData.fromJson(Map json) => ItemData( - id: json["id"], - name: json["name"], - price: json["price"].toString(), - manufactureDate: json["manufactureDate"], - description: json["description"], - pictureUrl: json["pictureUrl"], - companyId: json["companyID"], - serviceProviderServiceId: json["serviceProviderServiceID"], - isActive: json["isActive"], - isAllowAppointment: json["isAllowAppointment"], - isAppointmentCompanyLoc: json["isAppointmentCompanyLoc"], - isAppointmentCustomerLoc: json["isAppointmentCustomerLoc"], + id: json["id"], + name: json["name"], + price: json["price"].toString(), + manufactureDate: json["manufactureDate"], + description: json["description"], + pictureUrl: json["pictureUrl"], + companyId: json["companyID"], + serviceProviderServiceId: json["serviceProviderServiceID"], + isActive: json["isActive"], + isAllowAppointment: json["isAllowAppointment"], + isAppointmentCompanyLoc: json["isAppointmentCompanyLoc"], + isAppointmentCustomerLoc: json["isAppointmentCustomerLoc"], isUpdateOrSelected: false, - ); + ); Map toJson() => { - "id": id, - "name": name, - "price": price, - "manufactureDate": manufactureDate, - "description": description, - "pictureUrl": pictureUrl, - "companyID": companyId, - "serviceProviderServiceID": serviceProviderServiceId, - "isActive": isActive, - "isAllowAppointment": isAllowAppointment, - "isAppointmentCompanyLoc": isAppointmentCompanyLoc, - "isAppointmentCustomerLoc": isAppointmentCustomerLoc, - }; -} + "id": id, + "name": name, + "price": price, + "manufactureDate": manufactureDate, + "description": description, + "pictureUrl": pictureUrl, + "companyID": companyId, + "serviceProviderServiceID": serviceProviderServiceId, + "isActive": isActive, + "isAllowAppointment": isAllowAppointment, + "isAppointmentCompanyLoc": isAppointmentCompanyLoc, + "isAppointmentCustomerLoc": isAppointmentCustomerLoc, + }; +} \ No newline at end of file diff --git a/lib/models/services/near_branch_model.dart b/lib/models/services/near_branch_model.dart deleted file mode 100644 index 93d9cd6..0000000 --- a/lib/models/services/near_branch_model.dart +++ /dev/null @@ -1,39 +0,0 @@ -// To parse this JSON data, do -// -// final nearBrancheModel = nearBrancheModelFromJson(jsonString); - -import 'dart:convert'; - -import 'branch_model.dart'; - -NearBrancheModel nearBrancheModelFromJson(String str) => NearBrancheModel.fromJson(json.decode(str)); - -String nearBrancheModelToJson(NearBrancheModel data) => json.encode(data.toJson()); - -class NearBrancheModel { - final int? messageStatus; - final int? totalItemsCount; - final List? data; - final String? message; - - NearBrancheModel({ - this.messageStatus, - this.totalItemsCount, - this.data, - this.message, - }); - - factory NearBrancheModel.fromJson(Map json) => NearBrancheModel( - messageStatus: json["messageStatus"], - totalItemsCount: json["totalItemsCount"], - data: json["data"] == null ? [] : List.from(json["data"]!.map((x) => BranchModel.fromJson(x))), - message: json["message"], - ); - - Map toJson() => { - "messageStatus": messageStatus, - "totalItemsCount": totalItemsCount, - "data": data == null ? [] : List.from(data!.map((x) => x.toJson())), - "message": message, - }; -} diff --git a/lib/models/services/service_model.dart b/lib/models/services/service_model.dart index 3d04657..5306dd5 100644 --- a/lib/models/services/service_model.dart +++ b/lib/models/services/service_model.dart @@ -1,3 +1,4 @@ + import 'package:mc_common_app/models/services/item_model.dart'; class ServiceModel { @@ -75,4 +76,9 @@ class ServiceModel { "itemsCount": itemsCount, "branchServiceItems": serviceItems == null ? [] : List.from(serviceItems!.map((x) => x.toJson())), }; + + @override + String toString() { + return 'ServiceModel{serviceProviderServiceId: $serviceProviderServiceId, providerServiceDescription: $providerServiceDescription, categoryId: $categoryId, categoryName: $categoryName, serviceId: $serviceId, serviceDescription: $serviceDescription, serviceDescriptionN: $serviceDescriptionN, serviceStatus: $serviceStatus, statusText: $statusText, isAllowAppointment: $isAllowAppointment, isAllowAppointmentHome: $isAllowAppointmentHome, customerLocationRange: $customerLocationRange, rangePricePerKm: $rangePricePerKm, itemsCount: $itemsCount, serviceItems: $serviceItems, isExpandedOrSelected: $isExpandedOrSelected}'; + } } diff --git a/lib/packages/cutom_country_code_picker.dart b/lib/packages/cutom_country_code_picker.dart new file mode 100644 index 0000000..3e1aa11 --- /dev/null +++ b/lib/packages/cutom_country_code_picker.dart @@ -0,0 +1,302 @@ +import 'package:collection/collection.dart' show IterableExtension; +import 'package:country_code_picker/country_code_picker.dart'; +import 'package:flutter/material.dart'; + +class CustomCountryCodePicker extends StatefulWidget { + final bool isTextNeeded; + final ValueChanged? onChanged; + final ValueChanged? onInit; + final String? initialSelection; + final List favorite; + final TextStyle? textStyle; + final EdgeInsetsGeometry padding; + final bool showCountryOnly; + final InputDecoration searchDecoration; + final TextStyle? searchStyle; + final TextStyle? dialogTextStyle; + final WidgetBuilder? emptySearchBuilder; + final Function(CountryCode?)? builder; + final bool enabled; + final TextOverflow textOverflow; + final Icon closeIcon; + + /// Barrier color of ModalBottomSheet + final Color? barrierColor; + + /// Background color of ModalBottomSheet + final Color? backgroundColor; + + /// BoxDecoration for dialog + final BoxDecoration? boxDecoration; + + /// the size of the selection dialog + final Size? dialogSize; + + /// Background color of selection dialog + final Color? dialogBackgroundColor; + + /// used to customize the country list + final List? countryFilter; + + /// shows the name of the country instead of the dialcode + final bool showOnlyCountryWhenClosed; + + /// aligns the flag and the Text left + /// + /// additionally this option also fills the available space of the widget. + /// this is especially useful in combination with [showOnlyCountryWhenClosed], + /// because longer country names are displayed in one line + final bool alignLeft; + + /// shows the flag + final bool showFlag; + + final bool hideMainText; + + final bool? showFlagMain; + + final bool? showFlagDialog; + + /// Width of the flag images + final double flagWidth; + + /// Use this property to change the order of the options + final Comparator? comparator; + + /// Set to true if you want to hide the search part + final bool hideSearch; + + /// Set to true if you want to show drop down button + final bool showDropDownButton; + + /// [BoxDecoration] for the flag image + final Decoration? flagDecoration; + + /// An optional argument for injecting a list of countries + /// with customized codes. + final List> countryList; + + const CustomCountryCodePicker({ + this.isTextNeeded = true, + this.onChanged, + this.onInit, + this.initialSelection, + this.favorite = const [], + this.textStyle, + this.padding = const EdgeInsets.all(8.0), + this.showCountryOnly = false, + this.searchDecoration = const InputDecoration(), + this.searchStyle, + this.dialogTextStyle, + this.emptySearchBuilder, + this.showOnlyCountryWhenClosed = false, + this.alignLeft = false, + this.showFlag = true, + this.showFlagDialog, + this.hideMainText = false, + this.showFlagMain, + this.flagDecoration, + this.builder, + this.flagWidth = 32.0, + this.enabled = true, + this.textOverflow = TextOverflow.ellipsis, + this.barrierColor, + this.backgroundColor, + this.boxDecoration, + this.comparator, + this.countryFilter, + this.hideSearch = false, + this.showDropDownButton = false, + this.dialogSize, + this.dialogBackgroundColor, + this.closeIcon = const Icon(Icons.close), + this.countryList = codes, + Key? key, + }) : super(key: key); + + @override + // ignore: no_logic_in_create_state + State createState() { + List> jsonList = countryList; + + List elements = jsonList.map((json) => CountryCode.fromJson(json)).toList(); + + if (comparator != null) { + elements.sort(comparator); + } + + if (countryFilter != null && countryFilter!.isNotEmpty) { + final uppercaseCustomList = countryFilter!.map((criteria) => criteria.toUpperCase()).toList(); + elements = elements.where((criteria) => uppercaseCustomList.contains(criteria.code) || uppercaseCustomList.contains(criteria.name) || uppercaseCustomList.contains(criteria.dialCode)).toList(); + } + + return CustomCountryCodePickerState(elements); + } +} + +class CustomCountryCodePickerState extends State { + CountryCode? selectedItem; + List elements = []; + List favoriteElements = []; + + CustomCountryCodePickerState(this.elements); + + @override + Widget build(BuildContext context) { + Widget internalWidget; + if (widget.builder != null) { + internalWidget = InkWell( + onTap: showCountryCodePickerDialog, + child: widget.builder!(selectedItem), + ); + } else { + internalWidget = TextButton( + onPressed: widget.enabled ? showCountryCodePickerDialog : null, + child: Padding( + padding: widget.padding, + child: Flex( + direction: Axis.horizontal, + mainAxisSize: MainAxisSize.min, + children: [ + if (widget.showFlagMain != null ? widget.showFlagMain! : widget.showFlag) + Flexible( + flex: widget.alignLeft ? 0 : 1, + fit: widget.alignLeft ? FlexFit.tight : FlexFit.loose, + child: Container( + clipBehavior: widget.flagDecoration == null ? Clip.none : Clip.hardEdge, + decoration: widget.flagDecoration, + margin: widget.alignLeft ? const EdgeInsets.only(right: 16.0, left: 8.0) : const EdgeInsets.only(right: 16.0), + child: Image.asset( + selectedItem!.flagUri!, + package: 'country_code_picker', + width: widget.flagWidth, + ), + ), + ), + if (!widget.hideMainText) + Flexible( + fit: widget.alignLeft ? FlexFit.tight : FlexFit.loose, + child: Text( + widget.showOnlyCountryWhenClosed ? selectedItem!.toCountryStringOnly() : selectedItem.toString(), + style: widget.textStyle ?? Theme.of(context).textTheme.labelLarge, + overflow: widget.textOverflow, + ), + ), + if (widget.showDropDownButton) + Flexible( + flex: widget.alignLeft ? 0 : 1, + fit: widget.alignLeft ? FlexFit.tight : FlexFit.loose, + child: Padding( + padding: widget.alignLeft ? const EdgeInsets.only(right: 16.0, left: 8.0) : const EdgeInsets.only(right: 16.0), + child: Icon( + Icons.arrow_drop_down, + color: Colors.grey, + size: widget.flagWidth, + )), + ), + ], + ), + ), + ); + } + return internalWidget; + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + + elements = elements.map((element) => element.localize(context)).toList(); + _onInit(selectedItem); + } + + @override + void didUpdateWidget(CustomCountryCodePicker oldWidget) { + super.didUpdateWidget(oldWidget); + + if (oldWidget.initialSelection != widget.initialSelection) { + if (widget.initialSelection != null) { + selectedItem = elements.firstWhere( + (criteria) => + (criteria.code!.toUpperCase() == widget.initialSelection!.toUpperCase()) || + (criteria.dialCode == widget.initialSelection) || + (criteria.name!.toUpperCase() == widget.initialSelection!.toUpperCase()), + orElse: () => elements[0]); + } else { + selectedItem = elements[0]; + } + _onInit(selectedItem); + } + } + + @override + void initState() { + super.initState(); + + if (widget.initialSelection != null) { + selectedItem = elements.firstWhere( + (item) => + (item.code!.toUpperCase() == widget.initialSelection!.toUpperCase()) || + (item.dialCode == widget.initialSelection) || + (item.name!.toUpperCase() == widget.initialSelection!.toUpperCase()), + orElse: () => elements[0]); + } else { + selectedItem = elements[0]; + } + + favoriteElements = elements + .where((item) => + widget.favorite.firstWhereOrNull((criteria) => item.code!.toUpperCase() == criteria.toUpperCase() || item.dialCode == criteria || item.name!.toUpperCase() == criteria.toUpperCase()) != + null) + .toList(); + } + + void showCountryCodePickerDialog() async { + final item = await showDialog( + barrierColor: widget.barrierColor ?? Colors.grey.withOpacity(0.5), + context: context, + builder: (context) => Center( + child: Dialog( + child: SelectionDialog( + elements, + favoriteElements, + showCountryOnly: widget.showCountryOnly, + emptySearchBuilder: widget.emptySearchBuilder, + searchDecoration: widget.searchDecoration, + searchStyle: widget.searchStyle, + textStyle: widget.dialogTextStyle, + boxDecoration: widget.boxDecoration, + showFlag: widget.showFlagDialog ?? widget.showFlag, + flagWidth: widget.flagWidth, + size: widget.dialogSize, + backgroundColor: widget.dialogBackgroundColor, + barrierColor: widget.barrierColor, + hideSearch: widget.hideSearch, + closeIcon: widget.closeIcon, + flagDecoration: widget.flagDecoration, + ), + ), + ), + ); + + if (item != null) { + setState(() { + selectedItem = item; + }); + + _publishSelection(item); + } + } + + void _publishSelection(CountryCode countryCode) { + if (widget.onChanged != null) { + widget.onChanged!(countryCode); + } + } + + void _onInit(CountryCode? countryCode) { + if (widget.onInit != null) { + widget.onInit!(countryCode); + } + } +} diff --git a/lib/repositories/ads_repo.dart b/lib/repositories/ads_repo.dart index f4d1520..fb54c80 100644 --- a/lib/repositories/ads_repo.dart +++ b/lib/repositories/ads_repo.dart @@ -1,16 +1,23 @@ +import 'dart:developer'; + import 'package:mc_common_app/api/api_client.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/dependencies.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart'; +import 'package:mc_common_app/models/advertisment_models/reserved_ads_models.dart'; import 'package:mc_common_app/models/advertisment_models/special_service_model.dart'; import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart'; import 'package:mc_common_app/models/generic_resp_model.dart'; +import 'package:mc_common_app/utils/enums.dart'; abstract class AdsRepo { Future> getVehicleTypes(); + Future> getVehicleBrands({required int vehicleTypeId}); + Future> getVehicleModels({required int vehicleTypeId}); Future> getVehicleModelYears({required int vehicleTypeId}); @@ -33,7 +40,7 @@ abstract class AdsRepo { Future> getVehicleDamageParts(); - Future getVehicleDetails({required int vehicleTypeId}); + Future getVehicleDetails({required int vehicleTypeId, required int vehicleBrandId}); Future> getAdsDuration(); @@ -43,6 +50,8 @@ abstract class AdsRepo { Future> getAllAds({required bool isMyAds}); + Future> getMyReservedAds(); + Future> getMyAds(); } @@ -145,6 +154,17 @@ class AdsRepoImp implements AdsRepo { return vehicleModels; } + @override + Future> getVehicleBrands({required int vehicleTypeId}) async { + var postParams = { + "VehicleType": vehicleTypeId.toString(), + }; + GenericRespModel adsGenericModel = + await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleBrandGet, queryParameters: postParams); + List vehicleBrands = List.generate(adsGenericModel.data.length, (index) => VehicleBrandsModel.fromJson(adsGenericModel.data[index])); + return vehicleBrands; + } + @override Future> getVehicleSellerTypes({required int vehicleTypeId}) async { var postParams = { @@ -168,11 +188,11 @@ class AdsRepoImp implements AdsRepo { } @override - Future getVehicleDetails({required int vehicleTypeId}) async { + Future getVehicleDetails({required int vehicleTypeId, required int vehicleBrandId}) async { var postParams = { "vehicleType": vehicleTypeId.toString(), "isVehicleBrand": "true", - "vehicleBrand": "0", + "vehicleBrand": vehicleBrandId.toString(), "isVehicleCategory": "true", "isVehicleColor": "true", "isVehicleCondition": "true", @@ -306,17 +326,37 @@ class AdsRepoImp implements AdsRepo { @override Future> getAllAds({required isMyAds}) async { - var params = { + var onlyMyAdsParams = { "userID": appState.getUser.data!.userInfo!.userId ?? "", }; + var allAdsParams = { + "AdsStatuses": ["${AdPostStatus.active.getIdFromAdPostStatusEnum()}"], //only Active ADS + "IsPaid": "true", //only Active ADS + }; GenericRespModel adsGenericModel = await apiClient.getJsonForObject( token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsGet, - queryParameters: isMyAds ? params : null, + queryParameters: isMyAds ? onlyMyAdsParams : allAdsParams, + ); + List vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], isMyAds)); + return vehicleAdsDetails; + } + + @override + Future> getMyReservedAds() async { + var params = { + "userID": appState.getUser.data!.userInfo!.userId ?? "", + }; + + GenericRespModel adsGenericModel = await apiClient.getJsonForObject( + token: appState.getUser.data!.accessToken, + (json) => GenericRespModel.fromJson(json), + ApiConsts.myAdsReserveGet, + queryParameters: params, ); - List vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index])); + List vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => MyReservedAdsRespModel.fromJson(adsGenericModel.data[index])); return vehicleAdsDetails; } @@ -331,7 +371,7 @@ class AdsRepoImp implements AdsRepo { queryParameters: params, ApiConsts.vehicleAdsGet, ); - List vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index])); + List vehicleAdsDetails = List.generate(adsGenericModel.data.length, (index) => AdDetailsModel.fromJson(adsGenericModel.data[index], true)); return vehicleAdsDetails; } } diff --git a/lib/repositories/common_repo.dart b/lib/repositories/common_repo.dart index 7101638..13caa08 100644 --- a/lib/repositories/common_repo.dart +++ b/lib/repositories/common_repo.dart @@ -2,16 +2,10 @@ import 'package:mc_common_app/api/api_client.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/dependencies.dart'; -import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; -import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart'; -import 'package:mc_common_app/models/advertisment_models/special_service_model.dart'; import 'package:mc_common_app/models/advertisment_models/ss_car_check_schedule_model.dart'; import 'package:mc_common_app/models/advertisment_models/ss_photo_schedule_model.dart'; -import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; import 'package:mc_common_app/models/generic_resp_model.dart'; -import 'package:mc_common_app/models/provider_category_model.dart'; -import 'package:mc_common_app/models/provider_service_model.dart'; import 'package:mc_common_app/models/user/cities.dart'; import 'package:mc_common_app/models/user/country.dart'; import 'package:mc_common_app/models/user/role.dart'; @@ -23,16 +17,15 @@ abstract class CommonRepo { Future getRoles(); - Future> getMyAppointments(); Future getCarCheckServiceScheduleDetails({required double lat, required double long}); Future getPhotographyServiceScheduleDetails({required double lat, required double long}); - Future> getProviderServiceCategories(); + // Future> getProviderServiceCategories(); - Future> getProviderServices({required int categoryId}); +// Future> getProviderServices({required int categoryId}); } class CommonRepoImp implements CommonRepo { @@ -57,7 +50,6 @@ class CommonRepoImp implements CommonRepo { return await apiClient.getJsonForObject((json) => Role.fromJson(json), ApiConsts.GetProviderRoles); } - @override Future> getMyAppointments() async { var params = { @@ -104,22 +96,22 @@ class CommonRepoImp implements CommonRepo { SSPhotoScheduleModel ssPhotoScheduleModel = SSPhotoScheduleModel.fromJson(genericRespModel.data[0]); return ssPhotoScheduleModel; } - - @override - Future> getProviderServiceCategories() async { - GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.serviceCategoryGet); - List providerCategories = List.generate(adsGenericModel.data.length, (index) => ProviderCategoryModel.fromJson(adsGenericModel.data[index])); - return providerCategories; - } - - @override - Future> getProviderServices({required int categoryId}) async { - var postParams = { - "ServiceCategoryID": categoryId.toString(), - }; - GenericRespModel adsGenericModel = - await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.serviceCategoryGet, queryParameters: postParams); - List providerServices = List.generate(adsGenericModel.data.length, (index) => ProviderServiceModel.fromJson(adsGenericModel.data[index])); - return providerServices; - } + // +// @override +// Future> getProviderServiceCategories() async { +// GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.serviceCategoryGet); +// List providerCategories = List.generate(adsGenericModel.data.length, (index) => ProviderCategoryModel.fromJson(adsGenericModel.data[index])); +// return providerCategories; +// } + +// @override +// Future> getProviderServices({required int categoryId}) async { +// var postParams = { +// "ServiceCategoryID": categoryId.toString(), +// }; +// GenericRespModel adsGenericModel = +// await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.serviceCategoryGet, queryParameters: postParams); +// List providerServices = List.generate(adsGenericModel.data.length, (index) => ProviderServiceModel.fromJson(adsGenericModel.data[index])); +// return providerServices; +// } } diff --git a/lib/services/payments_service.dart b/lib/services/payments_service.dart index 7ff2949..74d19dc 100644 --- a/lib/services/payments_service.dart +++ b/lib/services/payments_service.dart @@ -50,10 +50,11 @@ class PaymentServiceImp implements PaymentService { required Function() onSuccess, required Function() onFailure, }) async { + print("PaymentUrl: ${ApiConsts.paymentWebViewUrl}?PaymentType=$paymentType&AdsID=$id"); myInAppBrowser = MyInAppBrowser(onExitCallback: () { log("Browser Exited"); }, onLoadStartCallback: (String url) { - log("Browser LoadStart"); + log("Browser LoadStart for : $url"); onBrowserLoadStart(onFailure: onFailure, onSuccess: onSuccess, url: url); }); await myInAppBrowser!.openUrlRequest( diff --git a/lib/utils/enums.dart b/lib/utils/enums.dart index dc9e841..d005c0f 100644 --- a/lib/utils/enums.dart +++ b/lib/utils/enums.dart @@ -5,6 +5,22 @@ // unverified, // } +enum VehicleTypeEnum { + car, + motorCycle, + golfCart, + buggy, +} + +enum AdReserveStatus { + defaultStatus, + reserved, + cancelledByOwner, + cancelledByAdmin, +} + +enum CreatedByRoleEnum { customer, provider, admin, allAds } + enum AdPostStatus { pendingForReview, pendingForPayment, diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index b7dbc27..3ba8337 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -23,13 +23,7 @@ class Utils { static void showToast(String message) { Fluttertoast.showToast( - msg: message, - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - timeInSecForIosWeb: 2, - backgroundColor: Colors.black54, - textColor: Colors.white, - fontSize: 16.0); + msg: message, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 2, backgroundColor: Colors.black54, textColor: Colors.white, fontSize: 16.0); } static Future pickDateFromDatePicker(BuildContext context, {DateTime? firstDate, DateTime? lastDate}) async { @@ -54,11 +48,7 @@ class Utils { return ""; } - return ("${timeOfDay.hour - .toString() - .length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute - .toString() - .length == 1 ? "0" : ""}${timeOfDay.minute}").toString(); + return ("${timeOfDay.hour.toString().length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute.toString().length == 1 ? "0" : ""}${timeOfDay.minute}").toString(); } static dynamic getNotNullValue(List list, int index) { @@ -214,7 +204,6 @@ class Utils { } } - static statusContainerChip({required String text, EdgeInsetsGeometry padding = const EdgeInsets.symmetric(vertical: 3, horizontal: 6), Color chipColor = MyColors.greenColor}) { return Container( decoration: BoxDecoration( @@ -358,7 +347,7 @@ class Utils { border: Border.all( width: w, // color: color // <--- border width here - ), + ), borderRadius: BorderRadius.circular(radius), ); } @@ -381,7 +370,7 @@ class Utils { border: Border.all( width: 1, // color: color // <--- border width here - ), + ), borderRadius: BorderRadius.circular(radius), ); } diff --git a/lib/view_models/ad_view_model.dart b/lib/view_models/ad_view_model.dart index ac49f95..31076db 100644 --- a/lib/view_models/ad_view_model.dart +++ b/lib/view_models/ad_view_model.dart @@ -9,6 +9,7 @@ import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart'; +import 'package:mc_common_app/models/advertisment_models/reserved_ads_models.dart'; import 'package:mc_common_app/models/advertisment_models/special_service_model.dart'; import 'package:mc_common_app/models/advertisment_models/ss_car_check_schedule_model.dart'; import 'package:mc_common_app/models/advertisment_models/ss_photo_schedule_model.dart'; @@ -37,6 +38,7 @@ class AdVM extends BaseVM { VehicleDetailsModel? vehicleDetails; List vehicleTypes = []; + List vehicleBrands = []; List vehicleModels = []; List vehicleModelYears = []; List vehicleColors = []; @@ -64,11 +66,13 @@ class AdVM extends BaseVM { String adStartDateError = ""; String damagePartSearchValue = ""; String adReservePriceError = ""; + String adPhoneNumberError = ""; List exploreAds = []; List exploreAdsFilteredList = []; List myAdsFilteredList = []; List myAds = []; + List myReservedAdsRespModel = []; List myActiveAdsForHome = []; List vehicleDamageCards = []; @@ -138,9 +142,10 @@ class AdVM extends BaseVM { isExploreAdsTapped = value; //To show the Active Ads - applyFilterOnMyAds(index: 0, selectedFilterId: 6); + applyFilterOnMyAds(index: 0, adPostStatusEnum: AdPostStatus.active); + applyFilterOnExploreAds(index: 0, createdByRoleFilter: CreatedByRoleEnum.allAds); // if (value) { - // await getAllAds(); + // await getExploreAds(); // } notifyListeners(); } @@ -149,13 +154,12 @@ class AdVM extends BaseVM { List myAdsFilterOptions = []; populateAdsFilterList() { - exploreAdsFilterOptions.clear(); exploreAdsFilterOptions.clear(); exploreAdsFilterOptions = [ FilterListModel(title: "All Ads", isSelected: true, id: -1), - FilterListModel(title: "Customer Ads", isSelected: false, id: 0), - FilterListModel(title: "Provider Ads", isSelected: false, id: 1), - FilterListModel(title: "Mowater Ads", isSelected: false, id: 2), + FilterListModel(title: "Mowater Ads", isSelected: false, id: 1), + FilterListModel(title: "Customer Ads", isSelected: false, id: 2), + FilterListModel(title: "Provider Ads", isSelected: false, id: 3), ]; myAdsFilterOptions = [ @@ -163,14 +167,14 @@ class AdVM extends BaseVM { FilterListModel(title: "Active", isSelected: false, id: 6), FilterListModel(title: "Pending For Review", isSelected: false, id: 1), FilterListModel(title: "Pending For Payment", isSelected: false, id: 2), + FilterListModel(title: "Reserved", isSelected: false, id: 9), FilterListModel(title: "Rejected", isSelected: false, id: 3), FilterListModel(title: "Pending For Post", isSelected: false, id: 5), - FilterListModel(title: "Reserved", isSelected: false, id: 9), ]; notifyListeners(); } - applyFilterOnExploreAds({required int index}) { + applyFilterOnExploreAds({required int index, required CreatedByRoleEnum createdByRoleFilter}) { if (exploreAdsFilterOptions.isEmpty) return; for (var value in exploreAdsFilterOptions) { value.isSelected = false; @@ -178,25 +182,39 @@ class AdVM extends BaseVM { exploreAdsFilterOptions[index].isSelected = true; // TODO: --> here we will filter the allAds list // TODO: --> and get the updated list into this new list everytime filter changes + if (createdByRoleFilter == CreatedByRoleEnum.allAds) { + exploreAdsFilteredList = exploreAds; + notifyListeners(); + return; + } + + exploreAdsFilteredList = exploreAds.where((element) => element.createdByRoleEnum == createdByRoleFilter).toList(); - exploreAdsFilteredList = exploreAds; notifyListeners(); } - applyFilterOnMyAds({required int index, required int selectedFilterId}) { + applyFilterOnMyAds({required int index, required AdPostStatus adPostStatusEnum}) { if (myAdsFilterOptions.isEmpty) return; for (var value in myAdsFilterOptions) { value.isSelected = false; } myAdsFilterOptions[index].isSelected = true; - if (selectedFilterId == -1) { + if (adPostStatusEnum.getIdFromAdPostStatusEnum() == -1) { myAdsFilteredList = myAds; notifyListeners(); return; } + // this means if the filter is reserved ads + dynamic selectedIds = []; + if (index == 3 && adPostStatusEnum.getIdFromAdPostStatusEnum() == 9) { + selectedIds = myReservedAdsRespModel.map((component) => component.adsID).toList(); + myAdsFilteredList = myAds.where((element) => selectedIds.contains(element.id)).toList(); + notifyListeners(); + return; + } - myAdsFilteredList = myAds.where((element) => element.statusID! == selectedFilterId).toList(); + myAdsFilteredList = myAds.where((element) => element.statusID! == adPostStatusEnum.getIdFromAdPostStatusEnum()).toList(); notifyListeners(); } @@ -206,15 +224,23 @@ class AdVM extends BaseVM { myAds = await adsRepo.getAllAds(isMyAds: true); final myActiveAds = myAds.where((element) => element.adPostStatus == AdPostStatus.active).toList(); myActiveAdsForHome = myActiveAds.length >= 3 ? myActiveAds.take(3).toList() : myActiveAds; + await getMyReservedAds(); + isFetchingLists = true; + setState(ViewState.idle); + } + Future getMyReservedAds() async { isFetchingLists = true; + setState(ViewState.busy); + myReservedAdsRespModel = await adsRepo.getMyReservedAds(); + isFetchingLists = false; setState(ViewState.idle); } Future getExploreAds() async { setState(ViewState.busy); exploreAds = await adsRepo.getAllAds(isMyAds: false); - myAdsFilteredList = exploreAds; + exploreAdsFilteredList = exploreAds; setState(ViewState.idle); } @@ -236,31 +262,39 @@ class AdVM extends BaseVM { bool isFetchingLists = false; bool isCountryFetching = false; - Future getAllDataBasedOnVehicleTypeId() async { + // Future getAllDataBasedOnVehicleTypeId() async { + // if (vehicleTypeId.selectedId == -1) { + // return; + // } + // isFetchingLists = true; + // notifyListeners(); + // vehicleModels = await adsRepo.getVehicleModels(vehicleTypeId: vehicleTypeId.selectedId); + // vehicleModelYears = await adsRepo.getVehicleModelYears(vehicleTypeId: vehicleTypeId.selectedId); + // vehicleColors = await adsRepo.getVehicleColors(vehicleTypeId: vehicleTypeId.selectedId); + // vehicleConditions = await adsRepo.getVehicleConditions(vehicleTypeId: vehicleTypeId.selectedId); + // vehicleCategories = await adsRepo.getVehicleCategories(vehicleTypeId: vehicleTypeId.selectedId); + // vehicleMileages = await adsRepo.getVehicleMileages(vehicleTypeId: vehicleTypeId.selectedId); + // vehicleTransmissions = await adsRepo.getVehicleTransmission(vehicleTypeId: vehicleTypeId.selectedId); + // vehicleCountries = await adsRepo.getVehicleCountries(); + // isFetchingLists = false; + // notifyListeners(); + // } + + getVehicleBrandsByVehicleTypeId() async { if (vehicleTypeId.selectedId == -1) { return; } - isFetchingLists = true; - notifyListeners(); - vehicleModels = await adsRepo.getVehicleModels(vehicleTypeId: vehicleTypeId.selectedId); - vehicleModelYears = await adsRepo.getVehicleModelYears(vehicleTypeId: vehicleTypeId.selectedId); - vehicleColors = await adsRepo.getVehicleColors(vehicleTypeId: vehicleTypeId.selectedId); - vehicleConditions = await adsRepo.getVehicleConditions(vehicleTypeId: vehicleTypeId.selectedId); - vehicleCategories = await adsRepo.getVehicleCategories(vehicleTypeId: vehicleTypeId.selectedId); - vehicleMileages = await adsRepo.getVehicleMileages(vehicleTypeId: vehicleTypeId.selectedId); - vehicleTransmissions = await adsRepo.getVehicleTransmission(vehicleTypeId: vehicleTypeId.selectedId); - vehicleCountries = await adsRepo.getVehicleCountries(); - isFetchingLists = false; + vehicleBrands = await adsRepo.getVehicleBrands(vehicleTypeId: vehicleTypeId.selectedId); notifyListeners(); } - Future getVehicleDetailsByVehicleId() async { - if (vehicleTypeId.selectedId == -1) { + Future getVehicleDetailsByVehicleBrandId() async { + if (vehicleBrandId.selectedId == -1 || vehicleTypeId.selectedId == -1) { return; } isFetchingLists = true; notifyListeners(); - vehicleDetails = await adsRepo.getVehicleDetails(vehicleTypeId: vehicleTypeId.selectedId); + vehicleDetails = await adsRepo.getVehicleDetails(vehicleTypeId: vehicleTypeId.selectedId, vehicleBrandId: vehicleBrandId.selectedId); if (vehicleDetails != null) { vehicleModels = vehicleDetails!.vehicleModels!; @@ -285,6 +319,21 @@ class AdVM extends BaseVM { notifyListeners(); } + String adPhoneNumber = ""; + + void updateAdPhoneNumber(String date) { + adPhoneNumber = date; + if (adPhoneNumber.isNotEmpty) adPhoneNumberError = ""; + notifyListeners(); + } + + String adPhoneNumberDialCode = "+966"; + + void updateAdPhoneNumberDialCode(String date) { + adPhoneNumberDialCode = date; + notifyListeners(); + } + String adReserveAmount = ""; void updateAdReservePriceAmount(String date) { @@ -307,7 +356,16 @@ class AdVM extends BaseVM { void updateSelectionVehicleTypeId(SelectionModel id) async { vehicleTypeId = id; - getVehicleDetailsByVehicleId(); + getVehicleBrandsByVehicleTypeId(); + notifyListeners(); + } + + SelectionModel vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + + void updateSelectionVehicleBrandId(SelectionModel id) { + vehicleBrandId = id; + getVehicleDetailsByVehicleBrandId(); + notifyListeners(); } @@ -444,18 +502,17 @@ class AdVM extends BaseVM { void updateVehicleAdsSpecialServicesId(SelectionModel id) async { vehicleAdsSpecialServicesId = id; - isFetchingLists = true; - adSSTimeSlots.clear(); - vehicleAdsPhotoServiceDate = SelectionModel(selectedId: -1, selectedOption: ""); - vehicleAdsCarCheckServicesDate = SelectionModel(selectedId: -1, selectedOption: ""); - notifyListeners(); - - if (id.selectedId == 1) { - ssPhotoScheduleModel = await commonRepo.getPhotographyServiceScheduleDetails(lat: 0.0, long: 0.0); - } else if (id.selectedId == 3) { - ssCarCheckScheduleModel = await commonRepo.getCarCheckServiceScheduleDetails(lat: 0.0, long: 0.0); - } else {} - isFetchingLists = false; + // isFetchingLists = true; + // adSSTimeSlots.clear(); + // vehicleAdsPhotoServiceDate = SelectionModel(selectedId: -1, selectedOption: ""); + // vehicleAdsCarCheckServicesDate = SelectionModel(selectedId: -1, selectedOption: ""); + // notifyListeners(); + // if (id.selectedId == 1) { + // ssPhotoScheduleModel = await commonRepo.getPhotographyServiceScheduleDetails(lat: 0.0, long: 0.0); + // } else if (id.selectedId == 3) { + // ssCarCheckScheduleModel = await commonRepo.getCarCheckServiceScheduleDetails(lat: 0.0, long: 0.0); + // } else {} + // isFetchingLists = false; notifyListeners(); } @@ -728,19 +785,26 @@ class AdVM extends BaseVM { adStartDateError = ""; } - if (vehicleAdReservableId.selectedId == -1) { - vehicleAdReservableId.errorValue = "Please select if the Ad is Reservable or not."; + if (isPhoneNumberShown && adPhoneNumber.isEmpty) { + adPhoneNumberError = GlobalConsts.adDurationPhoneNumberError; isValidated = false; } else { - vehicleAdReservableId.errorValue = ""; - } - - if (adReserveAmount.isEmpty) { - adReservePriceError = GlobalConsts.adReservablePriceErrorConst; - isValidated = false; - } else { - adStartDateError = ""; + adPhoneNumberError = ""; } + // + // if (vehicleAdReservableId.selectedId == -1) { + // vehicleAdReservableId.errorValue = "Please select if the Ad is Reservable or not."; + // isValidated = false; + // } else { + // vehicleAdReservableId.errorValue = ""; + // } + // + // if (adReserveAmount.isEmpty) { + // adReservePriceError = GlobalConsts.adReservablePriceErrorConst; + // isValidated = false; + // } else { + // adStartDateError = ""; + // } notifyListeners(); return isValidated; @@ -804,6 +868,7 @@ class AdVM extends BaseVM { currentProgressStep = AdCreationStepsEnum.vehicleDetails; resetValues(); updateIsExploreAds(false); + applyFilterOnMyAds(index: 1, adPostStatusEnum: AdPostStatus.pendingForReview); //pending for review navigateReplaceWithName(context, AppRoutes.dashboard); } catch (e) { Utils.hideLoading(context); @@ -821,6 +886,20 @@ class AdVM extends BaseVM { notifyListeners(); } + bool isPhoneNumberShown = false; + + void updateIsPhoneNumberShownStatus(bool status) { + isPhoneNumberShown = status; + notifyListeners(); + } + + bool isNumberOnWhatsApp = false; + + void updateIsNumberOnWhatsAppStatus(bool status) { + isNumberOnWhatsApp = status; + notifyListeners(); + } + List pickedVehicleImages = []; void removeImageFromList(String filePath) { @@ -905,7 +984,8 @@ class AdVM extends BaseVM { specialServiceCards.clear(); currentProgressStep = AdCreationStepsEnum.vehicleDetails; vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); - vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); + vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleColorId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleConditionId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); @@ -988,6 +1068,8 @@ class AdVM extends BaseVM { demandAmount: int.parse(vehicleDemandAmount), vehiclePostingImages: vehicleImages, vehiclePostingDamageParts: vehicleDamageImages, + phoneNo: isPhoneNumberShown ? adPhoneNumberDialCode + adPhoneNumber : null, + whatsAppNo: (isPhoneNumberShown && isNumberOnWhatsApp) ? adPhoneNumberDialCode + adPhoneNumber : null, ); AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting); diff --git a/lib/view_models/payment_view_model.dart b/lib/view_models/payment_view_model.dart index f41f9b8..2fc559d 100644 --- a/lib/view_models/payment_view_model.dart +++ b/lib/view_models/payment_view_model.dart @@ -27,13 +27,13 @@ class PaymentVM extends ChangeNotifier { notifyListeners(); } - Future onContinuePressed(BuildContext context) async { + Future onContinuePressed(BuildContext context, {required PaymentTypesEnum paymentType}) async { switch (selectedPaymentMethod) { case PaymentMethodsEnum.mada: // TODO: Handle this case. break; case PaymentMethodsEnum.visa: - await onVisaCardSelected(context); + await onVisaCardSelected(context, paymentType); break; case PaymentMethodsEnum.applePay: // TODO: Handle this case. @@ -49,7 +49,8 @@ class PaymentVM extends ChangeNotifier { return; } - Future onVisaCardSelected(BuildContext context) async { + Future onVisaCardSelected(BuildContext context, PaymentTypesEnum paymentType) async { + currentPaymentType = paymentType; switch (currentPaymentType) { case PaymentTypesEnum.subscription: // TODO: Handle this case. @@ -68,10 +69,12 @@ class PaymentVM extends ChangeNotifier { }, onSuccess: () async { Utils.showLoading(context); - PayOrderDetailRespModel payOrderDetailRespModel = await paymentRepo.getPayOrderDetails(paymentId: paymentType, adId: 3); - await Future.delayed(Duration(seconds: 2)); + PayOrderDetailRespModel payOrderDetailRespModel = await paymentRepo.getPayOrderDetails(paymentId: paymentType, adId: currentAdId); + await Future.delayed(const Duration(seconds: 2)); Utils.hideLoading(context); + print("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}"); + if (payOrderDetailRespModel.isPaid == null || !payOrderDetailRespModel.isPaid!) { Utils.showToast("Payment Failed!"); return; @@ -85,7 +88,33 @@ class PaymentVM extends ChangeNotifier { ); break; case PaymentTypesEnum.adReserve: - // TODO: Handle this case. + if (currentAdId == -1) return; + int paymentType = 4; + await paymentService.placeAdPayment( + id: currentAdId, + paymentType: paymentType, + onFailure: () { + Utils.showToast("Payment Failed!"); + }, + onSuccess: () async { + Utils.showLoading(context); + PayOrderDetailRespModel payOrderDetailRespModel = await paymentRepo.getPayOrderDetails(paymentId: paymentType, adId: currentAdId); + await Future.delayed(const Duration(seconds: 2)); + Utils.hideLoading(context); + + print("payOrderDetailRespModel: ${payOrderDetailRespModel.toString()}"); + + if (payOrderDetailRespModel.isPaid == null || !payOrderDetailRespModel.isPaid!) { + Utils.showToast("Payment Failed!"); + return; + } + + if (payOrderDetailRespModel.isPaid != null && payOrderDetailRespModel.isPaid!) { + Utils.showToast("Payment Successfully Completed!"); + navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard); + } + }, + ); break; case PaymentTypesEnum.request: // TODO: Handle this case. 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 b8a733e..5d42ada 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_duration_container.dart @@ -1,3 +1,5 @@ +import 'package:country_code_picker/country_code_picker.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; @@ -33,7 +35,16 @@ class AdDuration extends StatelessWidget { isScrollControlled: true, enableDrag: true, builder: (BuildContext context) { - return InfoBottomSheet(title: "Reserve Ad Price Info", description: GlobalConsts.reserveAdPriceInfo); + return InfoBottomSheet( + title: "Reserve Ad Price Info", + description: Flexible( + child: GlobalConsts.reserveAdPriceInfo.toText( + textAlign: TextAlign.justify, + fontSize: 16, + color: MyColors.lightTextColor, + isBold: false, + )), + ); }); } @@ -49,20 +60,34 @@ class AdDuration extends StatelessWidget { children: [ "Ad Duration".toText(fontSize: 18, isBold: true), 8.height, - Builder(builder: (context) { - List vehicleAdsDurationsDrop = []; - for (var element in adVM.vehicleAdsDurations) { - vehicleAdsDurationsDrop.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateVehicleAdDurationId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - errorValue: adVM.vehicleAdDurationId.errorValue, - list: vehicleAdsDurationsDrop, - hint: "Select Duration", - dropdownValue: adVM.vehicleAdDurationId.selectedId != -1 ? DropValue(adVM.vehicleAdDurationId.selectedId, adVM.vehicleAdDurationId.selectedOption, "") : null, - ); - }), + TxtField( + isBackgroundEnabled: true, + isButtonEnable: false, + isNeedBorder: false, + hint: 'Ad Duration', + value: adVM.vehicleAdDurationId.selectedOption, + isNeedClickAll: true, + postFixDataColor: MyColors.darkTextColor, + onTap: () async { + final formattedDate = await Utils.pickDateFromDatePicker(context); + adVM.updateSelectionDurationStartDate(formattedDate); + }, + ), + // Builder(builder: (context) { + // List vehicleAdsDurationsDrop = []; + // for (var element in adVM.vehicleAdsDurations) { + // vehicleAdsDurationsDrop.add(DropValue(element.id?.toInt() ?? 0, element.name ?? "", "")); + // } + // return DropdownField( + // (DropValue value) => adVM.updateVehicleAdDurationId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + // errorValue: adVM.vehicleAdDurationId.errorValue, + // list: vehicleAdsDurationsDrop, + // hint: "Select Duration", + // dropdownValue: adVM.vehicleAdDurationId.selectedId != -1 ? DropValue(adVM.vehicleAdDurationId.selectedId, adVM.vehicleAdDurationId.selectedOption, "") : null, + // ); + // }), 8.height, + TxtField( errorValue: adVM.adStartDateError, hint: 'Start Date', @@ -75,49 +100,135 @@ class AdDuration extends StatelessWidget { adVM.updateSelectionDurationStartDate(formattedDate); }, ), - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)), + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // "Reservable Ad".toText(fontSize: 18, isBold: true), + // 8.height, + // Builder(builder: (context) { + // List adReservableOptions = []; + // adReservableOptions.add(DropValue(1, "Yes", "")); + // adReservableOptions.add(DropValue(0, "No", "")); + // return DropdownField( + // (DropValue value) => adVM.updateVehicleAdReservableId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + // errorValue: adVM.vehicleAdReservableId.errorValue, + // list: adReservableOptions, + // hint: "Reservable", + // dropdownValue: adVM.vehicleAdReservableId.selectedId != -1 ? DropValue(adVM.vehicleAdReservableId.selectedId, adVM.vehicleAdReservableId.selectedOption, "") : null, + // ); + // }), + // if (adVM.vehicleAdReservableId.selectedId == 1) ...[ + // 8.height, + // TxtField( + // postfixData: Icons.info_outline_rounded, + // postFixDataColor: MyColors.grey77Color, + // onPostFixPressed: () => reservePriceInfoClicked(context), + // value: adVM.adReserveAmount, + // errorValue: adVM.adReservePriceError, + // keyboardType: TextInputType.number, + // hint: "Ad Reserve Price", + // onChanged: (v) => adVM.updateAdReservePriceAmount(v), + // ), + // ], + // ], + // ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Reservable Ad".toText(fontSize: 18, isBold: true), + "Contact Details".toText(fontSize: 18, isBold: true), 8.height, - Builder(builder: (context) { - List adReservableOptions = []; - adReservableOptions.add(DropValue(1, "Yes", "")); - adReservableOptions.add(DropValue(0, "No", "")); - return DropdownField( - (DropValue value) => adVM.updateVehicleAdReservableId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - errorValue: adVM.vehicleAdReservableId.errorValue, - list: adReservableOptions, - hint: "Reservable", - dropdownValue: adVM.vehicleAdReservableId.selectedId != -1 ? DropValue(adVM.vehicleAdReservableId.selectedId, adVM.vehicleAdReservableId.selectedOption, "") : null, - ); - }), - if (adVM.vehicleAdReservableId.selectedId == 1) ...[ - 8.height, + Row( + children: [ + "Do you want to show your number to the buyers?".toText(fontSize: 14), + ], + ), + 6.height, + Container( + width: 38, + height: 25, + decoration: BoxDecoration( + color: adVM.isPhoneNumberShown ? MyColors.darkPrimaryColor : MyColors.white, + borderRadius: BorderRadius.circular(25.0), + border: Border.all(color: MyColors.black, width: 1), + ), + child: Transform.scale( + scale: 0.6, + child: CupertinoSwitch( + activeColor: MyColors.darkPrimaryColor, + trackColor: MyColors.white, + thumbColor: MyColors.grey98Color, + value: adVM.isPhoneNumberShown, + onChanged: (value) { + adVM.updateIsPhoneNumberShownStatus(value); + }, + ), + ), + ), + if (adVM.isPhoneNumberShown) ...[ + 10.height, TxtField( - postfixData: Icons.info_outline_rounded, - postFixDataColor: MyColors.grey77Color, - onPostFixPressed: () { - reservePriceInfoClicked(context); - }, - value: adVM.adReserveAmount, - errorValue: adVM.adReservePriceError, - keyboardType: TextInputType.number, - hint: "Ad Reserve Price", - onChanged: (v) => adVM.updateAdReservePriceAmount(v), + preFixWidget: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [adVM.adPhoneNumberDialCode.toText(fontSize: 14)], + ).paddingOnly(left: 15, right: 15), + postfixWidget: SizedBox( + width: 110, + child: Row( + children: [ + CountryCodePicker( + onChanged: (CountryCode code) => adVM.updateAdPhoneNumberDialCode(code.dialCode ?? ""), + hideMainText: true, + initialSelection: '+966', + showOnlyCountryWhenClosed: false, + alignLeft: false, + ), + const Icon( + Icons.arrow_forward_ios_outlined, + size: 18, + color: MyColors.darkTextColor, + ).paddingOnly(right: 5) + ], + ), + ), + errorValue: adVM.adPhoneNumberError, + hint: '123456789', + value: adVM.adPhoneNumber, + onChanged: (v) => adVM.updateAdPhoneNumber(v), + ), + 10.height, + Row( + children: [ + SizedBox( + height: 40.0, + width: 30.0, + child: Transform.scale( + scale: 1.3, + child: Checkbox( + value: adVM.isNumberOnWhatsApp, + activeColor: !adVM.isNumberOnWhatsApp ? MyColors.lightTextColor : MyColors.darkPrimaryColor, + onChanged: (value) { + adVM.updateIsNumberOnWhatsAppStatus(value ?? false); + }, + ), + ), + ), + const SizedBox(width: 10), + "Is this number registered on WhatsApp?".toString().toText(fontSize: 14) + ], ), ], ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)), + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ "Select Special Services".toText(fontSize: 18, isBold: true), 8.height, CustomAddButton( + needsBorder: true, + bgColor: MyColors.white, onTap: () { onAddServiceButtonTapped(context, adVM); }, @@ -169,44 +280,46 @@ class AdDuration extends StatelessWidget { // (specialServicesCard.duration ?? "").toText(fontSize: 12, isBold: true).expand(), // ], // ), - 8.height, - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Description: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - (specialServicesCard.description ?? "").toText(fontSize: 12, isBold: true).expand(), - ], - ), - ], - if (specialServicesCard.serviceSelectedId!.selectedId == 1 || specialServicesCard.serviceSelectedId!.selectedId == 3) ...[ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon( - weight: 2, - Icons.location_on_outlined, - color: MyColors.primaryColor, - size: 17, - ), - "${specialServicesCard.duration} km".toText(fontSize: 10, color: MyColors.primaryColor), - ], - ), - 8.height, - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Branch Address: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - (specialServicesCard.address ?? "").toText(fontSize: 12, isBold: true).expand(), - ], - ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Appointment Time: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - "${specialServicesCard.serviceDate} - ${specialServicesCard.serviceTime}".toText(fontSize: 12, isBold: true).expand(), - ], - ), + if (specialServicesCard.description != null && specialServicesCard.description!.isNotEmpty) ...[ + 4.height, + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Description: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + (specialServicesCard.description ?? "").toText(fontSize: 12, isBold: true).expand(), + ], + ), + ], ], + // if ((specialServicesCard.serviceSelectedId!.selectedId == 1 || specialServicesCard.serviceSelectedId!.selectedId == 3)) ...[ + // Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // const Icon( + // weight: 2, + // Icons.location_on_outlined, + // color: MyColors.primaryColor, + // size: 17, + // ), + // "${specialServicesCard.duration} km".toText(fontSize: 10, color: MyColors.primaryColor), + // ], + // ), + // 8.height, + // Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // "Branch Address: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + // (specialServicesCard.address ?? "").toText(fontSize: 12, isBold: true).expand(), + // ], + // ), + // Row( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // "Appointment Time: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + // "${specialServicesCard.serviceDate} - ${specialServicesCard.serviceTime}".toText(fontSize: 12, isBold: true).expand(), + // ], + // ), + // ], 6.height, Row( crossAxisAlignment: CrossAxisAlignment.end, @@ -229,7 +342,7 @@ class AdDuration extends StatelessWidget { }, ), ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)), + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), ], ); }, diff --git a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart index 4de0e27..193ab0c 100644 --- a/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart +++ b/lib/views/advertisement/ad_creation_steps/ad_review_containers.dart @@ -14,10 +14,11 @@ class ReviewAd extends StatelessWidget { Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - VehicleDetailsReview(), - DamagePartsReview(), - AdDurationReview(), + children: [ + VehicleDetailsReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), + DamagePartsReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), + AdDurationReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), + AdContactDetailsReview().toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)), ], ); } @@ -46,81 +47,79 @@ class VehicleDetailsReview extends StatelessWidget { @override Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, + AdVM adVM = context.read(); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Vehicle Details".toText(fontSize: 18, isBold: true), + 8.height, + Row( + mainAxisAlignment: MainAxisAlignment.start, children: [ - "Vehicle Details".toText(fontSize: 18, isBold: true), - 8.height, - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - flex: 7, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleDetailWidget(text: adVM.vehicleTypeId.selectedOption, type: "Vehicle Type"), - 16.height, - SingleDetailWidget(text: adVM.vehicleModelYearId.selectedOption, type: "Vehicle Year"), - 16.height, - SingleDetailWidget(text: adVM.vehicleConditionId.selectedOption, type: "Vehicle Condition"), - 16.height, - SingleDetailWidget(text: adVM.vehicleMileageId.selectedOption, type: "Vehicle Mileage"), - 16.height, - SingleDetailWidget(text: adVM.vehicleSellerTypeId.selectedOption, type: "Seller Type"), - 16.height, - SingleDetailWidget(text: adVM.vehicleCityId.selectedOption, type: "Vehicle City"), - 16.height, - SingleDetailWidget(text: adVM.vehicleVin, type: "Vehicle VIN"), - 16.height, - SingleDetailWidget(text: "${adVM.warrantyDuration} Years", type: "Warranty Available"), - 16.height, - ], - ), - ), - Expanded( - flex: 5, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleDetailWidget(text: adVM.vehicleModelId.selectedOption, type: "Vehicle Model"), - 16.height, - SingleDetailWidget(text: adVM.vehicleColorId.selectedOption, type: "Vehicle Color"), - 16.height, - SingleDetailWidget(text: adVM.vehicleCategoryId.selectedOption, type: "Vehicle Category"), - 16.height, - SingleDetailWidget(text: adVM.vehicleTransmissionId.selectedOption, type: "Vehicle Transmission"), - 16.height, - SingleDetailWidget(text: adVM.vehicleCountryId.selectedOption, type: "Vehicle Country"), - 16.height, - SingleDetailWidget(text: adVM.vehicleDemandAmount, type: "Vehicle Amount"), - 16.height, - SingleDetailWidget(text: adVM.vehicleTitle, type: "Vehicle Title"), - 16.height, - SingleDetailWidget(text: adVM.financeAvailableStatus ? "Yes" : "No", type: "Finance Available"), - 16.height, - ], - ), - ), - ], + Expanded( + flex: 7, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleDetailWidget(text: adVM.vehicleTypeId.selectedOption, type: "Vehicle Type"), + 16.height, + SingleDetailWidget(text: adVM.vehicleModelYearId.selectedOption, type: "Vehicle Year"), + 16.height, + SingleDetailWidget(text: adVM.vehicleConditionId.selectedOption, type: "Vehicle Condition"), + 16.height, + SingleDetailWidget(text: adVM.vehicleMileageId.selectedOption, type: "Vehicle Mileage"), + 16.height, + SingleDetailWidget(text: adVM.vehicleSellerTypeId.selectedOption, type: "Seller Type"), + 16.height, + SingleDetailWidget(text: adVM.vehicleCityId.selectedOption, type: "Vehicle City"), + 16.height, + SingleDetailWidget(text: adVM.vehicleVin, type: "Vehicle VIN"), + 16.height, + SingleDetailWidget(text: "${adVM.warrantyDuration} Years", type: "Warranty Available"), + 16.height, + ], + ), ), - SingleDetailWidget(text: adVM.vehicleDescription, type: "Description"), - 8.height, - "Vehicle Pictures:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - if (adVM.pickedVehicleImages.isNotEmpty) ...[ - // 10.height, - PickedImagesContainer( - pickedImages: adVM.pickedVehicleImages, - onCrossPressedPrimary: adVM.removeImageFromList, - isReview: true, - onAddImagePressed: () {}, + Expanded( + flex: 5, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SingleDetailWidget(text: adVM.vehicleModelId.selectedOption, type: "Vehicle Model"), + 16.height, + SingleDetailWidget(text: adVM.vehicleColorId.selectedOption, type: "Vehicle Color"), + 16.height, + SingleDetailWidget(text: adVM.vehicleCategoryId.selectedOption, type: "Vehicle Category"), + 16.height, + SingleDetailWidget(text: adVM.vehicleTransmissionId.selectedOption, type: "Vehicle Transmission"), + 16.height, + SingleDetailWidget(text: adVM.vehicleCountryId.selectedOption, type: "Vehicle Country"), + 16.height, + SingleDetailWidget(text: adVM.vehicleDemandAmount, type: "Vehicle Amount"), + 16.height, + SingleDetailWidget(text: adVM.vehicleTitle, type: "Vehicle Title"), + 16.height, + SingleDetailWidget(text: adVM.financeAvailableStatus ? "Yes" : "No", type: "Finance Available"), + 16.height, + ], ), - ], + ), ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }, + ), + SingleDetailWidget(text: adVM.vehicleDescription, type: "Description"), + 8.height, + "Vehicle Pictures:".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + if (adVM.pickedVehicleImages.isNotEmpty) ...[ + // 10.height, + PickedImagesContainer( + pickedImages: adVM.pickedVehicleImages, + onCrossPressedPrimary: adVM.removeImageFromList, + isReview: true, + onAddImagePressed: () {}, + ), + ], + ], ); } } @@ -160,16 +159,14 @@ class DamagePartsReview extends StatelessWidget { @override Widget build(BuildContext context) { - return Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - "Vehicle Damage Part".toText(fontSize: 18, isBold: true), - buildDamagePartList(adVM), - ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); - }, + AdVM adVM = context.read(); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Vehicle Damage Part".toText(fontSize: 18, isBold: true), + buildDamagePartList(adVM), + ], ); } } @@ -198,23 +195,23 @@ class AdDurationReview extends StatelessWidget { ), ], ), - 15.height, - "Reservable Ad".toText(fontSize: 18, isBold: true), - 8.height, - Row( - children: [ - Expanded( - flex: 7, - child: SingleDetailWidget(type: "Reservable", text: adVM.vehicleAdReservableId.selectedId == 1 ? "Yes" : "No"), - ), - Expanded( - flex: 5, - child: adVM.vehicleAdReservableId.selectedId == 1 - ? SingleDetailWidget(type: "Reserve Price", text: adVM.adReserveAmount) - : const SizedBox(), - ), - ], - ), + // 15.height, + // "Reservable Ad".toText(fontSize: 18, isBold: true), + // 8.height, + // Row( + // children: [ + // Expanded( + // flex: 7, + // child: SingleDetailWidget(type: "Reservable", text: adVM.vehicleAdReservableId.selectedId == 1 ? "Yes" : "No"), + // ), + // Expanded( + // flex: 5, + // child: adVM.vehicleAdReservableId.selectedId == 1 + // ? SingleDetailWidget(type: "Reserve Price", text: adVM.adReserveAmount) + // : const SizedBox(), + // ), + // ], + // ), if (adVM.specialServiceCards.isNotEmpty) ...[ 15.height, "Special Services".toText(fontSize: 18, isBold: true), @@ -250,39 +247,69 @@ class AdDurationReview extends StatelessWidget { ), ], ), - if (adVM.specialServiceCards[index].serviceSelectedId!.selectedId == 1 || adVM.specialServiceCards[index].serviceSelectedId!.selectedId == 3) ...[ - Row( - children: [ - Expanded( - flex: 7, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - 8.height, - SingleDetailWidget(type: "Branch Address", text: adVM.specialServiceCards[index].address ?? ""), - ], - ), - ), - Expanded( - flex: 5, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SingleDetailWidget(type: "Appointment Time", text: "${adVM.specialServiceCards[index].serviceDate ?? ""} - ${adVM.specialServiceCards[index].serviceTime}"), - ], - ), - ), - ], - ) - ], + // if (adVM.specialServiceCards[index].serviceSelectedId!.selectedId == 1 || adVM.specialServiceCards[index].serviceSelectedId!.selectedId == 3) ...[ + // Row( + // children: [ + // Expanded( + // flex: 7, + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // 8.height, + // SingleDetailWidget(type: "Branch Address", text: adVM.specialServiceCards[index].address ?? ""), + // ], + // ), + // ), + // Expanded( + // flex: 5, + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // SingleDetailWidget(type: "Appointment Time", text: "${adVM.specialServiceCards[index].serviceDate ?? ""} - ${adVM.specialServiceCards[index].serviceTime}"), + // ], + // ), + // ), + // ], + // ) + // ], ], ); }, ) ], ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + ); }, ); } } + +class AdContactDetailsReview extends StatelessWidget { + const AdContactDetailsReview({super.key}); + + @override + Widget build(BuildContext context) { + AdVM adVM = context.read(); + return adVM.isPhoneNumberShown + ? Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + "Ad Contact Details".toText(fontSize: 18, isBold: true), + 8.height, + Row( + children: [ + Expanded( + flex: 7, + child: SingleDetailWidget(type: "Phone Number", text: "${adVM.adPhoneNumberDialCode}${adVM.adPhoneNumber}"), + ), + Expanded( + flex: 5, + child: SingleDetailWidget(type: "On WhatsApp", text: adVM.isNumberOnWhatsApp ? "Yes" : "No"), + ), + ], + ), + ], + ) + : const SizedBox.shrink(); + } +} diff --git a/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart index ba53e82..4004158 100644 --- a/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart +++ b/lib/views/advertisement/ad_creation_steps/damage_parts_container.dart @@ -33,8 +33,6 @@ class DamageParts extends StatelessWidget { }); } - - @override Widget build(BuildContext context) { return Consumer( @@ -43,6 +41,8 @@ class DamageParts extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ CustomAddButton( + needsBorder: true, + bgColor: MyColors.white, onTap: () { onAddButtonTapped(context, adVM); }, @@ -53,7 +53,7 @@ class DamageParts extends StatelessWidget { decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), child: const Icon(Icons.add, color: MyColors.white), )).horPaddingMain(), - 9.height, + 8.height, ListView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, @@ -129,7 +129,7 @@ class DamageParts extends StatelessWidget { ).paddingOnly(right: 10) ], ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 4)); }, ), // DottedRectContainer( 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 173a777..b772ca5 100644 --- a/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart +++ b/lib/views/advertisement/ad_creation_steps/vehicle_details_container.dart @@ -24,26 +24,24 @@ class VehicleDetails extends StatelessWidget { children: [ "Vehicle Detail".toText(fontSize: 18, isBold: true), 8.height, - Builder( - builder: (BuildContext context) { - List vehicleTypesDrop = []; - for (var element in adVM.vehicleTypes) { - vehicleTypesDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleTypeName ?? "", "")); - } - return DropdownField( - (DropValue value) => adVM.updateSelectionVehicleTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value, errorValue: "")), - list: vehicleTypesDrop, - dropdownValue: adVM.vehicleTypeId.selectedId != -1 ? DropValue(adVM.vehicleTypeId.selectedId, adVM.vehicleTypeId.selectedOption, "") : null, - errorValue: adVM.vehicleTypeId.errorValue, - hint: "Vehicle Type", - ); - }, - ), - if (adVM.vehicleTypeId.selectedId != -1) ...[ + Builder(builder: (context) { + List vehicleBrandsDrop = []; + for (var element in adVM.vehicleBrands) { + vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleBrandDescription ?? "", "")); + } + return DropdownField( + (DropValue value) => adVM.updateSelectionVehicleBrandId(SelectionModel(selectedId: value.id, selectedOption: value.value)), + list: vehicleBrandsDrop, + dropdownValue: adVM.vehicleBrandId.selectedId != -1 ? DropValue(adVM.vehicleBrandId.selectedId, adVM.vehicleBrandId.selectedOption, "") : null, + hint: "Vehicle Brand", + errorValue: adVM.vehicleBrandId.errorValue, + ); + }), + if (adVM.vehicleBrandId.selectedId != -1) ...[ if (adVM.isFetchingLists) ...[ - Row( + const Row( mainAxisAlignment: MainAxisAlignment.center, - children: const [ + children: [ CircularProgressIndicator(), ], ).paddingAll(10), @@ -240,21 +238,24 @@ class VehicleDetails extends StatelessWidget { "Finance Available".toText(fontSize: 16), 8.height, Container( - width: 65, - height: 37, + width: 50, + height: 30, decoration: BoxDecoration( color: adVM.financeAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white, borderRadius: BorderRadius.circular(25.0), - border: Border.all(color: MyColors.black, width: 1.5), + border: Border.all(color: MyColors.black, width: 1), ), - child: CupertinoSwitch( - activeColor: MyColors.darkPrimaryColor, - trackColor: MyColors.white, - thumbColor: MyColors.grey98Color, - value: adVM.financeAvailableStatus, - onChanged: (value) { - adVM.updateFinanceAvailableStatus(value); - }, + child: Transform.scale( + scale: 0.8, + child: CupertinoSwitch( + activeColor: MyColors.darkPrimaryColor, + trackColor: MyColors.white, + thumbColor: MyColors.grey98Color, + value: adVM.financeAvailableStatus, + onChanged: (value) { + adVM.updateFinanceAvailableStatus(value); + }, + ), ), ), 28.height, diff --git a/lib/views/advertisement/ad_duration_selection_sheet_content.dart b/lib/views/advertisement/ad_duration_selection_sheet_content.dart new file mode 100644 index 0000000..6efc03e --- /dev/null +++ b/lib/views/advertisement/ad_duration_selection_sheet_content.dart @@ -0,0 +1,113 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/config/routes.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/advertisment_models/ads_duration_model.dart'; +import 'package:mc_common_app/models/widgets_models.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/navigator.dart'; +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/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; + +class AdDurationSelectionSheetContent extends StatelessWidget { + const AdDurationSelectionSheetContent({super.key}); + + @override + Widget build(BuildContext context) { + AdVM adVM = context.watch(); + + print("hello : ${adVM.vehicleAdDurationId.selectedId}"); + return SizedBox( + height: MediaQuery.of(context).size.height / 1.2, + child: Column( + children: [ + Row( + children: [ + "Select Duration".toText(fontSize: 22, isBold: true).paddingOnly(top: 10, left: 21, right: 21), + ], + ), + Expanded( + child: ListView.separated( + shrinkWrap: true, + itemCount: adVM.vehicleAdsDurations.length, + itemBuilder: (BuildContext context, int index) { + AdsDurationModel adDuration = adVM.vehicleAdsDurations[index]; + return SizedBox( + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + "${adDuration.days} Days".toString().toText(fontSize: 16, isBold: true), + 4.height, + "Your Ad will be active for ${adDuration.days} Days and then you will need to extend it to keep it active. ".toText( + fontSize: 14, + color: MyColors.lightTextColor, + ), + 12.height, + "Ad Charges".toText(fontSize: 14, color: MyColors.lightTextColor, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "${adDuration.price}".toText(fontSize: 22, isBold: true), + 2.width, + Padding( + padding: const EdgeInsets.only(bottom: 4), + child: "SAR".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + ), + ], + ), + ], + ), + ), + ], + ).toWhiteContainer(width: double.infinity, allPading: 12, isBorderRequired: adDuration.id == adVM.vehicleAdDurationId.selectedId ? true : false), + ).onPress(() { + adVM.updateVehicleAdDurationId( + SelectionModel( + selectedId: adDuration.id ?? 0, + selectedOption: "${adDuration.days} Days", + itemPrice: adDuration.price!.toInt().toString(), + ), + ); + }); + }, + separatorBuilder: (BuildContext context, int index) { + return 12.height; + }, + padding: const EdgeInsets.all(20), + ), + ), + ShowFillButton( + title: "Select", + maxWidth: double.infinity, + margin: const EdgeInsets.all(21), + onPressed: () { + + navigateReplaceWithName(context, AppRoutes.createAdView); + }, + ).toContainer(paddingAll: 0, backgroundColor: Colors.white), + ], + ), + ); + } + + Widget showItem(String item, String value, {Color valueColor = Colors.black}) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + item.toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + 4.width, + value.toText(fontSize: 12, color: valueColor, isBold: true), + ], + ); + } +} diff --git a/lib/views/advertisement/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view.dart index 614fab3..30465cf 100644 --- a/lib/views/advertisement/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view.dart @@ -11,6 +11,7 @@ import 'package:mc_common_app/view_models/payment_view_model.dart'; import 'package:mc_common_app/views/advertisement/ads_images_slider.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; @@ -21,12 +22,16 @@ class AdsDetailView extends StatelessWidget { @override Widget build(BuildContext context) { + print("adId: ${adDetails.id}"); + print("statusID: ${adDetails.adPostStatus}"); return Scaffold( appBar: CustomAppBar( title: "Ads", profileImageUrl: MyAssets.bnCar, isRemoveBackButton: false, isDrawerEnabled: false, + actions: [const Icon(Icons.chat_outlined).paddingOnly(right: 21)], + onTap: () {}, ), body: Container( padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21), @@ -106,11 +111,11 @@ class AdsDetailView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ adDetails.vehicle!.demandAmount!.toInt().toString().toText(fontSize: 30, isBold: true), - "SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor), + " SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5), ], ), 14.height, - BuildAdDetailsActionButton(adPostStatus: adDetails.adPostStatus!, adId: adDetails.id!), + adDetails.isMyAd ?? false ? BuildAdDetailsActionButtonForMyAds(adDetailsModel: adDetails) : BuildAdDetailsActionButtonForExploreAds(adDetailsModel: adDetails), ], ), ) @@ -121,11 +126,456 @@ class AdsDetailView extends StatelessWidget { } } -class BuildAdDetailsActionButton extends StatelessWidget { - final AdPostStatus adPostStatus; - final int adId; +class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { + final AdDetailsModel adDetailsModel; - const BuildAdDetailsActionButton({Key? key, required this.adPostStatus, required this.adId}) : super(key: key); + const BuildAdDetailsActionButtonForExploreAds({Key? key, required this.adDetailsModel}) : super(key: key); + + void reserveAdPriceBreakDownClicked(BuildContext context, AdDetailsModel adDetailsModel) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + enableDrag: true, + builder: (BuildContext context) { + return InfoBottomSheet( + title: "Reserve Ad", + description: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Reservation Amounts".toText(fontSize: 16, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "${adDetailsModel.reservePrice}".toText(fontSize: 19, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), + ], + ) + ], + ), + const Divider(), + "Below Amount that you will pay later".toText(fontSize: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "Car Price".toText(fontSize: 16, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "${adDetailsModel.vehicle!.demandAmount ?? 0.0}".toText(fontSize: 19, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), + ], + ) + ], + ), + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // "Tax".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + // Row( + // crossAxisAlignment: CrossAxisAlignment.end, + // children: [ + // "${adDetailsModel.taxPrice}".toText(fontSize: 16, isBold: true), + // 2.width, + // "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 0), + // ], + // ) + // ], + // ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + "VAT Excluded".toText(fontSize: 10, isBold: true), + ], + ), + const Divider(), + "Special Services".toText(fontSize: 16, isBold: true), + 5.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Car insurance Service".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor, fontWeight: FontWeight.w500), + "To be Decided".toText(fontSize: 12, isBold: true), + ], + ), + 5.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Registration & Car Plates".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "To be Decided".toText(fontSize: 12, isBold: true), + ], + ), + 5.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Home Delivery Service".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "To be Decided".toText(fontSize: 12, isBold: true), + ], + ), + 12.height, + "Special service charges will be added based on desired insurance and delivery Location".toText(fontSize: 12), + 30.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Total Amount ".toText(fontSize: 16, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "${(adDetailsModel.vehicle!.demandAmount ?? 0.0)}".toText(fontSize: 19, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), + ], + ) + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + "Estimated".toText(fontSize: 10, isBold: true), + ], + ), + 44.height, + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const Icon( + Icons.warning, + color: MyColors.adPendingStatusColor, + size: 19, + ).paddingOnly(bottom: 2), + 3.width, + "Some services are mandatory while reserving the Ad.".toText( + color: MyColors.adPendingStatusColor, + fontSize: 12, + isItalic: true, + ), + ], + ), + 15.height, + Row( + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Complete Reservation", + onPressed: () { + Navigator.pop(context); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypesEnum.adReserve); + }, + ), + ), + ], + ), + 19.height, + ], + )); + }); + } + + Widget cancelReservationAction(BuildContext context) { + return Row( + children: [ + Expanded( + child: ShowFillButton( + borderColor: MyColors.redColor, + txtColor: MyColors.redColor, + isFilled: false, + fontSize: 16, + maxHeight: 55, + title: "Cancel Reservation", + onPressed: () {}, + ), + ), + ], + ); + } + + Widget reserveAdAction(BuildContext context, AdDetailsModel adDetailsModel) { + return Row( + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Reserve Ad", + onPressed: () { + reserveAdPriceBreakDownClicked(context, adDetailsModel); + // navigateWithName(context, AppRoutes.paymentMethodsView); + }, + ), + ), + if (adDetailsModel.whatsAppNo != null) ...[ + 8.width, + Container( + height: 55, + width: 55, + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), + //TODO: It Will be replaced by a WhatsApp Icon + child: const Icon(Icons.message, color: MyColors.black), + ).onPress(() {}), + ], + if (adDetailsModel.phoneNo != null) ...[ + 8.width, + Container( + height: 55, + width: 55, + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), + child: const Icon(Icons.phone, color: MyColors.black), + ).onPress(() {}), + ] + ], + ); + } + + Widget defaultActionForProviderAndCustomer(BuildContext context, AdDetailsModel adDetailsModel) { + return (adDetailsModel.phoneNo != null) + ? Row( + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Contact", + fontSize: 18, + isBold: false, + iconWidget: const Padding( + padding: EdgeInsets.only(right: 10), + child: Icon(Icons.phone, color: MyColors.white, size: 24), + ), + onPressed: () {}, + ), + ), + if (adDetailsModel.whatsAppNo != null) ...[ + 8.width, + Container( + height: 55, + width: 55, + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), + //TODO: It Will be replaced by a WhatsApp Icon + child: const Icon(Icons.message, color: MyColors.black), + ).onPress(() {}), + ], + ], + ) + : const SizedBox.shrink(); + } + + @override + Widget build(BuildContext context) { + context.read().updateCurrentAdId(id: adDetailsModel.id!); + // switch (adPostStatus) { + // case AdPostStatus.pendingForPayment: + // break; + // case AdPostStatus.active: + // break; + // case AdPostStatus.reserved: + // return cancelReservationAction(context); + // + // case AdPostStatus.buyingService: + // case AdPostStatus.reserveCancel: + // case AdPostStatus.rejected: + // case AdPostStatus.cancelled: + // case AdPostStatus.pendingForPost: + // case AdPostStatus.pendingForReview: + // case AdPostStatus.sold: + // case AdPostStatus.expired: + // break; + // } + // return defaultAction(context); + + switch (adDetailsModel.createdByRoleEnum!) { + case CreatedByRoleEnum.customer: + case CreatedByRoleEnum.provider: + return defaultActionForProviderAndCustomer(context, adDetailsModel); + case CreatedByRoleEnum.admin: + return reserveAdAction(context, adDetailsModel); + case CreatedByRoleEnum.allAds: + return SizedBox.shrink(); + } + } +} + +class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { + final AdDetailsModel adDetailsModel; + + const BuildAdDetailsActionButtonForMyAds({Key? key, required this.adDetailsModel}) : super(key: key); + + void reserveAdPriceBreakDownClicked(BuildContext context) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + enableDrag: true, + builder: (BuildContext context) { + return InfoBottomSheet( + title: "Reserve Ad", + description: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Reservation Amounts".toText(fontSize: 16, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "500".toText(fontSize: 19, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), + ], + ) + ], + ), + const Divider(), + "Below Amount that you will pay later".toText(fontSize: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "Car Price".toText(fontSize: 16, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "30,000".toText(fontSize: 19, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), + ], + ) + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Tax".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "4,500".toText(fontSize: 16, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 0), + ], + ) + ], + ), + const Divider(), + "Special Services".toText(fontSize: 16, isBold: true), + 5.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Car insurance Service".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor, fontWeight: FontWeight.w500), + "To be Decided".toText(fontSize: 12, isBold: true), + ], + ), + 5.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Registration & Car Plates".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "To be Decided".toText(fontSize: 12, isBold: true), + ], + ), + 5.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Home Delivery Service".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + "To be Decided".toText(fontSize: 12, isBold: true), + ], + ), + 12.height, + "Special service charges will be added based on desired insurance and delivery Location".toText(fontSize: 12), + 30.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + "Total Amount ".toText(fontSize: 16, isBold: true), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + "34,500".toText(fontSize: 19, isBold: true), + 2.width, + "SAR".toText(color: MyColors.lightTextColor, fontSize: 10, isBold: true).paddingOnly(bottom: 3), + ], + ) + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + "Estimated".toText(fontSize: 10, isBold: true), + ], + ), + 44.height, + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const Icon( + Icons.warning, + color: MyColors.adPendingStatusColor, + size: 19, + ).paddingOnly(bottom: 2), + 3.width, + "Some services are mandatory while reserving the Ad.".toText( + color: MyColors.adPendingStatusColor, + fontSize: 12, + isItalic: true, + ), + ], + ), + 15.height, + Row( + children: [ + Expanded( + child: ShowFillButton( + maxHeight: 55, + title: "Complete Reservation", + onPressed: () { + Navigator.pop(context); + navigateWithName(context, AppRoutes.paymentMethodsView); + }, + ), + ), + ], + ), + 19.height, + ], + )); + }); + } + + Widget pendingForReviewAction(BuildContext context, {required int adID}) { + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row( + children: [ + Expanded( + child: ShowFillButton( + backgroundColor: MyColors.grey98Color.withOpacity(0.3), + txtColor: MyColors.lightTextColor, + maxHeight: 55, + title: "Waiting for Admins Approval", + isBold: false, + onPressed: () {}, + ), + ), + ], + ), + ], + ); + } Widget pendingForPaymentAction(BuildContext context, {required int adID}) { return Column( @@ -138,7 +588,7 @@ class BuildAdDetailsActionButton extends StatelessWidget { maxHeight: 55, title: "Pay Now", onPressed: () { - navigateWithName(context, AppRoutes.paymentMethodsView); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypesEnum.ads); }, ), ), @@ -176,17 +626,18 @@ class BuildAdDetailsActionButton extends StatelessWidget { ], ), Row( - mainAxisAlignment: MainAxisAlignment.center, children: [ - InkWell( - onTap: () {}, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: "Delete Ad".toText(fontSize: 15, isBold: true, color: MyColors.redColor), + Expanded( + child: ShowFillButton( + isFilled: true, + borderColor: MyColors.darkPrimaryColor, + maxHeight: 55, + title: "Deactivate Ad", + onPressed: () {}, ), ), ], - ) + ), ], ); } @@ -217,16 +668,26 @@ class BuildAdDetailsActionButton extends StatelessWidget { maxHeight: 55, title: "Reserve Ad", onPressed: () { - navigateWithName(context, AppRoutes.paymentMethodsView); + reserveAdPriceBreakDownClicked(context); + // navigateWithName(context, AppRoutes.paymentMethodsView); }, ), ), - 12.width, + 8.width, + Container( + height: 55, + width: 55, + alignment: Alignment.center, + decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), + //TODO: It Will be replaced by a WhatsApp Icon + child: const Icon(Icons.message, color: MyColors.black), + ).onPress(() {}), + 8.width, Container( height: 55, width: 55, alignment: Alignment.center, - decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 3)), + decoration: BoxDecoration(border: Border.all(color: MyColors.black, width: 2)), child: const Icon(Icons.phone, color: MyColors.black), ).onPress(() {}), ], @@ -235,26 +696,27 @@ class BuildAdDetailsActionButton extends StatelessWidget { @override Widget build(BuildContext context) { - context.read().updateCurrentAdId(id: adId); - switch (adPostStatus) { + context.read().updateCurrentAdId(id: adDetailsModel.id!); + switch (adDetailsModel.adPostStatus!) { case AdPostStatus.pendingForPayment: - return pendingForPaymentAction(context, adID: adId); + return pendingForPaymentAction(context, adID: adDetailsModel.id!); case AdPostStatus.active: return markAsSoldAction(context); case AdPostStatus.reserved: - return cancelReservationAction(context); - + break; case AdPostStatus.buyingService: case AdPostStatus.reserveCancel: case AdPostStatus.rejected: case AdPostStatus.cancelled: case AdPostStatus.pendingForPost: case AdPostStatus.pendingForReview: - return pendingForPaymentAction(context, adID: adId); + return pendingForReviewAction(context, adID: adDetailsModel.id!); + + // return pendingForPaymentAction(context, adID: adId); case AdPostStatus.sold: case AdPostStatus.expired: break; } - return defaultAction(context); + return const SizedBox.shrink(); } } diff --git a/lib/views/advertisement/ads_list.dart b/lib/views/advertisement/ads_list.dart index 0ae4ecf..afdaa3f 100644 --- a/lib/views/advertisement/ads_list.dart +++ b/lib/views/advertisement/ads_list.dart @@ -10,7 +10,6 @@ import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; -import 'package:sizer/sizer.dart'; class BuildAdsList extends StatelessWidget { final List adsList; @@ -46,7 +45,7 @@ class BuildAdsList extends StatelessWidget { isAdsFragment: isAdsFragment, shouldShowAdStatus: shouldShowAdStatus, ).onPress( - () { + () { navigateWithName(context, AppRoutes.adsDetailView, arguments: adsList[index]); }, ); @@ -54,7 +53,7 @@ class BuildAdsList extends StatelessWidget { separatorBuilder: (BuildContext context, int index) { return 12.height; }, - padding: EdgeInsets.symmetric(horizontal: 21), + padding: const EdgeInsets.symmetric(horizontal: 21), ); } } @@ -100,12 +99,7 @@ class AdCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - if (isAdsFragment && context - .read() - .isExploreAdsTapped) ...[ - Utils.statusContainerChip(text: adDetails.statuslabel!, chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)), - ], - if (shouldShowAdStatus) ...[ + if (isAdsFragment && !context.read().isExploreAdsTapped) ...[ Utils.statusContainerChip(text: adDetails.statuslabel!, chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)), ], (adDetails.vehicle!.vehicleTitle ?? "").toText(fontSize: 16, isBold: true), @@ -139,8 +133,8 @@ class AdCard extends StatelessWidget { ), adDetails.createdOn != null ? DateTime.parse(adDetails.createdOn!).getTimeAgo().toText( - color: MyColors.lightTextColor, - ) + color: MyColors.lightTextColor, + ) : const SizedBox(), ], ), @@ -191,6 +185,9 @@ class AdCard extends StatelessWidget { else const SizedBox(), ], - ).toWhiteContainer(width: double.infinity, allPading: 12,); + ).toWhiteContainer( + width: double.infinity, + allPading: 12, + ); } } diff --git a/lib/views/advertisement/ads_search_filter_view.dart b/lib/views/advertisement/ads_search_filter_view.dart new file mode 100644 index 0000000..313f7db --- /dev/null +++ b/lib/views/advertisement/ads_search_filter_view.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; + +class AdsSearchFilterView extends StatelessWidget { + const AdsSearchFilterView({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + title: "Filter Ads", + profileImageUrl: MyAssets.bnCar, + isRemoveBackButton: false, + isDrawerEnabled: false, + ), + ); + } +} diff --git a/lib/views/advertisement/bottom_sheet_content.dart b/lib/views/advertisement/bottom_sheet_content.dart index f3eade5..6a270ba 100644 --- a/lib/views/advertisement/bottom_sheet_content.dart +++ b/lib/views/advertisement/bottom_sheet_content.dart @@ -11,6 +11,7 @@ import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:provider/provider.dart'; +import 'package:sizer/sizer.dart'; class BottomSheetListContent extends StatefulWidget { const BottomSheetListContent({Key? key}) : super(key: key); @@ -103,7 +104,6 @@ class _BottomSheetListContentState extends State { const SizedBox(width: 20), vehiclePart.partName.toString().toText( fontSize: 16, - isBold: true, color: vehiclePart.isSelected! ? MyColors.lightTextColor : MyColors.black, ) ], @@ -147,7 +147,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { const BottomSheetAdSpecialServiceContent({Key? key}) : super(key: key); bool isButtonTappable(AdVM adVM) { - bool status = (adVM.vehicleAdsSpecialServicesId.selectedId != -1) && (adVM.vehicleAdsSpecialServicesId.selectedOption != "" && adVM.slotSelectedIndex != null); + bool status = (adVM.vehicleAdsSpecialServicesId.selectedId != -1) && (adVM.vehicleAdsSpecialServicesId.selectedOption != ""); if (status) { return true; } @@ -164,7 +164,6 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { Flexible( child: description.toText( fontSize: 15, - isBold: true, color: MyColors.lightTextColor, ), ), @@ -217,55 +216,56 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { ] else ...[ 8.height, if ((adVM.vehicleAdsSpecialServicesId.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, + // 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.vehicleAdsSpecialServicesId.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, + // 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.vehicleAdsSpecialServicesId.selectedId != 3 && adVM.vehicleAdsSpecialServicesId.selectedId != 1) ...[ descriptionCard( - description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "", + description: + adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "Some Dummy Service Description!!", ), ], if (adVM.adSSTimeSlots.isNotEmpty) ...[ @@ -278,8 +278,14 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { ], 22.height, "Service Amount".toText(fontSize: 16, isBold: true, color: MyColors.lightTextColor), - adVM.vehicleAdsSpecialServicesId.itemPrice.toText(fontSize: 20, isBold: true), - "SAR".toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + adVM.vehicleAdsSpecialServicesId.itemPrice.toText(fontSize: 20, isBold: true), + SizedBox(width: 1.w), + "SAR".toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 2), + ], + ), ], ], ], @@ -298,28 +304,41 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget { 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, + 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), ), diff --git a/lib/views/advertisement/create_ad_progress_steps.dart b/lib/views/advertisement/create_ad_progress_steps.dart index c1b26cc..6033ed2 100644 --- a/lib/views/advertisement/create_ad_progress_steps.dart +++ b/lib/views/advertisement/create_ad_progress_steps.dart @@ -23,11 +23,10 @@ class CreateAdProgressSteps extends StatelessWidget { color: isSelected ? MyColors.darkPrimaryColor : MyColors.white, border: Border.all( color: isSelected ? MyColors.darkPrimaryColor : MyColors.lightIconColor, + width: 0.3, ), ), - child: icon.buildSvg( - color: isSelected ? MyColors.white : MyColors.lightIconColor, - ), + child: icon.buildSvg(color: isSelected ? MyColors.white : MyColors.lightIconColor).paddingAll(3), ), 5.height, title.toText( @@ -41,24 +40,36 @@ class CreateAdProgressSteps extends StatelessWidget { } bool isStepCompleted({required AdCreationStepsEnum currentStep}) { - return true; } + int getProgressStepNumber({required AdCreationStepsEnum currentStep}) { + switch (currentStep) { + case AdCreationStepsEnum.vehicleDetails: + return 1; + case AdCreationStepsEnum.damageParts: + return 2; + case AdCreationStepsEnum.adDuration: + return 3; + case AdCreationStepsEnum.reviewAd: + return 4; + } + } + @override Widget build(BuildContext context) { AdVM adVM = context.watch(); return Stack( // alignment: Alignment.center, children: [ - const Divider(thickness: 2).paddingOnly(left: 21, right: 21, top: 15), + const Divider(thickness: 1).paddingOnly(left: 21, right: 21, top: 15), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - buildStep(MyAssets.carIcon, "Vehicle \n Details", adVM.currentProgressStep == AdCreationStepsEnum.vehicleDetails), - buildStep(MyAssets.carHitIcon, "Damage \n Parts", adVM.currentProgressStep == AdCreationStepsEnum.damageParts), - buildStep(MyAssets.clockIcon, "Ad \n Duration", adVM.currentProgressStep == AdCreationStepsEnum.adDuration), - buildStep(MyAssets.reviewIcon, "Review \n Ad", adVM.currentProgressStep == AdCreationStepsEnum.reviewAd), + buildStep(MyAssets.carIcon, "Vehicle \n Details", getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 1), + buildStep(MyAssets.carHitIcon, "Damage \n Parts", getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 2), + buildStep(MyAssets.clockIcon, "Additional \n Details", getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 3), + buildStep(MyAssets.reviewIcon, "Review \n Ad", getProgressStepNumber(currentStep: adVM.currentProgressStep) >= 4), ], ), ], diff --git a/lib/views/advertisement/custom_add_button.dart b/lib/views/advertisement/custom_add_button.dart index 9947022..5cb5b5a 100644 --- a/lib/views/advertisement/custom_add_button.dart +++ b/lib/views/advertisement/custom_add_button.dart @@ -5,17 +5,19 @@ import 'package:mc_common_app/theme/colors.dart'; class CustomAddButton extends StatelessWidget { final Widget icon; final String text; + final Color bgColor; + final bool needsBorder; final Function() onTap; - const CustomAddButton({Key? key, required this.text, required this.onTap, required this.icon}) : super(key: key); + const CustomAddButton({Key? key, required this.text, required this.onTap, required this.icon, required this.bgColor, required this.needsBorder}) : super(key: key); @override Widget build(BuildContext context) { return InkWell( onTap: onTap, child: Container( - height: 110, - decoration: BoxDecoration(color: MyColors.greyButtonColor, border: Border.all(width: 2, color: MyColors.greyAddBorderColor)), + height: 80, + decoration: BoxDecoration(color: bgColor, border: needsBorder ? Border.all(width: 2, color: MyColors.darkPrimaryColor) : null), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/lib/views/advertisement/select_ad_type_view.dart b/lib/views/advertisement/select_ad_type_view.dart new file mode 100644 index 0000000..fa2654b --- /dev/null +++ b/lib/views/advertisement/select_ad_type_view.dart @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/config/routes.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart'; +import 'package:mc_common_app/models/widgets_models.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/view_models/ad_view_model.dart'; +import 'package:mc_common_app/views/advertisement/ad_duration_selection_sheet_content.dart'; +import 'package:mc_common_app/widgets/bottom_sheet.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:provider/provider.dart'; + +class SelectAdTypeView extends StatelessWidget { + final bool isProvider; + + const SelectAdTypeView({ + Key? key, + this.isProvider = true, + }) : super(key: key); + + Widget getVehicleAdTypeIcon(VehicleTypeEnum vehicleTypeEnum) { + switch (vehicleTypeEnum) { + case VehicleTypeEnum.car: + return MyAssets.vehicleTypeCar.buildSvg(height: 22); + + case VehicleTypeEnum.motorCycle: + return MyAssets.vehicleTypeMotorcycle.buildSvg(height: 26); + + case VehicleTypeEnum.golfCart: + return MyAssets.vehicleTypeGolfCart.buildSvg(height: 26); + + case VehicleTypeEnum.buggy: + return MyAssets.vehicleTypeBuggy.buildSvg(height: 26); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + title: "Select Ad Type", + profileImageUrl: MyAssets.bnCar, + isRemoveBackButton: false, + isDrawerEnabled: false, + ), + body: Column( + children: [ + Expanded( + child: Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) { + return ListView.separated( + itemCount: adVM.vehicleTypes.length, + itemBuilder: (BuildContext context, int index) { + VehicleTypeModel vehicleTypeModel = adVM.vehicleTypes[index]; + return InkWell( + onTap: () { + adVM.updateSelectionVehicleTypeId( + SelectionModel(selectedId: vehicleTypeModel.id!, selectedOption: vehicleTypeModel.vehicleTypeName ?? "", errorValue: ""), + ); + + showMyBottomSheet(context, child: const AdDurationSelectionSheetContent()); + }, + child: SizedBox( + width: double.infinity, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + vehicleTypeModel.vehicleTypeName.toString().toText(fontSize: 18, isBold: true), + getVehicleAdTypeIcon(vehicleTypeModel.vehicleTypeEnum!), + ], + ), + if (isProvider) ...[ + Row( + children: [ + "Duration: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + "Valid Until Subscription Expiration".toText(fontSize: 13, isBold: true), + ], + ).paddingOnly(top: 5, bottom: 5), + ] else ...[ + Row( + children: [ + "Duration: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + adVM.vehicleAdDurationId.selectedOption.toText(fontSize: 13, isBold: true), + const Icon(Icons.keyboard_arrow_down_sharp, color: MyColors.darkPrimaryColor, size: 20), + ], + ).paddingOnly(top: 5, bottom: 5), + ], + if (!isProvider) ...[ + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + adVM.vehicleAdDurationId.itemPrice.toText(fontSize: 22, isBold: true), + 2.width, + Padding( + padding: const EdgeInsets.only(bottom: 4), + child: "SAR".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + ), + ], + ), + ], + ], + ), + ), + ], + ), + ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.symmetric(horizontal: 20, vertical: 10)), + ); + }, + separatorBuilder: (BuildContext context, int index) { + return 9.height; + }, + padding: const EdgeInsets.all(20), + ); + }), + ), + if (isProvider) ...[ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + "5 of 10 ".toText(fontSize: 29, isBold: true, letterSpacing: 0, height: 1), + "Ads Remaining ".toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true), + ], + ), + const Text.rich( + TextSpan( + children: [ + TextSpan( + text: "You have left with 05 out of 50 ads given in the subscription. ", + style: TextStyle( + fontSize: 14, + color: MyColors.lightTextColor, + )), + TextSpan( + text: "Update Subscription", + style: TextStyle( + decoration: TextDecoration.underline, + fontSize: 14, + fontWeight: FontWeight.w600, + color: MyColors.darkPrimaryColor, + )) + ], + ), + ), + 10.height, + ], + ).toContainer(paddingAll: 20, backgroundColor: Colors.white), + ] + ], + ), + ); + } +} diff --git a/lib/views/payments/payment_methods_view.dart b/lib/views/payments/payment_methods_view.dart index c96b521..01d6071 100644 --- a/lib/views/payments/payment_methods_view.dart +++ b/lib/views/payments/payment_methods_view.dart @@ -11,7 +11,9 @@ import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:provider/provider.dart'; class PaymentMethodsView extends StatelessWidget { - const PaymentMethodsView({Key? key}) : super(key: key); + final PaymentTypesEnum paymentType; + + const PaymentMethodsView({Key? key, required this.paymentType}) : super(key: key); @override Widget build(BuildContext context) { @@ -68,7 +70,7 @@ class PaymentMethodsView extends StatelessWidget { maxHeight: 55, title: "Continue", onPressed: () { - context.read().onContinuePressed(context); + context.read().onContinuePressed(context, paymentType: paymentType); }, backgroundColor: MyColors.darkPrimaryColor, ), diff --git a/lib/views/user/login_with_password_page.dart b/lib/views/user/login_with_password_page.dart index 16204a9..0d74b32 100644 --- a/lib/views/user/login_with_password_page.dart +++ b/lib/views/user/login_with_password_page.dart @@ -28,7 +28,8 @@ class _LoginWithPasswordState extends State { int otpType = 1; ClassType type = ClassType.EMAIL; - String phoneNum = "580816976", password = "123@Shf"; + //TODO: ONLY FOR DEVELOPMENT PURPOSE + String phoneNum = "966504278213", password = "Fa@1234"; String email = ""; String countryCode = ""; Country? _country; diff --git a/lib/widgets/button/show_fill_button.dart b/lib/widgets/button/show_fill_button.dart index 644870c..e55f813 100644 --- a/lib/widgets/button/show_fill_button.dart +++ b/lib/widgets/button/show_fill_button.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; class ShowFillButton extends StatelessWidget { String title; @@ -12,6 +13,7 @@ class ShowFillButton extends StatelessWidget { EdgeInsets? margin; bool isFilled; Color borderColor; + Widget? iconWidget; ShowFillButton({ super.key, @@ -31,6 +33,7 @@ class ShowFillButton extends StatelessWidget { this.horizontalMargin = 0, this.verticalMargin = 0, this.margin, + this.iconWidget, this.borderColor = MyColors.primaryColor, }); @@ -62,21 +65,37 @@ class ShowFillButton extends StatelessWidget { Widget showButton() { return Container( // decoration: isFlatButton ? null : MyColors.gradientButton, - color: isFlatButton ? null : isFilled ? backgroundColor : null, + color: isFlatButton + ? null + : isFilled + ? backgroundColor + : null, margin: EdgeInsets.symmetric(horizontal: horizontalMargin, vertical: verticalMargin), child: MaterialButton( onPressed: onPressed, - shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(radius), - side: isFilled ? BorderSide.none: BorderSide(width: 2, color: borderColor), - ), - child: title.toText( - fontSize: fontSize, - isBold: isBold, - color: txtColor, - maxLines: 1, + side: isFilled ? BorderSide.none : BorderSide(width: 2, color: borderColor), ), + child: iconWidget != null + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + iconWidget!, + title.toText( + fontSize: fontSize, + isBold: isBold, + color: txtColor, + maxLines: 1, + ), + ], + ) + : title.toText( + fontSize: fontSize, + isBold: isBold, + color: txtColor, + maxLines: 1, + ), ), ); } diff --git a/lib/widgets/checkbox_with_title_desc.dart b/lib/widgets/checkbox_with_title_desc.dart index 99088aa..5419254 100644 --- a/lib/widgets/checkbox_with_title_desc.dart +++ b/lib/widgets/checkbox_with_title_desc.dart @@ -3,11 +3,11 @@ import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/theme/colors.dart'; class CheckBoxWithTitleDescription extends StatelessWidget { - bool isSelected; - String title, description; - Function(bool) onSelection; + final bool isSelected; + final String title, description; + final Function(bool) onSelection; - CheckBoxWithTitleDescription({required this.isSelected, required this.title, required this.description, required this.onSelection, Key? key}) : super(key: key); + const CheckBoxWithTitleDescription({required this.isSelected, required this.title, required this.description, required this.onSelection, Key? key}) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/common_widgets/info_bottom_sheet.dart b/lib/widgets/common_widgets/info_bottom_sheet.dart index 26b81a4..5c0d6c4 100644 --- a/lib/widgets/common_widgets/info_bottom_sheet.dart +++ b/lib/widgets/common_widgets/info_bottom_sheet.dart @@ -6,14 +6,14 @@ import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; class InfoBottomSheet extends StatelessWidget { final String title; - final String description; + final Widget description; const InfoBottomSheet({Key? key, required this.title, required this.description}) : super(key: key); @override Widget build(BuildContext context) { - return SizedBox( - height: MediaQuery.of(context).size.height * 0.4, + return SingleChildScrollView( + // height: MediaQuery.of(context).size.height * 0.35, child: Column( children: [ Container( @@ -30,13 +30,7 @@ class InfoBottomSheet extends StatelessWidget { ], ), 8.height, - Flexible( - child: description.toText( - textAlign: TextAlign.justify, - fontSize: 16, - color: MyColors.lightTextColor, - isBold: true, - )), + description, ], ).horPaddingMain()); } diff --git a/lib/widgets/common_widgets/provider_details_card.dart b/lib/widgets/common_widgets/provider_details_card.dart index 69c3048..169f1c2 100644 --- a/lib/widgets/common_widgets/provider_details_card.dart +++ b/lib/widgets/common_widgets/provider_details_card.dart @@ -16,7 +16,7 @@ class ProviderDetailsCard extends StatelessWidget { final String providerRatings; //TODO: items can be make a generaic, so we can add services/items in the future - final List? items; + final List? services; final Function() onCardTapped; const ProviderDetailsCard({ @@ -26,7 +26,7 @@ class ProviderDetailsCard extends StatelessWidget { this.providerName, required this.providerRatings, required this.providerLocation, - this.items, + this.services, required this.onCardTapped, }) : super(key: key); @@ -66,7 +66,7 @@ class ProviderDetailsCard extends StatelessWidget { title.toText(fontSize: 16, isBold: true), Row( children: [ - (LocaleKeys.location.tr() + ":").toText(color: MyColors.lightTextColor, fontSize: 12), + ("${LocaleKeys.location.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12), 4.width, providerLocation.toText(fontSize: 12, isBold: true), ], @@ -74,7 +74,7 @@ class ProviderDetailsCard extends StatelessWidget { if (providerName != null) Row( children: [ - (LocaleKeys.providers.tr() + ":").toText(color: MyColors.lightTextColor, fontSize: 12), + ("${LocaleKeys.providers.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12), 4.width, providerName!.toText(fontSize: 12, isBold: true), ], @@ -97,9 +97,9 @@ class ProviderDetailsCard extends StatelessWidget { ], ), 8.height, - if (items != null) + if (services != null) Column( - children: items! + children: services! .take(2) .map( (e) => @@ -117,8 +117,8 @@ class ProviderDetailsCard extends StatelessWidget { ) .toList(), ), - if (items != null && items!.length > 2) - ("+${items!.length - 2} more").toText( + if (services != null && services!.length > 2) + ("+${services!.length - 2} more").toText( color: MyColors.primaryColor, isUnderLine: true, isBold: true, diff --git a/lib/widgets/common_widgets/time_slots.dart b/lib/widgets/common_widgets/time_slots.dart index 0514d69..9e56974 100644 --- a/lib/widgets/common_widgets/time_slots.dart +++ b/lib/widgets/common_widgets/time_slots.dart @@ -15,8 +15,10 @@ class BuildTimeSlots extends StatelessWidget { height: 37, width: double.infinity, child: ListView.builder( + physics: const BouncingScrollPhysics(), itemCount: timeSlots.length, scrollDirection: Axis.horizontal, + shrinkWrap: true, itemBuilder: (BuildContext context, int index) { return InkWell( onTap: () { diff --git a/lib/widgets/extensions/extensions_widget.dart b/lib/widgets/extensions/extensions_widget.dart index ab7487b..31164a2 100644 --- a/lib/widgets/extensions/extensions_widget.dart +++ b/lib/widgets/extensions/extensions_widget.dart @@ -23,11 +23,12 @@ extension ExtendedText on Widget { } extension ContainerExt on Widget { - Widget toWhiteContainer({required double width, double? allPading, EdgeInsets? pading, EdgeInsets? margin, VoidCallback? onTap, Color? backgroundColor}) { + Widget toWhiteContainer({required double width, double? allPading, EdgeInsets? pading, EdgeInsets? margin, VoidCallback? onTap, Color? backgroundColor, bool isBorderRequired = false}) { return InkWell( onTap: onTap, child: Container( decoration: BoxDecoration( + border: isBorderRequired ? Border.all(color: MyColors.darkPrimaryColor, width: 2) : null, color: backgroundColor ?? MyColors.white, boxShadow: const [ BoxShadow( @@ -75,12 +76,12 @@ extension ContainerExt on Widget { boxShadow: !isShadowEnabled ? null : [ - BoxShadow( - color: const Color(0xff000000).withOpacity(.05), - blurRadius: 26, - offset: const Offset(0, -3), - ), - ], + BoxShadow( + color: const Color(0xff000000).withOpacity(.05), + blurRadius: 26, + offset: const Offset(0, -3), + ), + ], ), padding: padding ?? EdgeInsets.all(paddingAll), margin: margin ?? EdgeInsets.all(marginAll), @@ -354,5 +355,3 @@ extension LocaleSetup on MultiProvider { extension WidgetExtensions on Widget { Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this); } - - diff --git a/lib/widgets/txt_field.dart b/lib/widgets/txt_field.dart index 21537e9..37304a7 100644 --- a/lib/widgets/txt_field.dart +++ b/lib/widgets/txt_field.dart @@ -32,6 +32,7 @@ class TxtField extends StatelessWidget { TextInputType? keyboardType; bool isBackgroundEnabled = false; Widget? postfixWidget; + Widget? preFixWidget; TxtField({ Key? key, @@ -58,6 +59,7 @@ class TxtField extends StatelessWidget { this.keyboardType, this.isBackgroundEnabled = false, this.postfixWidget, + this.preFixWidget, this.onPostFixPressed, }) : super(key: key); @@ -84,6 +86,7 @@ class TxtField extends StatelessWidget { borderRadius: const BorderRadius.all(Radius.circular(0)), ), child: TextField( + style: const TextStyle(color: MyColors.darkTextColor), textInputAction: isSearchBar ? TextInputAction.search : null, keyboardType: keyboardType, autofocus: false, @@ -99,17 +102,17 @@ class TxtField extends StatelessWidget { alignLabelWithHint: true, fillColor: Colors.white, focusedBorder: OutlineInputBorder( - borderSide: BorderSide(color: MyColors.darkPrimaryColor, width: isNeedBorder ? 2.0 : 0), + borderSide: BorderSide(color: isNeedBorder ? MyColors.darkPrimaryColor : Colors.transparent, width: isNeedBorder ? 2.0 : 0), borderRadius: BorderRadius.circular(0.0), ), enabledBorder: OutlineInputBorder( // borderSide: BorderSide(color: MyColors.textFieldColor, width: isNeedBorder ? 1.0 : 0), - borderSide: BorderSide(color: MyColors.darkPrimaryColor, width: isNeedBorder ? 2.0 : 0), + borderSide: BorderSide(color: isNeedBorder ? MyColors.darkPrimaryColor : Colors.transparent, width: isNeedBorder ? 2.0 : 0), borderRadius: BorderRadius.circular(0.0), ), disabledBorder: OutlineInputBorder( // borderSide: BorderSide(color: MyColors.textFieldColor, width: isNeedBorder ? 1.0 : 0), - borderSide: BorderSide(color: MyColors.darkPrimaryColor, width: isNeedBorder ? 2.0 : 0), + borderSide: BorderSide(color: isNeedBorder ? MyColors.darkPrimaryColor : Colors.transparent, width: isNeedBorder ? 2.0 : 0), borderRadius: BorderRadius.circular(0.0), ), suffixIcon: postfixData != null @@ -117,8 +120,8 @@ class TxtField extends StatelessWidget { onTap: onPostFixPressed, child: Icon(postfixData, color: postFixDataColor), ) - : postfixWidget ?? null, - prefixIcon: prefixData != null ? const Icon(Icons.search, color: borderColor) : null, + : postfixWidget, + prefixIcon: prefixData != null ? Icon(prefixData, color: borderColor) : preFixWidget, labelStyle: TextStyle(color: borderColor, fontSize: 13.sp), hintStyle: TextStyle(color: borderColor, fontSize: 10.sp), hintText: hint ?? "", diff --git a/pubspec.lock b/pubspec.lock index b41a13e..18dfded 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: args - sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" async: dependency: transitive description: @@ -29,10 +29,10 @@ packages: dependency: "direct main" description: name: badges - sha256: "6e7f3ec561ec08f47f912cfe349d4a1707afdc8dda271e17b046aa6d42c89e77" + sha256: a7b6bbd60dce418df0db3058b53f9d083c22cdb5132a052145dc267494df0b84 url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" boolean_selector: dependency: transitive description: @@ -97,46 +97,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.1" + country_code_picker: + dependency: "direct main" + description: + name: country_code_picker + sha256: "92818885f0e47486539f80463b66f649970506a91dd3c0731ca3ba5308324a4d" + url: "https://pub.dev" + source: hosted + version: "3.0.0" cross_file: dependency: transitive description: name: cross_file - sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb url: "https://pub.dev" source: hosted - version: "0.3.3+4" + version: "0.3.3+5" crypto: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" dropdown_button2: dependency: "direct main" description: name: dropdown_button2 - sha256: "374f2390161bf782b4896f0b1b24cbb2b5daaa1cfb11047c3307461dcdf44e07" + sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.3.9" easy_localization: dependency: "direct main" description: name: easy_localization - sha256: "30ebf25448ffe169e0bd9bc4b5da94faa8398967a2ad2ca09f438be8b6953645" + sha256: de63e3b422adfc97f256cbb3f8cf12739b6a4993d390f3cadb3f51837afaefe5 url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" easy_logger: dependency: transitive description: @@ -185,6 +201,38 @@ packages: url: "https://pub.dev" source: hosted version: "4.6.1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "182c3f8350cee659f7b115e956047ee3dc672a96665883a545e81581b9a82c72" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262" + url: "https://pub.dev" + source: hosted + version: "2.6.1" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" flutter: dependency: "direct main" description: flutter @@ -202,10 +250,10 @@ packages: dependency: transitive description: name: flutter_cache_manager - sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.1" flutter_inappwebview: dependency: "direct main" description: @@ -218,10 +266,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.3" flutter_localizations: dependency: transitive description: flutter @@ -231,10 +279,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" + sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" flutter_svg: dependency: "direct main" description: @@ -261,46 +309,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.2" - geocoding: - dependency: "direct main" - description: - name: geocoding - sha256: b34c0501bbbaf3190b85bef3078b27cf66c28a8915c6d3af50d67f356aa7da31 - url: "https://pub.dev" - source: hosted - version: "2.1.0" - geocoding_android: - dependency: transitive - description: - name: geocoding_android - sha256: "5a1fc0cec9b0497b44ca31c1fa8d1c891f3aded1053e6bb2eac075d3bd1bf046" - url: "https://pub.dev" - source: hosted - version: "2.1.0" - geocoding_ios: - dependency: transitive - description: - name: geocoding_ios - sha256: c85495ce8fb34e4fbd2dd8fc5f79263d622d9f88c4af948c965daf6b27a7f3a1 - url: "https://pub.dev" - source: hosted - version: "2.1.0" - geocoding_platform_interface: - dependency: transitive - description: - name: geocoding_platform_interface - sha256: "8848605d307d844d89937cdb4b8ad7dfa880552078f310fa24d8a460f6dddab4" - url: "https://pub.dev" - source: hosted - version: "2.0.1" geolocator: dependency: "direct main" description: name: geolocator - sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8" + sha256: "9d6eff112971b9f195271834b390fc0e1899a9a6c96225ead72efd5d4aaa80c7" url: "https://pub.dev" source: hosted - version: "9.0.2" + version: "10.0.0" geolocator_android: dependency: transitive description: @@ -313,10 +329,10 @@ packages: dependency: transitive description: name: geolocator_apple - sha256: "22b60ca3b8c0f58e6a9688ff855ee39ab813ca3f0c0609a48d282f6631266f2e" + sha256: "36527c555f4c425f7d8fa8c7c07d67b78e3ff7590d40448051959e1860c1cfb4" url: "https://pub.dev" source: hosted - version: "2.2.5" + version: "2.2.7" geolocator_platform_interface: dependency: transitive description: @@ -337,58 +353,82 @@ packages: dependency: transitive description: name: geolocator_windows - sha256: f5911c88e23f48b598dd506c7c19eff0e001645bdc03bb6fecb9f4549208354d + sha256: "463045515b08bd83f73e014359c4ad063b902eb3899952cfb784497ae6c6583b" url: "https://pub.dev" source: hosted - version: "0.1.1" + version: "0.2.0" + google_maps: + dependency: transitive + description: + name: google_maps + sha256: "555d5d736339b0478e821167ac521c810d7b51c3b2734e6802a9f046b64ea37a" + url: "https://pub.dev" + source: hosted + version: "6.3.0" google_maps_flutter: dependency: "direct main" description: name: google_maps_flutter - sha256: abefcb1e5e5c96bdd8084939dda555257af272c7972902ca46d5631092c1df68 + sha256: d4914cb38b3dcb62c39c085d968d434de0f8050f00f4d9f5ba4a7c7e004934cb url: "https://pub.dev" source: hosted - version: "2.2.8" + version: "2.5.0" google_maps_flutter_android: dependency: transitive description: name: google_maps_flutter_android - sha256: "9512c862df77c1f0fa5f445513dd3c57f5996f0a809dccb74e54b690ee4e3a0f" + sha256: e6cb018169e49332f88d23b1d2119b09e8ab4e7d3a1b889a1b7b3fd113e034ba url: "https://pub.dev" source: hosted - version: "2.4.15" + version: "2.5.1" google_maps_flutter_ios: dependency: transitive description: name: google_maps_flutter_ios - sha256: a9462a433bf3ebe60aadcf4906d2d6341a270d69d3e0fcaa8eb2b64699fcfb4f + sha256: "2a595c9789070786c654e9772ec0d1bb759ae37d2dd776291af5398531274e06" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.1" google_maps_flutter_platform_interface: dependency: transitive description: name: google_maps_flutter_platform_interface - sha256: "308f0af138fa78e8224d598d46ca182673874d0ef4d754b7157c073b5b4b8e0d" + sha256: a3e9e6896501e566d902c6c69f010834d410ef4b7b5c18b90c77e871c86b7907 url: "https://pub.dev" source: hosted - version: "2.2.7" + version: "2.4.1" + google_maps_flutter_web: + dependency: transitive + description: + name: google_maps_flutter_web + sha256: "05067c5aa762ebee44b7ef4902a311ed8cf891ef655e2798bae063aa3050c8d9" + url: "https://pub.dev" + source: hosted + version: "0.5.4+1" hexcolor: dependency: "direct main" description: name: hexcolor - sha256: e572c3346f4b26422a281dc4c10f83022131f56f7364837671b50f53c7adc5e7 + sha256: c07f4bbb9095df87eeca87e7c69e8c3d60f70c66102d7b8d61c4af0453add3f6 url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "3.0.1" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" http: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "0.13.6" http_parser: dependency: transitive description: @@ -401,42 +441,66 @@ packages: dependency: "direct main" description: name: image_picker - sha256: "9978d3510af4e6a902e545ce19229b926e6de6a1828d6134d3aab2e129a4d270" + sha256: b6951e25b795d053a6ba03af5f710069c99349de9341af95155d52665cb4607c url: "https://pub.dev" source: hosted - version: "0.8.7+5" + version: "0.8.9" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: c2f3c66400649bd132f721c88218945d6406f693092b2f741b79ae9cdb046e59 + sha256: d32a997bcc4ee135aebca8e272b7c517927aa65a74b9c60a81a2764ef1a0462d url: "https://pub.dev" source: hosted - version: "0.8.6+16" + version: "0.8.7+5" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - sha256: "98f50d6b9f294c8ba35e25cc0d13b04bfddd25dbc8d32fa9d566a6572f2c081c" + sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0" url: "https://pub.dev" source: hosted - version: "2.1.12" + version: "2.2.0" image_picker_ios: dependency: transitive description: name: image_picker_ios - sha256: d779210bda268a03b57e923fb1e410f32f5c5e708ad256348bcbf1f44f558fd0 + sha256: c5538cacefacac733c724be7484377923b476216ad1ead35a0d2eadcdc0fc497 url: "https://pub.dev" source: hosted - version: "0.8.7+4" + version: "0.8.8+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - sha256: "1991219d9dbc42a99aff77e663af8ca51ced592cd6685c9485e3458302d3d4f8" + sha256: ed9b00e63977c93b0d2d2b343685bed9c324534ba5abafbb3dfbd6a780b1b514 + url: "https://pub.dev" + source: hosted + version: "2.9.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" url: "https://pub.dev" source: hosted - version: "2.6.3" + version: "0.2.1+1" injector: dependency: "direct main" description: @@ -461,62 +525,70 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + js_wrapping: + dependency: transitive + description: + name: js_wrapping + sha256: e385980f7c76a8c1c9a560dfb623b890975841542471eade630b2871d243851c + url: "https://pub.dev" + source: hosted + version: "0.7.4" lints: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.1" local_auth: dependency: "direct main" description: name: local_auth - sha256: "0cf238be2bfa51a6c9e7e9cfc11c05ea39f2a3a4d3e5bb255d0ebc917da24401" + sha256: "7e6c63082e399b61e4af71266b012e767a5d4525dd6e9ba41e174fd42d76e115" url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" local_auth_android: dependency: transitive description: name: local_auth_android - sha256: c5e48c4a67fc0e5dd9b5725cc8766b67e2da9a54155c82c6e2ea4a0d1cf9ef93 + sha256: "9ad0b1ffa6f04f4d91e38c2d4c5046583e23f4cae8345776a994e8670df57fb1" url: "https://pub.dev" source: hosted - version: "1.0.28" + version: "1.0.34" local_auth_ios: dependency: transitive description: name: local_auth_ios - sha256: edc2977c5145492f3451db9507a2f2f284ee4f408950b3e16670838726761940 + sha256: "26a8d1ad0b4ef6f861d29921be8383000fda952e323a5b6752cf82ca9cf9a7a9" url: "https://pub.dev" source: hosted - version: "1.1.3" + version: "1.1.4" local_auth_platform_interface: dependency: transitive description: name: local_auth_platform_interface - sha256: "9e160d59ef0743e35f1b50f4fb84dc64f55676b1b8071e319ef35e7f3bc13367" + sha256: fc5bd537970a324260fda506cfb61b33ad7426f37a8ea5c461cf612161ebba54 url: "https://pub.dev" source: hosted - version: "1.0.7" + version: "1.0.8" local_auth_windows: dependency: transitive description: name: local_auth_windows - sha256: "19323b75ab781d5362dbb15dcb7e0916d2431c7a6dbdda016ec9708689877f73" + sha256: "505ba3367ca781efb1c50d3132e44a2446bccc4163427bc203b9b4d8994d97ea" url: "https://pub.dev" source: hosted - version: "1.0.8" + version: "1.0.10" logger: dependency: "direct main" description: name: logger - sha256: db2ff852ed77090ba9f62d3611e4208a3d11dfa35991a81ae724c113fcb3e3f7 + sha256: "7ad7215c15420a102ec687bb320a7312afd449bac63bfb1c60d9787c27b9767f" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" matcher: dependency: transitive description: @@ -541,6 +613,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" nested: dependency: transitive description: @@ -593,34 +673,34 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.2.0" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.11" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.1" path_provider_windows: dependency: transitive description: @@ -629,86 +709,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.7" - pedantic: - dependency: transitive - description: - name: pedantic - sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" - url: "https://pub.dev" - source: hosted - version: "1.11.1" permission_handler: dependency: "direct main" description: name: permission_handler - sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" + sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" url: "https://pub.dev" source: hosted - version: "10.2.0" + version: "10.4.3" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: d8cc6a62ded6d0f49c6eac337e080b066ee3bce4d405bd9439a61e1f1927bfe8 + sha256: d74e77a5ecd38649905db0a7d05ef16bed42ff263b9efb73ed794317c5764ec3 url: "https://pub.dev" source: hosted - version: "10.2.1" + version: "10.3.4" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: ee96ac32f5a8e6f80756e25b25b9f8e535816c8e6665a96b6d70681f8c4f7e85 + sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" url: "https://pub.dev" source: hosted - version: "9.0.8" + version: "9.1.4" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" + sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.11.3" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b + sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 url: "https://pub.dev" source: hosted - version: "0.1.2" + version: "0.1.3" petitparser: dependency: transitive description: name: petitparser - sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.4.0" platform: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.4" - process: - dependency: transitive - description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.dev" - source: hosted - version: "4.2.4" + version: "2.1.6" provider: dependency: "direct main" description: @@ -725,62 +789,70 @@ packages: url: "https://pub.dev" source: hosted version: "0.27.7" + sanitize_html: + dependency: transitive + description: + name: sanitize_html + sha256: "0a445f19bbaa196f5a4f93461aa066b94e6e025622eb1e9bc77872a5e25233a5" + url: "https://pub.dev" + source: hosted + version: "2.0.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022" + sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.2.1" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749" + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.1" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" + sha256: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" + sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" shimmer: dependency: "direct main" description: @@ -810,22 +882,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" sqflite: dependency: transitive description: name: sqflite - sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" url: "https://pub.dev" source: hosted - version: "2.2.8+4" + version: "2.3.0" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.5.0" stack_trace: dependency: transitive description: @@ -894,82 +974,82 @@ packages: dependency: transitive description: name: universal_io - sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d" + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.2" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" url: "https://pub.dev" source: hosted - version: "6.1.11" + version: "6.1.14" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51 + sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 url: "https://pub.dev" source: hosted - version: "6.0.35" + version: "6.1.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "6.1.5" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.7" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.5" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab" + sha256: ba140138558fcc3eead51a1c42e92a9fb074a1b1149ed3c73e66035b2ccd94f2 url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.19" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.8" uuid: dependency: transitive description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: e03928880bdbcbf496fb415573f5ab7b1ea99b9b04f669c01104d085893c3134 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.0.0" vector_math: dependency: transitive description: @@ -990,18 +1070,18 @@ packages: dependency: transitive description: name: xdg_directories - sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.3" xml: dependency: transitive description: name: xml - sha256: ac0e3f4bf00ba2708c33fbabbbe766300e509f8c82dbd4ab6525039813f7e2fb + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.3.0" sdks: - dart: ">=3.0.0-0 <4.0.0" - flutter: ">=3.3.0" + dart: ">=3.0.0 <4.0.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 3e04e24..ef7b31d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,18 +29,19 @@ dependencies: auto_size_text: any shimmer: ^2.0.0 local_auth: any - hexcolor: ^2.0.4 + hexcolor: ^3.0.1 cached_network_image: any url_launcher: ^6.1.7 badges: ^3.0.2 carousel_slider: ^4.2.1 dropdown_button2: ^2.0.0 flutter_inappwebview: ^5.7.2+3 + country_code_picker: ^3.0.0 # google google_maps_flutter: ^2.1.1 geolocator: any - geocoding: any +# geocoding: ^2.1.0 dev_dependencies: