aamir_dev
Faiz Hashmi 11 months ago
parent e79af29c8e
commit 71ae7cf3e4

@ -740,5 +740,7 @@
"blockedByAdmin": "تم حظرها من قبل المسؤول",
"active": "نشط",
"paymentType": "نوع الدفع",
"searchByCreatedDate": "البحث حسب تاريخ الإنشاء"
"searchByCreatedDate": "البحث حسب تاريخ الإنشاء",
"dealCompleted": "تم إتمام الصفقة",
"theDealNotCompleted": "لم تكتمل الصفقة"
}

@ -738,5 +738,7 @@
"blockedByAdmin": "Blocked by admin",
"active": "Active",
"paymentType": "Payment Type",
"searchByCreatedDate": "Search By Created Date"
"searchByCreatedDate": "Search By Created Date",
"dealCompleted": "The Deal Completed",
"theDealNotCompleted": "The Deal Not Completed"
}

@ -163,7 +163,8 @@ class ApiConsts {
static String createRequest = "${baseUrlServices}api/RequestManagement/Request_Create";
static String getRequest = "${baseUrlServices}api/RequestManagement/Request_Get";
static String getRequestOffers = "${baseUrlServices}api/RequestManagement/ReqOffer_Get";
static String updateRequestOffer = "${baseUrlServices}api/RequestManagement/RequestOffer_UpdateStatus";
static String updateRequestOfferStatus = "${baseUrlServices}api/RequestManagement/RequestOffer_UpdateStatus";
static String updateRequestOffer = "${baseUrlServices}api/RequestManagement/ReqOffer_Upadte";
static String updateRequestCustomer = "${baseUrlServices}api/RequestManagement/Request_StatusUpdate_Customer";
static String updateRequestProvider = "${baseUrlServices}api/RequestManagement/Request_StatusUpdate_Provider";
static String requestOffersSpsGet = "${baseUrlServices}api/RequestManagement/Request_OfferSPs_Get";

@ -756,7 +756,9 @@ class CodegenLoader extends AssetLoader{
"blockedByAdmin": "تم حظرها من قبل المسؤول",
"active": "نشط",
"paymentType": "نوع الدفع",
"searchByCreatedDate": "البحث حسب تاريخ الإنشاء"
"searchByCreatedDate": "البحث حسب تاريخ الإنشاء",
"dealCompleted": "تم إتمام الصفقة",
"theDealNotCompleted": "لم تكتمل الصفقة"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1498,7 +1500,9 @@ static const Map<String,dynamic> en_US = {
"blockedByAdmin": "Blocked by admin",
"active": "Active",
"paymentType": "Payment Type",
"searchByCreatedDate": "Search By Created Date"
"searchByCreatedDate": "Search By Created Date",
"dealCompleted": "The Deal Completed",
"theDealNotCompleted": "The Deal Not Completed"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -720,5 +720,7 @@ abstract class LocaleKeys {
static const active = 'active';
static const paymentType = 'paymentType';
static const searchByCreatedDate = 'searchByCreatedDate';
static const dealCompleted = 'dealCompleted';
static const theDealNotCompleted = 'theDealNotCompleted';
}

@ -213,9 +213,7 @@ class AdsRepoImp implements AdsRepo {
"VehicleModelYearIDs": vehicleModelYearIdsList ?? [],
"CreatedByRoles": createdByRolesIdsList ?? [],
"AdsStatuses": ["${AdPostStatus.active.getIdFromAdPostStatusEnum()}"], //only Active ADS
// TODO: This has to be converted into list
"VehicleNew": (vehicleAdConditionIdsList != null && vehicleAdConditionIdsList.isNotEmpty) ? vehicleAdConditionIdsList.first.toString() : "",
"VehicleNew": vehicleAdConditionIdsList ?? [],
"CreatedOn": (vehicleAdCreatedDateList != null && vehicleAdCreatedDateList.isNotEmpty) ? vehicleAdCreatedDateList.first.toString() : "",
"isActive": "true", //only Active ADS
"isExplore": "true",

@ -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/main.dart';
import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/requests_models/offers_model.dart';
import 'package:mc_common_app/models/requests_models/provider_offers_model.dart';
@ -54,6 +55,19 @@ abstract class RequestRepo {
Future<GenericRespModel> updateRequestStatus({required RequestStatusEnum requestStatusEnum, required int requestId});
Future<GenericRespModel> updateRequestOfferStatus({required RequestOfferStatusEnum requestOfferStatusEnum, required int requestOfferId, required String comments});
Future<GenericRespModel> updateRequestOfferFromProvider({
required String message,
required int requestId,
required int offerId,
required String offerPrice,
required bool isDeliveryAvailable,
required String serviceItemName,
required int manufacturedById,
required String manufacturedOn,
required List requestImages,
required RequestOfferStatusEnum requestOfferStatusEnum,
});
}
class RequestRepoImp implements RequestRepo {
@ -322,6 +336,44 @@ class RequestRepoImp implements RequestRepo {
"offerStatus": requestOfferStatusEnum.getIdFromRequestOfferStatusEnum().toString(),
"comments": comments,
};
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.updateRequestOfferStatus,
queryParameters,
token: appState.getUser.data!.accessToken,
);
return genericRespModel;
}
@override
Future<GenericRespModel> updateRequestOfferFromProvider({
required String message,
required int requestId,
required int offerId,
required String offerPrice,
required bool isDeliveryAvailable,
required String serviceItemName,
required int manufacturedById,
required String manufacturedOn,
required List requestImages,
required RequestOfferStatusEnum requestOfferStatusEnum,
}) async {
final providerId = appState.getUser.data!.userInfo!.providerId;
var queryParameters = {
"id": offerId,
"requestID": requestId,
"serviceProviderID": providerId,
"offerStatus": requestOfferStatusEnum.getIdFromRequestOfferStatusEnum(),
"serviceItem": serviceItemName,
"comment": message,
"price": offerPrice,
"offeredItemCreatedBy": manufacturedById.toString(),
"offeredItemCreatedOn": manufacturedOn.toString(),
"reqOfferImages": requestImages,
"isDeliveryAvailable": isDeliveryAvailable
};
GenericRespModel genericRespModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.updateRequestOffer,

@ -114,7 +114,10 @@ class AdVM extends BaseVM {
}
void removeSpecialServiceCard(int index) {
String option = specialServiceCards.elementAt(index).serviceSelectedId!.selectedOption;
String option = specialServiceCards
.elementAt(index)
.serviceSelectedId!
.selectedOption;
for (var value in vehicleAdsSpecialServices) {
if (value.name == option) {
@ -1255,7 +1258,10 @@ class AdVM extends BaseVM {
}
void removeDamagePartCard(int index) {
String option = vehicleDamageCards.elementAt(index).partSelectedId!.selectedOption;
String option = vehicleDamageCards
.elementAt(index)
.partSelectedId!
.selectedOption;
for (var value in vehicleDamageParts) {
if (value.partName == option) {
@ -1533,7 +1539,9 @@ class AdVM extends BaseVM {
File file = File(imageModel.filePath!);
List<int> imageBytes = await file.readAsBytes();
String image = base64Encode(imageBytes);
String fileName = file.path.split('/').last;
String fileName = file.path
.split('/')
.last;
vehiclePostingImages = VehiclePostingImages(
imageName: fileName,
imageStr: image,
@ -1733,11 +1741,16 @@ class AdVM extends BaseVM {
if (vehicleAdCreatedDateSearchHistory.isEmpty) {
updateAdsFiltersCounter(adsFiltersCounter + 1);
}
vehicleAdCreatedDateSearchHistory.add(value);
if (vehicleAdCreatedDateSearchHistory.isEmpty) {
vehicleAdCreatedDateSearchHistory.add(value);
} else {
vehicleAdCreatedDateSearchHistory.first = value;
}
notifyListeners();
}
// Ad Condition
// Ad Condition
List<DropValue> vehicleAdConditionSearchHistory = [];
void removeVehicleAdConditionSearchHistory({bool isClear = false, required int index}) {
@ -2028,13 +2041,13 @@ class AdVM extends BaseVM {
final chatVM = context.read<ChatVM>();
await chatVM
.getUsersChatMessagesForAd(
context: context,
isForBuyer: true,
adsChatBuyerId: 1,
adID: adDetailsModel.id,
userID: myUserID,
senderName: adDetailsModel.adOwnerName,
)
context: context,
isForBuyer: true,
adsChatBuyerId: 1,
adID: adDetailsModel.id,
userID: myUserID,
senderName: adDetailsModel.adOwnerName,
)
.whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments));
}
}

@ -76,6 +76,26 @@ class ChatVM extends BaseVM {
}
}
List<OfferRequestCommentModel> dealOptionsModelList = [
OfferRequestCommentModel(
index: 0,
isSelected: false,
title: LocaleKeys.dealCompleted.tr(),
),
OfferRequestCommentModel(
index: 1,
isSelected: false,
title: LocaleKeys.theDealNotCompleted.tr(),
),
];
updateIsSelectedInDealOptionsModelList(int index, bool value) {
for (var element in dealOptionsModelList) {
element.isSelected = false;
}
dealOptionsModelList[index].isSelected = true;
}
List<int> indexesForCancelSpecialCarOffer = [0, 1, 6, 7];
List<int> indexesForCancelSparePartOffer = [2, 7];
List<int> indexesForRejectOffer = [3, 4, 5, 7];

@ -215,6 +215,11 @@ class RequestsVM extends BaseVM {
List<ImageModel> pickedVehicleImages = [];
String vehicleImageError = "";
void addImageToPickedVehicleImages(ImageModel imageModel) {
pickedVehicleImages.add(imageModel);
notifyListeners();
}
void removeImageFromList(String filePath) {
int index = pickedVehicleImages.indexWhere((element) => element.filePath == filePath);
if (index == -1) {
@ -707,10 +712,17 @@ class RequestsVM extends BaseVM {
brandForSearch = v;
}
Future<RequestPostingImages> convertFileToRequestPostingImages({required File file}) async {
List<int> imageBytes = await file.readAsBytes();
String image = base64Encode(imageBytes);
RequestPostingImages vehiclePostingImages = RequestPostingImages(requestImage: image);
Future<RequestPostingImages> convertFileToRequestPostingImages({required ImageModel imageModel}) async {
RequestPostingImages vehiclePostingImages;
log("imageModelxx: ${imageModel.isFromNetwork}");
if (imageModel.isFromNetwork == true) {
vehiclePostingImages = RequestPostingImages(id: imageModel.id, requestImage: imageModel.filePath);
} else {
File file = File(imageModel.filePath!);
List<int> imageBytes = await file.readAsBytes();
String image = base64Encode(imageBytes);
vehiclePostingImages = RequestPostingImages(requestImage: image);
}
return vehiclePostingImages;
}
@ -718,7 +730,7 @@ class RequestsVM extends BaseVM {
List<RequestPostingImages> requestImages = [];
for (var image in pickedVehicleImages) {
var value = await convertFileToRequestPostingImages(file: File(image.filePath!));
var value = await convertFileToRequestPostingImages(imageModel: image);
requestImages.add(value);
}
@ -735,37 +747,37 @@ class RequestsVM extends BaseVM {
requestImages.add(element.toJson());
});
try {
GenericRespModel respModel = await requestRepo.createRequest(
requestTypeId: requestTypeId.selectedId,
vehicleTypeId: vehicleTypeId.selectedId,
brand: brand,
model: model,
year: vehicleYearId.selectedOption,
isNew: vehicleConditionId.selectedId == 1,
// 1 for new, 2 for Used
countryID: vehicleCountryId.selectedId,
cityID: vehicleCityId.selectedId,
price: price.isEmpty ? "1.0" : price,
description: description,
address: address,
isSpecialServiceNeeded: false,
requestImages: requestImages,
);
Utils.hideLoading(context);
if (respModel.messageStatus == 1) {
Utils.showToast(LocaleKeys.requestSuccessfullyCreated.tr());
Navigator.pop(context);
resetRequestCreationForm();
await applyFilterOnRequestsVM(requestsTypeEnum: requestTypeId.selectedId == 1 ? RequestsTypeEnum.specialCarRequest : RequestsTypeEnum.serviceRequest);
} else {
Utils.showToast(respModel.message.toString());
}
} catch (e, s) {
Utils.hideLoading(context);
log(e.toString());
Utils.showToast(e.toString());
// try {
GenericRespModel respModel = await requestRepo.createRequest(
requestTypeId: requestTypeId.selectedId,
vehicleTypeId: vehicleTypeId.selectedId,
brand: brand,
model: model,
year: vehicleYearId.selectedOption,
isNew: vehicleConditionId.selectedId == 1,
// 1 for new, 2 for Used
countryID: vehicleCountryId.selectedId,
cityID: vehicleCityId.selectedId,
price: price.isEmpty ? "1.0" : price,
description: description,
address: address,
isSpecialServiceNeeded: false,
requestImages: requestImages,
);
Utils.hideLoading(context);
if (respModel.messageStatus == 1) {
Utils.showToast(LocaleKeys.requestSuccessfullyCreated.tr());
Navigator.pop(context);
await applyFilterOnRequestsVM(requestsTypeEnum: requestTypeId.selectedId.toRequestTypeEnum());
resetRequestCreationForm();
} else {
Utils.showToast(respModel.message.toString());
}
// } catch (e, s) {
// Utils.hideLoading(context);
// log(e.toString());
// Utils.showToast(e.toString());
// }
}
}
@ -931,17 +943,36 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
MessageImageModel convertFileToMessageImageModel({required File file, required int latestOfferId}) {
List<int> imageBytes = file.readAsBytesSync();
String image = base64Encode(imageBytes);
MessageImageModel vehiclePostingImages = MessageImageModel(imageStr: image, id: 0, isFromNetwork: false, reqOfferID: latestOfferId, imagePath: file.path);
return vehiclePostingImages;
MessageImageModel convertFileToMessageImageModel({required ImageModel imageModel, required int offerId}) {
MessageImageModel offerImages;
if (imageModel.isFromNetwork ?? false) {
offerImages = MessageImageModel(
id: imageModel.id,
imageStr: imageModel.filePath,
isFromNetwork: true,
reqOfferID: offerId,
);
} else {
File file = File(imageModel.filePath!);
List<int> imageBytes = file.readAsBytesSync();
String image = base64Encode(imageBytes);
offerImages = MessageImageModel(
id: 0,
imageStr: image,
isFromNetwork: false,
reqOfferID: offerId,
imagePath: file.path,
);
}
return offerImages;
}
List<MessageImageModel> getMessagesImageList({required int latestOfferId}) {
List<MessageImageModel> getMessagesImageList({required int offerId}) {
List<MessageImageModel> requestImages = [];
for (var image in pickedVehicleImages) {
var value = convertFileToMessageImageModel(file: File(image.filePath!), latestOfferId: latestOfferId);
var value = convertFileToMessageImageModel(imageModel: image, offerId: offerId);
requestImages.add(value);
}
return requestImages;
@ -954,6 +985,65 @@ class RequestsVM extends BaseVM {
notifyListeners();
}
Future<void> updateOfferFromProvider({
required String message,
required int requestId,
required int offerId,
required String offerPrice,
required bool isDeliveryAvailable,
required String serviceItemName,
required int manufacturedById,
required String manufacturedOn,
required int receiverId,
required int customerRequestIndex,
required BuildContext context,
}) async {
try {
if (isSendOfferValidated()) {
Utils.showLoading(context);
List<MessageImageModel> images = getMessagesImageList(offerId: offerId);
List offerImages = [];
images.forEach((element) {
offerImages.add(element.toJson());
});
GenericRespModel genericRespModel = await requestRepo.updateRequestOfferFromProvider(
message: message,
requestId: requestId,
offerId: offerId,
offerPrice: offerPrice,
isDeliveryAvailable: isDeliveryAvailable,
serviceItemName: serviceItemName,
manufacturedById: manufacturedById,
manufacturedOn: manufacturedOn,
requestImages: offerImages,
requestOfferStatusEnum: RequestOfferStatusEnum.offer,
);
Utils.hideLoading(context);
if (genericRespModel.messageStatus == 1) {
Utils.showToast(genericRespModel.message ?? "");
final chatVM = context.read<ChatVM>();
await chatVM.getRequestsChatMessagesForProvider(
context: context,
customerId: receiverId,
requestOfferId: offerId,
requestId: requestId,
customerRequestIndex: customerRequestIndex,
);
resetSendOfferBottomSheet();
pop(context);
}
}
} catch (e, s) {
Utils.hideLoading(context);
log(e.toString());
Utils.showToast(e.toString());
}
}
Future<void> onSendOfferPressed({
required BuildContext context,
required String receiverId,
@ -967,10 +1057,11 @@ class RequestsVM extends BaseVM {
required bool isDeliveryAvailable,
required int requestIndex,
required bool isFromChatScreen,
required int? offerId,
}) async {
if (isSendOfferValidated()) {
final chatVM = context.read<ChatVM>();
List<MessageImageModel> images = getMessagesImageList(latestOfferId: context.read<ChatVM>().latestOfferId);
List<MessageImageModel> images = getMessagesImageList(offerId: context.read<ChatVM>().latestOfferId);
List offerImages = [];
images.forEach((element) {
offerImages.add(element.toJson());

@ -117,19 +117,21 @@ class _AdsFilterViewState extends State<AdsFilterView> {
const Divider(thickness: 1.2).paddingOnly(top: 7, bottom: 7),
SearchEntityWidget(
title: LocaleKeys.searchByVehicleYear.tr(),
actionWidget: Builder(builder: (context) {
List<DropValue> vehicleBrandsDrop = [];
for (var element in adVM.vehicleModelYears) {
vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.modelYear ?? "", ""));
}
return DropdownField(
(DropValue value) => adVM.updateSelectionVehicleModelYearId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: vehicleBrandsDrop,
dropdownValue: adVM.vehicleModelYearId.selectedId != -1 ? DropValue(adVM.vehicleModelYearId.selectedId, adVM.vehicleModelYearId.selectedOption, "") : null,
hint: LocaleKeys.selectYear.tr(),
errorValue: adVM.vehicleModelYearId.errorValue,
);
}),
actionWidget: Builder(
builder: (context) {
List<DropValue> vehicleBrandsDrop = [];
for (var element in adVM.vehicleModelYears) {
vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.modelYear ?? "", ""));
}
return DropdownField(
(DropValue value) => adVM.updateSelectionVehicleModelYearId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true),
list: vehicleBrandsDrop,
dropdownValue: adVM.vehicleModelYearId.selectedId != -1 ? DropValue(adVM.vehicleModelYearId.selectedId, adVM.vehicleModelYearId.selectedOption, "") : null,
hint: LocaleKeys.selectYear.tr(),
errorValue: adVM.vehicleModelYearId.errorValue,
);
},
),
historyContent: adVM.vehicleYearAdSearchHistory,
onHistoryItemDeleted: (index) => adVM.removeVehicleYearAdSearchHistory(index: index),
onHistoryItemTapped: (DropValue value) => null,
@ -167,7 +169,10 @@ class _AdsFilterViewState extends State<AdsFilterView> {
isNeedClickAll: true,
postFixDataColor: MyColors.darkTextColor,
onTap: () async {
final formattedDate = await Utils.pickDateFromDatePicker(context);
final formattedDate = await Utils.pickDateFromDatePicker(context, firstDate: DateTime(2020), lastDate: DateTime.now());
if (formattedDate.isEmpty) {
return;
}
adVM.updateSelectionDurationStartDate(formattedDate);
DropValue value = DropValue(0, formattedDate, "");
adVM.addToVehicleAdCreatedDateSearchHistory(value: value);

@ -165,6 +165,7 @@ class _ChatViewState extends State<ChatView> {
ChatMessageModel chatMessageModel = chatMessages[index];
return ChatMessageCustomWidget(
chatMessageModel: chatMessageModel,
requestModel: chatViewArgumentsForRequest!.requestModel!,
requestStatusEnum: requestVM.currentSelectedRequest?.requestStatus,
chatTypeEnum: chatTypeEnum,
requestsTypeEnum: chatTypeEnum == ChatTypeEnum.requestOffer ? chatViewArgumentsForRequest!.requestModel!.requestType.toRequestTypeEnum() : RequestsTypeEnum.specialCarRequest,
@ -218,7 +219,10 @@ class _ChatViewState extends State<ChatView> {
),
),
] else ...[
if (AppState().currentAppType == AppType.provider && chatTypeEnum == ChatTypeEnum.requestOffer && requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted && chatVM.pickedImagesForMessage.isEmpty) ...[
if (AppState().currentAppType == AppType.provider &&
chatTypeEnum == ChatTypeEnum.requestOffer &&
requestVM.currentSelectedRequest!.requestStatus == RequestStatusEnum.submitted &&
chatVM.pickedImagesForMessage.isEmpty) ...[
Expanded(
flex: 1,
child: const Icon(
@ -227,8 +231,16 @@ class _ChatViewState extends State<ChatView> {
size: 30,
).onPress(
() {
RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(requestIndex: chatViewArgumentsForRequest!.requestIndex, requestModel: chatViewArgumentsForRequest!.requestModel!);
buildSendOfferBottomSheet(context: context, requestDetailPageArguments: requestDetailArguments, isFromChatScreen: true);
RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(
requestIndex: chatViewArgumentsForRequest!.requestIndex,
requestModel: chatViewArgumentsForRequest!.requestModel!,
);
buildSendOfferBottomSheet(
context: context,
requestDetailPageArguments: requestDetailArguments,
isFromChatScreen: true,
offerId: null, // null means creating new offer
);
},
),
),

@ -9,13 +9,16 @@ 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/chat_models/chat_message_model.dart';
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/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/requests/request_bottomsheets.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/info_bottom_sheet.dart';
@ -29,14 +32,130 @@ class ChatMessageCustomWidget extends StatefulWidget {
final RequestStatusEnum? requestStatusEnum;
final ChatTypeEnum chatTypeEnum;
final RequestsTypeEnum requestsTypeEnum;
final RequestModel requestModel;
const ChatMessageCustomWidget({super.key, required this.chatMessageModel, required this.requestStatusEnum, required this.chatTypeEnum, this.requestsTypeEnum = RequestsTypeEnum.specialCarRequest});
const ChatMessageCustomWidget({
super.key,
required this.chatMessageModel,
required this.requestStatusEnum,
required this.chatTypeEnum,
required this.requestModel,
this.requestsTypeEnum = RequestsTypeEnum.specialCarRequest,
});
@override
State<ChatMessageCustomWidget> createState() => _ChatMessageCustomWidgetState();
}
class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
Future buildDealBottomSheetForSpecialCar({required ChatMessageModel chatMessageModel, required RequestOfferStatusEnum requestOfferStatusEnum}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return Consumer(builder: (BuildContext context, ChatVM chatVM, Widget? child) {
return InfoBottomSheet(
title: LocaleKeys.pleaseSpecify.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
12.height,
ListView(
children: [
CheckBoxWithTitleDescription(
isSelected: chatVM.dealOptionsModelList[0].isSelected!,
title: '${chatVM.dealOptionsModelList[0].title}',
description: '',
onSelection: (bool value) {
chatVM.updateIsSelectedInDealOptionsModelList(0, value);
},
),
CheckBoxWithTitleDescription(
isSelected: chatVM.dealOptionsModelList[1].isSelected ?? false,
title: '${chatVM.dealOptionsModelList[1].title}',
description: '',
onSelection: (bool value) {
chatVM.updateIsSelectedInDealOptionsModelList(1, value);
},
),
],
),
if (chatVM.dealOptionsModelList[1].isSelected!) ...[
12.height,
TxtField(
maxLines: 5,
value: chatVM.rejectOfferDescription,
errorValue: chatVM.rejectOfferDescriptionError,
keyboardType: TextInputType.text,
hint: LocaleKeys.description.tr(),
onChanged: (v) => chatVM.updateRejectOfferDescription(v),
),
],
],
),
25.height,
ShowFillButton(
title: LocaleKeys.submit.tr(),
onPressed: () async {
String comments = "";
if (chatVM.selectedOfferRequestCommentModel.index == chatVM.offerRejectModelList.length - 1) //Other
{
comments = chatVM.rejectOfferDescription;
} else {
comments = chatVM.selectedOfferRequestCommentModel.title ?? "";
}
if (!chatVM.isRejectOfferButtonValidated()) {
return;
}
Navigator.pop(context);
bool status = await chatVM.onSendMessageForActionOnRequestOffer(
receiverId: (chatMessageModel.isMyMessage ?? false) ? chatMessageModel.receiverUserID ?? "" : chatMessageModel.senderUserID ?? "",
chatMessageType: ChatMessageTypeEnum.offer,
comments: comments,
requestId: chatMessageModel.reqOffer!.requestID ?? -1,
serviceProviderID: chatMessageModel.serviceProviderID ?? 0,
requestOfferID: chatMessageModel.reqOffer!.id ?? -1,
offerPrice: chatMessageModel.reqOffer!.price.toString(),
serviceItemName: chatMessageModel.reqOffer!.serviceItemName ?? "",
manufacturedOn: chatMessageModel.reqOffer!.manufacturedOn ?? "",
manufacturedById: chatMessageModel.reqOffer!.manufacturedById ?? 0,
requestOfferStatusEnum: requestOfferStatusEnum,
context: context,
);
if (status) {
final requestVM = context.read<RequestsVM>();
chatMessageModel.reqOffer!.requestOfferStatusEnum = requestOfferStatusEnum;
int index = chatVM.serviceProviderOffersList
.indexWhere((element) => (element.providerId == requestVM.currentSelectedOffer!.providerId) && (element.requestId == requestVM.currentSelectedOffer!.requestId));
if (index != -1) {
chatVM.serviceProviderOffersList[index].requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum;
}
setState(() {});
// Navigator.pop(context);
chatVM.updateRejectOfferDescription('');
Utils.showToast("Offer ${requestOfferStatusEnum == RequestOfferStatusEnum.rejected ? "Rejected" : "Cancelled"}");
// navigateReplaceWithName(context, AppRoutes.dashboard);
}
},
maxWidth: double.infinity,
),
19.height,
],
),
));
});
},
);
}
Future buildRejectOrCancelOfferBottomSheet({required ChatMessageModel chatMessageModel, required RequestOfferStatusEnum requestOfferStatusEnum}) {
return showModalBottomSheet(
context: context,
@ -149,7 +268,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
if (status) {
final requestVM = context.read<RequestsVM>();
chatMessageModel.reqOffer!.requestOfferStatusEnum = requestOfferStatusEnum;
int index = chatVM.serviceProviderOffersList.indexWhere((element) => (element.providerId == requestVM.currentSelectedOffer!.providerId) && (element.requestId == requestVM.currentSelectedOffer!.requestId));
int index = chatVM.serviceProviderOffersList
.indexWhere((element) => (element.providerId == requestVM.currentSelectedOffer!.providerId) && (element.requestId == requestVM.currentSelectedOffer!.requestId));
if (index != -1) {
chatVM.serviceProviderOffersList[index].requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum;
@ -207,7 +327,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
requestVM.currentSelectedRequest!.requestStatus = RequestStatusEnum.inProgress;
requestVM.updateAcceptedReqOffer(chatMessageModel.reqOffer!);
requestVM.updateAcceptedRequestOfferProviderName(chatMessageModel.senderName ?? "");
int index = chatVM.serviceProviderOffersList.indexWhere((element) => (element.providerId == requestVM.currentSelectedOffer!.providerId) && (element.requestId == requestVM.currentSelectedOffer!.requestId));
int index = chatVM.serviceProviderOffersList
.indexWhere((element) => (element.providerId == requestVM.currentSelectedOffer!.providerId) && (element.requestId == requestVM.currentSelectedOffer!.requestId));
if (index != -1) {
chatVM.serviceProviderOffersList[index].requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum;
@ -281,7 +402,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
fontSize: 12,
isItalic: true,
),
).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: chatMessageModel.isMyMessage! ? MyColors.adPendingStatusColor.withOpacity(0.16) : MyColors.grey98Color.withOpacity(0.1)),
).toContainer(
borderRadius: 40, width: double.infinity, backgroundColor: chatMessageModel.isMyMessage! ? MyColors.adPendingStatusColor.withOpacity(0.16) : MyColors.grey98Color.withOpacity(0.1)),
],
);
}
@ -294,7 +416,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"${(chatMessageModel.reqOffer!.price ?? 0.0).toInt()}".toText(fontSize: 19, isBold: true, color: AppState().currentAppType == AppType.provider ? MyColors.white : MyColors.darkTextColor),
"${(chatMessageModel.reqOffer!.price ?? 0.0).toInt()}"
.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),
],
@ -468,11 +591,37 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
return widget.toCircle(borderRadius: 100);
}
Future<void> onOfferEditIconPressed() async {
int index = context.read<RequestsVM>().myFilteredRequests.indexWhere((request) => request.id == widget.requestModel.id);
RequestDetailPageArguments requestDetailArguments = RequestDetailPageArguments(
requestIndex: index, // Not getting used in case of update offer
requestModel: widget.requestModel,
);
RequestsVM requestVM = context.read<RequestsVM>();
requestVM.resetSendOfferBottomSheet();
ReqOffer offer = widget.chatMessageModel.reqOffer!;
requestVM.updateOfferPrice((offer.price ?? "").toString());
requestVM.updateServiceItem((offer.serviceItemName ?? "").toString());
requestVM.updateItemManufacturer((offer.manufacturedById ?? "").toString());
requestVM.updateServiceItemCreatedOn((offer.manufacturedOn ?? "").toString());
requestVM.updateOfferDescription((widget.chatMessageModel.chatText ?? "").toString());
requestVM.updateIsDeliveryAvailableStatus((offer.isDeliveryAvailable ?? false));
if (offer.reqOfferImages != null && offer.reqOfferImages!.isNotEmpty) {
for (var element in offer.reqOfferImages!) {
if (element.imageUrl != null) {
ImageModel imageModel = ImageModel(id: element.id, filePath: element.imageUrl, isFromNetwork: true);
requestVM.addImageToPickedVehicleImages(imageModel);
}
}
}
buildSendOfferBottomSheet(context: context, requestDetailPageArguments: requestDetailArguments, isFromChatScreen: true, offerId: offer.id);
}
Widget buildFreeTextDetailsInMessage({required ChatMessageTypeEnum chatMessageTypeEnum}) {
return Row(
// crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (chatMessageTypeEnum == ChatMessageTypeEnum.offer && (widget.chatMessageModel.isMyMessage == true) && widget.chatMessageModel.isRead == true) ...[
if (chatMessageTypeEnum == ChatMessageTypeEnum.offer && (widget.chatMessageModel.isMyMessage == true) && (widget.chatMessageModel.isRead ?? false)) ...[
Row(
children: [
const Icon(Icons.remove_red_eye_outlined, size: 12, color: MyColors.lightTextColor),
@ -480,6 +629,8 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
LocaleKeys.viewed.tr().toText(fontSize: 10, color: MyColors.lightTextColor, fontWeight: MyFonts.Medium),
],
),
] else if (AppState().currentAppType == AppType.provider && chatMessageTypeEnum == ChatMessageTypeEnum.offer && (widget.chatMessageModel.isMyMessage == true)) ...[
MyAssets.icEdit.buildSvg(color: MyColors.white, height: 15).onPress(() => onOfferEditIconPressed()),
],
Expanded(
child: Directionality(
@ -487,7 +638,6 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
child: (widget.chatMessageModel.chatText ?? "").toText(
color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor,
fontSize: 12,
// isBold: true,
),
),
),
@ -518,12 +668,12 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
});
}
return SizedBox(
// height: (gridItemSize * 2) + (spacing * 2), // Fixed height for 2 rows including spacing
// height: (gridItemSize * 2) + (spacing * 2), // Fixed height for 2 rows including spacing
child: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
// Prevent scrolling inside grid
// Prevent scrolling inside grid
shrinkWrap: true,
// Shrink size to fit the content
// Shrink size to fit the content
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // Show 2 images per row
crossAxisSpacing: spacing,

@ -21,8 +21,14 @@ import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
Future buildSendOfferBottomSheet({required BuildContext context, required RequestDetailPageArguments requestDetailPageArguments, required bool isFromChatScreen}) {
Future buildSendOfferBottomSheet({
required BuildContext context,
required RequestDetailPageArguments requestDetailPageArguments,
required bool isFromChatScreen,
required int? offerId,
}) {
final requestDetail = requestDetailPageArguments.requestModel;
final requestIndex = requestDetailPageArguments.requestIndex;
return showModalBottomSheet(
context: context,
isScrollControlled: true,
@ -134,24 +140,42 @@ Future buildSendOfferBottomSheet({required BuildContext context, required Reques
),
25.height,
ShowFillButton(
title: LocaleKeys.submit.tr(),
title: offerId == null ? LocaleKeys.submit.tr() : LocaleKeys.update.tr(),
maxHeight: 55,
onPressed: () {
requestsVM.onSendOfferPressed(
context: context,
receiverId: requestDetail.customerID,
message: requestsVM.offerDescription,
requestId: requestDetail.id,
offerPrice: requestsVM.offerPrice,
requestModel: requestDetail,
isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus,
requestIndex: requestDetailPageArguments.requestIndex,
isFromChatScreen: isFromChatScreen,
manufacturedById: 1,
// Todo: It should be the ID of the manufacturer
manufacturedOn: requestsVM.serviceItemCreatedOn,
serviceItemName: requestsVM.serviceItem,
);
if (offerId == null) {
requestsVM.onSendOfferPressed(
context: context,
offerId: offerId,
receiverId: requestDetail.customerID,
message: requestsVM.offerDescription,
requestId: requestDetail.id,
offerPrice: requestsVM.offerPrice,
requestModel: requestDetail,
isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus,
requestIndex: requestDetailPageArguments.requestIndex,
isFromChatScreen: isFromChatScreen,
manufacturedById: 1,
// Todo: It should be the ID of the manufacturer
manufacturedOn: requestsVM.serviceItemCreatedOn,
serviceItemName: requestsVM.serviceItem,
);
} else {
requestsVM.updateOfferFromProvider(
message: requestsVM.offerDescription,
requestId: requestDetail.id,
offerId: offerId,
offerPrice: requestsVM.offerPrice,
isDeliveryAvailable: requestsVM.isDeliveryAvailableStatus,
serviceItemName: requestsVM.serviceItem,
manufacturedById: 1,
// Todo: It should be the ID of the manufacturer
manufacturedOn: requestsVM.serviceItemCreatedOn,
receiverId: requestDetail.customerId,
customerRequestIndex: requestIndex,
context: context,
);
}
},
maxWidth: double.infinity,
),
@ -164,6 +188,8 @@ Future buildSendOfferBottomSheet({required BuildContext context, required Reques
);
}
Future buildRequestStatusUpdateSheetForProvider({required BuildContext mainContext, required int requestId}) {
return showModalBottomSheet(
context: mainContext,

@ -159,7 +159,12 @@ class RequestDetailPage extends StatelessWidget {
title: LocaleKeys.provideOffer.tr(),
isBold: false,
fontSize: 18,
onPressed: () => buildSendOfferBottomSheet(context: context, requestDetailPageArguments: requestDetailPageArguments, isFromChatScreen: false),
onPressed: () => buildSendOfferBottomSheet(
context: context,
requestDetailPageArguments: requestDetailPageArguments,
isFromChatScreen: false,
offerId: null, // null means creating new offer
),
),
] else ...[
buildRequestDetailActionFooter(

Loading…
Cancel
Save