From a841c232de09dda316289af39d36a443ca136cd4 Mon Sep 17 00:00:00 2001 From: Faiz Hashmi Date: Sun, 17 Sep 2023 15:03:59 +0300 Subject: [PATCH] Ad Module Commit --- lib/classes/consts.dart | 1 + lib/extensions/string_extensions.dart | 71 +- .../advertisment_models/ad_details_model.dart | 28 +- .../reserved_ads_models.dart | 36 + lib/models/generic_resp_model.dart | 123 +-- .../pay_order_detail_resp_model.dart | 5 + lib/repositories/ads_repo.dart | 30 +- lib/services/payments_service.dart | 3 +- lib/utils/enums.dart | 6 +- lib/utils/utils.dart | 19 +- lib/view_models/ad_view_model.dart | 52 +- lib/view_models/payment_view_model.dart | 41 +- lib/views/advertisement/ads_detail_view.dart | 842 +++++++++--------- lib/views/advertisement/ads_list.dart | 7 +- .../advertisement/bottom_sheet_content.dart | 1 - lib/views/payments/payment_methods_view.dart | 6 +- lib/views/user/login_with_password_page.dart | 2 +- lib/widgets/button/show_fill_button.dart | 37 +- 18 files changed, 735 insertions(+), 575 deletions(-) create mode 100644 lib/models/advertisment_models/reserved_ads_models.dart diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 8a063a9..707b7cc 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -93,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"; diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index 02a0905..2f07f17 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -182,6 +182,63 @@ 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) { @@ -199,15 +256,17 @@ extension AdReserveStatusEnum on int { } extension AdOwnerEnum on int { - AdOwner toAdOwnerEnum() { - if (this == 0) { - return AdOwner.customer; + CreatedByRoleEnum toCreatedByRoleEnum() { + if (this == -1) { + return CreatedByRoleEnum.allAds; } else if (this == 1) { - return AdOwner.provider; + return CreatedByRoleEnum.admin; } else if (this == 2) { - return AdOwner.mowater; + return CreatedByRoleEnum.customer; + } else if (this == 3) { + return CreatedByRoleEnum.provider; } - return AdOwner.customer; + return CreatedByRoleEnum.customer; } } diff --git a/lib/models/advertisment_models/ad_details_model.dart b/lib/models/advertisment_models/ad_details_model.dart index c14f6e2..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'; @@ -38,7 +40,9 @@ class AdDetailsModel { AdPostStatus? adPostStatus; AdReserveStatus? adReserveStatus; bool? isMyAd; - AdOwner? adOwnerEnum; + String? phoneNo; + String? whatsAppNo; + CreatedByRoleEnum? createdByRoleEnum; AdDetailsModel( {this.id, @@ -74,9 +78,17 @@ class AdDetailsModel { this.adPostStatus, this.adReserveStatus, this.isMyAd, - this.adOwnerEnum, + this.phoneNo, + this.whatsAppNo, + this.createdByRoleEnum, this.modifiedOn}); + 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']; @@ -88,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']; @@ -119,11 +125,13 @@ 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; - // adReserveStatus = (json['adReserveStatusID'] as int).toAdRserveStatusEnum(); - adOwnerEnum = (json['statusID'] as int).toAdOwnerEnum(); + createdByRoleEnum = CreatedByRoleEnum.admin; + // createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum(); isMyAd = isMyAds; } 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/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/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/repositories/ads_repo.dart b/lib/repositories/ads_repo.dart index df78709..fb54c80 100644 --- a/lib/repositories/ads_repo.dart +++ b/lib/repositories/ads_repo.dart @@ -4,11 +4,14 @@ 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(); @@ -47,6 +50,8 @@ abstract class AdsRepo { Future> getAllAds({required bool isMyAds}); + Future> getMyReservedAds(); + Future> getMyAds(); } @@ -315,27 +320,46 @@ class AdsRepoImp implements AdsRepo { postParams, token: token, ); - log("value: ${adsGenericModel}"); return Future.value(adsGenericModel); } @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) => MyReservedAdsRespModel.fromJson(adsGenericModel.data[index])); + return vehicleAdsDetails; + } + @override Future> getMyAds() async { var params = { 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 0cc7d6f..d005c0f 100644 --- a/lib/utils/enums.dart +++ b/lib/utils/enums.dart @@ -19,11 +19,7 @@ enum AdReserveStatus { cancelledByAdmin, } -enum AdOwner { - customer, - provider, - mowater, -} +enum CreatedByRoleEnum { customer, provider, admin, allAds } enum AdPostStatus { pendingForReview, 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 e7cc19c..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'; @@ -71,6 +72,7 @@ class AdVM extends BaseVM { List exploreAdsFilteredList = []; List myAdsFilteredList = []; List myAds = []; + List myReservedAdsRespModel = []; List myActiveAdsForHome = []; List vehicleDamageCards = []; @@ -140,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(); } @@ -151,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 = [ @@ -172,7 +174,7 @@ class AdVM extends BaseVM { notifyListeners(); } - applyFilterOnExploreAds({required int index}) { + applyFilterOnExploreAds({required int index, required CreatedByRoleEnum createdByRoleFilter}) { if (exploreAdsFilterOptions.isEmpty) return; for (var value in exploreAdsFilterOptions) { value.isSelected = false; @@ -180,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(); } @@ -208,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); } @@ -844,7 +868,7 @@ class AdVM extends BaseVM { currentProgressStep = AdCreationStepsEnum.vehicleDetails; resetValues(); updateIsExploreAds(false); - applyFilterOnMyAds(index: 1, selectedFilterId: 1); + applyFilterOnMyAds(index: 1, adPostStatusEnum: AdPostStatus.pendingForReview); //pending for review navigateReplaceWithName(context, AppRoutes.dashboard); } catch (e) { Utils.hideLoading(context); @@ -1044,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/ads_detail_view.dart b/lib/views/advertisement/ads_detail_view.dart index 611a945..30465cf 100644 --- a/lib/views/advertisement/ads_detail_view.dart +++ b/lib/views/advertisement/ads_detail_view.dart @@ -22,17 +22,16 @@ class AdsDetailView extends StatelessWidget { @override Widget build(BuildContext context) { - print("adId: ${adDetails.isMyAd}"); + print("adId: ${adDetails.id}"); + print("statusID: ${adDetails.adPostStatus}"); return Scaffold( appBar: CustomAppBar( title: "Ads", profileImageUrl: MyAssets.bnCar, isRemoveBackButton: false, isDrawerEnabled: false, - actions: [Icon(Icons.chat_outlined).paddingOnly(right: 21)], - onTap: () { - print("heyyyy"); - }, + actions: [const Icon(Icons.chat_outlined).paddingOnly(right: 21)], + onTap: () {}, ), body: Container( padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21), @@ -116,9 +115,7 @@ class AdsDetailView extends StatelessWidget { ], ), 14.height, - adDetails.isMyAd ?? false - ? BuildAdDetailsActionButtonForMyAds(adPostStatus: adDetails.adPostStatus!, adId: adDetails.id!) - : BuildAdDetailsActionButtonForExploreAds(adPostStatus: adDetails.adPostStatus!, adId: adDetails.id!), + adDetails.isMyAd ?? false ? BuildAdDetailsActionButtonForMyAds(adDetailsModel: adDetails) : BuildAdDetailsActionButtonForExploreAds(adDetailsModel: adDetails), ], ), ) @@ -130,73 +127,159 @@ class AdsDetailView extends StatelessWidget { } class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { - final AdPostStatus adPostStatus; - final int adId; + final AdDetailsModel adDetailsModel; - const BuildAdDetailsActionButtonForExploreAds({Key? key, required this.adPostStatus, required this.adId}) : super(key: key); + const BuildAdDetailsActionButtonForExploreAds({Key? key, required this.adDetailsModel}) : super(key: key); - Widget pendingForPaymentAction(BuildContext context, {required int adID}) { - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - children: [ - Expanded( - child: ShowFillButton( - maxHeight: 55, - title: "Pay Now", - onPressed: () { - navigateWithName(context, AppRoutes.paymentMethodsView); - }, - ), - ), - ], - ), - 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), - ), - ), - ], - ) - ], - ); - } - - Widget markAsSoldAction(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Row( - children: [ - Expanded( - child: ShowFillButton( - maxHeight: 55, - title: "Mark As Sold", - onPressed: () {}, - ), - ), - ], - ), - 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), - ), - ), - ], - ) - ], - ); + 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) { @@ -217,151 +300,7 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { ); } - Widget defaultAction(BuildContext context) { - 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 reserveAdAction(BuildContext context, AdDetailsModel adDetailsModel) { return Row( children: [ Expanded( @@ -369,67 +308,274 @@ class BuildAdDetailsActionButtonForExploreAds extends StatelessWidget { maxHeight: 55, title: "Reserve Ad", onPressed: () { - reserveAdPriceBreakDownClicked(context); + reserveAdPriceBreakDownClicked(context, adDetailsModel); // navigateWithName(context, AppRoutes.paymentMethodsView); }, ), ), - 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: 2)), - child: const Icon(Icons.phone, color: MyColors.black), - ).onPress(() {}), + 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: adId); - switch (adPostStatus) { - case AdPostStatus.pendingForPayment: - return pendingForPaymentAction(context, adID: adId); - case AdPostStatus.active: - return markAsSoldAction(context); - case AdPostStatus.reserved: - return cancelReservationAction(context); - - case AdPostStatus.buyingService: - case AdPostStatus.reserveCancel: - case AdPostStatus.rejected: - case AdPostStatus.cancelled: - case AdPostStatus.pendingForPost: - case AdPostStatus.pendingForReview: - return pendingForPaymentAction(context, adID: adId); - - return defaultAction(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); - return pendingForPaymentAction(context, adID: adId); - case AdPostStatus.sold: - case AdPostStatus.expired: - break; + 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(); } - return defaultAction(context); } } class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { - final AdPostStatus adPostStatus; - final int adId; + final AdDetailsModel adDetailsModel; - const BuildAdDetailsActionButtonForMyAds({Key? key, required this.adPostStatus, required this.adId}) : super(key: key); + 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( @@ -442,7 +588,7 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { maxHeight: 55, title: "Pay Now", onPressed: () { - navigateWithName(context, AppRoutes.paymentMethodsView); + navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypesEnum.ads); }, ), ), @@ -480,17 +626,18 @@ class BuildAdDetailsActionButtonForMyAds 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: () {}, ), ), ], - ) + ), ], ); } @@ -514,150 +661,6 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { } Widget defaultAction(BuildContext context) { - 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, - ], - )); - }); - } - return Row( children: [ Expanded( @@ -693,10 +696,10 @@ class BuildAdDetailsActionButtonForMyAds 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: @@ -707,10 +710,9 @@ class BuildAdDetailsActionButtonForMyAds extends StatelessWidget { case AdPostStatus.cancelled: case AdPostStatus.pendingForPost: case AdPostStatus.pendingForReview: - break; - return defaultAction(context); + return pendingForReviewAction(context, adID: adDetailsModel.id!); - return pendingForPaymentAction(context, adID: adId); + // return pendingForPaymentAction(context, adID: adId); case AdPostStatus.sold: case AdPostStatus.expired: break; diff --git a/lib/views/advertisement/ads_list.dart b/lib/views/advertisement/ads_list.dart index c5e0e26..afdaa3f 100644 --- a/lib/views/advertisement/ads_list.dart +++ b/lib/views/advertisement/ads_list.dart @@ -53,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), ); } } @@ -99,10 +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), diff --git a/lib/views/advertisement/bottom_sheet_content.dart b/lib/views/advertisement/bottom_sheet_content.dart index 6698f63..6a270ba 100644 --- a/lib/views/advertisement/bottom_sheet_content.dart +++ b/lib/views/advertisement/bottom_sheet_content.dart @@ -104,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, ) ], 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 c3d4005..0d74b32 100644 --- a/lib/views/user/login_with_password_page.dart +++ b/lib/views/user/login_with_password_page.dart @@ -29,7 +29,7 @@ class _LoginWithPasswordState extends State { ClassType type = ClassType.EMAIL; //TODO: ONLY FOR DEVELOPMENT PURPOSE - String phoneNum = "966504278212", password = "Fa@123"; + 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, + ), ), ); }