Debugging changes for request management chat

master_new_changes
Faiz Hashmi 1 year ago
parent 7f0df61ff0
commit 9b50be3b05

@ -186,7 +186,7 @@
"updateBranch": "تحديث فرع",
"branches": "الفروع",
"requests": "الطلبات",
"noBranchFound" : "لم يتم العثور على فرع",
"noBranchFound": "لم يتم العثور على فرع",
"onlyProviderApp": "نأسف هذا التطبيق فقط لمقدمي الخدمات",
"pickAddress": "اختر العنوان",
"pickLocation": "اختر الموقع",
@ -202,19 +202,19 @@
"completeProfile2": "اكمل الملف الشخصي 2/3",
"completeProfile3": "اكمل الملف الشخصي 3/3",
"provider": "مزود",
"noRequeststoShow" : "لا توجد طلبات للعرض",
"noRequeststoShow": "لا توجد طلبات للعرض",
"myBranches": "فروعي",
"mergeAppointments" : "دمج المواعيد",
"addService" : "أضف الخدمة",
"selectServicestoAdd" : "حدد الخدمات التي تريد إضافتها",
"mergeAppointments": "دمج المواعيد",
"addService": "أضف الخدمة",
"selectServicestoAdd": "حدد الخدمات التي تريد إضافتها",
"noServiceFound": "لم يتم العثور على الخدمة",
"selectItems" : "اختيار العناصر",
"noItemSelectedYet" : "لم يتم تحديد أي عنصر بعد",
"totalAdditionalAmount" : "إجمالي المبلغ الإضافي",
"sar" : "ريال سعودي",
"cancel" : "يلغي",
"add" : "يضيف",
"itemsAddedSuccessfully" : "تمت إضافة العناصر بنجاح",
"selectItems": "اختيار العناصر",
"noItemSelectedYet": "لم يتم تحديد أي عنصر بعد",
"totalAdditionalAmount": "إجمالي المبلغ الإضافي",
"sar": "ريال سعودي",
"cancel": "يلغي",
"add": "يضيف",
"itemsAddedSuccessfully": "تمت إضافة العناصر بنجاح",
"pleaseSelectItems": "يرجى اختيار العناصر",
"totalAmount": "المبلغ الإجمالي",
"searchItems": "البحث عن العناصر",
@ -566,15 +566,6 @@
"defineLicenses": "تحديد التراخيص",
"logOut": "تسجيل الخروج",
"customer": "العميل",
"accept": "قبول"
"accept": "قبول",
"requestAlreadyInProgress": "هذا الطلب قيد التقدم بالفعل."
}

@ -423,93 +423,93 @@
"reserveAd": "Reserve Ad",
"reservationAmount": "Reservation Amount",
"belowAmountPayLater": "Below Amount that you will pay later",
"carPrice":"Car Price",
"vatExcluded":"VAT Excluded",
"carInsuranceService":"Car insurance Service",
"toBeDecided":"To be Decided",
"registrationCarPlates":"Registration & Car Plates",
"homeDeliveryService":"Home Delivery Service",
"specialServicechargesInsuranceDeliveryLocation":"Special service charges will be added based on desired insurance and delivery Location",
"estimated":"Estimated",
"servicesReservingAd":"Some services are mandatory while reserving Ad",
"completeReservation":"Complete Reservation",
"contact":"Contact",
"setDateandTime":"Set Date and Time",
"selectOffice":"Select Office",
"availableSlots":"Available Slots",
"bookAndPay":"Book and Pay",
"reservationAmounts":"Reservation Amounts",
"tax":"Tax",
"carPrice": "Car Price",
"vatExcluded": "VAT Excluded",
"carInsuranceService": "Car insurance Service",
"toBeDecided": "To be Decided",
"registrationCarPlates": "Registration & Car Plates",
"homeDeliveryService": "Home Delivery Service",
"specialServicechargesInsuranceDeliveryLocation": "Special service charges will be added based on desired insurance and delivery Location",
"estimated": "Estimated",
"servicesReservingAd": "Some services are mandatory while reserving Ad",
"completeReservation": "Complete Reservation",
"contact": "Contact",
"setDateandTime": "Set Date and Time",
"selectOffice": "Select Office",
"availableSlots": "Available Slots",
"bookAndPay": "Book and Pay",
"reservationAmounts": "Reservation Amounts",
"tax": "Tax",
"adsFilter": "Ads Filter",
"searchByCity":"Search By City",
"selectCity":"Select City",
"searchByBrandName":"Search By Brand Name",
"selectVehicleBrand":"Select Vehicle Brand",
"searchByVehicleYear":"Search By Vehicle Year",
"selectYear":"Select Year",
"searchByAdOwner":"Search By Ad Owner",
"selectOwner":"Select Owner",
"search":"Search",
"clearFilters":"Clear Filters",
"book":"Book",
"markAsSold":"Mark As Sold",
"deactivateAd":"Deactivate Ad",
"doWantDeactivateAd":"Do you want to the Deactivate this Ad?",
"stoptheBuyers":"We will stop showing this ad to the buyers",
"cancelReservation":"Cancel Reservation",
"reasonForCancellation":"Reason for Cancellation",
"doWantCancelReservation":"Do you want to cancel the reservation",
"yourAdVisibletoBuy.":"Your ad reservation will be cancelled and this ad will be again visible to everyone to buy",
"completeDeal":"Complete Deal",
"uploadBankReceipt":"Upload Bank Receipt",
"notesForAdmin":"Notes For Admin",
"extendAd":"Extend Ad",
"updateAdDetails":"Do you want to update the Ad Details",
"durationExtendingAd":"You can change the ad duration and details before extending the ad",
"waitingAdminsResponse":"Waiting for Admins Response",
"cancelledByOwner":"Cancelled by Owner",
"cancelledByAdmin":"Cancelled by Admin",
"reservationTimeOver":"Reservation Time Over",
"paymentVerified":"Payment Verified",
"rejectedFormAdmin":"Rejected form Admin",
"waitingAdminPost":"Waiting for admin to post",
"waitingAdminsApproval":"Waiting for Admins Approval",
"sold":"Sold",
"noAdsShow":"No Ads to show",
"damagePartList":"Damage Part List",
"searchPart":"Search Part",
"addSpecialService":"Add Special Service",
"vehicleVar":"Vehicle",
"detailsVar":"Details",
"damageVar":"Damage",
"searchByCity": "Search By City",
"selectCity": "Select City",
"searchByBrandName": "Search By Brand Name",
"selectVehicleBrand": "Select Vehicle Brand",
"searchByVehicleYear": "Search By Vehicle Year",
"selectYear": "Select Year",
"searchByAdOwner": "Search By Ad Owner",
"selectOwner": "Select Owner",
"search": "Search",
"clearFilters": "Clear Filters",
"book": "Book",
"markAsSold": "Mark As Sold",
"deactivateAd": "Deactivate Ad",
"doWantDeactivateAd": "Do you want to the Deactivate this Ad?",
"stoptheBuyers": "We will stop showing this ad to the buyers",
"cancelReservation": "Cancel Reservation",
"reasonForCancellation": "Reason for Cancellation",
"doWantCancelReservation": "Do you want to cancel the reservation",
"yourAdVisibletoBuy.": "Your ad reservation will be cancelled and this ad will be again visible to everyone to buy",
"completeDeal": "Complete Deal",
"uploadBankReceipt": "Upload Bank Receipt",
"notesForAdmin": "Notes For Admin",
"extendAd": "Extend Ad",
"updateAdDetails": "Do you want to update the Ad Details",
"durationExtendingAd": "You can change the ad duration and details before extending the ad",
"waitingAdminsResponse": "Waiting for Admins Response",
"cancelledByOwner": "Cancelled by Owner",
"cancelledByAdmin": "Cancelled by Admin",
"reservationTimeOver": "Reservation Time Over",
"paymentVerified": "Payment Verified",
"rejectedFormAdmin": "Rejected form Admin",
"waitingAdminPost": "Waiting for admin to post",
"waitingAdminsApproval": "Waiting for Admins Approval",
"sold": "Sold",
"noAdsShow": "No Ads to show",
"damagePartList": "Damage Part List",
"searchPart": "Search Part",
"addSpecialService": "Add Special Service",
"vehicleVar": "Vehicle",
"detailsVar": "Details",
"damageVar": "Damage",
"partsVar": "Parts",
"additional":"Additional",
"review":"Review",
"additional": "Additional",
"review": "Review",
"adVar": "Ad",
"updateAd":"Update Ad",
"createAd":"Create Ad",
"next":"Next",
"submitAd":"Submit Ad",
"selectAdType":"Select Ad Type",
"validUntilSubscriptionExpiration":"Valid Until Subscription Expiration",
"adsRemaining ":"Ads Remaining",
"youLeftAdsGivenSubscription":"You have left with 05 out of 50 ads given in the subscription.",
"updateSubscription":"Update Subscription",
"workInProgress":"Work In Progress",
"visitCompleted":"Visit Completed",
"youWantCancelAppointment":"Do you want to cancel this appointment?",
"appointmentCancelledCannotUndoAction":"Your appointment will be cancelled and you cannot undo this action.",
"appointment":"Appointment",
"rescheduleAppointment":"Reschedule Appointment",
"payforAppointment":"Pay for Appointment",
"appointmentsFilter":"Appointments Filter",
"searchByProvider":"Search By Provider",
"selectProvider":"Select Provider",
"searchByBranch":"Search By Branch",
"searchByCategory":"Search By Category",
"selectCategory":"Select Category",
"searchByService":"Search By Service",
"selectServices":"Select Services",
"updateAd": "Update Ad",
"createAd": "Create Ad",
"next": "Next",
"submitAd": "Submit Ad",
"selectAdType": "Select Ad Type",
"validUntilSubscriptionExpiration": "Valid Until Subscription Expiration",
"adsRemaining ": "Ads Remaining",
"youLeftAdsGivenSubscription": "You have left with 05 out of 50 ads given in the subscription.",
"updateSubscription": "Update Subscription",
"workInProgress": "Work In Progress",
"visitCompleted": "Visit Completed",
"youWantCancelAppointment": "Do you want to cancel this appointment?",
"appointmentCancelledCannotUndoAction": "Your appointment will be cancelled and you cannot undo this action.",
"appointment": "Appointment",
"rescheduleAppointment": "Reschedule Appointment",
"payforAppointment": "Pay for Appointment",
"appointmentsFilter": "Appointments Filter",
"searchByProvider": "Search By Provider",
"selectProvider": "Select Provider",
"searchByBranch": "Search By Branch",
"searchByCategory": "Search By Category",
"selectCategory": "Select Category",
"searchByService": "Search By Service",
"selectServices": "Select Services",
"modifyPackage": "Modify Package",
"schedule": "Schedule",
"serviceLocation": "Service Location:",
@ -527,13 +527,13 @@
"dateAndTime": "Date and Time",
"timeLocation": "Time & Location",
"serviceCharges": "Service Charges",
"locationCharges" : "Location Charges",
"locationCharges": "Location Charges",
"payableNow": "Payable Now",
"remainingAmount": "Remaining Amount",
"branchesFilter": "Branches Filter",
"searchByDistance": "Search By Distance",
"searchByDistance": "Search By Distance",
"searchByMinimumRatings": "Search By Minimum Ratings",
"chat": "Chat",
"chat": "Chat",
"noRequestsShow": "No Requests to show.",
"typeMessageHere": "Type your message here..",
"reject": "Reject",
@ -561,11 +561,12 @@
"termPrivacy": "Term & Privacy",
"inviteFriends": "Invite Friends",
"more": "More",
"language" :"Language",
"language": "Language",
"mySubscriptions": "My Subscriptions",
"subscriptions": "Subscriptions",
"defineLicenses": "Define Licenses",
"logOut": "Log Out",
"customer": "Customer",
"accept": "Accept"
"accept": "Accept",
"requestAlreadyInProgress": "This request is already in progress."
}

@ -582,7 +582,8 @@ class CodegenLoader extends AssetLoader{
"defineLicenses": "تحديد التراخيص",
"logOut": "تسجيل الخروج",
"customer": "العميل",
"accept": "قبول"
"accept": "قبول",
"requestAlreadyInProgress": "هذا الطلب قيد التقدم بالفعل."
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1153,7 +1154,8 @@ static const Map<String,dynamic> en_US = {
"defineLicenses": "Define Licenses",
"logOut": "Log Out",
"customer": "Customer",
"accept": "Accept"
"accept": "Accept",
"requestAlreadyInProgress": "This request is already in progress."
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -546,5 +546,6 @@ abstract class LocaleKeys {
static const logOut = 'logOut';
static const customer = 'customer';
static const accept = 'accept';
static const requestAlreadyInProgress = 'requestAlreadyInProgress';
}

@ -34,7 +34,7 @@ class RequestModel {
List<dynamic> requestProviderItem;
bool isActive;
int createdBy;
DateTime createdOn;
String? createdOn;
dynamic modifiedBy;
dynamic modifiedOn;
List<ChatMessageModel> chatMessages;
@ -110,7 +110,7 @@ class RequestModel {
requestProviderItem: List<dynamic>.from(json["requestProviderItem"].map((x) => x)),
isActive: json["isActive"],
createdBy: json["createdBy"],
createdOn: DateTime.parse(json["createdOn"]),
createdOn: json["createdOn"],
modifiedBy: json["modifiedBy"],
modifiedOn: json["modifiedOn"],
chatMessages: [],

@ -5,6 +5,17 @@
// unverified,
// }
//
//
class AppEnums {
static const int requestFilterEnumId = 16; // Requests Filter Enums
static const int myAdsFilterEnumId = 18; // My Ads Filter Enums
static const int exploreAdsFilterEnumId = 23; // Explore Ads Filter Enums
static const int appointmentsFilterEnumId = 13; // Appointments Filter Enums
}
enum VehicleType {
car,
motorCycle,
@ -78,15 +89,7 @@ enum PaymentMethods {
tamara,
}
enum PaymentTypes {
subscription,
appointment,
adReserve,
ads,
request,
extendAds,
partialAppointment
}
enum PaymentTypes { subscription, appointment, adReserve, ads, request, extendAds, partialAppointment }
enum AdCreationSteps {
vehicleDetails,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -102,41 +102,31 @@ class ChatVM extends ChangeNotifier {
return isValidated;
}
Future<void> onNewMessageReceived(
{required List<ChatMessageModel> messages,
required BuildContext context,
bool isMyOwnOffer = false}) async {
// log("message I received in onNewMessageReceived ${messages.first.toString()}");
Future<void> onNewMessageReceived({required List<ChatMessageModel> messages, required BuildContext context, bool isMyOwnOffer = false}) async {
if (AppState().currentAppType == AppType.customer) {
for (var msg in messages) {
int providerIndex = serviceProviderOffersList.indexWhere(
(element) => element.providerUserId == msg.senderUserID);
int providerIndex = serviceProviderOffersList.indexWhere((element) => element.providerUserId == msg.senderUserID); // TODO : NEED TO BE CHECKED
if (providerIndex != -1) {
serviceProviderOffersList[providerIndex].chatMessages!.add(msg);
}
}
//providerUserId
} else {
for (var msg in messages) {
// Where we need to call this function for saving a message in chat we will use receiverUserID and in those cases where received ID is null , it means it is a signal R call
int providerIndex = -1;
if (isMyOwnOffer) {
providerIndex =
context.read<RequestsVM>().myFilteredRequests.indexWhere(
(element) => element.customerUserID == msg.receiverUserID,
);
providerIndex = context.read<RequestsVM>().myFilteredRequests.indexWhere(
(element) => element.customerUserID == msg.receiverUserID,
);
} else {
providerIndex =
context.read<RequestsVM>().myFilteredRequests.indexWhere(
(element) => element.customerUserID == msg.senderUserID,
);
providerIndex = context.read<RequestsVM>().myFilteredRequests.indexWhere(
(element) => element.customerUserID == msg.senderUserID,
);
}
// log("here is it: $providerIndex");
// log("here is it: ${msg.senderUserID}");
// log("here is it: ${context.read<RequestsVM>().myFilteredRequests.first.customerUserID.toString()}");
if (providerIndex != -1) {
context
.read<RequestsVM>()
.addChatMessagesInRequestsModel(msg: msg, index: providerIndex);
context.read<RequestsVM>().addChatMessagesInRequestsModel(msg: msg, index: providerIndex);
}
}
}
@ -145,18 +135,15 @@ class ChatVM extends ChangeNotifier {
}
Future<void> buildHubConnection(BuildContext context) async {
if (hubConnection == null ||
hubConnection!.state != HubConnectionState.connected) {
if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) {
try {
hubConnection = await chatRepo.getHubConnection();
await hubConnection!.start();
hubConnection!.on("ReceiveMessageRequestOffer",
(List<Object?>? arguments) {
hubConnection!.on("ReceiveMessageRequestOffer", (List<Object?>? arguments) {
if (arguments == null || arguments.isEmpty) return;
List<ChatMessageModel> chat = [];
for (var message in arguments) {
final chatMessage =
ChatMessageModel.fromJson(message as Map<String, dynamic>);
final chatMessage = ChatMessageModel.fromJson(message as Map<String, dynamic>);
chat.add(chatMessage);
}
onNewMessageReceived(messages: chat, context: context);
@ -178,8 +165,7 @@ class ChatVM extends ChangeNotifier {
required String offerPrice,
required BuildContext context,
}) async {
if (hubConnection == null ||
hubConnection!.state != HubConnectionState.connected) {
if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) {
await buildHubConnection(context);
}
if (hubConnection!.state == HubConnectionState.connected) {
@ -197,8 +183,7 @@ class ChatVM extends ChangeNotifier {
"RequestID": requestId,
"Price": double.parse(offerPrice),
"ServiceProviderID": providerId,
"OfferStatus": RequestOfferStatusEnum.offer
.getIdFromRequestOfferStatusEnum(),
"OfferStatus": RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
"Comment": message,
},
}
@ -209,6 +194,21 @@ class ChatVM extends ChangeNotifier {
return false;
});
}
logger.i(<String, dynamic>{
"ReceiverUserID": receiverId,
"MessageType": chatMessageType.getIdFromChatMessageTypeEnum(),
"ChatText": message,
"RequestID": requestId,
"ReqOfferID": 0,
"ReqOffer": <String, dynamic>{
"RequestID": requestId,
"Price": double.parse(offerPrice),
"ServiceProviderID": AppState().getUser.data!.userInfo!.providerId,
"OfferStatus": RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
"Comment": message,
},
});
return true;
}
@ -222,22 +222,22 @@ class ChatVM extends ChangeNotifier {
}) async {
if (message.isEmpty) return false;
if (hubConnection == null ||
hubConnection!.state != HubConnectionState.connected) {
if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) {
await buildHubConnection(context);
}
if (hubConnection!.state == HubConnectionState.connected) {
final userId = AppState().getUser.data!.userInfo!.userId.toString();
final name = AppState().getUser.data!.userInfo!.firstName.toString();
log("I have saved this: ${(<String, dynamic>{
logger.i((<String, dynamic>{
"ReceiverUserID": receiverId,
"SenderUserID": userId,
"MessageType": chatMessageType.getIdFromChatMessageTypeEnum(),
"ChatText": message,
"RequestID": requestId,
"ReqOfferID": latestOfferId,
}).toString()}");
}));
hubConnection!.invoke(
"SendMessageRequestOffer",
args: <Object>[
@ -251,10 +251,11 @@ class ChatVM extends ChangeNotifier {
}
],
).catchError((e) {
logger.i("error in invoking SendMessageRequestOffer: ${e.toString()}");
logger.i("error in invoking SendMessage: ${e.toString()}");
Utils.showToast(e.toString());
return false;
});
ChatMessageModel chatMessageModel = ChatMessageModel(
messageType: chatMessageType.getIdFromChatMessageTypeEnum(),
chatText: message,
@ -267,21 +268,14 @@ class ChatVM extends ChangeNotifier {
);
if (AppState().currentAppType == AppType.customer) {
int providerIndex = serviceProviderOffersList
.indexWhere((element) => element.providerUserId == receiverId);
int providerIndex = serviceProviderOffersList.indexWhere((element) => element.providerUserId == receiverId);
if (providerIndex != -1) {
serviceProviderOffersList[providerIndex]
.chatMessages!
.add(chatMessageModel);
serviceProviderOffersList[providerIndex].chatMessages!.add(chatMessageModel);
}
} else {
int providerIndex = context
.read<RequestsVM>()
.myFilteredRequests
.indexWhere((element) => element.customerUserID == receiverId);
int providerIndex = context.read<RequestsVM>().myFilteredRequests.indexWhere((element) => element.customerUserID == receiverId);
if (providerIndex != -1) {
context.read<RequestsVM>().addChatMessagesInRequestsModel(
msg: chatMessageModel, index: providerIndex);
context.read<RequestsVM>().addChatMessagesInRequestsModel(msg: chatMessageModel, index: providerIndex);
}
}
return true;
@ -291,12 +285,10 @@ class ChatVM extends ChangeNotifier {
List<ServiceProvidersOffers> serviceProviderOffersList = [];
Future<void> getOffersFromProvidersByRequest(
{required int requestId, required BuildContext context}) async {
Future<void> getOffersFromProvidersByRequest({required int requestId, required BuildContext context}) async {
try {
Utils.showLoading(context);
ProviderOffersModel providerOffersModel = await requestRepo
.getOffersFromProvidersByRequest(requestId: requestId);
ProviderOffersModel providerOffersModel = await requestRepo.getOffersFromProvidersByRequest(requestId: requestId);
Utils.hideLoading(context);
serviceProviderOffersList.clear();
serviceProviderOffersList = providerOffersModel.serviceProviders ?? [];
@ -318,15 +310,10 @@ class ChatVM extends ChangeNotifier {
try {
int customerId = AppState().getUser.data!.userInfo!.customerId!;
Utils.showLoading(context);
List<ChatMessageModel> chatMessages = await chatRepo.getUsersChatMessages(
providerId: providerId,
customerId: customerId,
requestOfferId: requestOfferId,
requestId: requestId);
List<ChatMessageModel> chatMessages = await chatRepo.getUsersChatMessages(providerId: providerId, customerId: customerId, requestOfferId: requestOfferId, requestId: requestId);
serviceProviderOffersList[providerOfferIndex].chatMessages = chatMessages;
if (serviceProviderOffersList[providerOfferIndex].chatMessages != null) {
for (var message
in serviceProviderOffersList[providerOfferIndex].chatMessages!) {
for (var message in serviceProviderOffersList[providerOfferIndex].chatMessages!) {
if (message.chatMessageTypeEnum == ChatMessageTypeEnum.offer) {
updateLatestOfferId(message.reqOfferID ?? 0);
log("latestOfferId: $latestOfferId");
@ -352,13 +339,8 @@ class ChatVM extends ChangeNotifier {
try {
int providerId = AppState().getUser.data!.userInfo!.providerId!;
Utils.showLoading(context);
List<ChatMessageModel> chatMessages = await chatRepo.getUsersChatMessages(
providerId: providerId,
customerId: customerId,
requestOfferId: requestOfferId,
requestId: requestId);
context.read<RequestsVM>().overwriteChatMessagesInRequestsModel(
messages: chatMessages, index: customerRequestIndex);
List<ChatMessageModel> chatMessages = await chatRepo.getUsersChatMessages(providerId: providerId, customerId: customerId, requestOfferId: requestOfferId, requestId: requestId);
context.read<RequestsVM>().overwriteChatMessagesInRequestsModel(messages: chatMessages, index: customerRequestIndex);
Utils.hideLoading(context);
} catch (e) {
logger.i(e.toString());
@ -367,16 +349,10 @@ class ChatVM extends ChangeNotifier {
}
}
Future<int> onActionOfferTapped(
{required BuildContext context,
required RequestOfferStatusEnum requestOfferStatusEnum,
required int reqOfferId}) async {
Future<int> onActionOfferTapped({required BuildContext context, required RequestOfferStatusEnum requestOfferStatusEnum, required int reqOfferId}) async {
try {
Utils.showLoading(context);
GenericRespModel genericRespModel =
await requestRepo.updateOfferRequestStatus(
requestOfferStatusEnum: requestOfferStatusEnum,
requestOfferId: reqOfferId);
GenericRespModel genericRespModel = await requestRepo.updateOfferRequestStatus(requestOfferStatusEnum: requestOfferStatusEnum, requestOfferId: reqOfferId);
Utils.hideLoading(context);
return genericRespModel.messageStatus == 1 ? reqOfferId : -1;
} catch (e) {

@ -33,10 +33,7 @@ class RequestsVM extends BaseVM {
final CommonRepo commonRepo;
final RequestRepo requestRepo;
RequestsVM(
{required this.commonServices,
required this.commonRepo,
required this.requestRepo});
RequestsVM({required this.commonServices, required this.commonRepo, required this.requestRepo});
List<RequestModel> myRequests = [];
List<RequestModel> myFilteredRequests = [];
@ -45,27 +42,26 @@ class RequestsVM extends BaseVM {
List<EnumsModel> myRequestsTypeEnum = [];
RequestModel? currentSelectedRequest;
void updateCurrentSelectedRequest(RequestModel value) {
currentSelectedRequest = value;
}
populateRequestsFilterList() async {
if (requestsTypeFilterOptions.isNotEmpty) return;
if (myRequestsTypeEnum.isEmpty) {
myRequestsTypeEnum = await commonRepo.getEnumTypeValues(
enumTypeID: 16); //TODO: 16 is to get Requests Filter Enums
myRequestsTypeEnum = await commonRepo.getEnumTypeValues(enumTypeID: AppEnums.requestFilterEnumId);
}
for (int i = 0; i < myRequestsTypeEnum.length; i++) {
requestsTypeFilterOptions.add(FilterListModel(
title: myRequestsTypeEnum[i].enumValueStr,
isSelected: false,
id: myRequestsTypeEnum[i].enumValue));
requestsTypeFilterOptions.add(FilterListModel(title: myRequestsTypeEnum[i].enumValueStr, isSelected: false, id: myRequestsTypeEnum[i].enumValue));
}
log("requestsTypeFilterOptions: ${requestsTypeFilterOptions.toString()}");
notifyListeners();
}
Future<void> getRequests(
{bool isNeedToRebuild = false, required AppType appType}) async {
Future<void> getRequests({bool isNeedToRebuild = false, required AppType appType}) async {
if (isNeedToRebuild) setState(ViewState.busy);
var paramsForGetRequests = <String, dynamic>{};
@ -76,29 +72,22 @@ class RequestsVM extends BaseVM {
"requestType": 0,
};
if (appType == AppType.provider) {
paramsForGetRequests.addEntries([
MapEntry("providerID", AppState().getUser.data!.userInfo!.providerId)
]);
paramsForGetRequests.addEntries([MapEntry("providerID", AppState().getUser.data!.userInfo!.providerId)]);
} else {
paramsForGetRequests.addEntries([
MapEntry("customerID", AppState().getUser.data!.userInfo!.customerId)
]);
paramsForGetRequests.addEntries([MapEntry("customerID", AppState().getUser.data!.userInfo!.customerId)]);
}
myRequests = await requestRepo.getRequests(paramsForGetRequests);
applyFilterOnRequestsVM(
requestsTypeEnum: RequestsTypeEnum.specialCarRequest);
applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest);
setState(ViewState.idle);
notifyListeners();
}
addChatMessagesInRequestsModel(
{required ChatMessageModel msg, required int index}) {
addChatMessagesInRequestsModel({required ChatMessageModel msg, required int index}) {
myFilteredRequests[index].chatMessages.add(msg);
notifyListeners();
}
overwriteChatMessagesInRequestsModel(
{required List<ChatMessageModel> messages, required int index}) {
overwriteChatMessagesInRequestsModel({required List<ChatMessageModel> messages, required int index}) {
myFilteredRequests[index].chatMessages.clear();
myFilteredRequests[index].chatMessages = messages;
notifyListeners();
@ -109,14 +98,8 @@ class RequestsVM extends BaseVM {
for (var value in requestsTypeFilterOptions) {
value.isSelected = false;
}
requestsTypeFilterOptions[
requestsTypeEnum.getIdFromRequestTypeStatusEnum() - 1]
.isSelected = true; // -1 to match with the index
myFilteredRequests = myRequests
.where((element) =>
element.requestType ==
requestsTypeEnum.getIdFromRequestTypeStatusEnum())
.toList();
requestsTypeFilterOptions[requestsTypeEnum.getIdFromRequestTypeStatusEnum() - 1].isSelected = true; // -1 to match with the index
myFilteredRequests = myRequests.where((element) => element.requestType == requestsTypeEnum.getIdFromRequestTypeStatusEnum()).toList();
notifyListeners();
}
@ -125,8 +108,7 @@ class RequestsVM extends BaseVM {
String vehicleImageError = "";
void removeImageFromList(String filePath) {
int index = pickedVehicleImages
.indexWhere((element) => element.filePath == filePath);
int index = pickedVehicleImages.indexWhere((element) => element.filePath == filePath);
if (index == -1) {
return;
}
@ -156,8 +138,7 @@ class RequestsVM extends BaseVM {
List<VehicleCountryModel> vehicleCountries = [];
List<VehicleCityModel> vehicleCities = [];
SelectionModel requestTypeId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel requestTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionRequestTypeId(SelectionModel id) async {
requestTypeId = id;
@ -165,8 +146,7 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
SelectionModel vehicleTypeId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
Future<void> getVehicleTypes() async {
resetRequestCreationForm();
@ -197,8 +177,7 @@ class RequestsVM extends BaseVM {
// }
isFetchingVehicleDetail = true;
notifyListeners();
vehicleDetails = await commonRepo.getVehicleDetails(
vehicleTypeId: vehicleTypeId.selectedId);
vehicleDetails = await commonRepo.getVehicleDetails(vehicleTypeId: vehicleTypeId.selectedId);
if (vehicleDetails != null) {
vehicleBrands = vehicleDetails!.vehicleBrands!;
@ -210,30 +189,24 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
SelectionModel vehicleBrandId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionVehicleBrandId(SelectionModel id) {
vehicleBrandId = id;
vehicleModelId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleModelYearId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
notifyListeners();
}
SelectionModel vehicleModelId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionVehicleModelId(SelectionModel id) {
vehicleModelId = id;
vehicleModelYearId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
notifyListeners();
}
SelectionModel vehicleModelYearId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionVehicleModelYearId(SelectionModel id) {
vehicleModelYearId = id;
@ -248,21 +221,18 @@ class RequestsVM extends BaseVM {
}
bool isCountryFetching = false;
SelectionModel vehicleCountryId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel vehicleCountryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionVehicleCountryId(SelectionModel id) async {
vehicleCountryId = id;
isCountryFetching = true;
notifyListeners();
vehicleCities = await commonRepo.getVehicleCities(
countryId: vehicleCountryId.selectedId);
vehicleCities = await commonRepo.getVehicleCities(countryId: vehicleCountryId.selectedId);
isCountryFetching = false;
notifyListeners();
}
SelectionModel vehicleCityId =
SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel vehicleCityId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateSelectionVehicleCityId(SelectionModel id) {
vehicleCityId = id;
@ -280,12 +250,10 @@ class RequestsVM extends BaseVM {
description = v;
}
Future<RequestPostingImages> convertFileToRequestPostingImages(
{required File file}) async {
Future<RequestPostingImages> convertFileToRequestPostingImages({required File file}) async {
List<int> imageBytes = await file.readAsBytes();
String image = base64Encode(imageBytes);
RequestPostingImages vehiclePostingImages =
RequestPostingImages(requestImage: image);
RequestPostingImages vehiclePostingImages = RequestPostingImages(requestImage: image);
return vehiclePostingImages;
}
@ -294,8 +262,7 @@ class RequestsVM extends BaseVM {
log("requestImages: ${pickedVehicleImages.length}");
for (var image in pickedVehicleImages) {
var value =
await convertFileToRequestPostingImages(file: File(image.filePath!));
var value = await convertFileToRequestPostingImages(file: File(image.filePath!));
requestImages.add(value);
}
@ -306,8 +273,7 @@ class RequestsVM extends BaseVM {
if (validateCreateRequestForm()) {
Utils.showLoading(context);
List<RequestPostingImages> vehicleImages =
await getVehiclePostingImageList();
List<RequestPostingImages> vehicleImages = await getVehiclePostingImageList();
List requestImages = [];
vehicleImages.forEach((element) {
requestImages.add(element.toJson());
@ -377,12 +343,10 @@ class RequestsVM extends BaseVM {
return isValid;
}
Future<List<OffersModel>> getOffersByRequest(
{required int requestId, required BuildContext context}) async {
Future<List<OffersModel>> getOffersByRequest({required int requestId, required BuildContext context}) async {
try {
Utils.showLoading(context);
List<OffersModel> respModel =
await requestRepo.getOffersByRequest(requestId: requestId);
List<OffersModel> respModel = await requestRepo.getOffersByRequest(requestId: requestId);
Utils.hideLoading(context);
return respModel;
} catch (e) {
@ -473,26 +437,22 @@ class RequestsVM extends BaseVM {
ChatMessageModel chatMessageModel = ChatMessageModel(
isMyMessage: true,
chatText: message,
messageType:
ChatMessageTypeEnum.offer.getIdFromChatMessageTypeEnum(),
messageType: ChatMessageTypeEnum.offer.getIdFromChatMessageTypeEnum(),
senderName: senderName,
senderUserID: senderId,
receiverUserID: receiverId,
chatMessageTypeEnum: ChatMessageTypeEnum.offer,
requestID: requestModel.id,
offerStatus:
RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
offerStatus: RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
reqOffer: ReqOffer(
offerStatus: RequestOfferStatusEnum.offer
.getIdFromRequestOfferStatusEnum(),
offerStatus: RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
requestID: requestModel.id,
price: double.parse(offerPrice),
requestOfferStatusEnum: RequestOfferStatusEnum.offer,
comment: message,
offerStatusText: "",
));
context.read<ChatVM>().onNewMessageReceived(
messages: [chatMessageModel], context: context, isMyOwnOffer: true);
context.read<ChatVM>().onNewMessageReceived(messages: [chatMessageModel], context: context, isMyOwnOffer: true);
if (!isFromChatScreen) {
ChatViewArguments chatViewArguments = ChatViewArguments(
chatTypeEnum: ChatTypeEnum.requestOffer,
@ -502,8 +462,7 @@ class RequestsVM extends BaseVM {
requestIndex: requestIndex,
providerIndex: -1,
);
navigateWithName(context, AppRoutes.chatView,
arguments: chatViewArguments);
navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments);
}
}
}

@ -104,7 +104,7 @@ class AdCard extends StatelessWidget {
(adDetails.vehicle!.vehicleTitle ?? "").toText(fontSize: 16, isBold: true),
Row(
children: [
(LocaleKeys.model.tr() + ":").toText(
("${LocaleKeys.model.tr()}:").toText(
color: MyColors.lightTextColor,
),
2.width,
@ -113,7 +113,7 @@ class AdCard extends StatelessWidget {
),
Row(
children: [
(LocaleKeys.mileage.tr() + ":").toText(
("${LocaleKeys.mileage.tr()}:").toText(
color: MyColors.lightTextColor,
),
2.width,

@ -16,7 +16,6 @@ import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
class AppointmentDetailView extends StatelessWidget {
final AppointmentListModel appointmentListModel;
@ -267,7 +266,7 @@ class AppointmentDetailView extends StatelessWidget {
),
],
15.height,
if (appointmentListModel.appointmentStatusEnum != AppointmentStatusEnum.workStarted && appointmentListModel.appointmentStatusEnum != AppointmentStatusEnum.visitCompleted) ...[
if (appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.booked || appointmentListModel.appointmentStatusEnum == AppointmentStatusEnum.confirmed) ...[
Row(
children: [
CardButtonWithIcon(

@ -34,15 +34,11 @@ class ChatView extends StatelessWidget {
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return Consumer(builder:
(BuildContext context, RequestsVM requestsVM, Widget? child) {
return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) {
return InfoBottomSheet(
title: LocaleKeys.makeAnOffer
.tr()
.toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
title: LocaleKeys.makeAnOffer.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: [
@ -64,8 +60,7 @@ class ChatView extends StatelessWidget {
errorValue: requestsVM.offerDescriptionError,
keyboardType: TextInputType.text,
hint: LocaleKeys.description.tr(),
onChanged: (v) =>
requestsVM.updateOfferDescription(v),
onChanged: (v) => requestsVM.updateOfferDescription(v),
),
],
),
@ -99,29 +94,21 @@ class ChatView extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.chat.tr()),
body: Consumer2<ChatVM, RequestsVM>(builder: (BuildContext context,
ChatVM chatVM, RequestsVM requestVM, Widget? child) {
body: Consumer2<ChatVM, RequestsVM>(builder: (BuildContext context, ChatVM chatVM, RequestsVM requestVM, Widget? child) {
final chatMessages = AppState().currentAppType == AppType.customer
? chatVM.serviceProviderOffersList[chatViewArguments.providerIndex]
.chatMessages
: requestVM.myFilteredRequests[chatViewArguments.requestIndex]
.chatMessages;
? chatVM.serviceProviderOffersList[chatViewArguments.providerIndex].chatMessages
: requestVM.myFilteredRequests[chatViewArguments.requestIndex].chatMessages;
return chatMessages == null
? Center(
child: LocaleKeys.noRequestsShow
.tr()
.toText(fontSize: 16, color: MyColors.lightTextColor))
? Center(child: LocaleKeys.noRequestsShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor))
: Column(
children: [
Expanded(
child: ListView.separated(
itemCount: chatMessages.length,
separatorBuilder: (BuildContext context, int index) =>
20.height,
separatorBuilder: (BuildContext context, int index) => 20.height,
itemBuilder: (BuildContext context, int index) {
ChatMessageModel chatMessageModel = chatMessages[index];
return ChatMessageCustomWidget(
chatMessageModel: chatMessageModel);
return ChatMessageCustomWidget(chatMessageModel: chatMessageModel);
},
).horPaddingMain(),
),
@ -129,54 +116,64 @@ class ChatView extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (AppState().currentAppType == AppType.provider) ...[
if (requestVM.currentSelectedRequest!.requestStatus == RequestStatus.inProgress) ...[
Center(
child: LocaleKeys.requestAlreadyInProgress.tr().toText(
textAlign: TextAlign.center,
color: MyColors.lightTextColor,
fontSize: 14,
),
).paddingAll(15)
] else ...[
if (AppState().currentAppType == AppType.provider) ...[
Expanded(
flex: 1,
child: const Icon(
Icons.local_offer_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(
() async {
buildSendOfferBottomSheet(context);
},
),
),
],
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.local_offer_rounded,
Icons.send_rounded,
color: MyColors.darkPrimaryColor,
size: 30,
).onPress(
() async {
buildSendOfferBottomSheet(context);
log("chatViewArguments.requestId:${chatViewArguments.requestId}");
final status = await chatVM.onTextMessageSend(
context: context,
receiverId: chatViewArguments.receiverId,
message: chatVM.chatMessageText,
requestId: chatViewArguments.requestId ?? 0,
offerPrice: "0.0",
chatMessageType: ChatMessageTypeEnum.freeText,
);
if (status) {
chatVM.clearChatMessageText();
}
},
),
),
],
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 {
log("chatViewArguments.requestId:${chatViewArguments.requestId}");
final status = await chatVM.onTextMessageSend(
context: context,
receiverId: chatViewArguments.receiverId,
message: chatVM.chatMessageText,
requestId: chatViewArguments.requestId ?? 0,
offerPrice: "0.0",
chatMessageType: ChatMessageTypeEnum.freeText,
);
if (status) {
chatVM.clearChatMessageText();
}
},
),
)
],
).toContainer(isShadowEnabled: true),
],
@ -193,8 +190,7 @@ class ChatMessageCustomWidget extends StatefulWidget {
const ChatMessageCustomWidget({super.key, required this.chatMessageModel});
@override
State<ChatMessageCustomWidget> createState() =>
_ChatMessageCustomWidgetState();
State<ChatMessageCustomWidget> createState() => _ChatMessageCustomWidgetState();
}
class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
@ -204,15 +200,11 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return Consumer(
builder: (BuildContext context, ChatVM chatVM, Widget? child) {
return Consumer(builder: (BuildContext context, ChatVM chatVM, Widget? child) {
return InfoBottomSheet(
title: LocaleKeys.makeAnOffer
.tr()
.toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
title: LocaleKeys.makeAnOffer.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: [
@ -223,18 +215,14 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
ListView.separated(
shrinkWrap: true,
itemCount: chatVM.offerRejectModelList.length,
separatorBuilder: (BuildContext context, int index) =>
const Divider(thickness: 0.5),
separatorBuilder: (BuildContext context, int index) => const Divider(thickness: 0.5),
itemBuilder: (BuildContext context, int index) {
OfferRequestCommentModel offerRequestCommentModel =
chatVM.offerRejectModelList[index];
OfferRequestCommentModel offerRequestCommentModel = chatVM.offerRejectModelList[index];
return CircleCheckBoxWithTitle(
isChecked:
offerRequestCommentModel.isSelected ?? false,
isChecked: offerRequestCommentModel.isSelected ?? false,
title: '${offerRequestCommentModel.title}',
onSelected: () {
chatVM.updateSelectionInOfferRejectModelList(
index);
chatVM.updateSelectionInOfferRejectModelList(index);
},
selectedColor: MyColors.darkPrimaryColor,
);
@ -247,8 +235,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
errorValue: chatVM.rejectOfferDescriptionError,
keyboardType: TextInputType.text,
hint: LocaleKeys.description.tr(),
onChanged: (v) =>
chatVM.updateRejectOfferDescription(v),
onChanged: (v) => chatVM.updateRejectOfferDescription(v),
),
],
),
@ -267,12 +254,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
);
}
Widget buildOfferDetailsInChatMessage(
{required ChatMessageModel chatMessageModel,
required BuildContext context}) {
final requestOfferStatusEnum =
chatMessageModel.reqOffer!.requestOfferStatusEnum ??
RequestOfferStatusEnum.offer;
Widget buildOfferDetailsInChatMessage({required ChatMessageModel chatMessageModel, required BuildContext context}) {
final requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum ?? RequestOfferStatusEnum.offer;
switch (requestOfferStatusEnum) {
case RequestOfferStatusEnum.offer:
@ -282,18 +265,9 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"${chatMessageModel.reqOffer!.price}".toText(
fontSize: 19,
isBold: true,
color: AppState().currentAppType == AppType.provider
? MyColors.white
: MyColors.darkTextColor),
"${chatMessageModel.reqOffer!.price}".toText(fontSize: 19, isBold: true, color: AppState().currentAppType == AppType.provider ? MyColors.white : MyColors.darkTextColor),
5.width,
LocaleKeys.sar.tr().toText(
color: MyColors.lightTextColor,
height: 2.2,
fontSize: 10,
isBold: true),
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, height: 2.2, fontSize: 10, isBold: true),
],
),
if (widget.chatMessageModel.isMyMessage == false) ...[
@ -308,19 +282,15 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
borderColor: MyColors.greenColor,
isFilled: false,
onPressed: () async {
int status =
await context.read<ChatVM>().onActionOfferTapped(
context: context,
requestOfferStatusEnum:
RequestOfferStatusEnum.accepted,
reqOfferId: chatMessageModel.reqOfferID ?? -1,
);
int status = await context.read<ChatVM>().onActionOfferTapped(
context: context,
requestOfferStatusEnum: RequestOfferStatusEnum.accepted,
reqOfferId: chatMessageModel.reqOfferID ?? -1,
);
if (status != -1) {
log("accepted: $status");
if (chatMessageModel.reqOfferID == status) {
chatMessageModel.reqOffer!.requestOfferStatusEnum =
RequestOfferStatusEnum.accepted;
chatMessageModel.reqOffer!.requestOfferStatusEnum = RequestOfferStatusEnum.accepted;
setState(() {});
}
}
@ -358,11 +328,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
fontSize: 12,
isItalic: true,
),
).toContainer(
borderRadius: 40,
width: double.infinity,
backgroundColor:
MyColors.adPendingStatusColor.withOpacity(0.16)),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
case RequestOfferStatusEnum.accepted:
@ -374,11 +340,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
fontSize: 12,
isItalic: true,
),
).toContainer(
borderRadius: 40,
width: double.infinity,
backgroundColor:
MyColors.adPendingStatusColor.withOpacity(0.16)),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
case RequestOfferStatusEnum.rejected:
@ -390,11 +352,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
fontSize: 12,
isItalic: true,
),
).toContainer(
borderRadius: 40,
width: double.infinity,
backgroundColor:
MyColors.adPendingStatusColor.withOpacity(0.16)),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
case RequestOfferStatusEnum.cancel:
@ -406,11 +364,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
fontSize: 12,
isItalic: true,
),
).toContainer(
borderRadius: 40,
width: double.infinity,
backgroundColor:
MyColors.adPendingStatusColor.withOpacity(0.16)),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)),
],
);
}
@ -419,9 +373,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: (widget.chatMessageModel.isMyMessage ?? false)
? TextDirection.rtl
: TextDirection.ltr,
textDirection: (widget.chatMessageModel.isMyMessage ?? false) ? TextDirection.rtl : TextDirection.ltr,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -443,10 +395,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
((widget.chatMessageModel.isMyMessage ?? false)
? "You"
: widget.chatMessageModel.senderName ?? "")
.toText(fontSize: 16, isBold: true),
((widget.chatMessageModel.isMyMessage ?? false) ? "You" : widget.chatMessageModel.senderName ?? "").toText(fontSize: 16, isBold: true),
],
),
5.height,
@ -458,13 +407,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
Expanded(
child: Directionality(
textDirection: TextDirection.ltr,
child:
(widget.chatMessageModel.chatText ?? "").toText(
color:
(widget.chatMessageModel.isMyMessage ?? false)
? MyColors.white
: MyColors.lightTextColor,
child: (widget.chatMessageModel.chatText ?? "").toText(
color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor,
fontSize: 12,
// isBold: true,
),
@ -472,26 +416,15 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
),
],
),
if (widget.chatMessageModel.chatMessageTypeEnum ==
ChatMessageTypeEnum.offer) ...[
buildOfferDetailsInChatMessage(
chatMessageModel: widget.chatMessageModel,
context: context),
if (widget.chatMessageModel.chatMessageTypeEnum == ChatMessageTypeEnum.offer) ...[
buildOfferDetailsInChatMessage(chatMessageModel: widget.chatMessageModel, context: context),
],
],
).toContainer(
isShadowEnabled:
!(widget.chatMessageModel.isMyMessage ?? false),
backgroundColor:
(widget.chatMessageModel.isMyMessage ?? false)
? MyColors.darkIconColor
: MyColors.white,
isShadowEnabled: !(widget.chatMessageModel.isMyMessage ?? false),
backgroundColor: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.darkIconColor : MyColors.white,
borderRadius: 0,
margin: EdgeInsets.fromLTRB(
(widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0,
0,
!(widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0,
0),
margin: EdgeInsets.fromLTRB((widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0, 0, !(widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0, 0),
),
],
),

@ -1,9 +1,6 @@
import 'dart:io';
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.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';
@ -11,14 +8,9 @@ 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/theme/colors.dart';
import 'package:mc_common_app/utils/app_permission_handler.dart';
import 'package:mc_common_app/view_models/service_view_model.dart';
import 'package:mc_common_app/view_models/user_view_model.dart';
import 'package:mc_common_app/views/setting_options/widgets/custom_setting_options_tile.dart';
import 'package:mc_common_app/views/user/change_password_page.dart';
import 'package:mc_common_app/views/user/change_password_page.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
@ -46,7 +38,6 @@ class _ProfileScreenState extends State<ProfileScreen> {
backgroundColor: const Color(0xffefefef),
body: Consumer<UserVM>(builder: (_, model, __) {
return Stack(
// fit: StackFit.loose,
children: [
Column(
children: [
@ -54,29 +45,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
flex: 3,
child: Container(
decoration: BoxDecoration(
image: AppState()
.getUser
.data!
.userInfo!
.userLocalImage !=
null
image: AppState().getUser.data!.userInfo!.userLocalImage != null
? DecorationImage(
image: FileImage(AppState()
.getUser
.data!
.userInfo!
.userLocalImage!),
image: FileImage(AppState().getUser.data!.userInfo!.userLocalImage!),
fit: BoxFit.cover,
)
: AppState().getUser.data!.userInfo!.userImageUrl !=
null
: AppState().getUser.data!.userInfo!.userImageUrl != null
? DecorationImage(
image: CachedNetworkImageProvider(
AppState()
.getUser
.data!
.userInfo!
.userImageUrl,
AppState().getUser.data!.userInfo!.userImageUrl,
),
fit: BoxFit.cover,
)
@ -103,9 +80,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
child: ListView(
children: [
20.height,
"${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}"
.toText(fontSize: 20)
.paddingOnly(left: 25),
"${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25),
Column(
children: [
CustomProfileOptionsTile(
@ -116,39 +91,29 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
CustomProfileOptionsTile(
titleText: LocaleKeys.email.tr(),
subtitleText:
"${AppState().getUser.data!.userInfo!.email}",
subtitleText: "${AppState().getUser.data!.userInfo!.email}",
needBorderBelow: true,
onTap: () {
Navigator.pushNamed(
context, AppRoutes.changeEmailPage);
Navigator.pushNamed(context, AppRoutes.changeEmailPage);
},
),
CustomProfileOptionsTile(
titleText: LocaleKeys.phoneNumber.tr(),
subtitleText:
"${AppState().getUser.data!.userInfo!.email}",
subtitleText: "${AppState().getUser.data!.userInfo!.email}",
needBorderBelow: true,
onTap: () {
Navigator.pushNamed(
context, AppRoutes.changeMobilePage);
Navigator.pushNamed(context, AppRoutes.changeMobilePage);
},
),
CustomProfileOptionsTile(
titleText: LocaleKeys.password.tr(),
subtitleText: "************",
onTap: () {
Navigator.pushNamed(
context, AppRoutes.changePassword);
Navigator.pushNamed(context, AppRoutes.changePassword);
},
),
],
).toContainer(
width: double.infinity,
isShadowEnabled: true,
paddingAll: 10,
margin: const EdgeInsets.fromLTRB(24, 20, 24, 0),
borderRadius: 0),
).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 20, 24, 0), borderRadius: 0),
],
),
),
@ -161,8 +126,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
height: 90,
alignment: Alignment.centerLeft,
child: ClipOval(
child: AppState().getUser.data!.userInfo!.userLocalImage !=
null
child: AppState().getUser.data!.userInfo!.userLocalImage != null
? Image.file(
AppState().getUser.data!.userInfo!.userLocalImage!,
width: 90,
@ -170,8 +134,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
fit: BoxFit.fill,
)
: CachedNetworkImage(
imageUrl:
"${AppState().getUser.data!.userInfo!.userImageUrl}",
imageUrl: "${AppState().getUser.data!.userInfo!.userImageUrl}",
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
image: DecorationImage(
@ -180,10 +143,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
),
placeholder: (context, url) =>
const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) =>
const Icon(Icons.error),
placeholder: (context, url) => const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => const Icon(Icons.error),
width: 90,
height: 90,
fit: BoxFit.fill,
@ -200,14 +161,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
child: Container(
height: 35,
width: 35,
decoration: BoxDecoration(
color: MyColors.white,
shape: BoxShape.circle,
border:
Border.all(color: MyColors.darkTextColor, width: 0.1)),
child: const Icon(Icons.edit_note,
color: MyColors.darkIconColor, size: 27)
.paddingOnly(left: 5),
decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)),
child: const Icon(Icons.edit_note, color: MyColors.darkIconColor, size: 27).paddingOnly(left: 5),
).onPress(
() async {
model.updateUserImage(context);

@ -23,29 +23,23 @@ class OfferListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final List<ServiceProvidersOffers> serviceProviderOffers =
offerListPageArguments.serviceProviderOffers;
final List<ServiceProvidersOffers> serviceProviderOffers = offerListPageArguments.serviceProviderOffers;
return Scaffold(
appBar: CustomAppBar(title: LocaleKeys.offers.tr()),
body: serviceProviderOffers.isEmpty
? Center(
child: LocaleKeys.noOffersShow
.tr()
.toText(fontSize: 16, color: MyColors.lightTextColor))
? Center(child: LocaleKeys.noOffersShow.tr().toText(fontSize: 16, color: MyColors.lightTextColor))
: ListView.separated(
itemCount: serviceProviderOffers.length,
padding: const EdgeInsets.all(16),
itemBuilder: (context, index) {
ServiceProvidersOffers offersModel =
serviceProviderOffers[index];
ServiceProvidersOffers offersModel = serviceProviderOffers[index];
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(offersModel.name ?? "")
.toText(fontSize: 16, isBold: true),
(offersModel.name ?? "").toText(fontSize: 16, isBold: true),
Center(
child: "${offersModel.offerCount}".toText(
color: Colors.white,
@ -56,8 +50,8 @@ class OfferListPage extends StatelessWidget {
backgroundColor: MyColors.redColor,
borderRadius: 100,
paddingAll: 1,
width: 20,
height: 20,
width: 22,
height: 22,
),
],
),
@ -72,6 +66,13 @@ class OfferListPage extends StatelessWidget {
color: MyColors.lightTextColor,
fontSize: 12,
),
//TODO: createdOn parameter need to be added in the backend
// if (offersModel.createdOn != null) ...[
// DateTime.parse(offersModel.createdOn!).getTimeAgo().toText(
// color: MyColors.lightTextColor,
// ),
// ],
" | 1 hour ago".toText(
color: MyColors.lightTextColor,
fontSize: 12,
@ -90,12 +91,10 @@ class OfferListPage extends StatelessWidget {
ChatViewArguments chatViewArguments = ChatViewArguments(
chatTypeEnum: ChatTypeEnum.requestOffer,
receiverId: "${offersModel.providerUserId}",
senderId:
AppState().getUser.data!.userInfo!.userId.toString(),
senderId: AppState().getUser.data!.userInfo!.userId.toString(),
requestId: offerListPageArguments.requestId,
providerIndex: index,
requestIndex:
-1, // This will be only send in case of provider
requestIndex: -1, // This will be only send in case of provider
);
final chatVM = context.read<ChatVM>();
@ -109,8 +108,7 @@ class OfferListPage extends StatelessWidget {
providerOfferIndex: index,
)
.whenComplete(
() => navigateWithName(context, AppRoutes.chatView,
arguments: chatViewArguments),
() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments),
);
}).toContainer(isShadowEnabled: true);
},

@ -13,6 +13,7 @@ import 'package:mc_common_app/models/requests_models/request_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
@ -22,11 +23,7 @@ class RequestItem extends StatelessWidget {
final AppType appType;
final int requestIndex;
const RequestItem(
{super.key,
required this.request,
required this.appType,
required this.requestIndex});
const RequestItem({super.key, required this.request, required this.appType, required this.requestIndex});
@override
Widget build(BuildContext context) {
@ -40,16 +37,11 @@ class RequestItem extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.statusContainerChip(
text: request.requestStatusName,
chipColor: Utils.getChipColorByRequestStatus(
request.requestStatus)),
Utils.statusContainerChip(text: request.requestStatusName, chipColor: Utils.getChipColorByRequestStatus(request.requestStatus)),
6.height,
"${request.brand} ${request.model}"
.toText(fontSize: 16, isBold: true),
showItem((LocaleKeys.model.tr()), "${request.year}"),
showItem(
(LocaleKeys.customerName.tr()), request.customerName),
"${request.brand} ${request.model}".toText(fontSize: 16, isBold: true),
showItem("${LocaleKeys.model.tr()}:", "${request.year}"),
showItem("${LocaleKeys.customerName.tr()}:", request.customerName),
],
),
),
@ -62,28 +54,30 @@ class RequestItem extends StatelessWidget {
child: "${request.offerCount}".toText(
color: Colors.white,
isBold: true,
fontSize: 10,
fontSize: 12,
),
).toContainer(
backgroundColor: MyColors.redColor,
borderRadius: 100,
paddingAll: 1,
width: 20,
height: 20,
width: 25,
height: 25,
),
],
2.height,
request.cityName.toText(
color: MyColors.lightTextColor,
),
"9 Hours Ago".toText(
color: MyColors.lightTextColor,
)
if (request.createdOn != null) ...[
DateTime.parse(request.createdOn!).getTimeAgo().toText(
color: MyColors.lightTextColor,
),
],
],
)
],
),
showItem((LocaleKeys.description.tr()), request.description),
showItem("${LocaleKeys.description.tr()}:", request.description),
showItem("Price Range: ", ""),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -109,33 +103,31 @@ class RequestItem extends StatelessWidget {
),
],
),
const Icon(
Icons.arrow_forward,
color: MyColors.darkIconColor,
size: 18,
),
request.requestStatus == RequestStatus.submitted
? const Icon(
Icons.arrow_forward,
color: MyColors.darkIconColor,
size: 18,
)
: const SizedBox()
],
),
],
).toContainer(isShadowEnabled: true).onPress(() async {
RequestsVM requestsVM = context.read<RequestsVM>();
requestsVM.updateCurrentSelectedRequest(request);
if (request.requestStatus == RequestStatus.pending) {
return;
}
if (appType == AppType.provider) {
RequestDetailPageArguments requestDetailPageArguments =
RequestDetailPageArguments(
requestIndex: requestIndex, requestModel: request);
navigateWithName(context, AppRoutes.requestsDetailPage,
arguments: requestDetailPageArguments);
RequestDetailPageArguments requestDetailPageArguments = RequestDetailPageArguments(requestIndex: requestIndex, requestModel: request);
navigateWithName(context, AppRoutes.requestsDetailPage, arguments: requestDetailPageArguments);
} else {
ChatVM chatVM = context.read<ChatVM>();
await chatVM.getOffersFromProvidersByRequest(
requestId: request.id, context: context);
OfferListPageArguments offerListPageArguments = OfferListPageArguments(
serviceProviderOffers: chatVM.serviceProviderOffersList,
requestId: request.id);
navigateWithName(context, AppRoutes.offersListPage,
arguments: offerListPageArguments);
await chatVM.getOffersFromProvidersByRequest(requestId: request.id, context: context);
OfferListPageArguments offerListPageArguments = OfferListPageArguments(serviceProviderOffers: chatVM.serviceProviderOffersList, requestId: request.id);
navigateWithName(context, AppRoutes.offersListPage, arguments: offerListPageArguments);
}
});
}

Loading…
Cancel
Save