12 feb,2025

aamir_dev
Faiz Hashmi 9 months ago
parent 021618fa6b
commit 59875f5198

@ -805,5 +805,8 @@
"enterEndPrice": "أدخل سعر النهاية",
"searchByVehicleType": "البحث حسب نوع المركبة",
"selectVehicleType": "اختر نوع المركبة",
"specialRequestsChats": "دردشات الطلبات الخاصة"
"specialRequestsChats": "دردشات الطلبات الخاصة",
"selectDeliveryOption": "اختر خيار التوصيل",
"deliveryOptions": "خيارات التوصيل",
"selfPickup": "الالتقاط الذاتي"
}

@ -803,5 +803,8 @@
"enterEndPrice": "Enter end price",
"searchByVehicleType": "Search by vehicle type",
"selectVehicleType": "Select vehicle type",
"specialRequestsChats": "Special Requests Chats"
"specialRequestsChats": "Special Requests Chats",
"selectDeliveryOption": "Select Delivery Option",
"deliveryOptions": "Delivery Options",
"selfPickup": "Self Pickup"
}

@ -182,6 +182,8 @@ class ApiConsts {
//Shipping
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";
//Chat
static String chatHubUrl = "$baseUrlServices/McHub";
@ -190,6 +192,7 @@ class ApiConsts {
static String getChatMessagesForRequests = "${baseUrlServices}api/RequestManagement/ReqOfferChat_Get";
static String getChatMessagesForAds = "${baseUrlServices}api/Advertisement/AdsChat_Get";
static String getChatBuyersForAds = "${baseUrlServices}api/Advertisement/AdsChatBuyer_Get";
static String reqChatUnreadGet = "${baseUrlServices}api/RequestManagement/Req_ChatUnread_Get";
//Settings Options
static String getAllFAQs = "${baseUrlServices}api/Common/FAQ_Get";
@ -226,6 +229,7 @@ class GlobalConsts {
static String welcomeVideoUrl = "welcomeVideoUrl";
static String doNotShowWelcomeVideo = "doNotShowWelcomeVideo";
static String demandAmountError = "Amount Cannot be Empty";
static String deliveryOptionSelectionError = "At least one delivery option should be selected.";
static String reservationCancelError = "Cancellation Reason Cannot be Empty";
static String descriptionError = "Description should be more than 5 letters.";
static String acceptingThisOffer = "I am accepting this offer.";
@ -420,42 +424,44 @@ class SignalrConsts {
}
class GuestConsts {
UserInfo userInfo = UserInfo.fromJson({
"id": -1,
"userID": null,
"firstName": "Guest",
"lastName": "User",
"companyName": null,
"accountStatus": "2",
"activityStatus": "Offline",
"accountStatusText": null,
"subscriptionDate": null,
"mobileNo": "966123456789",
"email": "mowatter@gmail.com",
"userImageUrl": "https://ms.hmg.com/api/ProfileImage?imageName=User_Default.png",
"roleID": 4,
"roleName": "Customer",
"isEmailVerified": false,
"serviceProviderBranch": [],
"isVerified": true,
"userRoles": [],
"isProviderDealership": false,
"isProviderIndividual": false,
"isProvider": false,
"providerID": null,
"isCustomer": true,
"customerID": 25,
"countryID": 1,
"countryName": "Saudi Arabia",
"cityID": 1,
"cityName": "Riyadh",
"dealershipUserID": null,
"serviceProviderBranchID": null,
"createdOn": "2024-12-24T09:20:47.6733333",
"genderID": 1,
"genderName": "Male",
"serviceProviderPayment": [],
"deviceType": "1",
"deviceToken": null,
});
UserInfo userInfo = UserInfo.fromJson(
{
"id": -1,
"userID": null,
"firstName": "Guest",
"lastName": "User",
"companyName": null,
"accountStatus": "2",
"activityStatus": "Offline",
"accountStatusText": null,
"subscriptionDate": null,
"mobileNo": "966123456789",
"email": "mowatter@gmail.com",
"userImageUrl": "https://ms.hmg.com/api/ProfileImage?imageName=User_Default.png",
"roleID": 4,
"roleName": "Customer",
"isEmailVerified": false,
"serviceProviderBranch": [],
"isVerified": true,
"userRoles": [],
"isProviderDealership": false,
"isProviderIndividual": false,
"isProvider": false,
"providerID": null,
"isCustomer": true,
"customerID": 25,
"countryID": 1,
"countryName": "Saudi Arabia",
"cityID": 1,
"cityName": "Riyadh",
"dealershipUserID": null,
"serviceProviderBranchID": null,
"createdOn": "2024-12-24T09:20:47.6733333",
"genderID": 1,
"genderName": "Male",
"serviceProviderPayment": [],
"deviceType": "1",
"deviceToken": null,
},
);
}

@ -975,7 +975,7 @@ extension ShippingStatusEnumExt on int {
return ShippingRequestStatusEnum.inTransit;
} else if (this == 3) {
return ShippingRequestStatusEnum.outForDelivery;
} else if (this == 4) {
} else if (this == 4) {
return ShippingRequestStatusEnum.delivered;
}
return ShippingRequestStatusEnum.pending;
@ -1003,6 +1003,83 @@ extension ShippingStatusEnumToInt on ShippingRequestStatusEnum {
}
}
extension SelfPickupStatusEnumExt on int {
SelfPickupRequestStatusEnum toSelfPickupStatusEnum() {
if (this == -1) {
return SelfPickupRequestStatusEnum.allRequests;
} else if (this == 0) {
return SelfPickupRequestStatusEnum.allRequests;
} else if (this == 1) {
return SelfPickupRequestStatusEnum.preparingToCollect;
} else if (this == 2) {
return SelfPickupRequestStatusEnum.readyToCollect;
} else if (this == 3) {
return SelfPickupRequestStatusEnum.collected;
}
return SelfPickupRequestStatusEnum.allRequests;
}
}
extension SelfPickupStatusEnumToInt on SelfPickupRequestStatusEnum {
int getIdFromSelfPickupStatusEnum() {
switch (this) {
case SelfPickupRequestStatusEnum.allRequests:
return 0;
case SelfPickupRequestStatusEnum.preparingToCollect:
return 1;
case SelfPickupRequestStatusEnum.readyToCollect:
return 2;
case SelfPickupRequestStatusEnum.collected:
return 3;
default:
return -1;
}
}
}
extension RequestDeliveryOptionEnumExt on int {
RequestDeliveryOptionEnum toRequestDeliveryOptionEnum() {
if (this == 1) {
return RequestDeliveryOptionEnum.delivery;
} else if (this == 2) {
return RequestDeliveryOptionEnum.selfPickup;
} else if (this == 3) {
return RequestDeliveryOptionEnum.both;
}
return RequestDeliveryOptionEnum.none;
}
}
extension RequestDeliveryOptionEnumToIntExt on RequestDeliveryOptionEnum {
int getIdRequestDeliveryOptionEnum() {
switch (this) {
case RequestDeliveryOptionEnum.delivery:
return 1;
case RequestDeliveryOptionEnum.selfPickup:
return 2;
case RequestDeliveryOptionEnum.both:
return 3;
default:
return 0;
}
}
}
extension RequestDeliveryOptionEnumTosTRINGExt on RequestDeliveryOptionEnum {
String getStringFromRequestDeliveryOptionEnum() {
switch (this) {
case RequestDeliveryOptionEnum.delivery:
return "Delivery";
case RequestDeliveryOptionEnum.selfPickup:
return "Self Pickup";
case RequestDeliveryOptionEnum.both:
return "Delivery, Self Pickup";
default:
return "Self Pickup";
}
}
}
extension CapitalizeFirstLetter on String {
String capitalizeFirstLetter() {
if (isEmpty) {

@ -821,7 +821,10 @@ class CodegenLoader extends AssetLoader{
"enterEndPrice": "أدخل سعر النهاية",
"searchByVehicleType": "البحث حسب نوع المركبة",
"selectVehicleType": "اختر نوع المركبة",
"specialRequestsChats": "دردشات الطلبات الخاصة"
"specialRequestsChats": "دردشات الطلبات الخاصة",
"selectDeliveryOption": "اختر خيار التوصيل",
"deliveryOptions": "خيارات التوصيل",
"selfPickup": "الالتقاط الذاتي"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1628,7 +1631,10 @@ static const Map<String,dynamic> en_US = {
"enterEndPrice": "Enter end price",
"searchByVehicleType": "Search by vehicle type",
"selectVehicleType": "Select vehicle type",
"specialRequestsChats": "Special Requests Chats"
"specialRequestsChats": "Special Requests Chats",
"selectDeliveryOption": "Select Delivery Option",
"deliveryOptions": "Delivery Options",
"selfPickup": "Self Pickup"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -785,5 +785,8 @@ abstract class LocaleKeys {
static const searchByVehicleType = 'searchByVehicleType';
static const selectVehicleType = 'selectVehicleType';
static const specialRequestsChats = 'specialRequestsChats';
static const selectDeliveryOption = 'selectDeliveryOption';
static const deliveryOptions = 'deliveryOptions';
static const selfPickup = 'selfPickup';
}

@ -84,6 +84,7 @@ class ReqOffer {
String? manufacturedOn;
double? price;
bool? isDeliveryAvailable;
RequestDeliveryOptionEnum? requestDeliveryOption;
RequestsTypeEnum? requestsTypeEnum;
RequestOfferStatusEnum? requestOfferStatusEnum;
List<MessageImageModel>? reqOfferImages;
@ -100,6 +101,7 @@ class ReqOffer {
this.manufacturedOn,
this.price,
this.isDeliveryAvailable,
this.requestDeliveryOption,
this.requestOfferStatusEnum,
this.requestsTypeEnum,
this.reqOfferImages,
@ -117,6 +119,7 @@ class ReqOffer {
manufacturedOn = json['offeredItemCreatedOn'] ?? json["createdOn"];
price = json['price'];
isDeliveryAvailable = json['isDeliveryAvailable'];
requestDeliveryOption = ((json['offerDeliveryOption'] ?? 0) as int).toRequestDeliveryOptionEnum();
requestOfferStatusEnum = ((json['offerStatus']) as int).toRequestOfferStatusEnum();
requestsTypeEnum = RequestsTypeEnum.serviceRequest;
// if (isForReqOfferImagesURLs) {

@ -0,0 +1,45 @@
class OffersUnreadChatModel {
final int reqTotal;
final List<OffersUnreadChatDataModel> reqChatUnread;
OffersUnreadChatModel({
required this.reqTotal,
required this.reqChatUnread,
});
factory OffersUnreadChatModel.fromJson(Map<String, dynamic> json) {
return OffersUnreadChatModel(
reqTotal: json['reqTotal'],
reqChatUnread: (json['reqChatUnread'] as List).map((e) => OffersUnreadChatDataModel.fromJson(e)).toList(),
);
}
}
class OffersUnreadChatDataModel {
final String senderUserID;
final int unreadMessagesCount;
final int requestId;
final String lastChatTime;
final String lastChatText;
final String customerName;
OffersUnreadChatDataModel({
required this.senderUserID,
required this.unreadMessagesCount,
required this.requestId,
required this.lastChatTime,
required this.lastChatText,
required this.customerName,
});
factory OffersUnreadChatDataModel.fromJson(Map<String, dynamic> json) {
return OffersUnreadChatDataModel(
senderUserID: json['senderUserID'],
unreadMessagesCount: json['unreadMessagesCount'],
requestId: json['requestId'] ?? 0,
lastChatTime: json['lastChatTime'],
lastChatText: json['lastChatText'],
customerName: json['customerName'],
);
}
}

@ -66,6 +66,7 @@ class ServiceProvidersOffers {
RequestOfferStatusEnum? requestOfferStatusEnum;
int? offerCount;
int? requestId;
String? providerAddress;
List<ChatMessageModel>? chatMessages;
ServiceProvidersOffers({
@ -80,6 +81,7 @@ class ServiceProvidersOffers {
this.providerUserId,
this.createdOn,
this.requestOfferStatusEnum,
this.providerAddress,
});
ServiceProvidersOffers.fromJson(Map<String, dynamic> json, int? reqId) {
@ -93,6 +95,7 @@ class ServiceProvidersOffers {
requestId = reqId;
createdOn = json['createdOn'];
requestOfferStatusEnum = ((json['offerStatusLast']) as int).toRequestOfferStatusEnum();
providerAddress = "Will be in API in case of self pickup";
chatMessages = [];
}

@ -6,6 +6,7 @@ import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependency_injection.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/requests_models/offers_unread_chat_model.dart';
import 'package:mc_common_app/models/requests_models/provider_offers_model.dart';
import 'package:mc_common_app/models/requests_models/providers_offers_chat_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
@ -30,6 +31,8 @@ abstract class RequestRepo {
Future<List<ProviderOffersChatsModel>> getOffersChatByProvider({int requestId = 0, required int serviceProviderId});
Future<OffersUnreadChatModel> getOffersChatsUnreadList({required String userId});
Future<ProviderOffersModel> getOffersFromProvidersByRequest({required int requestId});
Future<List<RequestModel>> getRequests({required int providerOrCustomerID});
@ -61,6 +64,7 @@ abstract class RequestRepo {
required int offerId,
required String offerPrice,
required bool isDeliveryAvailable,
required int offerDeliveryOption,
required String serviceItemName,
required String manufacturedByName,
required String manufacturedOn,
@ -293,6 +297,22 @@ class RequestRepoImp implements RequestRepo {
return offersList;
}
@override
Future<OffersUnreadChatModel> getOffersChatsUnreadList({required String userId}) async {
var queryParameters = {
"ReceiverUserID": userId.toString(),
};
GenericRespModel genericRespModel = await apiClient.getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.reqChatUnreadGet,
queryParameters: queryParameters,
token: appState.getUser.data!.accessToken,
);
OffersUnreadChatModel offersUnreadChatModel = OffersUnreadChatModel.fromJson(genericRespModel.data);
return offersUnreadChatModel;
}
@override
Future<ProviderOffersModel> getOffersFromProvidersByRequest({required int requestId}) async {
final customerId = appState.getUser.data!.userInfo!.customerId;
@ -353,6 +373,7 @@ class RequestRepoImp implements RequestRepo {
required int offerId,
required String offerPrice,
required bool isDeliveryAvailable,
required int offerDeliveryOption,
required String serviceItemName,
required String manufacturedByName,
required String manufacturedOn,
@ -372,7 +393,8 @@ class RequestRepoImp implements RequestRepo {
"offeredItemCreatedByName": manufacturedByName.toString(),
"offeredItemCreatedOn": manufacturedOn.toString(),
"reqOfferImages": requestImages,
"isDeliveryAvailable": isDeliveryAvailable
"isDeliveryAvailable": isDeliveryAvailable,
"offerDeliveryOption": offerDeliveryOption
};
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),

@ -14,9 +14,13 @@ import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
abstract class ShippingRepo {
Future<List<ShippingRequestModel>> getSelfPickupRequestListByStatus({SelfPickupRequestStatusEnum? selfPickupRequestStatus, int? requestId});
Future<List<ShippingRequestModel>> getShippingRequestListByStatus({ShippingRequestStatusEnum? shippingStatusEnum, int? requestId});
Future<GenericRespModel> updateShippingRequestStatus({required ShippingRequestStatusEnum shippingStatusEnum, required int shippingRequestId, String? comment});
Future<GenericRespModel> updateSelfPickupRequestStatus({required SelfPickupRequestStatusEnum selfPickupStatusEnum, required int shippingRequestId, String? comment});
}
class ShippingRepoImp extends ShippingRepo {
@ -48,6 +52,31 @@ class ShippingRepoImp extends ShippingRepo {
return list;
}
@override
Future<List<ShippingRequestModel>> getSelfPickupRequestListByStatus({SelfPickupRequestStatusEnum? selfPickupRequestStatus, int? requestId}) async {
String token = appState.getUser.data!.accessToken ?? "";
Map queryParameters = {
"requestID": "${requestId ?? 0}",
"selfPickUpStatus": "${selfPickupRequestStatus != null ? selfPickupRequestStatus.getIdFromSelfPickupStatusEnum() : -1}", // -1 to get all requests
};
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.selfPickupRequestStatusGet,
queryParameters,
token: token,
);
if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) {
Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<ShippingRequestModel> list = List.generate(genericRespModel.data.length, (index) => ShippingRequestModel.fromJson(genericRespModel.data[index]));
return list;
}
@override
Future<GenericRespModel> updateShippingRequestStatus({required ShippingRequestStatusEnum shippingStatusEnum, required int shippingRequestId, String? comment}) async {
String token = appState.getUser.data!.accessToken ?? "";
@ -70,4 +99,27 @@ class ShippingRepoImp extends ShippingRepo {
return genericRespModel;
}
@override
Future<GenericRespModel> updateSelfPickupRequestStatus({required SelfPickupRequestStatusEnum selfPickupStatusEnum, required int shippingRequestId, String? comment}) async {
String token = appState.getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {
"id": "$shippingRequestId",
"selfPickUpStatus": "${selfPickupStatusEnum.getIdFromSelfPickupStatusEnum()}",
"comment": comment ?? "",
};
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.selfPickupRequestStatusUpdate,
queryParameters,
token: token,
);
if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) {
Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr());
}
return genericRespModel;
}
}

@ -19,6 +19,8 @@ class AppEnums {
static const int conditionEnumId = -1; // to get the Condition Filter Enums
static const int serviceDeliveryTypeEnumId = 24; // to get the serviceDeliveryType
static const int shippingStatusEnumId = 30; // to get the Shipping Filter Enums
static const int selfPickupStatusEnumId = 33; // to get the SelfPickup Status Enums
static const int deliveryOptionEnumId = 32; // to get the SelfPickup Status Enums
}
enum DashboardRouteEnum {
@ -223,10 +225,9 @@ enum SubscriptionActionTypeEnum {
ads,
users,
branches,
subscription
subscription,
}
enum ShippingRequestStatusEnum {
allRequests,
pending,
@ -236,10 +237,22 @@ enum ShippingRequestStatusEnum {
delivered,
}
enum SelfPickupRequestStatusEnum {
allRequests,
preparingToCollect,
readyToCollect,
collected,
}
enum RequestDeliveryOptionEnum {
none,
delivery,
selfPickup,
both,
}
enum InviteTypeEnum {
whatsapp,
sms,
email,
}

@ -362,6 +362,7 @@ class ChatVM extends BaseVM {
required int requestId,
required String offerPrice,
required bool isDeliveryAvailable,
required RequestDeliveryOptionEnum offerDeliveryOption,
required String serviceItemName,
required String manufacturedByName,
required String manufacturedOn,
@ -385,10 +386,11 @@ class ChatVM extends BaseVM {
"RequestID": requestId,
"Price": double.parse(offerPrice),
"IsDeliveryAvailable": isDeliveryAvailable,
"OfferDeliveryOption": offerDeliveryOption.getIdRequestDeliveryOptionEnum(),
"ServiceItem": serviceItemName,
"ReqOfferImages": offerImages,
"OfferedItemCreatedByName": manufacturedByName,
"OfferedItemCreatedOn": manufacturedOn, // TODO: This should be in String on Server, Right now it is in DateTime
// "OfferedItemCreatedOn": manufacturedOn, // TODO: This should be in String on Server, Right now it is in DateTime
"ServiceProviderID": providerId,
"OfferStatus": RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
"Comment": message,
@ -651,6 +653,8 @@ class ChatVM extends BaseVM {
required int serviceProviderID,
required int requestOfferID,
required String offerPrice,
required bool isDeliveryAvailable,
required RequestDeliveryOptionEnum offerDeliveryOption,
required String serviceItemName,
required String manufacturedByName,
required String manufacturedOn,
@ -675,6 +679,9 @@ class ChatVM extends BaseVM {
"Price": double.parse(offerPrice),
"ServiceItem": serviceItemName,
"OfferedItemCreatedByName": manufacturedByName,
"IsDeliveryAvailable": isDeliveryAvailable,
"OfferDeliveryOption": offerDeliveryOption.getIdRequestDeliveryOptionEnum(),
// We have commented this because Backend Team is using their server time for this. It was the time offer created by
// "OfferedItemCreatedOn": manufacturedOn,
"ServiceProviderID": serviceProviderID,
"OfferStatus": requestOfferStatusEnum.getIdFromRequestOfferStatusEnum(),

@ -68,6 +68,7 @@ class DashboardVmCustomer extends BaseVM {
await appointmentsVM.populateAppointmentsFilterList();
await adVM.populateAdsFilterList();
await requestsVM.populateDataForRequestsFilter();
await requestsVM.populateDeliveryOptionEnums();
await appointmentsVM.applyFilterOnAppointmentsVMForCustomers(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, shouldPopulateUpcoming: true);
await appointmentsVM.applyFilterOnBranches(index: 0); // to get all branches!
await appointmentsVM.getMyRecentBranches(); // to get my recent branches

@ -79,20 +79,23 @@ class DashboardVMProvider extends BaseVM {
final serviceVM = context.read<ServiceVM>();
final adVM = context.read<AdVM>();
final subscriptionsVM = context.read<SubscriptionsVM>();
requestsVM.populateDataForRequestsFilter();
appointmentVM.populateAppointmentsFilterList();
shippingManagementVM.populateShippingRequestFilterList();
await requestsVM.populateDataForRequestsFilter();
await requestsVM.populateDeliveryOptionEnums();
await appointmentVM.populateAppointmentsFilterList();
await adVM.populateAdsFilterList();
await serviceVM.populateBranchServiceFilters();
await serviceVM.getBranchAndServices();
await requestsVM.getRequests();
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
if (dashboardRouteEnum != DashboardRouteEnum.fromAdsPayment && dashboardRouteEnum != DashboardRouteEnum.fromAdsSubmit) {
await adVM.getMyAds();
await adVM.getExploreAds();
}
await shippingManagementVM.populateShippingRequestFilterList();
await shippingManagementVM.populateSelfPickupRequestFilterList();
await appointmentVM.applyFilterOnAppointmentsVMForProviders(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, shouldPopulateUpcoming: true);
adVM.populateAdsFilterList();
await requestsVM.getRequests();
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
await adVM.getVehicleTypes();
await adVM.getVehicleAdsDuration();
await chatVM.buildHubConnection(context);

@ -217,7 +217,7 @@ class PaymentVM extends ChangeNotifier {
context.read<DashboardVmCustomer>().onNavbarTapped(1);
}
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
}
}
Future<void> onVisaCardSelected(BuildContext context, PaymentTypes paymentType) async {
currentPaymentType = paymentType;

@ -18,6 +18,7 @@ import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/offers_unread_chat_model.dart';
import 'package:mc_common_app/models/requests_models/provider_offers_model.dart';
import 'package:mc_common_app/models/requests_models/providers_offers_chat_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
@ -843,12 +844,12 @@ class RequestsVM extends BaseVM {
return isValid;
}
List<ProviderOffersChatsModel> providerOffersChatsList = [];
Future<void> getOffersChatByProvider({required int providerId, required BuildContext context}) async {
List<ProviderOffersChatsModel> providerOffersChatsList = [];
Future<void> getProviderOffersChatsList({required int serviceProviderId, required BuildContext context}) async {
try {
Utils.showLoading(context);
List<ProviderOffersChatsModel> respModel = await requestRepo.getOffersChatByProvider(serviceProviderId: serviceProviderId);
List<ProviderOffersChatsModel> respModel = await requestRepo.getOffersChatByProvider(serviceProviderId: providerId);
Utils.hideLoading(context);
providerOffersChatsList.clear();
providerOffersChatsList = respModel;
@ -860,7 +861,26 @@ class RequestsVM extends BaseVM {
}
}
OffersUnreadChatModel? offersUnreadChatModel;
Future<void> getOffersChatsUnreadList({required String userId, required BuildContext context}) async {
try {
Utils.showLoading(context);
OffersUnreadChatModel respModel = await requestRepo.getOffersChatsUnreadList(userId: userId);
Utils.hideLoading(context);
offersUnreadChatModel = respModel;
log("offersUnreadChatModel: ${offersUnreadChatModel!.reqChatUnread.length}");
notifyListeners();
} catch (e) {
logger.e(e.toString());
Utils.showToast(e.toString());
Utils.hideLoading(context);
return;
}
}
String offerPriceError = "";
String offerDescriptionError = "";
String offerPrice = "";
@ -907,6 +927,39 @@ class RequestsVM extends BaseVM {
}
}
String deliveryOptionSelectionError = "";
List<EnumsModel> myDeliveryOptionsEnum = [];
List<FilterListModel> myDeliveryOptionsFilterOptions = [];
Future<void> populateDeliveryOptionEnums() async {
if (myDeliveryOptionsFilterOptions.isNotEmpty) return;
try {
notifyListeners();
myDeliveryOptionsEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.deliveryOptionEnumId);
for (int i = 0; i < myDeliveryOptionsEnum.length; i++) {
myDeliveryOptionsFilterOptions.add(FilterListModel(title: myDeliveryOptionsEnum[i].enumValueStr, isSelected: false, id: myDeliveryOptionsEnum[i].enumValue));
}
notifyListeners();
} catch (e) {
logger.e(e.toString());
}
}
Future<void> applyFilterOnDeliveryOption({required RequestDeliveryOptionEnum requestDeliveryOptionEnum}) async {
if (myDeliveryOptionsFilterOptions.isEmpty) return;
for (var value in myDeliveryOptionsFilterOptions) {
value.isSelected = false;
}
if (requestDeliveryOptionEnum != RequestDeliveryOptionEnum.none) {
myDeliveryOptionsFilterOptions[requestDeliveryOptionEnum.getIdRequestDeliveryOptionEnum() - 1].isSelected = true; // -1 to match with the index
}
notifyListeners();
}
List<OfferRequestCommentModel> providerDeliveryActionsList = [
OfferRequestCommentModel(
index: 0,
@ -974,19 +1027,40 @@ class RequestsVM extends BaseVM {
} else {
offerDescriptionError = "";
}
if (currentSelectedRequest != null && currentSelectedRequest!.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeEnum()) {
int index = myDeliveryOptionsFilterOptions.indexWhere((option) => option.isSelected);
if (index == -1) {
deliveryOptionSelectionError = GlobalConsts.deliveryOptionSelectionError;
log("indexindex: ${index}");
isValidated = false;
}
notifyListeners();
} else {
deliveryOptionSelectionError = "";
}
notifyListeners();
log("isValidatedisValidated: ${isValidated}");
return isValidated;
}
void resetSendOfferBottomSheet() {
offerPrice = "";
offerPriceError = "";
offerDescription = "";
offerDescriptionError = "";
deliveryOptionSelectionError = "";
serviceItem = "";
serviceItemCreatedOn = "";
itemManufacturer = "";
isDeliveryAvailableStatus = false;
if (myDeliveryOptionsFilterOptions.isNotEmpty) {
myDeliveryOptionsFilterOptions.forEach((option) => option.isSelected = false);
}
pickedVehicleImages.clear();
notifyListeners();
}
@ -1055,6 +1129,7 @@ class RequestsVM extends BaseVM {
required int offerId,
required String offerPrice,
required bool isDeliveryAvailable,
required RequestDeliveryOptionEnum offerDeliveryOption,
required String serviceItemName,
required String manufacturedByName,
required String manufacturedOn,
@ -1077,6 +1152,7 @@ class RequestsVM extends BaseVM {
offerId: offerId,
offerPrice: offerPrice,
isDeliveryAvailable: isDeliveryAvailable,
offerDeliveryOption: offerDeliveryOption.getIdRequestDeliveryOptionEnum(),
serviceItemName: serviceItemName,
manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn,
@ -1120,6 +1196,7 @@ class RequestsVM extends BaseVM {
required String manufacturedOn,
required RequestModel requestModel,
required bool isDeliveryAvailable,
required RequestDeliveryOptionEnum offerDeliveryOption,
required int requestIndex,
required bool isFromChatScreen,
required int? offerId,
@ -1139,6 +1216,7 @@ class RequestsVM extends BaseVM {
requestId: requestId,
offerPrice: offerPrice,
isDeliveryAvailable: isDeliveryAvailable,
offerDeliveryOption: offerDeliveryOption,
manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName,
@ -1173,6 +1251,7 @@ class RequestsVM extends BaseVM {
requestID: requestModel.id,
price: double.parse(offerPrice),
isDeliveryAvailable: isDeliveryAvailable,
requestDeliveryOption: offerDeliveryOption,
manufacturedByName: manufacturedByName,
manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName,
@ -1182,6 +1261,7 @@ class RequestsVM extends BaseVM {
reqOfferImages: images,
),
);
context.read<ChatVM>().onNewMessageReceivedForRequestOffer(messages: [chatMessageModel], requestsVM: this, isMyOwnOffer: true);
if (!isFromChatScreen) {

@ -21,8 +21,11 @@ class ShippingManagementVM extends BaseVM {
List<ShippingRequestModel> shippingRequestsList = [];
List<EnumsModel> shippingStatusEnums = [];
List<EnumsModel> selfPickupStatusEnums = [];
List<FilterListModel> selfPickupRequestsFilterOptions = [];
List<FilterListModel> selfPickupRequestsStatusesList = [];
List<EnumsModel> shippingStatusEnums = [];
List<FilterListModel> shippingRequestFilterOptions = [];
List<FilterListModel> shippingRequestStatusesList = [];
@ -32,15 +35,41 @@ class ShippingManagementVM extends BaseVM {
requestStatusComments = value;
}
bool isSelfPickupTapped = false;
void updateIsSelfPickupTapped(var value) {
isSelfPickupTapped = value;
notifyListeners();
}
resetFilters() {
if (shippingRequestFilterOptions.isEmpty) return;
for (var value in shippingRequestFilterOptions) {
value.isSelected = false;
}
shippingRequestFilterOptions[0].isSelected = true;
if (selfPickupRequestsFilterOptions.isEmpty) return;
for (var value in selfPickupRequestsFilterOptions) {
value.isSelected = false;
}
selfPickupRequestsFilterOptions[0].isSelected = true;
requestStatusComments = "";
}
Future<void> populateSelfPickupRequestFilterList() async {
selfPickupStatusEnums = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.selfPickupStatusEnumId);
selfPickupRequestsFilterOptions.clear();
selfPickupRequestsStatusesList.clear();
for (int i = 0; i < selfPickupStatusEnums.length; i++) {
selfPickupRequestsFilterOptions.add(FilterListModel(title: selfPickupStatusEnums[i].enumValueStrDes, isSelected: false, id: selfPickupStatusEnums[i].enumValue));
selfPickupRequestsStatusesList.add(FilterListModel(title: selfPickupStatusEnums[i].enumValueStrDes, isSelected: false, id: selfPickupStatusEnums[i].enumValue));
}
selfPickupRequestsFilterOptions.insert(0, FilterListModel(title: Utils.getNameByShippingRequestStatusEnum(ShippingRequestStatusEnum.allRequests), isSelected: true, id: -1));
notifyListeners();
}
Future<void> populateShippingRequestFilterList() async {
// if (shippingRequestFilterOptions.isNotEmpty && shippingRequestStatusesList.isNotEmpty) return;
@ -78,6 +107,22 @@ class ShippingManagementVM extends BaseVM {
notifyListeners();
}
Future<void> applyFiltersOnSelfPickupRequests({required SelfPickupRequestStatusEnum selfPickupRequestStatusEnum}) async {
for (var value in selfPickupRequestsFilterOptions) {
value.isSelected = false;
}
if (selfPickupRequestStatusEnum == SelfPickupRequestStatusEnum.allRequests) {
selfPickupRequestsFilterOptions[0].isSelected = true;
await getSelfPickupRequestsListByFilters();
notifyListeners();
return;
}
int index = selfPickupRequestsFilterOptions.indexWhere((element) => element.id == selfPickupRequestStatusEnum.getIdFromSelfPickupStatusEnum());
selfPickupRequestsFilterOptions[index].isSelected = true; // +1 to match with the index 0 index has all requests
await getSelfPickupRequestsListByFilters(selfPickupStatusEnum: selfPickupRequestStatusEnum);
notifyListeners();
}
void updateSelectionInShippingRequestStatuses(int index) {
for (var value in shippingRequestStatusesList) {
value.isSelected = false;
@ -99,6 +144,19 @@ class ShippingManagementVM extends BaseVM {
}
}
Future<void> getSelfPickupRequestsListByFilters({SelfPickupRequestStatusEnum? selfPickupStatusEnum}) async {
setState(ViewState.busy);
try {
shippingRequestsList = await shippingRepo.getSelfPickupRequestListByStatus(selfPickupRequestStatus: selfPickupStatusEnum);
setState(ViewState.idle);
notifyListeners();
} catch (e) {
logger.i(e.toString());
Utils.showToast(e.toString());
setState(ViewState.idle);
}
}
Future<bool> onUpdateShippingStatusTapped({required BuildContext context, required ShippingRequestStatusEnum shippingStatusEnum, required int shippingRequestId}) async {
Utils.showLoading(context);
try {

@ -370,7 +370,32 @@ class _AdsDetailViewState extends State<AdsDetailView> {
],
),
],
).paddingOnly(top: 5, bottom: 2).toWhiteContainer(width: double.infinity, allPading: 12);
).paddingOnly(top: 2, bottom: 2).toWhiteContainer(width: double.infinity, allPading: 12);
}
Widget buildSpecialServicesContainer() {
if (widget.adDetails.specialservice == null || widget.adDetails.specialservice!.isEmpty) {
return const SizedBox();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.specialServices.tr().toText(fontSize: 16),
3.height,
Column(
children: List.generate(
widget.adDetails.specialservice!.length,
(index) => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(child: ("${widget.adDetails.specialservice![index].name}").toText(fontSize: 14, color: MyColors.lightTextColor)),
("${widget.adDetails.specialservice![index].price} ${LocaleKeys.sar.tr()} ").toText(fontSize: 14, color: MyColors.lightTextColor),
],
)),
),
],
).paddingOnly(bottom: 2).toWhiteContainer(width: double.infinity, allPading: 12);
}
@override
@ -395,8 +420,12 @@ class _AdsDetailViewState extends State<AdsDetailView> {
width: 42,
);
} else if ((widget.adDetails.adPostStatus != AdPostStatus.pendingForPost)) {
actionWidget =
IconButton(icon: const Icon(Icons.chat_outlined, color: Colors.black), onPressed: () => adVM.onMessagesButtonPressed(context: context, adDetailsModel: widget.adDetails)).toContainer(
actionWidget = IconButton(
icon: const Icon(Icons.chat_outlined, color: Colors.black),
onPressed: () => adVM.onMessagesButtonPressed(
context: context,
adDetailsModel: widget.adDetails,
)).toContainer(
margin: const EdgeInsets.fromLTRB(0, 8, 21, 8),
paddingAll: 0,
borderRadius: 100,
@ -434,6 +463,10 @@ class _AdsDetailViewState extends State<AdsDetailView> {
buildPersonalInformationCard(context: context),
],
if (widget.adDetails.isMyAd ?? false) ...[
if (widget.adDetails.specialservice != null && widget.adDetails.specialservice!.isNotEmpty) ...[
12.height,
buildSpecialServicesContainer(),
],
12.height,
buildAdStartEndDates(),
],

@ -2,6 +2,7 @@ import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
@ -12,6 +13,7 @@ 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/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
@ -167,6 +169,7 @@ class AdDurationSelectionSheet extends StatelessWidget {
if (adVM.isFetchingLists) {
return;
} else {
final subscriptionsVM = context.read<SubscriptionsVM>();
if (isFromExtendAd && !isUpdateAdSelected) {
List<bool> statuses =
await adVM.createAdExtensionOrder(context, adId: adsID, adsDurationId: adVM.vehicleAdDurationId.selectedId); // [0] Means API response [1] means isPaymentRequired
@ -176,6 +179,7 @@ class AdDurationSelectionSheet extends StatelessWidget {
pop(context);
pop(context);
pop(context);
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
adVM.applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.active);
}
} else {

@ -11,6 +11,7 @@ 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/chat_view_model.dart';
import 'package:mc_common_app/view_models/dashboard_view_model_provider.dart';
import 'package:mc_common_app/view_models/payment_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/ads_buyer_chats_view.dart';
@ -175,30 +176,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 (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 &&
AppState().currentAppType == AppType.customer) ...[
requestVM.currentSelectedOffer!.requestOfferStatusEnum == RequestOfferStatusEnum.accepted ) ...[
Expanded(
child: ShowFillButton(
maxWidth: double.infinity,
@ -233,88 +234,93 @@ 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!,
);
buildSendOfferBottomSheet(
context: context,
requestDetailPageArguments: requestDetailArguments,
isFromChatScreen: true,
offerId: null, // null means creating new offer
);
},
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
);
});
},
),
),
),
],
if (chatVM.pickedImagesForMessage.isNotEmpty) ...[
Expanded(
flex: 8,
child: PickedFilesContainer(
pickedFiles: chatVM.pickedImagesForMessage,
onCrossPressedPrimary: chatVM.removeImageFromList,
onAddFilePressed: () => chatVM.pickMultipleImages(),
],
if (chatVM.pickedImagesForMessage.isNotEmpty) ...[
Expanded(
flex: 8,
child: PickedFilesContainer(
pickedFiles: chatVM.pickedImagesForMessage,
onCrossPressedPrimary: chatVM.removeImageFromList,
onAddFilePressed: () => chatVM.pickMultipleImages(),
),
),
),
] else if (chatTypeEnum == ChatTypeEnum.requestOffer) ...[
] 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),
),
),
],
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(
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;
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)
],

@ -128,6 +128,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
serviceProviderID: chatMessageModel.serviceProviderID ?? 0,
requestOfferID: chatMessageModel.reqOffer!.id ?? -1,
offerPrice: chatMessageModel.reqOffer!.price.toString(),
isDeliveryAvailable: chatMessageModel.reqOffer!.isDeliveryAvailable ?? false,
offerDeliveryOption: chatMessageModel.reqOffer!.requestDeliveryOption ?? RequestDeliveryOptionEnum.selfPickup,
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
@ -227,6 +229,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
serviceProviderID: chatMessageModel.serviceProviderID ?? 0,
requestOfferID: chatMessageModel.reqOffer!.id ?? -1,
offerPrice: chatMessageModel.reqOffer!.price.toString(),
isDeliveryAvailable: chatMessageModel.reqOffer!.isDeliveryAvailable ?? false,
offerDeliveryOption: chatMessageModel.reqOffer!.requestDeliveryOption ?? RequestDeliveryOptionEnum.selfPickup,
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
@ -374,6 +378,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
serviceProviderID: chatMessageModel.serviceProviderID ?? 0,
requestOfferID: chatMessageModel.reqOffer!.id ?? -1,
offerPrice: chatMessageModel.reqOffer!.price.toString(),
isDeliveryAvailable: chatMessageModel.reqOffer!.isDeliveryAvailable ?? false,
offerDeliveryOption: chatMessageModel.reqOffer!.requestDeliveryOption ?? RequestDeliveryOptionEnum.selfPickup,
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
@ -428,6 +434,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
serviceProviderID: chatMessageModel.serviceProviderID ?? 0,
requestOfferID: chatMessageModel.reqOffer!.id ?? -1,
offerPrice: chatMessageModel.reqOffer!.price.toString(),
isDeliveryAvailable: chatMessageModel.reqOffer!.isDeliveryAvailable ?? false,
offerDeliveryOption: chatMessageModel.reqOffer!.requestDeliveryOption ?? RequestDeliveryOptionEnum.selfPickup,
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedByName: chatMessageModel.reqOffer!.manufacturedByName ?? "",
@ -500,6 +508,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
Widget buildOfferDetailsInChatMessage({required RequestStatusEnum requestStatusEnum, required ChatMessageModel chatMessageModel, required BuildContext context}) {
final requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum ?? RequestOfferStatusEnum.offer;
if (requestStatusEnum != RequestStatusEnum.submitted && requestOfferStatusEnum != RequestOfferStatusEnum.accepted) {
return Column(
children: [
@ -744,6 +753,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
requestVM.updateOfferDescription((widget.chatMessageModel.chatText ?? "").toString());
requestVM.updateIsDeliveryAvailableStatus((offer.isDeliveryAvailable ?? false));
requestVM.applyFilterOnDeliveryOption(requestDeliveryOptionEnum: offer.requestDeliveryOption ?? RequestDeliveryOptionEnum.none);
if (offer.reqOfferImages != null && offer.reqOfferImages!.isNotEmpty) {
for (var element in offer.reqOfferImages!) {
if (element.imageUrl != null || element.imageStr != null) {
@ -886,6 +896,27 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
);
}
Widget buildDeliveryOptionsWidget({required RequestDeliveryOptionEnum deliveryOptionId}) {
Widget finalWidget = const SizedBox();
String finalText = "";
if (deliveryOptionId == RequestDeliveryOptionEnum.none) {
finalText = RequestDeliveryOptionEnum.selfPickup.getStringFromRequestDeliveryOptionEnum();
} else {
finalText = deliveryOptionId.getStringFromRequestDeliveryOptionEnum();
}
finalWidget = Directionality(
textDirection: TextDirection.ltr,
child: "${LocaleKeys.deliveryOptions.tr()} : $finalText".toText(
fontSize: 10,
color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor,
fontWeight: MyFonts.Medium,
),
);
return finalWidget;
}
Widget messageWidgetBasedOnType({required ChatMessageTypeEnum? chatMessageTypeEnum}) {
Widget messageTypeWidget = const SizedBox();
if (chatMessageTypeEnum == null) {
@ -908,14 +939,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
buildFreeTextDetailsInMessage(chatMessageTypeEnum: chatMessageTypeEnum),
if (widget.requestsTypeEnum == RequestsTypeEnum.serviceRequest) ...[
2.height,
Directionality(
textDirection: TextDirection.ltr,
child: "${LocaleKeys.deliveryAvailable.tr()} : ${(widget.chatMessageModel.reqOffer!.isDeliveryAvailable ?? false) ? LocaleKeys.yes.tr() : LocaleKeys.no.tr()}".toText(
fontSize: 10,
color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor,
fontWeight: MyFonts.Medium,
),
),
buildDeliveryOptionsWidget(deliveryOptionId: widget.chatMessageModel.reqOffer!.requestDeliveryOption ?? RequestDeliveryOptionEnum.none),
],
if (widget.chatMessageModel.reqOffer!.reqOfferImages != null && widget.chatMessageModel.reqOffer!.reqOfferImages!.isNotEmpty) ...[
5.height,

@ -8,6 +8,7 @@ import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/offers_unread_chat_model.dart';
import 'package:mc_common_app/models/requests_models/provider_offers_model.dart';
import 'package:mc_common_app/models/requests_models/providers_offers_chat_model.dart';
import 'package:mc_common_app/models/requests_models/request_model.dart';
@ -39,7 +40,7 @@ class _ProvidersChatListPageState extends State<ProvidersChatListPage> {
_onRefresh() async {
scheduleMicrotask(() async {
RequestsVM requestsVM = context.read<RequestsVM>();
await requestsVM.getProviderOffersChatsList(serviceProviderId: AppState().getUser.data!.userInfo!.providerId ?? 0, context: context);
await requestsVM.getOffersChatsUnreadList(userId: AppState().getUser.data!.userInfo!.userId ?? "", context: context);
});
}
@ -110,7 +111,7 @@ class _ProvidersChatListPageState extends State<ProvidersChatListPage> {
},
child: requestsVM.state == ViewState.busy
? const Center(child: CircularProgressIndicator())
: requestsVM.providerOffersChatsList.isEmpty
: requestsVM.offersUnreadChatModel == null || requestsVM.offersUnreadChatModel!.reqChatUnread.isEmpty
? Center(
child: LocaleKeys.noOffersShow.tr().toText(
fontSize: 16,
@ -118,58 +119,66 @@ class _ProvidersChatListPageState extends State<ProvidersChatListPage> {
),
)
: ListView.separated(
itemCount: requestsVM.providerOffersChatsList.length,
itemCount: requestsVM.offersUnreadChatModel!.reqChatUnread.length,
padding: const EdgeInsets.all(16),
itemBuilder: (context, index) {
ProviderOffersChatsModel providerOffersChatsModel = requestsVM.providerOffersChatsList[index];
OffersUnreadChatDataModel offersUnreadChatDataModel = requestsVM.offersUnreadChatModel!.reqChatUnread[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.statusContainerChip(
text: Utils.getNameByRequestOfferStatusEnum(providerOffersChatsModel.requestOfferStatusEnum!),
chipColor: Utils.getChipColorByRequestOfferStatusEnum(providerOffersChatsModel.requestOfferStatusEnum!),
),
// Utils.statusContainerChip(
// text: Utils.getNameByRequestOfferStatusEnum(providerOffersChatsModel.requestOfferStatusEnum!),
// chipColor: Utils.getChipColorByRequestOfferStatusEnum(providerOffersChatsModel.requestOfferStatusEnum!),
// ),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(providerOffersChatsModel.customerName ?? "").toText(
(offersUnreadChatDataModel.customerName).toText(
fontSize: 16,
isBold: true,
),
if (providerOffersChatsModel.createdOn != null && providerOffersChatsModel.createdOn!.isNotEmpty) ...[
DateTime.parse(providerOffersChatsModel.createdOn!).getTimeAgo().toText(color: MyColors.lightTextColor, fontSize: 14),
if (offersUnreadChatDataModel.unreadMessagesCount > 0) ...[
Center(
child: "${offersUnreadChatDataModel.unreadMessagesCount}".toText(
color: Colors.white,
isBold: true,
fontSize: 10,
),
).toContainer(
backgroundColor: MyColors.cancelledColor,
borderRadius: 100,
paddingAll: 1,
width: 22,
height: 22,
),
],
// if (providerOffersChatsModel. != null && offersModel.offerCount! > 0) ...[
// Center(
// child: "${providerOffersChatsModel.offerCount}".toText(
// color: Colors.white,
// isBold: true,
// fontSize: 10,
// ),
// ).toContainer(
// backgroundColor: MyColors.cancelledColor,
// borderRadius: 100,
// paddingAll: 1,
// width: 22,
// height: 22,
// ),
// ],
],
),
4.height,
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: "${providerOffersChatsModel.comment}".toText(color: MyColors.lightTextColor, fontSize: 14),
child: offersUnreadChatDataModel.lastChatText.toText(color: MyColors.lightTextColor, fontSize: 14),
),
const Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18),
4.height,
if (offersUnreadChatDataModel.lastChatTime.isNotEmpty) ...[
DateTime.parse(offersUnreadChatDataModel.lastChatTime).getTimeAgo().toText(color: MyColors.lightTextColor, fontSize: 12),
],
],
),
4.height,
const Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(Icons.arrow_forward, color: MyColors.darkIconColor, size: 18),
],
),
],
).onPress(() async => await onChatTapped(context: context, requestID: providerOffersChatsModel.requestID ?? 0)).toContainer(isShadowEnabled: true);
).onPress(() async => await onChatTapped(context: context, requestID: offersUnreadChatDataModel.requestId ?? 0)).toContainer(isShadowEnabled: true);
},
separatorBuilder: (context, index) => 16.height,
),

@ -19,6 +19,7 @@ import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart';
import 'package:mc_common_app/widgets/common_widgets/filters_list.dart';
import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
@ -96,7 +97,7 @@ Future buildSendOfferBottomSheet({
],
12.height,
TxtField(
maxLines: 5,
maxLines: 3,
value: requestsVM.offerDescription,
errorValue: requestsVM.offerDescriptionError,
keyboardType: TextInputType.text,
@ -105,32 +106,49 @@ Future buildSendOfferBottomSheet({
),
12.height,
if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeEnum()) ...[
LocaleKeys.deliveryAvailable.tr().toText(fontSize: 16),
8.height,
Container(
width: 50,
height: 30,
decoration: BoxDecoration(
color: requestsVM.isDeliveryAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white,
borderRadius: BorderRadius.circular(25.0),
border: Border.all(color: MyColors.black, width: 1),
),
child: Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
activeColor: MyColors.darkPrimaryColor,
trackColor: MyColors.white,
thumbColor: MyColors.grey98Color,
value: requestsVM.isDeliveryAvailableStatus,
onChanged: (value) {
requestsVM.updateIsDeliveryAvailableStatus(value);
},
),
LocaleKeys.selectDeliveryOption.tr().toText(fontSize: 16),
10.height,
// Container(
// width: 50,
// height: 30,
// decoration: BoxDecoration(
// color: requestsVM.isDeliveryAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white,
// borderRadius: BorderRadius.circular(25.0),
// border: Border.all(color: MyColors.black, width: 1),
// ),
// child: Transform.scale(
// scale: 0.8,
// child: CupertinoSwitch(
// activeTrackColor: MyColors.darkPrimaryColor,
// inactiveTrackColor: MyColors.white,
// thumbColor: MyColors.grey98Color,
// value: requestsVM.isDeliveryAvailableStatus,
// onChanged: (value) {
// requestsVM.updateIsDeliveryAvailableStatus(value);
// },
// ),
// ),
// ),
FiltersList(
filterList: requestsVM.myDeliveryOptionsFilterOptions,
onFilterTapped: (index, selectedFilterId) {
requestsVM.applyFilterOnDeliveryOption(requestDeliveryOptionEnum: selectedFilterId.toRequestDeliveryOptionEnum());
},
needLeftPadding: false,
).paddingOnly(bottom: 21),
if (requestsVM.deliveryOptionSelectionError.isNotEmpty) ...[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
requestsVM.deliveryOptionSelectionError.toText(),
],
),
),
]
],
12.height,
if (requestsVM.pickedVehicleImages.isEmpty) ...[
5.height,
DottedRectContainer(
onTap: () => context.read<RequestsVM>().pickMultipleImages(),
text: LocaleKeys.attachImage.tr(),
@ -139,7 +157,7 @@ Future buildSendOfferBottomSheet({
),
],
if (requestsVM.pickedVehicleImages.isNotEmpty) ...[
16.height,
// 14.height,
PickedFilesContainer(
pickedFiles: requestsVM.pickedVehicleImages,
onCrossPressedPrimary: requestsVM.removeImageFromList,
@ -159,6 +177,12 @@ Future buildSendOfferBottomSheet({
"${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName}",
);
requestsVM.updateServiceItemCreatedOn(DateHelper.formatAsYearMonthDay(DateTime.now()));
RequestDeliveryOptionEnum requestDeliveryOptionEnum = RequestDeliveryOptionEnum.none;
int index = requestsVM.myDeliveryOptionsFilterOptions.indexWhere((option) => option.isSelected);
if (index != -1) {
requestDeliveryOptionEnum = requestsVM.myDeliveryOptionsFilterOptions[index].id.toRequestDeliveryOptionEnum();
}
if (offerId == null) {
requestsVM.onSendOfferPressed(
context: context,
@ -169,6 +193,7 @@ Future buildSendOfferBottomSheet({
offerPrice: requestsVM.offerPrice,
requestModel: requestDetail,
isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus,
offerDeliveryOption: requestDeliveryOptionEnum,
requestIndex: requestDetailPageArguments.requestIndex,
isFromChatScreen: isFromChatScreen,
manufacturedByName: requestsVM.itemManufacturer,
@ -182,6 +207,7 @@ Future buildSendOfferBottomSheet({
offerId: offerId,
offerPrice: requestsVM.offerPrice,
isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus,
offerDeliveryOption: requestDeliveryOptionEnum,
serviceItemName: requestsVM.serviceItem,
manufacturedByName: requestsVM.itemManufacturer,
manufacturedOn: requestsVM.serviceItemCreatedOn,

@ -26,6 +26,107 @@ class RequestDetailPage extends StatelessWidget {
const RequestDetailPage({super.key, required this.requestDetailPageArguments});
Widget buildRequestDetailsContainer(BuildContext context) {
final requestDetail = requestDetailPageArguments.requestModel;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
requestDetail.vehicleTypeName.toText(fontSize: 16, letterSpacing: -0.64),
showItem("${LocaleKeys.brand.tr()}: ", requestDetail.brand),
showItem("${LocaleKeys.model.tr()}: ", requestDetail.model),
showItem("${LocaleKeys.year.tr()}: ", "${requestDetail.year}"),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
"${requestDetail.city ?? ""} ${requestDetail.countryName}".toText(
color: MyColors.lightTextColor,
),
if (requestDetail.createdOn != null) ...[
DateTime.parse(requestDetail.createdOn!).getTimeAgo().toText(
color: MyColors.lightTextColor,
),
],
],
),
],
),
if (requestDetail.customerName.isNotEmpty) ...[
showItem("${LocaleKeys.customerName.tr()}: ", requestDetail.customerName),
],
showItem("${LocaleKeys.description.tr()}: ", requestDetail.description),
16.height,
if (AppState().currentAppType == AppType.provider &&
(requestDetailPageArguments.requestModel.requestStatus == RequestStatusEnum.inProgress || requestDetailPageArguments.requestModel.requestStatus == RequestStatusEnum.submitted)) ...[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
("${LocaleKeys.reportComplaint.tr()}?").toText(fontSize: 14, color: MyColors.darkTextColor),
],
).onPress(
() {
int customerID = requestDetailPageArguments.requestModel.customerId;
int complainType = 2;
String customerName = requestDetailPageArguments.requestModel.customerName;
context.read<AppointmentsVM>().buildComplaintBottomSheet(
customerID: customerID,
customerName: customerName,
complainType: complainType,
context: context,
);
},
),
],
// showItem("${LocaleKeys.priceRange.tr()}:", ""),
// Row(
// children: [
// Expanded(
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// "${requestDetail.price.toInt()}".toText(fontSize: 19, isBold: true, letterSpacing: -1.16),
// 2.width,
// LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4),
// ],
// ),
// Row(
// children: [
// Utils.statusContainerChip(
// text: (requestDetail.requestStatusName),
// chipColor: MyColors.grey98Color.withOpacity(0.1),
// textColor: MyColors.lightTextColor,
// ),
// ],
// ),
// ],
// ),
// ),
// // const Icon(Icons.arrow_forward)
// ],
// ),
],
);
}
Widget buildRequestDetailActionFooter({
required int requestId,
required RequestStatusEnum requestStatus,
@ -209,107 +310,6 @@ class RequestDetailPage extends StatelessWidget {
);
}
Widget buildRequestDetailsContainer(BuildContext context) {
final requestDetail = requestDetailPageArguments.requestModel;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
requestDetail.vehicleTypeName.toText(fontSize: 16, letterSpacing: -0.64),
showItem("${LocaleKeys.brand.tr()}: ", requestDetail.brand),
showItem("${LocaleKeys.model.tr()}: ", requestDetail.model),
showItem("${LocaleKeys.year.tr()}: ", "${requestDetail.year}"),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
children: [
"${requestDetail.city ?? ""} ${requestDetail.countryName}".toText(
color: MyColors.lightTextColor,
),
if (requestDetail.createdOn != null) ...[
DateTime.parse(requestDetail.createdOn!).getTimeAgo().toText(
color: MyColors.lightTextColor,
),
],
],
),
],
),
if (requestDetail.customerName.isNotEmpty) ...[
showItem("${LocaleKeys.customerName.tr()}: ", requestDetail.customerName),
],
showItem("${LocaleKeys.description.tr()}: ", requestDetail.description),
16.height,
if (AppState().currentAppType == AppType.provider &&
(requestDetailPageArguments.requestModel.requestStatus == RequestStatusEnum.inProgress || requestDetailPageArguments.requestModel.requestStatus == RequestStatusEnum.submitted)) ...[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
("${LocaleKeys.reportComplaint.tr()}?").toText(fontSize: 14, color: MyColors.darkTextColor),
],
).onPress(
() {
int customerID = requestDetailPageArguments.requestModel.customerId;
int complainType = 2;
String customerName = requestDetailPageArguments.requestModel.customerName;
context.read<AppointmentsVM>().buildComplaintBottomSheet(
customerID: customerID,
customerName: customerName,
complainType: complainType,
context: context,
);
},
),
],
// showItem("${LocaleKeys.priceRange.tr()}:", ""),
// Row(
// children: [
// Expanded(
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// Row(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// "${requestDetail.price.toInt()}".toText(fontSize: 19, isBold: true, letterSpacing: -1.16),
// 2.width,
// LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 10, letterSpacing: -0.4),
// ],
// ),
// Row(
// children: [
// Utils.statusContainerChip(
// text: (requestDetail.requestStatusName),
// chipColor: MyColors.grey98Color.withOpacity(0.1),
// textColor: MyColors.lightTextColor,
// ),
// ],
// ),
// ],
// ),
// ),
// // const Icon(Icons.arrow_forward)
// ],
// ),
],
);
}
Widget showItem(String title, String value) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,

@ -90,7 +90,12 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
Widget buildLocationInformation(BuildContext context) {
final requestVM = context.watch<RequestsVM>();
String address = "";
if (requestVM.acceptedRequestOffer != null && requestVM.acceptedRequestOffer!.requestDeliveryOption == RequestDeliveryOptionEnum.delivery) {
address = requestVM.currentSelectedRequest!.address;
} else {
address = requestVM.currentSelectedOffer!.providerAddress ?? "";
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -107,7 +112,11 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleDetailWidget(text: requestVM.currentSelectedRequest!.address ?? "", type: LocaleKeys.location.tr()),
Row(
children: [
SingleDetailWidget(text: address, type: LocaleKeys.location.tr()),
],
),
// 16.height,
// SingleDetailWidget(
// text: requestVM.additionalAddressSparePartRequestDelivery.isNotEmpty ? requestVM.additionalAddressSparePartRequestDelivery : "N/A",
@ -161,8 +170,9 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
// SingleDetailWidget(text: "${requestVM.acceptedRequestOffer!.price.toString()} ${LocaleKeys.sar.tr()}", type: LocaleKeys.offerPrice.tr()),
16.height,
SingleDetailWidget(text: requestVM.acceptedRequestOfferProviderName ?? "", type: LocaleKeys.providerName.tr()),
16.height,
SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()),
SingleDetailWidget(text: LocaleKeys.online.tr(), type: LocaleKeys.paymentType.tr()),
],
),
),
@ -180,21 +190,18 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
SingleDetailWidget(text: manufacturedOnFormattedDate, type: LocaleKeys.manufacturedOn.tr()),
],
16.height,
// SingleDetailWidget(text: "${requestVM.currentSelectedRequest!.price.toString()} ${LocaleKeys.sar.tr()}", type: LocaleKeys.totalPrice.tr()),
SingleDetailWidget(text: "${requestVM.acceptedRequestOffer!.price.toString()} ${LocaleKeys.sar.tr()}", type: LocaleKeys.offerPrice.tr()),
if (requestCreatedOn.isNotEmpty) ...[
16.height,
SingleDetailWidget(text: requestCreatedOn, type: LocaleKeys.requestCreatedOn.tr()),
],
16.height,
SingleDetailWidget(text: LocaleKeys.online.tr(), type: LocaleKeys.paymentType.tr()),
],
),
),
],
),
16.height,
SingleDetailWidget(text: requestVM.currentSelectedRequest!.description, type: LocaleKeys.description.tr()),
],
);
}

@ -108,7 +108,9 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
onTap: () {
navigateWithName(context, AppRoutes.shippingManagementView);
},
),
).toViewOnly(context, onTap: () {
navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
}),
],
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.settings, size: 20),

@ -1,7 +1,9 @@
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
@ -39,7 +41,14 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
if (shippingViewModel.shippingRequestFilterOptions.isNotEmpty) {
await shippingViewModel.populateShippingRequestFilterList();
}
await shippingViewModel.getShippingRequestsListByFilters();
if (shippingViewModel.selfPickupRequestsFilterOptions.isNotEmpty) {
await shippingViewModel.populateSelfPickupRequestFilterList();
}
if (shippingViewModel.isSelfPickupTapped) {
await shippingViewModel.getSelfPickupRequestsListByFilters();
} else {
await shippingViewModel.getShippingRequestsListByFilters();
}
});
super.initState();
}
@ -146,27 +155,78 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
Widget build(BuildContext context) {
return Consumer(builder: (BuildContext context, ShippingManagementVM shippingVm, Widget? child) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.shippingManagement.tr()),
body: Container(
color: MyColors.backgroundColor,
width: double.infinity,
height: double.infinity,
child: Column(
children: [
16.height,
appBar: CustomAppBar(title: LocaleKeys.shippingManagement.tr()),
body: Container(
color: MyColors.backgroundColor,
width: double.infinity,
height: double.infinity,
child: Column(
children: [
16.height,
Row(
children: [
Expanded(
child: ShowFillButton(
isFilled: !shippingVm.isSelfPickupTapped,
maxHeight: 55,
fontSize: 15,
title: LocaleKeys.delivery.tr(),
txtColor: !shippingVm.isSelfPickupTapped ? MyColors.white : MyColors.darkTextColor,
onPressed: () async {
shippingVm.updateIsSelfPickupTapped(false);
int index = shippingVm.shippingRequestFilterOptions.indexWhere((element) => element.isSelected);
int id = shippingVm.shippingRequestFilterOptions[index].id;
await shippingVm.getShippingRequestsListByFilters(shippingStatusEnum: id.toShippingStatusEnum());
},
),
),
12.width,
Expanded(
child: ShowFillButton(
isFilled: shippingVm.isSelfPickupTapped,
txtColor: shippingVm.isSelfPickupTapped ? MyColors.white : MyColors.darkTextColor,
maxHeight: 55,
fontSize: 15,
title: LocaleKeys.selfPickup.tr(),
onPressed: () async {
shippingVm.updateIsSelfPickupTapped(true);
int index = shippingVm.selfPickupRequestsFilterOptions.indexWhere((element) => element.isSelected);
int id = shippingVm.selfPickupRequestsFilterOptions[index].id;
await shippingVm.getSelfPickupRequestsListByFilters(selfPickupStatusEnum: id.toSelfPickupStatusEnum());
},
),
),
],
).horPaddingMain(),
16.height,
if (shippingVm.isSelfPickupTapped) ...[
FiltersList(
filterList: shippingVm.selfPickupRequestsFilterOptions,
onFilterTapped: (index, selectedFilterId) {
shippingVm.applyFiltersOnSelfPickupRequests(selfPickupRequestStatusEnum: selectedFilterId.toSelfPickupStatusEnum());
},
),
] else ...[
FiltersList(
filterList: shippingVm.shippingRequestFilterOptions,
onFilterTapped: (index, selectedFilterId) {
shippingVm.applyFiltersOnShippingRequests(shippingRequestStatusEnum: selectedFilterId.toShippingStatusEnum());
},
),
8.height,
Expanded(
child: RefreshIndicator(
],
8.height,
Expanded(
child: RefreshIndicator(
onRefresh: () async {
int index = shippingVm.shippingRequestFilterOptions.indexWhere((element) => element.isSelected);
int id = shippingVm.shippingRequestFilterOptions[index].id;
await shippingVm.getShippingRequestsListByFilters(shippingStatusEnum: id.toShippingStatusEnum());
if (shippingVm.isSelfPickupTapped) {
int index = shippingVm.selfPickupRequestsFilterOptions.indexWhere((element) => element.isSelected);
int id = shippingVm.selfPickupRequestsFilterOptions[index].id;
await shippingVm.getSelfPickupRequestsListByFilters(selfPickupStatusEnum: id.toSelfPickupStatusEnum());
} else {
int index = shippingVm.shippingRequestFilterOptions.indexWhere((element) => element.isSelected);
int id = shippingVm.shippingRequestFilterOptions[index].id;
await shippingVm.getShippingRequestsListByFilters(shippingStatusEnum: id.toShippingStatusEnum());
}
},
child: (shippingVm.state == ViewState.busy)
? const Center(child: CircularProgressIndicator())
@ -220,10 +280,12 @@ class _ShippingManagementViewState extends State<ShippingManagementView> {
},
separatorBuilder: (context, index) => 16.height,
),
)),
],
),
));
),
),
],
),
),
);
});
}
}

@ -36,6 +36,7 @@ class TxtField extends StatelessWidget {
Widget? preFixWidget;
bool numbersOnly;
bool allowOnlyOneDigit;
bool isNeedLabelOnTop;
TxtField({
super.key,
@ -66,6 +67,7 @@ class TxtField extends StatelessWidget {
this.onPostFixPressed,
this.numbersOnly = false,
this.allowOnlyOneDigit = false,
this.isNeedLabelOnTop = true,
});
TextEditingController controller = TextEditingController();
@ -77,7 +79,7 @@ class TxtField extends StatelessWidget {
return Column(
children: [
if (hint != null) ...[
if (isNeedLabelOnTop && hint != null) ...[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
@ -149,7 +151,7 @@ class TxtField extends StatelessWidget {
prefixIcon: prefixData != null ? Icon(prefixData, color: borderColor) : preFixWidget,
labelStyle: const TextStyle(color: borderColor, fontSize: 13, fontWeight: MyFonts.Medium),
hintStyle: const TextStyle(color: borderColor, fontSize: 13, fontWeight: MyFonts.Medium),
// hintText: hint ?? "",
hintText: isNeedLabelOnTop ? null : hint ?? "",
contentPadding: prefixData == null
? EdgeInsets.only(
left: 12,

Loading…
Cancel
Save