Compare commits

...

4 Commits

Author SHA1 Message Date
Faiz Hashmi 967306f75d Merge branch 'aamir_dev' into faiz_development_common
# Conflicts:
#	lib/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart
7 months ago
Faiz Hashmi da9c03a30f 16 April, 2025 7 months ago
Faiz Hashmi 6bea3daf78 SelfPickup Flow Completed 7 months ago
Aamir Muhammad 3a3868ed7f request subscription check 7 months ago

@ -808,5 +808,11 @@
"specialRequestsChats": "دردشات الطلبات الخاصة",
"selectDeliveryOption": "اختر خيار التوصيل",
"deliveryOptions": "خيارات التوصيل",
"selfPickup": "الالتقاط الذاتي"
"selfPickup": "الالتقاط الذاتي",
"updateYourLocationInfo": "قم بتحديث معلومات موقعك",
"initiateSelfPickup": "بدء الاستلام الذاتي",
"selfPickupStatus": "حالة الالتقاط الذاتي",
"myDraftAds": "مسودتي للإعلانات",
"scheduleDeletedSuccessfully": "تم حذف الجدول بنجاح",
"addValidAddress": "رجى إضافة عنوان صالح"
}

@ -806,5 +806,11 @@
"specialRequestsChats": "Special Requests Chats",
"selectDeliveryOption": "Select Delivery Option",
"deliveryOptions": "Delivery Options",
"selfPickup": "Self Pickup"
"selfPickup": "Self Pickup",
"updateYourLocationInfo": "Update your location information",
"initiateSelfPickup": "Initiate Self Pickup",
"selfPickupStatus": "Self Pickup Status",
"myDraftAds": "My Draft Ads",
"scheduleDeletedSuccessfully": "The schedule has been deleted successfully",
"addValidAddress": "Please add a valid address"
}

@ -178,10 +178,12 @@ class ApiConsts {
static String updateRequestProvider = "${baseUrlServices}api/RequestManagement/Request_StatusUpdate_Provider";
static String requestOffersSpsGet = "${baseUrlServices}api/RequestManagement/Request_OfferSPs_Get";
static String getServiceRequestsForProvider = "${baseUrlServices}api/RequestManagement/Request_ServiceProvider";
static String requestOfferUpdateDeliveryOptionByCustomer = "${baseUrlServices}api/RequestManagement/RequestOffer_UpdateDeliveryByCustomer";
static String requestUpdateAdditionalAddress = "${baseUrlServices}api/RequestManagement/Request_UpdateAdditionalAddress";
//Shipping
static String shippingRequestStatusUpdate = "${baseUrlServices}api/RequestManagement/ShippingRequestStatus_Update";
static String shippingRequestStatusUpdate = "${baseUrlServices}api/RequestManagement/ShippingRequestStatus_Update";
static String shippingRequestStatusGet = "${baseUrlServices}api/RequestManagement/ShippingRequestStatus_Get";
static String selfPickupRequestStatusGet = "${baseUrlServices}api/RequestManagement/SelfPickUpRequestStatus_Get";
static String selfPickupRequestStatusUpdate = "${baseUrlServices}api/RequestManagement/SelfPickUpRequestStatus_Update";

@ -9,6 +9,7 @@ import 'package:mc_common_app/views/advertisement/ads_buyer_chats_view.dart';
import 'package:mc_common_app/views/advertisement/ads_detail_view/ads_detail_view.dart';
import 'package:mc_common_app/views/advertisement/ads_filter_view.dart';
import 'package:mc_common_app/views/advertisement/create_ad_view.dart';
import 'package:mc_common_app/views/advertisement/my_draft_ads_view.dart';
import 'package:mc_common_app/views/advertisement/select_ad_type_view.dart';
import 'package:mc_common_app/views/chat/chat_view.dart';
import 'package:mc_common_app/views/payments/payment_methods_view.dart';
@ -130,6 +131,7 @@ class AppRoutes {
static const String createAdView = "/createAdView";
static const String adsFilterView = "/adsFilterView";
static const String adsBuyerChatsListView = "/adsBuyersChatListView";
static const String myDraftAdsView = "/myDraftAdsView";
// Payments
static const String paymentMethodsView = "/paymentMethodsView";
@ -208,6 +210,7 @@ class AppRoutes {
AppRoutes.adsDetailView: (context) => AdsDetailView(adDetails: ModalRoute.of(context)!.settings.arguments as AdDetailsModel),
AppRoutes.createAdView: (context) => const CreateAdView(),
AppRoutes.adsFilterView: (context) => const AdsFilterView(),
AppRoutes.myDraftAdsView: (context) => const MyDraftAdsView(),
AppRoutes.selectAdTypeView: (context) => SelectAdTypeView(arguments: ModalRoute.of(context)!.settings.arguments as List<dynamic>),
AppRoutes.chatView: (context) => ChatView(chatViewArguments: ModalRoute.of(context)!.settings.arguments as ChatViewArguments),
AppRoutes.adsBuyerChatsListView: (context) => AdsBuyerChatsView(buyersListViewArguments: ModalRoute.of(context)!.settings.arguments as List<BuyersChatForAdsModel>),

@ -182,6 +182,8 @@ extension RequestEnum on int {
return RequestStatusEnum.shipping;
} else if (this == 8) {
return RequestStatusEnum.delivery;
} else if (this == 9) {
return RequestStatusEnum.selfPickup;
} else {
return RequestStatusEnum.pending;
}
@ -207,6 +209,8 @@ extension RequestStatusEnumToInt on RequestStatusEnum {
return 7;
case RequestStatusEnum.delivery:
return 8;
case RequestStatusEnum.selfPickup:
return 9;
case RequestStatusEnum.pending:
return 0;
@ -1008,7 +1012,7 @@ extension SelfPickupStatusEnumExt on int {
if (this == -1) {
return SelfPickupRequestStatusEnum.allRequests;
} else if (this == 0) {
return SelfPickupRequestStatusEnum.allRequests;
return SelfPickupRequestStatusEnum.pending;
} else if (this == 1) {
return SelfPickupRequestStatusEnum.preparingToCollect;
} else if (this == 2) {
@ -1024,6 +1028,8 @@ extension SelfPickupStatusEnumToInt on SelfPickupRequestStatusEnum {
int getIdFromSelfPickupStatusEnum() {
switch (this) {
case SelfPickupRequestStatusEnum.allRequests:
return -1;
case SelfPickupRequestStatusEnum.pending:
return 0;
case SelfPickupRequestStatusEnum.preparingToCollect:
return 1;
@ -1118,3 +1124,36 @@ extension IntToInviteType on int {
}
}
}
extension AdCreationStepsToInt on AdCreationStepsEnum {
int toIntFromStepsEnum() {
switch (this) {
case AdCreationStepsEnum.vehicleDetails:
return 1;
case AdCreationStepsEnum.damageParts:
return 2;
case AdCreationStepsEnum.adDuration:
return 3;
case AdCreationStepsEnum.reviewAd:
return 4;
}
}
}
extension AdCreationStepsFromInt on int {
AdCreationStepsEnum toAdCreationStepsEnumFromInt() {
switch (this) {
case 0:
return AdCreationStepsEnum.vehicleDetails;
case 1:
return AdCreationStepsEnum.vehicleDetails;
case 2:
return AdCreationStepsEnum.damageParts;
case 3:
return AdCreationStepsEnum.adDuration;
case 4:
return AdCreationStepsEnum.reviewAd;
}
return AdCreationStepsEnum.vehicleDetails;
}
}

@ -824,7 +824,13 @@ class CodegenLoader extends AssetLoader{
"specialRequestsChats": "دردشات الطلبات الخاصة",
"selectDeliveryOption": "اختر خيار التوصيل",
"deliveryOptions": "خيارات التوصيل",
"selfPickup": "الالتقاط الذاتي"
"selfPickup": "الالتقاط الذاتي",
"updateYourLocationInfo": "قم بتحديث معلومات موقعك",
"initiateSelfPickup": "بدء الاستلام الذاتي",
"selfPickupStatus": "حالة الالتقاط الذاتي",
"myDraftAds": "مسودتي للإعلانات",
"scheduleDeletedSuccessfully": "تم حذف الجدول بنجاح",
"addValidAddress": "رجى إضافة عنوان صالح"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1634,7 +1640,13 @@ static const Map<String,dynamic> en_US = {
"specialRequestsChats": "Special Requests Chats",
"selectDeliveryOption": "Select Delivery Option",
"deliveryOptions": "Delivery Options",
"selfPickup": "Self Pickup"
"selfPickup": "Self Pickup",
"updateYourLocationInfo": "Update your location information",
"initiateSelfPickup": "Initiate Self Pickup",
"selfPickupStatus": "Self Pickup Status",
"myDraftAds": "My Draft Ads",
"scheduleDeletedSuccessfully": "The schedule has been deleted successfully",
"addValidAddress": "Please add a valid address"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -788,5 +788,11 @@ abstract class LocaleKeys {
static const selectDeliveryOption = 'selectDeliveryOption';
static const deliveryOptions = 'deliveryOptions';
static const selfPickup = 'selfPickup';
static const updateYourLocationInfo = 'updateYourLocationInfo';
static const initiateSelfPickup = 'initiateSelfPickup';
static const selfPickupStatus = 'selfPickupStatus';
static const myDraftAds = 'myDraftAds';
static const scheduleDeletedSuccessfully = 'scheduleDeletedSuccessfully';
static const addValidAddress = 'addValidAddress';
}

@ -2,7 +2,6 @@ import 'package:logger/logger.dart';
Logger logger = Logger(printer: PrettyPrinter(printEmojis: false, colors: true, printTime: false));
bool disableThingsForQA = true;
// Language Tile in Settings
@ -12,4 +11,3 @@ bool disableThingsForQA = true;
// todo terminal command to genertate translation keys
// flutter pub run easy_localization:generate --source-dir ./assets/langs -f keys -o locale_keys.g.dart
// command to generate languages data from json

@ -32,6 +32,7 @@ class AdDetailsModel {
String? qrCodePath;
bool? isCustomerAcknowledged;
int? createdByRole;
AdCreationStepsEnum? adCreationStepsEnum;
int? totalViews;
String? createdOn;
double? priceExcludingDiscount;
@ -80,6 +81,7 @@ class AdDetailsModel {
this.qrCodePath,
this.isCustomerAcknowledged,
this.createdByRole,
this.adCreationStepsEnum,
this.totalViews,
this.createdOn,
this.priceExcludingDiscount,
@ -135,10 +137,11 @@ class AdDetailsModel {
taxPrice = json['taxPrice'];
totalPrice = json['totalPrice'];
userID = json['userID'];
vehiclePostingID = json['vehiclePostingID'];
vehiclePostingID = (json['vehiclePostingID'] == null || json['vehiclePostingID'] == 0) ? json['id'] : 0;
qrCodePath = json['qrCodePath'];
isCustomerAcknowledged = json['isCustomerAcknowledged'];
createdByRole = json['createdByRole'];
adCreationStepsEnum = json['stepNo'] != null ? (json['stepNo'] as int).toAdCreationStepsEnumFromInt() : AdCreationStepsEnum.vehicleDetails;
totalViews = json['totalViews'];
createdOn = json['createdOn'];
priceExcludingDiscount = json['priceExcludingDiscount'];
@ -153,7 +156,7 @@ class AdDetailsModel {
adOwnerName = json['vehicle'] != null ? (json['vehicle']['adOwnerName'] ?? "") : "";
adOwnerEmail = json['vehicle'] != null ? (json['vehicle']['adOwnerEmail'] ?? "") : "";
adOwnerDetails = (json['vehicle'] != null && json['vehicle']['aDsUser'] != null) ? (AdOwnerDetails.fromJson(json['vehicle']['aDsUser'])) : null;
adPostStatus = (json['statusID'] as int).toAdPostEnum();
adPostStatus = ((json['statusID'] ?? 1) as int).toAdPostEnum();
adReserveStatus = AdReserveStatus.defaultStatus;
createdByRoleEnum = (json['createdByRole'] as int).toCreatedByRoleEnum();
isMyAd = isMyAds;

@ -10,17 +10,22 @@ class RequestModel {
RequestStatusEnum requestStatus;
int? shippingStatus;
ShippingRequestStatusEnum? shippingStatusEnum;
SelfPickupRequestStatusEnum? selfPickupRequestStatusEnum;
String cityName;
String vehicleTypeName;
String countryName;
String customerName;
String customerID;
String address;
String additionalAddressDetails;
dynamic serviceProviders;
int offerCount;
int id;
int customerId;
bool isChatted;
bool isOfferAccepted;
RequestDeliveryOptionEnum offerDeliveryOption;
RequestDeliveryOptionEnum selectedDeliveryOptionByCustomer;
String customerUserID;
dynamic customer;
String brand;
@ -50,6 +55,7 @@ class RequestModel {
required this.requestStatus,
required this.shippingStatus,
required this.shippingStatusEnum,
required this.selfPickupRequestStatusEnum,
required this.cityName,
required this.vehicleTypeName,
required this.countryName,
@ -60,9 +66,13 @@ class RequestModel {
required this.id,
required this.customerId,
required this.isChatted,
required this.isOfferAccepted,
required this.offerDeliveryOption,
required this.selectedDeliveryOptionByCustomer,
required this.customerUserID,
required this.customer,
required this.address,
required this.additionalAddressDetails,
required this.brand,
required this.model,
required this.year,
@ -102,17 +112,22 @@ class RequestModel {
requestStatus: (json['requestStatus'] as int).toRequestStatusEnum(),
shippingStatus: json['shippingRequestStatus'],
shippingStatusEnum: json['shippingRequestStatus'] != null ? (json['shippingRequestStatus'] as int).toShippingStatusEnum() : ShippingRequestStatusEnum.pending,
selfPickupRequestStatusEnum: json['selfPickupRequestStatus'] != null ? (json['selfPickupRequestStatus'] as int).toSelfPickupStatusEnum() : SelfPickupRequestStatusEnum.preparingToCollect,
cityName: json["cityName"],
vehicleTypeName: json["vehicleTypeName"],
countryName: json["countryName"],
customerName: json["customerName"] ?? "",
address: json["address"] ?? "",
additionalAddressDetails: json['additionalAddress'] ?? "",
customerID: json["customerUserID"],
serviceProviders: json["serviceProviders"],
offerCount: json["offerCount"],
id: json["id"],
customerId: json["customerID"],
isChatted: json["isChatted"],
isOfferAccepted: json["isOfferAccepted"],
offerDeliveryOption: ((json["offerDeliveryOption"] ?? 0) as int).toRequestDeliveryOptionEnum(),
selectedDeliveryOptionByCustomer: ((json["deliveryOption"] ?? 0) as int).toRequestDeliveryOptionEnum(),
customerUserID: json["customerUserID"],
customer: json["customer"],
brand: json["brand"],

@ -5,9 +5,10 @@ class ShippingRequestModel {
int? id;
int? requestID;
Request? request;
int? shippingStatus;
int? pickupOrshippingStatus;
ShippingRequestStatusEnum? shippingStatusEnum;
String? deliveredOn;
SelfPickupRequestStatusEnum? selfPickupRequestStatusEnum;
String? deliveredorCollectedOn;
String? comment;
String? createdOn;
int? customerID;
@ -19,8 +20,8 @@ class ShippingRequestModel {
this.id,
this.requestID,
this.request,
this.shippingStatus,
this.deliveredOn,
this.pickupOrshippingStatus,
this.deliveredorCollectedOn,
this.comment,
this.createdOn,
this.customerID,
@ -29,13 +30,15 @@ class ShippingRequestModel {
this.vehicleType,
});
ShippingRequestModel.fromJson(Map<String, dynamic> json) {
ShippingRequestModel.fromJsonShipping(Map<String, dynamic> json, bool isForShipping) {
id = json['id'];
requestID = json['requestID'];
request = json['request'] != null ? Request.fromJson(json['request']) : null;
shippingStatus = json['shippingStatus'];
shippingStatusEnum = json['shippingStatus'] != null ? (json['shippingStatus'] as int).toShippingStatusEnum() : ShippingRequestStatusEnum.initiated;
deliveredOn = json['deliveredOn'];
pickupOrshippingStatus = isForShipping ? json['shippingStatus'] : json['selfPickUpStatus'];
shippingStatusEnum = isForShipping ? (json['shippingStatus'] != null ? (json['shippingStatus'] as int).toShippingStatusEnum() : ShippingRequestStatusEnum.initiated) : null;
selfPickupRequestStatusEnum =
isForShipping ? null : (json['selfPickUpStatus'] != null ? (json['selfPickUpStatus'] as int).toSelfPickupStatusEnum() : SelfPickupRequestStatusEnum.preparingToCollect);
deliveredorCollectedOn = isForShipping ? json['deliveredOn'] : json['collectedOn'];
comment = json['comment'];
createdOn = json['createdOn'];
customerID = json['customerID'];

@ -25,6 +25,8 @@ abstract class AdsRepo {
Future<GenericRespModel> createOrUpdateAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew, required bool isExtendAdEditEnabled});
Future<GenericRespModel> createOrUpdateDraftAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew, required AdCreationStepsEnum stepNo});
Future<List<AdDetailsModel>> getAllAds({
required bool isMyAds,
AdPostStatus? adPostStatus,
@ -138,7 +140,7 @@ class AdsRepoImp implements AdsRepo {
"imageName": element.imageName,
"imageUrl": element.imageUrl,
"imageStr": element.imageStr,
"vehiclePostingID": element.vehiclePostingID ?? 0,
"vehiclePostingID": isCreateNew ? 0 : element.vehiclePostingID ?? 0,
"vehiclePosting": null,
};
vehiclePostingImages.add(imageMap);
@ -155,14 +157,14 @@ class AdsRepoImp implements AdsRepo {
"comment": element.comment,
"vehicleImageBase64": element.vehicleImageBase64,
"vehicleDamagePartID": element.vehicleDamagePartID,
"vehiclePostingID": element.vehiclePostingID ?? 0,
"vehiclePostingID": isCreateNew ? 0 : element.vehiclePostingID ?? 0,
"isActive": true
};
vehiclePostingDamageParts.add(imageMap);
});
var postParams = {
"ads": {
"id": adsCreationPayloadModel.ads!.id ?? 0,
"id": isCreateNew ? 0 : adsCreationPayloadModel.ads!.id ?? 0,
"adsDurationID": adsCreationPayloadModel.ads!.adsDurationID,
"startDate": adsCreationPayloadModel.ads!.startDate,
"countryId": adsCreationPayloadModel.ads!.countryId,
@ -172,7 +174,7 @@ class AdsRepoImp implements AdsRepo {
"isOnWhatsApp": adsCreationPayloadModel.ads!.isOnWhatsApp ?? false,
},
"vehiclePosting": {
"id": adsCreationPayloadModel.vehiclePosting!.id ?? 0,
"id": isCreateNew ? 0 : adsCreationPayloadModel.vehiclePosting!.id ?? 0,
"userID": adsCreationPayloadModel.vehiclePosting!.userID,
"vehicleType": adsCreationPayloadModel.vehiclePosting!.vehicleType,
"vehicleModelID": adsCreationPayloadModel.vehiclePosting!.vehicleModelID,
@ -215,6 +217,95 @@ class AdsRepoImp implements AdsRepo {
return Future.value(adsGenericModel);
}
@override
Future<GenericRespModel> createOrUpdateDraftAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew, required AdCreationStepsEnum stepNo}) async {
int sellerTypeID = AppState().getUser.data!.userInfo!.roleId ?? 0;
List vehiclePostingImages = [];
List vehiclePostingDamageParts = [];
if (adsCreationPayloadModel.vehiclePosting!.vehiclePostingImages != null) {
adsCreationPayloadModel.vehiclePosting!.vehiclePostingImages?.forEach(
(element) {
var imageMap = {
"id": element.id ?? 0,
"imageName": element.imageName,
"imageUrl": element.imageUrl,
"imageStr": element.imageStr,
"vehiclePostingDraftID": element.vehiclePostingID ?? 0,
"vehiclePosting": null,
};
vehiclePostingImages.add(imageMap);
},
);
}
if (adsCreationPayloadModel.vehiclePosting!.vehiclePostingDamageParts != null) {
adsCreationPayloadModel.vehiclePosting!.vehiclePostingDamageParts?.forEach((element) {
var imageMap = {
"id": element.id ?? 0,
"comment": element.comment,
"vehicleImageBase64": element.vehicleImageBase64,
"vehicleDamagePartID": element.vehicleDamagePartID,
"vehiclePostingDraftID": element.vehiclePostingID ?? 0,
"isActive": true
};
vehiclePostingDamageParts.add(imageMap);
});
}
var postParams = {
"adsDraft": {
"id": adsCreationPayloadModel.ads!.id ?? 0,
"adsDurationID": adsCreationPayloadModel.ads!.adsDurationID,
"startDate": adsCreationPayloadModel.ads!.startDate,
"countryId": adsCreationPayloadModel.ads!.countryId,
"specialServiceIDs": adsCreationPayloadModel.ads!.specialServiceIDs,
"isMCHandled": false,
"showContactDetail": adsCreationPayloadModel.ads!.showContactDetail ?? false,
"isOnWhatsApp": adsCreationPayloadModel.ads!.isOnWhatsApp ?? false,
},
"vehiclePostingDraft": {
"id": adsCreationPayloadModel.vehiclePosting!.id ?? 0,
"userID": adsCreationPayloadModel.vehiclePosting!.userID,
"vehicleType": adsCreationPayloadModel.vehiclePosting!.vehicleType,
"vehicleModelID": adsCreationPayloadModel.vehiclePosting!.vehicleModelID,
"vehicleModelYearID": adsCreationPayloadModel.vehiclePosting!.vehicleModelYearID,
"vehicleColorID": adsCreationPayloadModel.vehiclePosting!.vehicleColorID,
"vehicleCategoryID": adsCreationPayloadModel.vehiclePosting!.vehicleCategoryID,
"vehicleConditionID": adsCreationPayloadModel.vehiclePosting!.vehicleConditionID,
"vehicleMileageID": adsCreationPayloadModel.vehiclePosting!.vehicleMileageID,
"vehicleTransmissionID": adsCreationPayloadModel.vehiclePosting!.vehicleTransmissionID,
"vehicleSellerTypeID": sellerTypeID,
"cityID": adsCreationPayloadModel.vehiclePosting!.cityID,
"price": adsCreationPayloadModel.vehiclePosting!.price,
"vehicleVIN": adsCreationPayloadModel.vehiclePosting!.vehicleVIN,
"vehicleDescription": adsCreationPayloadModel.vehiclePosting!.vehicleDescription,
"vehicleTitle": adsCreationPayloadModel.vehiclePosting!.vehicleTitle,
"vehicleDescriptionN": adsCreationPayloadModel.vehiclePosting!.vehicleDescription,
"isFinanceAvailable": adsCreationPayloadModel.vehiclePosting!.isFinanceAvailable,
"warantyYears": adsCreationPayloadModel.vehiclePosting!.warantyYears,
"demandAmount": adsCreationPayloadModel.vehiclePosting!.demandAmount,
"vehiclePostingImagesDraft": vehiclePostingImages,
"vehiclePostingDamagePartsDraft": vehiclePostingDamageParts,
"mobileNo": adsCreationPayloadModel.vehiclePosting!.phoneNo,
"whatsAppNo": adsCreationPayloadModel.vehiclePosting!.whatsAppNo,
// "adStatus": 1,
},
"stepNo": stepNo.toIntFromStepsEnum(),
};
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
isCreateNew ? ApiConsts.adsSingleStepDraftCreate : ApiConsts.adsSingleStepDraftUpdate,
postParams,
token: token,
);
return Future.value(adsGenericModel);
}
@override
Future<List<AdDetailsModel>> getMyDraftAds({int? page}) async {
var draftAdsParams = {
@ -226,7 +317,7 @@ class AdsRepoImp implements AdsRepo {
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
ApiConsts.vehicleAdsGet,
ApiConsts.getMyDraftAds,
queryParameters: draftAdsParams,
);
List<AdDetailsModel> vehicleAdsDetails = List.generate(

@ -58,6 +58,8 @@ abstract class RequestRepo {
Future<GenericRespModel> updateRequestOfferStatus({required RequestOfferStatusEnum requestOfferStatusEnum, required int requestOfferId, required String comments});
Future<GenericRespModel> updateRequestDeliveryOptionByCustomer({required int requestID, required int requestOfferId, required RequestDeliveryOptionEnum deliveryOptionEnum});
Future<GenericRespModel> updateRequestOfferFromProvider({
required String message,
required int requestId,
@ -71,6 +73,8 @@ abstract class RequestRepo {
required List requestImages,
required RequestOfferStatusEnum requestOfferStatusEnum,
});
Future<GenericRespModel> updateRequestAdditionalAddress({required int requestID, required String additionalAddress});
}
class RequestRepoImp implements RequestRepo {
@ -210,6 +214,7 @@ class RequestRepoImp implements RequestRepo {
RequestStatusEnum.paid.getIdFromRequestStatusEnum().toString(),
RequestStatusEnum.delivery.getIdFromRequestStatusEnum().toString(),
RequestStatusEnum.shipping.getIdFromRequestStatusEnum().toString(),
RequestStatusEnum.selfPickup.getIdFromRequestStatusEnum().toString(),
];
if (parameters['requestStatus'] != null && parameters['requestStatus'] != "0") {
@ -227,7 +232,6 @@ class RequestRepoImp implements RequestRepo {
parameters.removeWhere((key, value) => key == "doPagination");
parameters.addEntries([MapEntry("ServiceProviderId", appState.getUser.data!.userInfo!.providerId.toString())]);
log("parameters: ${parameters}");
// final parameters = {
// "ServiceProviderId": serviceProviderID.toString(),
// "RequestType": "2", // Only to get the Service Request
@ -257,6 +261,7 @@ class RequestRepoImp implements RequestRepo {
RequestStatusEnum.paid.getIdFromRequestStatusEnum().toString(),
RequestStatusEnum.delivery.getIdFromRequestStatusEnum().toString(),
RequestStatusEnum.shipping.getIdFromRequestStatusEnum().toString(),
RequestStatusEnum.selfPickup.getIdFromRequestStatusEnum().toString(),
];
final parameters = {
"ServiceProviderId": serviceProviderID.toString(),
@ -349,6 +354,22 @@ class RequestRepoImp implements RequestRepo {
return genericRespModel;
}
@override
Future<GenericRespModel> updateRequestAdditionalAddress({required int requestID, required String additionalAddress}) async {
var queryParameters = {
"requestID": requestID.toString(),
"additionalAddress": additionalAddress.toString(),
};
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.requestUpdateAdditionalAddress,
queryParameters,
token: appState.getUser.data!.accessToken,
);
return genericRespModel;
}
@override
Future<GenericRespModel> updateRequestOfferStatus({required RequestOfferStatusEnum requestOfferStatusEnum, required int requestOfferId, required String comments}) async {
var queryParameters = {
@ -366,6 +387,23 @@ class RequestRepoImp implements RequestRepo {
return genericRespModel;
}
@override
Future<GenericRespModel> updateRequestDeliveryOptionByCustomer({required int requestID, required int requestOfferId, required RequestDeliveryOptionEnum deliveryOptionEnum}) async {
var queryParameters = {
"requestID": requestID.toString(),
"requestOfferId": requestOfferId.toString(),
"deliveryOption": deliveryOptionEnum.getIdRequestDeliveryOptionEnum().toString(),
};
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.requestOfferUpdateDeliveryOptionByCustomer,
queryParameters,
token: appState.getUser.data!.accessToken,
);
return genericRespModel;
}
@override
Future<GenericRespModel> updateRequestOfferFromProvider({
required String message,

@ -47,7 +47,7 @@ class ShippingRepoImp extends ShippingRepo {
return [];
}
List<ShippingRequestModel> list = List.generate(genericRespModel.data.length, (index) => ShippingRequestModel.fromJson(genericRespModel.data[index]));
List<ShippingRequestModel> list = List.generate(genericRespModel.data.length, (index) => ShippingRequestModel.fromJsonShipping(genericRespModel.data[index], true));
return list;
}
@ -72,7 +72,7 @@ class ShippingRepoImp extends ShippingRepo {
return [];
}
List<ShippingRequestModel> list = List.generate(genericRespModel.data.length, (index) => ShippingRequestModel.fromJson(genericRespModel.data[index]));
List<ShippingRequestModel> list = List.generate(genericRespModel.data.length, (index) => ShippingRequestModel.fromJsonShipping(genericRespModel.data[index], false));
return list;
}

@ -59,6 +59,7 @@ class MyColors {
static const Color expiredColor = Colors.grey;
static const Color shippingColor = Colors.purple;
static const Color deliveryColor = Colors.brown;
static const Color selfPickupColor = Colors.orange;
static Decoration gradient = BoxDecoration(
gradient: const LinearGradient(colors: [

@ -81,6 +81,7 @@ enum RequestStatusEnum {
expired,
shipping,
delivery,
selfPickup,
}
enum PaymentMethods {
@ -101,7 +102,7 @@ enum PaymentTypes {
partialAppointment,
}
enum AdCreationSteps {
enum AdCreationStepsEnum {
vehicleDetails,
damageParts,
adDuration,
@ -239,6 +240,7 @@ enum ShippingRequestStatusEnum {
enum SelfPickupRequestStatusEnum {
allRequests,
pending,
preparingToCollect,
readyToCollect,
collected,

@ -274,6 +274,8 @@ class Utils {
return MyColors.shippingColor;
case RequestStatusEnum.delivery:
return MyColors.deliveryColor;
case RequestStatusEnum.selfPickup:
return MyColors.selfPickupColor;
}
}
@ -332,6 +334,25 @@ class Utils {
}
}
static String getNameBySelfPickupRequestStatusEnum(SelfPickupRequestStatusEnum selfPickupRequestStatusEnum) {
switch (selfPickupRequestStatusEnum) {
case SelfPickupRequestStatusEnum.allRequests:
return "All Requests";
case SelfPickupRequestStatusEnum.pending:
return "Pending";
case SelfPickupRequestStatusEnum.preparingToCollect:
return "Preparing To Collect";
case SelfPickupRequestStatusEnum.readyToCollect:
return "Ready To Collect";
case SelfPickupRequestStatusEnum.collected:
return "Collected";
}
}
static Color getChipColorByShippingRequestStatusEnum(ShippingRequestStatusEnum shippingRequestStatusEnum) {
switch (shippingRequestStatusEnum) {
case ShippingRequestStatusEnum.allRequests:
@ -354,6 +375,25 @@ class Utils {
}
}
static Color getChipColorBySelfPickupRequestStatusEnum(SelfPickupRequestStatusEnum selfPickupRequestStatusEnum) {
switch (selfPickupRequestStatusEnum) {
case SelfPickupRequestStatusEnum.allRequests:
return MyColors.submittedColor;
case SelfPickupRequestStatusEnum.pending:
return MyColors.pendingColor;
case SelfPickupRequestStatusEnum.preparingToCollect:
return MyColors.submittedColor;
case SelfPickupRequestStatusEnum.readyToCollect:
return MyColors.shippingColor;
case SelfPickupRequestStatusEnum.collected:
return MyColors.deliveryColor;
}
}
static Color getChipColorByBranchStatus(BranchStatusEnum branchStatusEnum) {
switch (branchStatusEnum) {
case BranchStatusEnum.pending:
@ -733,12 +773,12 @@ class NoInternetDialog {
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
LocaleKeys.connectionProblem,
title: Text(
LocaleKeys.connectionProblem.tr(),
textAlign: TextAlign.center,
),
content: const Text(
LocaleKeys.pleaseCheckConnection,
content: Text(
LocaleKeys.pleaseCheckConnection.tr(),
textAlign: TextAlign.center,
),
actions: [

@ -44,7 +44,7 @@ class AdVM extends BaseVM {
AdVM({required this.commonServices, required this.commonRepo, required this.adsRepo});
AdCreationSteps currentProgressStep = AdCreationSteps.vehicleDetails;
AdCreationStepsEnum currentProgressStep = AdCreationStepsEnum.vehicleDetails;
VehicleDetailsModel? vehicleDetails;
@ -82,6 +82,7 @@ class AdVM extends BaseVM {
// Edit Variables Amir
bool isExtendAdEditEnabled = false;
bool isAdEditEnabled = false;
bool isDraftEditEnabled = false;
AdDetailsModel? previousAdDetails;
List<AdDetailsModel> myDraftAds = [];
@ -347,15 +348,20 @@ class AdVM extends BaseVM {
int pageIndexForMyDrafts = 1;
Future<void> getMyDraftAds() async {
pageIndexForMyAds = 1;
hasMoreDataForMyAds = true;
setState(ViewState.busy);
myDraftAds = await adsRepo.getMyDraftAds();
notifyListeners();
setState(ViewState.idle);
try {
pageIndexForMyAds = 1;
hasMoreDataForMyAds = true;
setState(ViewState.busy);
myDraftAds = await adsRepo.getMyDraftAds();
notifyListeners();
setState(ViewState.idle);
} catch (e) {
setState(ViewState.idle);
logger.e(e.toString());
}
}
Future<void> fetchMoreDraftAds({required AdPostStatus adsStatus}) async {
Future<void> fetchMoreDraftAds() async {
if (isLoadingMore) return;
hasMoreDataForMyDraftsAds = true;
isLoadingMore = true;
@ -1213,64 +1219,167 @@ class AdVM extends BaseVM {
void onBackButtonPressed(BuildContext context) {
switch (currentProgressStep) {
case AdCreationSteps.vehicleDetails:
case AdCreationStepsEnum.vehicleDetails:
isAdEditEnabled = false;
isDraftEditEnabled = false;
resetValues();
pop(context);
break;
case AdCreationSteps.damageParts:
currentProgressStep = AdCreationSteps.vehicleDetails;
case AdCreationStepsEnum.damageParts:
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
notifyListeners();
break;
case AdCreationSteps.adDuration:
currentProgressStep = AdCreationSteps.damageParts;
case AdCreationStepsEnum.adDuration:
currentProgressStep = AdCreationStepsEnum.damageParts;
notifyListeners();
break;
case AdCreationSteps.reviewAd:
currentProgressStep = AdCreationSteps.adDuration;
case AdCreationStepsEnum.reviewAd:
currentProgressStep = AdCreationStepsEnum.adDuration;
notifyListeners();
break;
}
}
Future<int> saveAdVehicleDetailsDraft({required bool isNew, required BuildContext context, required AdCreationStepsEnum stepNoEnum}) async {
AppState appState = injector.get<AppState>();
log("selectionDurationStartDate: $selectionDurationStartDate");
log("specialServiceCards: ${specialServiceCards.length}");
List<int> adsSelectedServices = [];
for (var value in specialServiceCards) {
adsSelectedServices.add(value.serviceSelectedId!.selectedId);
}
Utils.showLoading(context);
try {
Ads ads = Ads(
id: !isNew ? previousAdDetails!.id : 0,
adsDurationID: vehicleAdDurationId.selectedId == -1 ? 0 : vehicleAdDurationId.selectedId,
startDate: selectionDurationStartDate,
countryId: vehicleCountryId.selectedId,
specialServiceIDs: adsSelectedServices,
showContactDetail: isPhoneNumberShown,
isOnWhatsApp: isNumberOnWhatsApp,
);
List<VehiclePostingImages> vehicleImages = [];
for (var image in pickedPostingImages) {
vehicleImages.add(await convertFileToVehiclePostingImages(imageModel: image));
}
List<VehiclePostingDamageParts> vehicleDamageImages = [];
for (var card in vehicleDamageCards) {
if (card.partImages != null && card.partImages!.isNotEmpty) {
for (var image in card.partImages!) {
VehiclePostingDamageParts stringImage = await convertFileToVehiclePostingDamageParts(
imageModel: image,
damagePartId: card.partSelectedId!.selectedId,
commentParam: card.damagePartDescription ?? "",
);
vehicleDamageImages.add(stringImage);
}
}
}
VehiclePosting vehiclePosting = VehiclePosting(
id: !isNew ? previousAdDetails!.vehiclePostingID : null,
userID: appState.getUser.data!.userInfo!.userId,
vehicleType: vehicleTypeId.selectedId,
vehicleModelID: vehicleModelId.selectedId,
vehicleModelYearID: vehicleModelYearId.selectedId,
vehicleColorID: vehicleColorId.selectedId,
vehicleCategoryID: vehicleCategoryId.selectedId,
vehicleConditionID: vehicleConditionId.selectedId,
vehicleMileageID: vehicleMileageId.selectedId,
vehicleTransmissionID: vehicleTransmissionId.selectedId,
vehicleSellerTypeID: vehicleSellerTypeId.selectedId == -1 ? 1 : vehicleSellerTypeId.selectedId,
cityID: vehicleCityId.selectedId,
price: int.parse(vehicleDemandAmount),
vehicleVIN: vehicleVin,
vehicleDescription: vehicleDescription,
vehicleTitle: vehicleTitle,
vehicleDescriptionN: vehicleDescription,
isFinanceAvailable: financeAvailableStatus,
warantyYears: int.parse(warrantyDuration),
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);
GenericRespModel respModel = await adsRepo.createOrUpdateDraftAd(
adsCreationPayloadModel: adsCreationPayloadModel,
isCreateNew: isNew,
stepNo: stepNoEnum,
);
Utils.hideLoading(context);
return Future.value(respModel.messageStatus == 1 ? respModel.data : -1);
} catch (e) {
Utils.hideLoading(context);
logger.e(e.toString());
return -1;
}
}
Future saveAdDamagePartDetailsDraft() async {}
Future saveAdDurationsDraft() async {}
void updateCurrentStep(BuildContext context) async {
switch (currentProgressStep) {
case AdCreationSteps.vehicleDetails:
case AdCreationStepsEnum.vehicleDetails:
if (isVehicleDetailsValidated()) {
currentProgressStep = AdCreationSteps.damageParts;
int adID = await saveAdVehicleDetailsDraft(isNew: previousAdDetails == null || previousAdDetails!.id == null, context: context, stepNoEnum: AdCreationStepsEnum.vehicleDetails);
if (previousAdDetails == null || previousAdDetails!.id == null) {
previousAdDetails = AdDetailsModel();
previousAdDetails!.id = adID;
}
currentProgressStep = AdCreationStepsEnum.damageParts;
getVehicleDamagePartsList();
notifyListeners();
}
break;
case AdCreationSteps.damageParts:
case AdCreationStepsEnum.damageParts:
if (isDamagePartsValidated()) {
currentProgressStep = AdCreationSteps.adDuration;
await saveAdVehicleDetailsDraft(isNew: false, context: context, stepNoEnum: AdCreationStepsEnum.damageParts);
currentProgressStep = AdCreationStepsEnum.adDuration;
if (vehicleAdsDurations.isEmpty) {
getVehicleAdsDuration();
}
getVehicleAdsSpecialServices(countryId: vehicleCountryId.selectedId, cityId: vehicleCityId.selectedId, specialServiceType: 1);
notifyListeners();
}
break;
case AdCreationSteps.adDuration:
case AdCreationStepsEnum.adDuration:
// log("state: ${AppState().getUser.data!.accessToken}");
if (isAdDurationValidated()) {
currentProgressStep = AdCreationSteps.reviewAd;
await saveAdVehicleDetailsDraft(isNew: false, context: context, stepNoEnum: AdCreationStepsEnum.adDuration);
currentProgressStep = AdCreationStepsEnum.reviewAd;
notifyListeners();
}
break;
case AdCreationSteps.reviewAd:
case AdCreationStepsEnum.reviewAd:
Utils.showLoading(context);
try {
int status = await createNewAd();
if (status != 1) {
bool status = await createNewAd();
if (!status) {
Utils.hideLoading(context);
return;
}
isAdEditEnabled = false;
isDraftEditEnabled = false;
isExtendAdEditEnabled = false;
Utils.hideLoading(context);
currentProgressStep = AdCreationSteps.vehicleDetails;
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
resetValues();
updateIsExploreAds(false);
applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.pendingForReview); //pending for review
@ -1444,7 +1553,7 @@ class AdVM extends BaseVM {
vehicleDamageCards.clear();
specialServiceCards.clear();
vehicleAdsSpecialServices.clear();
currentProgressStep = AdCreationSteps.vehicleDetails;
currentProgressStep = AdCreationStepsEnum.vehicleDetails;
vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
// vehicleAdDurationId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
@ -1604,7 +1713,7 @@ class AdVM extends BaseVM {
}
}
Future<int> createNewAd() async {
Future<bool> createNewAd() async {
AppState appState = injector.get<AppState>();
List<int> adsSelectedServices = [];
@ -1625,7 +1734,11 @@ class AdVM extends BaseVM {
log("selectionDurationStartDate: $selectionDurationStartDate");
Ads ads = Ads(
id: isAdEditEnabled ? previousAdDetails!.id : null,
id: isDraftEditEnabled
? null
: isAdEditEnabled
? previousAdDetails!.id
: null,
adsDurationID: vehicleAdDurationId.selectedId == -1 ? 0 : vehicleAdDurationId.selectedId,
startDate: selectionDurationStartDate,
countryId: vehicleCountryId.selectedId,
@ -1683,11 +1796,15 @@ class AdVM extends BaseVM {
AdsCreationPayloadModel adsCreationPayloadModel = AdsCreationPayloadModel(ads: ads, vehiclePosting: vehiclePosting);
GenericRespModel respModel = await adsRepo.createOrUpdateAd(adsCreationPayloadModel: adsCreationPayloadModel, isCreateNew: !isAdEditEnabled, isExtendAdEditEnabled: isExtendAdEditEnabled);
GenericRespModel respModel = await adsRepo.createOrUpdateAd(
adsCreationPayloadModel: adsCreationPayloadModel,
isCreateNew: isDraftEditEnabled ? true : !isAdEditEnabled,
isExtendAdEditEnabled: isExtendAdEditEnabled,
);
Utils.showToast(respModel.message.toString());
return Future.value(respModel.messageStatus);
return Future.value(respModel.messageStatus == 1);
}
Future<VehiclePostingImages> convertFileToVehiclePostingImages({required ImageModel imageModel}) async {
@ -2221,13 +2338,16 @@ class AdVM extends BaseVM {
return [];
}
void onEditUpdateAdPressed({required BuildContext context, required AdDetailsModel previousDetails, required bool isFromExtendAd}) {
void onEditUpdateAdPressed({required BuildContext context, required AdDetailsModel previousDetails, required bool isFromExtendAd, bool isForDraft = false}) {
isAdEditEnabled = true;
isDraftEditEnabled = true;
isExtendAdEditEnabled = isFromExtendAd;
previousAdDetails = previousDetails;
autoFillSelectedVehicleType();
autoFillSelectedVehicleAdsDuration();
if (isForDraft) {
autoFillSelectedVehicleAdsDetails();
}
navigateWithName(context, AppRoutes.selectAdTypeView, arguments: [AppState().currentAppType == AppType.provider, isFromExtendAd, previousDetails.id]);
}
@ -2256,12 +2376,14 @@ class AdVM extends BaseVM {
void autoFillSelectedVehicleType() async {
if (vehicleTypes.isEmpty) {
await getVehicleTypes();
return;
// return;
}
if (vehicleTypes.isNotEmpty) {
for (var vehicle in vehicleTypes) {
vehicle.isSelected = false;
if (vehicle.id == previousAdDetails!.vehicle?.vehicleType) {
vehicle.isSelected = true;
log("Hi: ${vehicle.vehicleTypeName}");
break;
}
}
@ -2302,6 +2424,9 @@ class AdVM extends BaseVM {
}
void autoFillSelectedVehicleAdsDetails() async {
if (vehicleBrands.isEmpty) {
await getVehicleBrandsByVehicleTypeId();
}
int index = vehicleBrands.indexWhere((element) => element.id == previousAdDetails!.vehicle!.model!.vehicleBrandID);
if (index != -1) {
@ -2335,6 +2460,7 @@ class AdVM extends BaseVM {
for (var element in previousAdDetails!.vehicle!.image!) {
if (element.imageUrl != null) {
ImageModel imageModel = ImageModel(id: element.id, filePath: element.imageUrl, isFromNetwork: true);
log("running");
pickedPostingImages.add(imageModel);
}
}
@ -2376,12 +2502,16 @@ class AdVM extends BaseVM {
address: "",
serviceTime: "",
);
addNewSpecialServiceCard(specialServiceCard: specialServiceCard);
int index = ifSpecialServiceAlreadyThere(element.specialServiceID!);
log("Found at : $index");
if (index == -1) {
addNewSpecialServiceCard(specialServiceCard: specialServiceCard);
}
}
}
// selectionDurationStartDate = DateHelper.formatDateT(previousAdDetails!.startdate ?? "");
selectionDurationStartDate = "";
selectionDurationStartDate = ""; // You have to mention this each time
isPhoneNumberShown = previousAdDetails!.showContactDetail ?? false;
adPhoneNumber = previousAdDetails!.adOwnerDetails!.mobileNo ?? "";

@ -307,9 +307,7 @@ class AppointmentsVM extends BaseVM {
}
void removeServiceInCurrentAppointment(int index) {
int serviceId = servicesInCurrentAppointment
.elementAt(index)
.serviceProviderServiceId ?? -1;
int serviceId = servicesInCurrentAppointment.elementAt(index).serviceProviderServiceId ?? -1;
allSelectedItemsInAppointments.removeWhere((element) => element.serviceProviderServiceId == serviceId);
servicesInCurrentAppointment[index].serviceItems!.clear();
servicesInCurrentAppointment.removeAt(index);
@ -372,13 +370,15 @@ class AppointmentsVM extends BaseVM {
if (shouldPopulateUpcoming) {
myUpComingAppointments = myFilteredAppointmentsForProvider
.where((element) =>
(element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
(element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
.toList();
log("myUpComingAppointments: ${myUpComingAppointments.length}");
}
if (isNeedCustomerFilter) {
log("myFilteredAppointmentsForProvider: ${myFilteredAppointmentsForProvider.length}");
myFilteredAppointmentsForProvider = findAppointmentsBasedOnCustomers(myFilteredAppointmentsForProvider);
}
notifyListeners();
@ -400,8 +400,8 @@ class AppointmentsVM extends BaseVM {
if (shouldPopulateUpcoming) {
myUpComingAppointments = myFilteredAppointmentsForCustomers
.where((element) =>
(element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
(element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
(DateHelper.parseStringToDate(element.appointmentDate!).isAfter(DateTime.now())))
.toList();
}
@ -416,19 +416,14 @@ class AppointmentsVM extends BaseVM {
List<AppointmentListModel> groupedList = uniqueCustomerIDs.map((id) {
List<AppointmentListModel> list = appointments.where((item) => item.customerID == id).toList();
list.sort((a, b) =>
DateHelper
.parseStringToDate(DateHelper.formatDateT(b.appointmentDate!))
.millisecondsSinceEpoch
.compareTo(DateHelper
.parseStringToDate(DateHelper.formatDateT(a.appointmentDate!))
.millisecondsSinceEpoch));
list.sort((a, b) => DateHelper.parseStringToDate(DateHelper.formatDateT(b.appointmentDate!))
.millisecondsSinceEpoch
.compareTo(DateHelper.parseStringToDate(DateHelper.formatDateT(a.appointmentDate!)).millisecondsSinceEpoch));
AppointmentListModel model = list.first;
model.customerAppointmentList = list;
return model;
}).toList();
return groupedList;
}
@ -492,6 +487,9 @@ class AppointmentsVM extends BaseVM {
}
bool isShowMergeButton() {
if (myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList == null) {
return false;
}
return myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList!.every((appointment) => appointment.appointmentStatusEnum == AppointmentStatusEnum.confirmed) &&
myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList!.length > 1;
}
@ -507,7 +505,7 @@ class AppointmentsVM extends BaseVM {
void updateCheckBoxInMergeRequest(int currentIndex) {
myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected =
!(myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
!(myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
int count = countSelected(myFilteredAppointmentsForProvider[selectedAppointmentIndex].customerAppointmentList ?? []);
if (count > 1) {
@ -519,10 +517,7 @@ class AppointmentsVM extends BaseVM {
}
int countSelected(List<AppointmentListModel> appointments) {
return appointments
.where((appointment) => appointment.isSelected == true)
.toList()
.length;
return appointments.where((appointment) => appointment.isSelected == true).toList().length;
}
updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) {
@ -698,14 +693,13 @@ class AppointmentsVM extends BaseVM {
Column(
children: List.generate(
selectedService.serviceItems!.length,
(index) =>
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${selectedService.serviceItems![index].price} ${LocaleKeys.sar.tr()}".toText(fontSize: 12, isBold: true),
],
),
(index) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${selectedService.serviceItems![index].price} ${LocaleKeys.sar.tr()}".toText(fontSize: 12, isBold: true),
],
),
),
),
Row(
@ -924,10 +918,7 @@ class AppointmentsVM extends BaseVM {
return InfoBottomSheet(
title: LocaleKeys.reportComplaint.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery
.of(context)
.viewInsets
.bottom),
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

@ -635,7 +635,7 @@ class ChatVM extends BaseVM {
try {
GenericRespModel genericRespModel = await requestRepo.updateRequestOfferStatus(requestOfferStatusEnum: requestOfferStatusEnum, requestOfferId: reqOfferId, comments: comments);
Utils.showToast(genericRespModel.message.toString());
Utils.showLoading(context);
Utils.hideLoading(context);
return genericRespModel.messageStatus == 1 ? reqOfferId : -1;
} catch (e) {
logger.i(e.toString());

@ -94,7 +94,11 @@ class DashboardVMProvider extends BaseVM {
}
await shippingManagementVM.populateShippingRequestFilterList();
await shippingManagementVM.populateSelfPickupRequestFilterList();
await appointmentVM.applyFilterOnAppointmentsVMForProviders(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, shouldPopulateUpcoming: true);
await appointmentVM.applyFilterOnAppointmentsVMForProviders(
appointmentStatusEnum: AppointmentStatusEnum.allAppointments,
isNeedCustomerFilter: true,
shouldPopulateUpcoming: true,
);
await adVM.getVehicleTypes();
await adVM.getVehicleAdsDuration();

@ -81,9 +81,11 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
void updateAdditionalAddressSparePartRequestDelivery(String value) {
void updateAdditionalAddressSparePartRequestDelivery(String value, bool isNotify) {
additionalAddressSparePartRequestDelivery = value;
notifyListeners();
if (isNotify) {
notifyListeners();
}
}
RequestDeliveryOptionEnum? selectedDeliveryOptionEnum;
@ -859,7 +861,7 @@ class RequestsVM extends BaseVM {
Utils.showToast(LocaleKeys.addValidDescription.tr());
isValid = false;
} else if (address.isEmpty && requestTypeId.selectedId == 2) {
Utils.showToast(LocaleKeys.addValidDescription.tr());
Utils.showToast(LocaleKeys.addValidAddress.tr());
isValid = false;
}
return isValid;
@ -974,7 +976,13 @@ class RequestsVM extends BaseVM {
void populateRequestDeliveryOptions() {
deliveryOptionsForReviewRequest.clear();
deliveryOptionsForReviewRequest.addAll(myDeliveryOptionsFilterOptions.where((element) => element.id != RequestDeliveryOptionEnum.both.getIdRequestDeliveryOptionEnum()).toList());
log("acceptedRequestOffer!.requestDeliveryOption: ${acceptedRequestOffer!.requestDeliveryOption}");
if (acceptedRequestOffer != null && acceptedRequestOffer!.requestDeliveryOption == RequestDeliveryOptionEnum.both) {
deliveryOptionsForReviewRequest.addAll(myDeliveryOptionsFilterOptions.where((element) => element.id != RequestDeliveryOptionEnum.both.getIdRequestDeliveryOptionEnum()).toList());
} else {
deliveryOptionsForReviewRequest.addAll(myDeliveryOptionsFilterOptions.where((element) => element.id == acceptedRequestOffer!.requestDeliveryOption!.getIdRequestDeliveryOptionEnum()));
}
notifyListeners();
}
@ -1309,4 +1317,38 @@ class RequestsVM extends BaseVM {
}
}
}
Future<int> onRequestDeliveryOptionTapped({required BuildContext context, required int requestID, required int reqOfferId, required RequestDeliveryOptionEnum deliveryOptionEnum}) async {
Utils.showLoading(context);
try {
GenericRespModel genericRespModel = await requestRepo.updateRequestDeliveryOptionByCustomer(requestID: requestID, requestOfferId: reqOfferId, deliveryOptionEnum: deliveryOptionEnum);
Utils.hideLoading(context);
return genericRespModel.messageStatus == 1 ? reqOfferId : -1;
} catch (e) {
logger.i(e.toString());
Utils.showToast(e.toString());
Utils.hideLoading(context);
return -1;
}
}
Future<bool> updateRequestAdditionalAddress({required BuildContext context, required String additionalAddress, required int requestId, bool needLoading = true}) async {
if (needLoading) {
Utils.showLoading(context);
}
try {
GenericRespModel genericRespModel = await requestRepo.updateRequestAdditionalAddress(requestID: requestId, additionalAddress: additionalAddress);
if (needLoading) {
Utils.hideLoading(context);
}
return genericRespModel.messageStatus == 1;
} catch (e) {
logger.i(e.toString());
Utils.showToast(e.toString());
if (needLoading) {
Utils.hideLoading(context);
}
return false;
}
}
}

@ -92,11 +92,14 @@ class SettingOptionsVM extends BaseVM {
List<AppInvitationHistoryModel> appInvitationHistoryList = [];
Future<void> getAppInvitationHistoryList() async {
Future<void> getAppInvitationHistoryList(BuildContext context) async {
Utils.showLoading(context);
try {
appInvitationHistoryList = await settingOptionsRepo.getAppInvitationsHistory();
Utils.hideLoading(context);
} catch (e) {
logger.i(e.toString());
Utils.hideLoading(context);
}
}
}

@ -66,6 +66,9 @@ class ShippingManagementVM extends BaseVM {
selfPickupRequestsStatusesList.add(FilterListModel(title: selfPickupStatusEnums[i].enumValueStrDes, isSelected: false, id: selfPickupStatusEnums[i].enumValue));
}
selfPickupRequestsFilterOptions.sort((FilterListModel a, FilterListModel b) => a.id.compareTo(b.id));
selfPickupRequestsStatusesList.sort((FilterListModel a, FilterListModel b) => a.id.compareTo(b.id));
selfPickupRequestsFilterOptions.insert(0, FilterListModel(title: Utils.getNameByShippingRequestStatusEnum(ShippingRequestStatusEnum.allRequests), isSelected: true, id: -1));
notifyListeners();
}
@ -82,6 +85,9 @@ class ShippingManagementVM extends BaseVM {
}
int index = shippingRequestFilterOptions.indexWhere((element) => element.id == 0);
shippingRequestFilterOptions.sort((FilterListModel a, FilterListModel b) => a.id.compareTo(b.id));
shippingRequestStatusesList.sort((FilterListModel a, FilterListModel b) => a.id.compareTo(b.id));
if (index == -1) {
log("index: $index");
shippingRequestFilterOptions.insert(0, FilterListModel(title: Utils.getNameByShippingRequestStatusEnum(0.toShippingStatusEnum()), isSelected: false, id: 0));
@ -131,6 +137,14 @@ class ShippingManagementVM extends BaseVM {
notifyListeners();
}
void updateSelectionInSelfPickupRequestStatuses(int index) {
for (var value in selfPickupRequestsStatusesList) {
value.isSelected = false;
}
selfPickupRequestsStatusesList[index].isSelected = true;
notifyListeners();
}
Future<void> getShippingRequestsListByFilters({ShippingRequestStatusEnum? shippingStatusEnum}) async {
setState(ViewState.busy);
try {
@ -172,4 +186,21 @@ class ShippingManagementVM extends BaseVM {
return false;
}
}
Future<bool> onUpdateSelfPickupStatusTapped({required BuildContext context, required SelfPickupRequestStatusEnum selfPickupRequestStatusEnum, required int shippingRequestId}) async {
Utils.showLoading(context);
try {
GenericRespModel? genericRespModel =
await shippingRepo.updateSelfPickupRequestStatus(selfPickupStatusEnum: selfPickupRequestStatusEnum, shippingRequestId: shippingRequestId, comment: requestStatusComments);
Utils.showToast(genericRespModel.message.toString());
Utils.hideLoading(context);
requestStatusComments = "";
return genericRespModel.messageStatus == 1;
} catch (e) {
logger.i(e.toString());
Utils.showToast(e.toString());
Utils.hideLoading(context);
return false;
}
}
}

@ -169,8 +169,8 @@ class AdDurationSelectionSheet extends StatelessWidget {
if (adVM.isFetchingLists) {
return;
} else {
final subscriptionsVM = context.read<SubscriptionsVM>();
if (isFromExtendAd && !isUpdateAdSelected) {
if (isFromExtendAd && !isUpdateAdSelected && AppState().currentAppType == AppType.provider) {
final subscriptionsVM = context.read<SubscriptionsVM>();
List<bool> statuses =
await adVM.createAdExtensionOrder(context, adId: adsID, adsDurationId: adVM.vehicleAdDurationId.selectedId); // [0] Means API response [1] means isPaymentRequired
if (statuses[0] && statuses[1]) {

@ -23,6 +23,7 @@ class AdsListWidget extends StatelessWidget {
final bool isAdsFragment;
final bool shouldShowAdStatus;
final bool hasMoreData;
final bool isDraftAds;
final Function()? onFetchMoreAds;
const AdsListWidget({
@ -30,6 +31,7 @@ class AdsListWidget extends StatelessWidget {
required this.adsList,
required this.shouldShowAdStatus,
required this.hasMoreData,
required this.isDraftAds,
this.onFetchMoreAds,
this.scrollPhysics,
this.isAdsFragment = false,
@ -47,7 +49,6 @@ class AdsListWidget extends StatelessWidget {
}
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification scrollInfo) {
log("hasMoreData: $hasMoreData");
if (scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent && hasMoreData) {
if (onFetchMoreAds != null) {
onFetchMoreAds!();
@ -64,9 +65,20 @@ class AdsListWidget extends StatelessWidget {
adDetails: adsList[index],
isAdsFragment: isAdsFragment,
shouldShowAdStatus: shouldShowAdStatus,
).onPress(() => navigateWithName(context, AppRoutes.adsDetailView, arguments: adsList[index])).toViewOnly(context, onTap: () {
navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
});
).onPress(
() {
if (isDraftAds) {
context.read<AdVM>().onEditUpdateAdPressed(
context: context,
previousDetails: adsList[index],
isFromExtendAd: false,
isForDraft: true,
);
} else {
navigateWithName(context, AppRoutes.adsDetailView, arguments: adsList[index]);
}
},
).toViewOnly(context, onTap: () => navigateWithName(context, AppRoutes.loginWithPassword, arguments: false));
},
separatorBuilder: (BuildContext context, int index) {
return 12.height;
@ -89,110 +101,120 @@ class AdCard extends StatelessWidget {
return Stack(
alignment: Alignment.center,
children: [
Row(
children: [
adDetails.vehicle!.image!.first.imageUrl.buildNetworkImage(
width: 80,
height: 80,
fit: BoxFit.cover,
if (adDetails.vehicle == null) ...[
Expanded(
child: Column(
children: [
"Zahoor will update the Ad Format".toText(),
],
),
12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (isAdsFragment && adDetails.adPostStatus! == AdPostStatus.sold) ...[
Utils.statusContainerChip(text: adDetails.statuslabel!, chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)),
] else if (isAdsFragment && !context.read<AdVM>().isExploreAdsTapped) ...[
Utils.statusContainerChip(text: adDetails.statuslabel!, chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)),
],
(adDetails.vehicle!.vehicleTitle ?? "").toText(
fontSize: 16,
letterSpacing: -0.64,
height: 25 / 16,
),
Row(
children: [
("${LocaleKeys.model.tr()}:").toText(
fontSize: 12,
color: MyColors.lightTextColor,
letterSpacing: -0.48,
height: 18 / 12,
),
2.width,
(adDetails.vehicle!.modelyear!.label ?? "").toText(
fontSize: 12,
letterSpacing: -0.48,
height: 18 / 12,
),
],
),
Row(
children: [
("${LocaleKeys.mileage.tr()}:").toText(
color: MyColors.lightTextColor,
fontSize: 12,
letterSpacing: -0.48,
height: 18 / 12,
),
2.width,
(adDetails.vehicle!.mileage!.mileageEnd ?? "").toText(
fontSize: 12,
letterSpacing: -0.48,
height: 18 / 12,
),
),
] else ...[
Row(
children: [
adDetails.vehicle!.image!.first.imageUrl.buildNetworkImage(
width: 80,
height: 80,
fit: BoxFit.cover,
),
12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (isAdsFragment && adDetails.adPostStatus! == AdPostStatus.sold && adDetails.statuslabel != null && adDetails.statuslabel!.isNotEmpty) ...[
Utils.statusContainerChip(text: adDetails.statuslabel ?? "", chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)),
] else if (isAdsFragment && !context.read<AdVM>().isExploreAdsTapped && adDetails.statuslabel != null && adDetails.statuslabel!.isNotEmpty) ...[
Utils.statusContainerChip(text: adDetails.statuslabel ?? "", chipColor: Utils.getChipColorByAdStatus(adDetails.adPostStatus!)),
],
),
],
(adDetails.vehicle!.vehicleTitle ?? "").toText(
fontSize: 16,
letterSpacing: -0.64,
height: 25 / 16,
),
Row(
children: [
("${LocaleKeys.model.tr()}:").toText(
fontSize: 12,
color: MyColors.lightTextColor,
letterSpacing: -0.48,
height: 18 / 12,
),
2.width,
(adDetails.vehicle!.modelyear!.label ?? "").toText(
fontSize: 12,
letterSpacing: -0.48,
height: 18 / 12,
),
],
),
Row(
children: [
("${LocaleKeys.mileage.tr()}:").toText(
color: MyColors.lightTextColor,
fontSize: 12,
letterSpacing: -0.48,
height: 18 / 12,
),
2.width,
(adDetails.vehicle!.mileage!.mileageEnd ?? "").toText(
fontSize: 12,
letterSpacing: -0.48,
height: 18 / 12,
),
],
),
],
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(adDetails.vehicle!.cityName ?? "").toText(color: MyColors.lightTextColor),
adDetails.createdOn != null ? DateTime.parse(adDetails.createdOn!).getTimeAgo().toText(color: MyColors.lightTextColor) : const SizedBox(),
],
),
],
),
8.height,
Row(
children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(adDetails.vehicle!.demandAmount!.toInt().toString()).toText(fontSize: 19, isBold: true, letterSpacing: -1.16, height: 29 / 19),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4, height: 16 / 10).paddingOnly(bottom: 3),
(adDetails.vehicle!.cityName ?? "").toText(color: MyColors.lightTextColor),
adDetails.createdOn != null ? DateTime.parse(adDetails.createdOn!).getTimeAgo().toText(color: MyColors.lightTextColor) : const SizedBox(),
],
),
),
SvgPicture.asset(
MyAssets.arrowRight,
height: 9.69,
width: 13,
),
],
),
8.height,
Row(
children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(adDetails.vehicle!.demandAmount!.toInt().toString()).toText(fontSize: 19, isBold: true, letterSpacing: -1.16, height: 29 / 19),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4, height: 16 / 10).paddingOnly(bottom: 3),
],
),
),
SvgPicture.asset(
MyAssets.arrowRight,
height: 9.69,
width: 13,
),
// const Icon(Icons.arrow_forward)
],
),
],
// const Icon(Icons.arrow_forward)
],
),
],
),
),
),
],
),
],
),
],
if (false)
Container(
height: 100,

@ -41,19 +41,19 @@ class CreateAdProgressSteps extends StatelessWidget {
);
}
bool isStepCompleted({required AdCreationSteps currentStep}) {
bool isStepCompleted({required AdCreationStepsEnum currentStep}) {
return true;
}
int getProgressStepNumber({required AdCreationSteps currentStep}) {
int getProgressStepNumber({required AdCreationStepsEnum currentStep}) {
switch (currentStep) {
case AdCreationSteps.vehicleDetails:
case AdCreationStepsEnum.vehicleDetails:
return 1;
case AdCreationSteps.damageParts:
case AdCreationStepsEnum.damageParts:
return 2;
case AdCreationSteps.adDuration:
case AdCreationStepsEnum.adDuration:
return 3;
case AdCreationSteps.reviewAd:
case AdCreationStepsEnum.reviewAd:
return 4;
}
}

@ -1,9 +1,13 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_duration_container.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_review_containers.dart';
@ -75,7 +79,7 @@ class BuildFooterButton extends StatelessWidget {
return Consumer(
builder: (BuildContext context, AdVM adVm, Widget? child) {
switch (adVm.currentProgressStep) {
case AdCreationSteps.vehicleDetails:
case AdCreationStepsEnum.vehicleDetails:
return SizedBox(
width: double.infinity,
child: ShowFillButton(
@ -85,7 +89,7 @@ class BuildFooterButton extends StatelessWidget {
},
),
);
case AdCreationSteps.damageParts:
case AdCreationStepsEnum.damageParts:
return Row(
children: [
Expanded(
@ -94,8 +98,14 @@ class BuildFooterButton extends StatelessWidget {
maxHeight: 55,
title: LocaleKeys.cancel.tr(),
onPressed: () {
adVm.isDraftEditEnabled = false;
adVm.resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
Utils.showToast('Saved as Draft');
adVm.getMyDraftAds();
},
backgroundColor: MyColors.greyButtonColor,
),
@ -113,7 +123,7 @@ class BuildFooterButton extends StatelessWidget {
),
],
);
case AdCreationSteps.adDuration:
case AdCreationStepsEnum.adDuration:
return Row(
children: [
Expanded(
@ -122,8 +132,15 @@ class BuildFooterButton extends StatelessWidget {
maxHeight: 55,
title: LocaleKeys.cancel.tr(),
onPressed: () {
adVm.isDraftEditEnabled = false;
adVm.resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
Utils.showToast('Saved as Draft');
adVm.getMyDraftAds();
},
backgroundColor: MyColors.greyButtonColor,
),
@ -141,7 +158,7 @@ class BuildFooterButton extends StatelessWidget {
),
],
);
case AdCreationSteps.reviewAd:
case AdCreationStepsEnum.reviewAd:
return Row(
children: [
Expanded(
@ -150,8 +167,15 @@ class BuildFooterButton extends StatelessWidget {
maxHeight: 55,
title: LocaleKeys.cancel.tr(),
onPressed: () {
adVm.isDraftEditEnabled = false;
adVm.resetValues();
pop(context);
if (AppState().currentAppType == AppType.customer) {
pop(context);
}
Utils.showToast('Saved as Draft');
adVm.getMyDraftAds();
},
backgroundColor: MyColors.greyButtonColor,
),
@ -184,7 +208,7 @@ class BuildAdStepContainer extends StatelessWidget {
final WidgetBuilder onDamageParts;
final WidgetBuilder onAdDuration;
final WidgetBuilder onReviewAd;
final AdCreationSteps adCreationStepsEnum;
final AdCreationStepsEnum adCreationStepsEnum;
const BuildAdStepContainer({
super.key,
@ -198,16 +222,16 @@ class BuildAdStepContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
switch (adCreationStepsEnum) {
case AdCreationSteps.vehicleDetails:
case AdCreationStepsEnum.vehicleDetails:
return onVehicleDetails(context);
case AdCreationSteps.damageParts:
case AdCreationStepsEnum.damageParts:
return onDamageParts(context);
case AdCreationSteps.adDuration:
case AdCreationStepsEnum.adDuration:
return onAdDuration(context);
case AdCreationSteps.reviewAd:
case AdCreationStepsEnum.reviewAd:
return onReviewAd(context);
}
}

@ -0,0 +1,68 @@
import 'dart:async';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/views/advertisement/components/ads_list_widget.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class MyDraftAdsView extends StatefulWidget {
const MyDraftAdsView({super.key});
@override
State<MyDraftAdsView> createState() => _MyDraftAdsViewState();
}
class _MyDraftAdsViewState extends State<MyDraftAdsView> {
@override
void initState() {
scheduleMicrotask(() async => context.read<AdVM>().getMyDraftAds());
super.initState();
}
@override
Widget build(BuildContext context) {
return Consumer(builder: (BuildContext context, AdVM adVM, Widget? child) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.myDraftAds.tr()),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Expanded(
child: RefreshIndicator(
onRefresh: () async {
await adVM.getMyDraftAds();
},
child: adVM.state == ViewState.busy
? const Center(child: CircularProgressIndicator())
: AdsListWidget(
isAdsFragment: true,
isDraftAds: true,
shouldShowAdStatus: false,
adsList: adVM.myDraftAds,
hasMoreData: adVM.hasMoreDataForMyDraftsAds,
onFetchMoreAds: () async {
await adVM.fetchMoreDraftAds();
},
),
),
),
if (adVM.isLoadingMore) ...[
const Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: CircularProgressIndicator(),
))
]
],
),
),
);
});
}
}

@ -78,7 +78,8 @@ class SelectAdTypeView extends StatelessWidget {
onTap: () async {
adVM.updateSelectionVehicleTypeId(SelectionModel(selectedId: vehicleTypeModel.id!, selectedOption: vehicleTypeModel.vehicleTypeName ?? "", errorValue: ""));
if (adVM.isAdEditEnabled) {
adVM.autoFillSelectedVehicleAdsDetails();
adVM.
autoFillSelectedVehicleAdsDetails();
}
if (AppState().currentAppType == AppType.provider) {
if (isFromExtendAd && !adVM.isAdEditEnabled) {

@ -106,7 +106,15 @@ class _ChatViewState extends State<ChatView> {
final requestVM = context.read<RequestsVM>();
if (chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest != null &&
(requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.shipping || requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.delivery)) {
((requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.shipping || requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.delivery) ||
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.selfPickup)) {
var name = '';
if (requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.shipping || requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.delivery) {
name = Utils.getNameByShippingRequestStatusEnum(requestVM.currentSelectedRequest?.shippingStatusEnum ?? ShippingRequestStatusEnum.pending);
} else {
name = Utils.getNameBySelfPickupRequestStatusEnum(requestVM.currentSelectedRequest?.selfPickupRequestStatusEnum ?? SelfPickupRequestStatusEnum.preparingToCollect);
}
appBarHeadlines = Container(
width: double.infinity,
color: MyColors.darkIconColor,
@ -120,8 +128,7 @@ class _ChatViewState extends State<ChatView> {
child: Row(
children: [
Flexible(
child: "${LocaleKeys.deliveryStatus.tr()} ${Utils.getNameByShippingRequestStatusEnum(requestVM.currentSelectedRequest?.shippingStatusEnum ?? ShippingRequestStatusEnum.pending)}"
.toText(
child: "${LocaleKeys.deliveryStatus.tr()} $name".toText(
fontSize: 12,
color: Colors.white,
decorationColor: MyColors.white,
@ -131,7 +138,8 @@ class _ChatViewState extends State<ChatView> {
),
),
10.width,
if ((requestVM.currentSelectedRequest?.shippingStatusEnum ?? ShippingRequestStatusEnum.pending) == ShippingRequestStatusEnum.delivered) ...[
if ((requestVM.currentSelectedRequest?.shippingStatusEnum == ShippingRequestStatusEnum.delivered) ||
(requestVM.currentSelectedRequest?.selfPickupRequestStatusEnum == SelfPickupRequestStatusEnum.collected)) ...[
Expanded(
flex: 2,
child: "${LocaleKeys.markAsCompleted.tr()} ".toText(isUnderLine: true, fontSize: 12, color: Colors.white, decorationColor: MyColors.white).onPress(() {
@ -176,30 +184,30 @@ class _ChatViewState extends State<ChatView> {
child: chatMessages.isEmpty
? Center(child: LocaleKeys.noChatMessage.tr().toText(fontSize: 16, color: MyColors.lightTextColor, textAlign: TextAlign.center)).paddingAll(22)
: ListView.separated(
controller: chatVM.scrollController,
itemCount: chatMessages.length,
separatorBuilder: (BuildContext context, int index) => 20.height,
itemBuilder: (BuildContext context, int index) {
ChatMessageModel chatMessageModel = chatMessages[index];
return ChatMessageCustomWidget(
chatMessageModel: chatMessageModel,
requestModel: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel! : null,
requestStatusEnum: requestVM.currentSelectedRequest?.requestStatus,
chatTypeEnum: chatTypeEnum,
requestsTypeEnum: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel!.requestType.toRequestTypeEnum() : RequestsTypeEnum.specialCarRequest,
);
},
).horPaddingMain(),
controller: chatVM.scrollController,
itemCount: chatMessages.length,
separatorBuilder: (BuildContext context, int index) => 20.height,
itemBuilder: (BuildContext context, int index) {
ChatMessageModel chatMessageModel = chatMessages[index];
return ChatMessageCustomWidget(
chatMessageModel: chatMessageModel,
requestModel: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel! : null,
requestStatusEnum: requestVM.currentSelectedRequest?.requestStatus,
chatTypeEnum: chatTypeEnum,
requestsTypeEnum: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel!.requestType.toRequestTypeEnum() : RequestsTypeEnum.specialCarRequest,
);
},
).horPaddingMain(),
),
10.height,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (
AppState().currentAppType == AppType.customer && chatTypeEnum == ChatTypeEnum.requestOffer &&
if (AppState().currentAppType == AppType.customer &&
chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestType.toRequestTypeEnum() == RequestsTypeEnum.serviceRequest &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.inProgress &&
requestVM.currentSelectedOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.accepted ) ...[
requestVM.currentSelectedOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.accepted) ...[
Expanded(
child: ShowFillButton(
maxWidth: double.infinity,
@ -209,6 +217,7 @@ class _ChatViewState extends State<ChatView> {
isBold: false,
onPressed: () {
context.read<PaymentVM>().updateRequestId(id: requestVM.currentSelectedRequest!.id);
requestVM.selectedDeliveryOptionEnum = null;
navigateWithName(context, AppRoutes.reviewRequestOffer, arguments: PaymentTypes.request);
},
),
@ -234,93 +243,91 @@ class _ChatViewState extends State<ChatView> {
// ),
// ]
//
else
...[
if (AppState().currentAppType == AppType.provider &&
chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted &&
chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 1,
child: const Icon(
Icons.local_offer_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(
() {
requestVM.resetSendOfferBottomSheet();
RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(
requestIndex: chatViewArgumentsForRequest!.requestIndex,
requestModel: chatViewArgumentsForRequest!.requestModel!,
else ...[
if (AppState().currentAppType == AppType.provider &&
chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted &&
chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 1,
child: const Icon(
Icons.local_offer_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(
() {
requestVM.resetSendOfferBottomSheet();
RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(
requestIndex: chatViewArgumentsForRequest!.requestIndex,
requestModel: chatViewArgumentsForRequest!.requestModel!,
);
context.read<DashboardVMProvider>().checkUserSubscription(SubscriptionActionTypeEnum.subscription, context, callback: () {
buildSendOfferBottomSheet(
context: context,
requestDetailPageArguments: requestDetailArguments,
isFromChatScreen: true,
offerId: null, // null means creating new offer
);
context.read<DashboardVMProvider>().checkUserSubscription(SubscriptionActionTypeEnum.subscription, context, callback: () {
buildSendOfferBottomSheet(
context: context,
requestDetailPageArguments: requestDetailArguments,
isFromChatScreen: true,
offerId: null, // null means creating new offer
);
});
},
),
),
],
if (chatVM.pickedImagesForMessage.isNotEmpty) ...[
Expanded(
flex: 8,
child: PickedFilesContainer(
pickedFiles: chatVM.pickedImagesForMessage,
onCrossPressedPrimary: chatVM.removeImageFromList,
onAddFilePressed: () => chatVM.pickMultipleImages(),
),
});
},
),
] else
if (chatTypeEnum == ChatTypeEnum.requestOffer) ...[
Expanded(
flex: 1,
child: const Icon(
Icons.photo_library_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(() => chatVM.pickMultipleImages()),
),
],
if (chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 8,
child: TxtField(
isNeedLabelOnTop: false,
value: chatVM.chatMessageText,
hint: LocaleKeys.typeMessageHere.tr(),
keyboardType: TextInputType.text,
isNeedBorder: false,
onChanged: (v) => chatVM.updateChatMessageText(v),
),
),
],
if (chatVM.pickedImagesForMessage.isNotEmpty) ...[
Expanded(
flex: 8,
child: PickedFilesContainer(
pickedFiles: chatVM.pickedImagesForMessage,
onCrossPressedPrimary: chatVM.removeImageFromList,
onAddFilePressed: () => chatVM.pickMultipleImages(),
),
],
),
] else if (chatTypeEnum == ChatTypeEnum.requestOffer) ...[
Expanded(
flex: 1,
child: const Icon(Icons.send_rounded, color: MyColors.darkPrimaryColor, size: 30).onPress(
() async {
ChatMessageTypeEnum chatMessageTypeEnum = ChatMessageTypeEnum.freeText;
child: const Icon(
Icons.photo_library_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(() => chatVM.pickMultipleImages()),
),
],
if (chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 8,
child: TxtField(
isNeedLabelOnTop: false,
value: chatVM.chatMessageText,
hint: LocaleKeys.typeMessageHere.tr(),
keyboardType: TextInputType.text,
isNeedBorder: false,
onChanged: (v) => chatVM.updateChatMessageText(v),
),
),
],
Expanded(
flex: 1,
child: const Icon(Icons.send_rounded, color: MyColors.darkPrimaryColor, size: 30).onPress(
() async {
ChatMessageTypeEnum chatMessageTypeEnum = ChatMessageTypeEnum.freeText;
if (chatVM.pickedImagesForMessage.isNotEmpty) {
chatMessageTypeEnum = ChatMessageTypeEnum.image;
}
final status = await onMessageSend(chatMessageType: chatMessageTypeEnum);
if (chatVM.pickedImagesForMessage.isNotEmpty) {
chatMessageTypeEnum = ChatMessageTypeEnum.image;
}
final status = await onMessageSend(chatMessageType: chatMessageTypeEnum);
if (status) {
chatVM.scrollChatDown();
if (chatMessageTypeEnum == ChatMessageTypeEnum.freeText) {
chatVM.clearChatMessageText();
} else if (chatMessageTypeEnum == ChatMessageTypeEnum.image) {
chatVM.clearPickedImagesForMessage();
}
if (status) {
chatVM.scrollChatDown();
if (chatMessageTypeEnum == ChatMessageTypeEnum.freeText) {
chatVM.clearChatMessageText();
} else if (chatMessageTypeEnum == ChatMessageTypeEnum.image) {
chatVM.clearPickedImagesForMessage();
}
},
),
}
},
),
],
),
],
],
).toContainer(isShadowEnabled: true)
],

@ -150,6 +150,7 @@ class AdsFragment extends StatelessWidget {
? const Center(child: CircularProgressIndicator())
: AdsListWidget(
isAdsFragment: true,
isDraftAds: false,
shouldShowAdStatus: !adVM.isExploreAdsTapped,
adsList: getAdsList(adVM),
hasMoreData: adVM.isExploreAdsTapped ? adVM.hasMoreDataForExploreAds : adVM.hasMoreDataForMyAds,

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/gestures.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
@ -176,6 +178,9 @@ class MyRequestsFragment extends StatelessWidget {
onTap: () async {
RequestModel request = requestsVM.myFilteredRequests[index];
requestsVM.updateCurrentSelectedRequest(request);
log("request.requestStatus: ${request.requestStatus}");
if (request.requestStatus == RequestStatusEnum.pending ||
request.requestStatus == RequestStatusEnum.cancelled ||
request.requestStatus == RequestStatusEnum.expired) {

@ -20,6 +20,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 CreateRequestPage extends StatelessWidget {
const CreateRequestPage({super.key});
@ -240,7 +241,7 @@ class CreateRequestPage extends StatelessWidget {
text: LocaleKeys.attachImage.tr(),
icon: MyAssets.attachmentIcon.buildSvg(),
extensions: GlobalConsts.allowedFileExtensions,
),
).paddingOnly(top: 8),
],
if (requestsVM.vehicleImageError != "") ...[
10.height,

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/routes.dart';
@ -129,9 +131,11 @@ class RequestDetailPage extends StatelessWidget {
Widget buildRequestDetailActionFooter({
required int requestId,
required RequestDeliveryOptionEnum selectedDeliveryOption,
required RequestStatusEnum requestStatus,
required RequestsTypeEnum requestTypeEnum,
required ShippingRequestStatusEnum shippingRequestStatusEnum,
required SelfPickupRequestStatusEnum selfPickupRequestStatusEnum,
required String statusText,
required BuildContext context,
}) {
@ -155,6 +159,23 @@ class RequestDetailPage extends StatelessWidget {
case RequestStatusEnum.paid:
if (AppState().currentAppType == AppType.provider) {
if (selectedDeliveryOption == RequestDeliveryOptionEnum.selfPickup) {
return ShowFillButton(
maxWidth: double.infinity,
margin: const EdgeInsets.all(15),
maxHeight: 55,
title: LocaleKeys.initiateSelfPickup.tr(),
isBold: false,
onPressed: () async {
final requestVM = context.read<RequestsVM>();
bool status = await requestVM.onActionRequestTapped(context: context, requestStatusEnum: RequestStatusEnum.selfPickup, requestId: requestId);
if (status) {
await requestVM.getRequests(isNeedToRebuild: true);
pop(context);
}
},
);
}
return ShowFillButton(
maxWidth: double.infinity,
margin: const EdgeInsets.all(15),
@ -210,6 +231,33 @@ class RequestDetailPage extends StatelessWidget {
},
);
}
case RequestStatusEnum.selfPickup:
if (AppState().currentAppType == AppType.customer && selfPickupRequestStatusEnum == SelfPickupRequestStatusEnum.collected) {
return Column(
children: [
Utils.buildStatusContainer("${LocaleKeys.selfPickupStatus.tr()} ${Utils.getNameBySelfPickupRequestStatusEnum(selfPickupRequestStatusEnum).capitalizeFirstLetter()}")
.paddingOnly(left: 8, right: 8),
ShowFillButton(
maxWidth: double.infinity,
margin: const EdgeInsets.all(15),
maxHeight: 55,
title: LocaleKeys.markAsCompleted.tr(),
onPressed: () {
return dealCompletedConsentBottomSheet(
mainContext: context,
requestStatusEnum: RequestStatusEnum.completed,
requestId: requestId,
showAcknowledgement: AppState().currentAppType == AppType.customer,
);
},
)
],
);
} else if (AppState().currentAppType == AppType.provider) {
return Utils.buildStatusContainer(LocaleKeys.shippingManagementInstruction.tr());
} else {
return Utils.buildStatusContainer(statusText);
}
case RequestStatusEnum.completed:
case RequestStatusEnum.cancelled:
case RequestStatusEnum.expired:
@ -301,7 +349,9 @@ class RequestDetailPage extends StatelessWidget {
statusText: "Offer ${requestDetailPageArguments.requestModel.requestStatusName}",
requestTypeEnum: requestDetailPageArguments.requestModel.requestType.toRequestTypeEnum(),
shippingRequestStatusEnum: requestDetailPageArguments.requestModel.shippingStatusEnum ?? ShippingRequestStatusEnum.pending,
selfPickupRequestStatusEnum: requestDetailPageArguments.requestModel.selfPickupRequestStatusEnum ?? SelfPickupRequestStatusEnum.preparingToCollect,
context: context,
selectedDeliveryOption: requestDetailPageArguments.requestModel.selectedDeliveryOptionByCustomer,
),
],
],

@ -37,9 +37,10 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
@override
void initState() {
final requestVM = context.read<RequestsVM>();
if (requestVM.acceptedRequestOffer != null && requestVM.acceptedRequestOffer!.requestDeliveryOption == RequestDeliveryOptionEnum.both) {
populateRequestDeliveryOptions();
}
log("requestVM.acceptedRequestOffer!.requestDeliveryOption: ${requestVM.acceptedRequestOffer!.requestDeliveryOption}");
// if (requestVM.acceptedRequestOffer != null && requestVM.acceptedRequestOffer!.requestDeliveryOption == RequestDeliveryOptionEnum.both) {
populateRequestDeliveryOptions();
// }
if (requestVM.currentSelectedRequest != null && requestVM.currentSelectedRequest!.address.isEmpty) {
requestVM.addressSparePartRequestDelivery = "";
@ -56,7 +57,9 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
populateRequestDeliveryOptions() {
scheduleMicrotask(() {
final requestVM = context.read<RequestsVM>();
requestVM.populateRequestDeliveryOptions();
requestVM.updateAdditionalAddressSparePartRequestDelivery(requestVM.currentSelectedRequest!.additionalAddressDetails, false);
});
}
@ -136,8 +139,16 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
8.height,
FiltersList(
filterList: requestVM.deliveryOptionsForReviewRequest,
onFilterTapped: (index, selectedFilterId) {
requestVM.updateSelectedDeliveryOptionEnum(selectedFilterId.toRequestDeliveryOptionEnum());
onFilterTapped: (index, selectedFilterId) async {
int response = await requestVM.onRequestDeliveryOptionTapped(
context: context,
requestID: requestVM.currentSelectedRequest!.id,
reqOfferId: requestVM.acceptedRequestOffer!.id ?? 0,
deliveryOptionEnum: selectedFilterId.toRequestDeliveryOptionEnum());
if (response != -1) {
requestVM.updateSelectedDeliveryOptionEnum(selectedFilterId.toRequestDeliveryOptionEnum());
}
},
needLeftPadding: false,
).paddingOnly(bottom: 8),
@ -149,7 +160,22 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleDetailWidget(text: address, type: LocaleKeys.location.tr()),
if (requestVM.selectedDeliveryOptionEnum == RequestDeliveryOptionEnum.selfPickup) ...[
if (requestVM.selectedDeliveryOptionEnum == RequestDeliveryOptionEnum.delivery) ...[
8.height,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
("${LocaleKeys.additionalAddressDetails.tr()}:").toText(fontSize: 12, color: MyColors.lightTextColor),
MyAssets.icEdit.buildSvg(height: 15).onPress(() => buildLocationInformationEditBottomSheet(context, requestVM)),
],
),
(requestVM.additionalAddressSparePartRequestDelivery).toText(fontSize: 14, color: MyColors.darkTextColor),
],
),
] else if (requestVM.selectedDeliveryOptionEnum == RequestDeliveryOptionEnum.selfPickup) ...[
Row(
children: [
LocaleKeys.openMapLocation.tr().toText(
@ -274,32 +300,33 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Update your location information".toText(fontSize: 14, fontWeight: MyFonts.Medium),
8.height,
TxtField(
hint: LocaleKeys.address.tr(),
isNeedClickAll: false,
value: requestsVM.addressSparePartRequestDelivery,
postfixWidget: IconButton(
icon: const Icon(
size: 28,
Icons.add_location_outlined,
),
onPressed: () {
navigateTo(
context,
PickLocationPage(
onPickAddress: (double latitude, double longitude, String address) {
requestsVM.updateAddressSparePartRequestDelivery(address);
setState(() {});
},
),
);
}),
onChanged: (e) => requestsVM.updateAddressSparePartRequestDelivery(e),
),
LocaleKeys.updateYourLocationInfo.tr().toText(fontSize: 14, fontWeight: MyFonts.Medium),
// 8.height,
// TxtField(
// hint: LocaleKeys.address.tr(),
// isNeedClickAll: false,
// value: requestsVM.addressSparePartRequestDelivery,
// postfixWidget: IconButton(
// icon: const Icon(
// size: 28,
// Icons.add_location_outlined,
// ),
// onPressed: () {
// navigateTo(
// context,
// PickLocationPage(
// onPickAddress: (double latitude, double longitude, String address) {
// requestsVM.updateAddressSparePartRequestDelivery(address);
// setState(() {});
// },
// ),
// );
// }),
// onChanged: (e) => requestsVM.updateAddressSparePartRequestDelivery(e),
// ),
8.height,
TxtField(
maxLines: 2,
hint: LocaleKeys.additionalAddressDetails.tr(),
isNeedClickAll: false,
value: requestsVM.additionalAddressSparePartRequestDelivery,
@ -312,12 +339,14 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
Expanded(
child: ShowFillButton(
title: LocaleKeys.submit.tr(),
onPressed: () {
// TODO: Call some api here to update this info for this specific request.
requestsVM.currentSelectedRequest!.address = requestsVM.addressSparePartRequestDelivery;
requestsVM.updateAdditionalAddressSparePartRequestDelivery(additionalDetails);
requestsVM.notifyListeners();
pop(context);
onPressed: () async {
bool status = await requestsVM.updateRequestAdditionalAddress(context: context, additionalAddress: additionalDetails, requestId: requestsVM.currentSelectedRequest!.id);
if (status) {
requestsVM.updateAdditionalAddressSparePartRequestDelivery(additionalDetails, true);
requestsVM.notifyListeners();
pop(context);
}
},
),
)
@ -381,7 +410,7 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
onPressed: () {
final requestVM = context.read<RequestsVM>();
// context.read<PaymentVM>().updateRequestId(id: requestVM.currentSelectedRequest!.id);
if (requestVM.acceptedRequestOffer!.requestDeliveryOption == RequestDeliveryOptionEnum.both && requestVM.selectedDeliveryOptionEnum == null) {
if (requestVM.selectedDeliveryOptionEnum == null) {
requestVM.updateSelectedDeliveryOptionEnumError(GlobalConsts.deliveryOptionSelectionError);
} else {
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.request);

@ -10,6 +10,7 @@ import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/document.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
@ -201,9 +202,10 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
hint: LocaleKeys.expiryDate.tr(),
value: document.dateExpire != null && document.status == DocumentStatusEnum.pending || document.status == DocumentStatusEnum.approvedOrActive ? "${DateFormat('yyyy-MM-dd').format(
DateTime.parse(document.dateExpire!))}" : formattedDate == null
DateTime.parse(formatDate(document.dateExpire!)))}" : formattedDate == null
? ""
: "${DateFormat('yyyy-MM-dd').format(DateTime.parse(document.dateExpire!))}",
: "${formatDate(document.dateExpire!)}",
isNeedClickAll: true,
postFixDataColor: MyColors.darkTextColor,
onTap: () async {
@ -218,6 +220,7 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
.now()
.day), firstDate: DateTime.now());
if (formattedDate!.isNotEmpty) {
print(formattedDate);
document.dateExpire = formattedDate;
setState(() {});
}
@ -367,3 +370,17 @@ Color getColorByStatus(DocumentStatusEnum docStatus) {
return MyColors.adPendingStatusColor;
}
}
String formatDate(String dateString) {
List<String> parts = dateString.split('-');
if (parts[1].length == 1) {
parts[1] = '0${parts[1]}';
}
if (parts[2].length == 1) {
parts[2] = '0${parts[2]}';
}
String formattedDateString = parts.join('-');
DateTime dateTime = DateTime.parse(formattedDateString);
return DateFormat('yyyy-MM-dd').format(dateTime);
}

@ -128,7 +128,8 @@ class SettingOptionsInviteFriends extends StatelessWidget {
leadingWidget: const Icon(Icons.group, size: 20),
titleText: LocaleKeys.inviteFriends.tr(),
needBorderBelow: true,
onTap: () {
onTap: () async {
await context.read<SettingOptionsVM>().getAppInvitationHistoryList(context);
return buildInviteFriendsBottomSheet(context);
},
),
@ -140,12 +141,11 @@ class SettingOptionsInviteFriends extends StatelessWidget {
onTap: () => navigateWithName(context, AppRoutes.settingOptionsHelp),
),
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.person, size: 20),
titleText: LocaleKeys.account.tr(),
needBorderBelow: false,
onTap: () {
navigateWithName(context, AppRoutes.profileView);
}),
leadingWidget: const Icon(Icons.person, size: 20),
titleText: LocaleKeys.account.tr(),
needBorderBelow: false,
onTap: () => navigateWithName(context, AppRoutes.profileView),
),
],
).toContainer(
width: double.infinity,

@ -112,12 +112,25 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
}),
],
CustomSettingOptionsTile(
leadingWidget: SvgPicture.asset(
MyAssets.icAds,
height: 20,
width: 20,
color: MyColors.darkIconColor,
),
titleText: LocaleKeys.myDraftAds.tr(),
needBorderBelow: true,
onTap: () {
navigateWithName(context, AppRoutes.myDraftAdsView);
},
),
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.settings, size: 20),
titleText: LocaleKeys.settings.tr(),
needBorderBelow: false,
onTap: () {
context.read<SettingOptionsVM>().getAppInvitationHistoryList();
// context.read<SettingOptionsVM>().getAppInvitationHistoryList();
navigateWithName(context, AppRoutes.settingOptionsInviteFriends);
}),
],

@ -53,7 +53,7 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
super.initState();
}
List<FilterListModel> getAvailableStatusesList(List<FilterListModel> list, ShippingRequestStatusEnum shippingRequestStatusEnum) {
List<FilterListModel> getAvailableStatusesShippingList(List<FilterListModel> list, ShippingRequestStatusEnum shippingRequestStatusEnum) {
List<FilterListModel> newList = [];
for (var element in list) {
@ -64,6 +64,17 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
return newList;
}
List<FilterListModel> getAvailableStatusesPickupList(List<FilterListModel> list, SelfPickupRequestStatusEnum selfPickupRequestStatusEnum) {
List<FilterListModel> newList = [];
for (var element in list) {
if (element.id > selfPickupRequestStatusEnum.getIdFromSelfPickupStatusEnum()) {
newList.add(element);
}
}
return newList;
}
Future buildUpdateShippingStatusBottomSheet({required int shippingRequestId, required ShippingRequestStatusEnum shippingRequestStatusEnum}) {
return showModalBottomSheet(
context: context,
@ -84,7 +95,7 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
12.height,
ListView.separated(
shrinkWrap: true,
itemCount: getAvailableStatusesList(shippingManagementVM.shippingRequestStatusesList, shippingRequestStatusEnum).length,
itemCount: getAvailableStatusesShippingList(shippingManagementVM.shippingRequestStatusesList, shippingRequestStatusEnum).length,
separatorBuilder: (BuildContext context, int index) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 3.0),
@ -92,7 +103,7 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
);
},
itemBuilder: (BuildContext context, int index) {
List<FilterListModel> list = getAvailableStatusesList(shippingManagementVM.shippingRequestStatusesList, shippingRequestStatusEnum);
List<FilterListModel> list = getAvailableStatusesShippingList(shippingManagementVM.shippingRequestStatusesList, shippingRequestStatusEnum);
FilterListModel shippingFilterListModel = list[index];
int id = list[index].id;
return CircleCheckBoxWithTitle(
@ -145,6 +156,91 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
);
}
Future buildUpdateSelfPickupStatusBottomSheet({required int shippingRequestId, required SelfPickupRequestStatusEnum selfPickupRequestStatusEnum}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return Consumer(builder: (BuildContext context, ShippingManagementVM shippingManagementVM, Widget? child) {
return InfoBottomSheet(
title: LocaleKeys.pleaseSpecify.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
12.height,
ListView.separated(
shrinkWrap: true,
itemCount: getAvailableStatusesPickupList(shippingManagementVM.selfPickupRequestsStatusesList, selfPickupRequestStatusEnum).length,
separatorBuilder: (BuildContext context, int index) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 3.0),
child: Divider(thickness: 0.5),
);
},
itemBuilder: (BuildContext context, int index) {
List<FilterListModel> list = getAvailableStatusesPickupList(shippingManagementVM.selfPickupRequestsStatusesList, selfPickupRequestStatusEnum);
FilterListModel shippingFilterListModel = list[index];
int id = list[index].id;
return CircleCheckBoxWithTitle(
isChecked: shippingFilterListModel.isSelected,
title: shippingFilterListModel.title,
onSelected: () {
int i = shippingManagementVM.selfPickupRequestsStatusesList.indexWhere((element) => element.id == id);
if (i == -1) {
return;
}
shippingManagementVM.updateSelectionInSelfPickupRequestStatuses(i);
},
selectedColor: MyColors.darkPrimaryColor,
);
},
),
12.height,
TxtField(
maxLines: 4,
value: shippingManagementVM.requestStatusComments,
errorValue: "",
keyboardType: TextInputType.text,
hint: LocaleKeys.comment.tr(),
onChanged: (v) => shippingManagementVM.updateRequestStatusComments(v),
),
],
),
25.height,
ShowFillButton(
title: LocaleKeys.submit.tr(),
onPressed: () async {
FilterListModel value = shippingManagementVM.selfPickupRequestsStatusesList.firstWhere((element) => element.isSelected);
SelfPickupRequestStatusEnum selfPickupRequestStatusEnum = value.id.toSelfPickupStatusEnum();
bool status = await shippingManagementVM.onUpdateSelfPickupStatusTapped(
selfPickupRequestStatusEnum: selfPickupRequestStatusEnum,
shippingRequestId: shippingRequestId,
context: context,
);
if (status) {
pop(context);
int index = shippingManagementVM.selfPickupRequestsFilterOptions.indexWhere((element) => element.isSelected);
int id = shippingManagementVM.selfPickupRequestsFilterOptions[index].id;
await shippingManagementVM.getSelfPickupRequestsListByFilters(selfPickupStatusEnum: id.toSelfPickupStatusEnum());
}
},
maxWidth: double.infinity,
),
19.height,
],
),
));
});
},
);
}
@override
void dispose() {
shippingViewModel.resetFilters();
@ -240,10 +336,17 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.statusContainerChip(
text: Utils.getNameByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated),
chipColor: Utils.getChipColorByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated),
),
if (shippingVm.isSelfPickupTapped) ...[
Utils.statusContainerChip(
text: Utils.getNameBySelfPickupRequestStatusEnum(shippingRequest.selfPickupRequestStatusEnum ?? SelfPickupRequestStatusEnum.preparingToCollect),
chipColor: Utils.getChipColorBySelfPickupRequestStatusEnum(shippingRequest.selfPickupRequestStatusEnum ?? SelfPickupRequestStatusEnum.preparingToCollect),
),
] else ...[
Utils.statusContainerChip(
text: Utils.getNameByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated),
chipColor: Utils.getChipColorByShippingRequestStatusEnum(shippingRequest.shippingStatusEnum ?? ShippingRequestStatusEnum.initiated),
),
],
("${shippingRequest.request!.brand} ${shippingRequest.request!.model} | ${shippingRequest.requestID.toString()}").toText(fontSize: 16),
(shippingRequest.request!.description ?? "").toText(color: MyColors.lightTextColor, fontSize: 12, fontWeight: MyFonts.Medium),
if (shippingRequest.vehicleType != null && shippingRequest.vehicleType!.isNotEmpty) ...[
@ -265,17 +368,30 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
],
],
),
if (shippingRequest.shippingStatusEnum != ShippingRequestStatusEnum.delivered) ...[
const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18),
if (shippingVm.isSelfPickupTapped) ...[
if (shippingRequest.selfPickupRequestStatusEnum != SelfPickupRequestStatusEnum.collected) ...[
const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18),
],
] else ...[
if (shippingRequest.shippingStatusEnum != ShippingRequestStatusEnum.delivered) ...[
const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18),
],
],
],
),
],
).onPress(() {
if (shippingRequest.shippingStatusEnum == ShippingRequestStatusEnum.delivered) {
return;
if (shippingVm.isSelfPickupTapped) {
if (shippingRequest.selfPickupRequestStatusEnum == SelfPickupRequestStatusEnum.collected) {
return;
}
buildUpdateSelfPickupStatusBottomSheet(shippingRequestId: shippingRequest.id!, selfPickupRequestStatusEnum: shippingRequest.selfPickupRequestStatusEnum!);
} else {
if (shippingRequest.shippingStatusEnum == ShippingRequestStatusEnum.delivered) {
return;
}
buildUpdateShippingStatusBottomSheet(shippingRequestId: shippingRequest.id!, shippingRequestStatusEnum: shippingRequest.shippingStatusEnum!);
}
buildUpdateShippingStatusBottomSheet(shippingRequestId: shippingRequest.id!, shippingRequestStatusEnum: shippingRequest.shippingStatusEnum!);
}).toContainer(isShadowEnabled: true);
},
separatorBuilder: (context, index) => 16.height,

Loading…
Cancel
Save