You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
461 lines
16 KiB
Dart
461 lines
16 KiB
Dart
// ignore_for_file: use_build_context_synchronously, avoid_function_literals_in_foreach_calls
|
|
|
|
import 'dart:convert';
|
|
import 'dart:developer';
|
|
import 'dart:io';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:mc_common_app/classes/app_state.dart';
|
|
import 'package:mc_common_app/classes/consts.dart';
|
|
import 'package:mc_common_app/config/routes.dart';
|
|
import 'package:mc_common_app/extensions/string_extensions.dart';
|
|
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.dart';
|
|
import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
|
|
import 'package:mc_common_app/models/general_models/enums_model.dart';
|
|
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
|
|
import 'package:mc_common_app/models/requests_models/offers_model.dart';
|
|
import 'package:mc_common_app/models/requests_models/request_model.dart';
|
|
import 'package:mc_common_app/models/general_models/widgets_models.dart';
|
|
import 'package:mc_common_app/repositories/common_repo.dart';
|
|
import 'package:mc_common_app/repositories/request_repo.dart';
|
|
import 'package:mc_common_app/services/common_services.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/base_view_model.dart';
|
|
import 'package:mc_common_app/view_models/chat_view_model.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
class RequestsVM extends BaseVM {
|
|
final CommonAppServices commonServices;
|
|
final CommonRepo commonRepo;
|
|
final RequestRepo requestRepo;
|
|
|
|
RequestsVM({required this.commonServices, required this.commonRepo, required this.requestRepo});
|
|
|
|
List<RequestModel> myRequests = [];
|
|
List<RequestModel> myFilteredRequests = [];
|
|
|
|
List<FilterListModel> requestsTypeFilterOptions = [];
|
|
|
|
List<EnumsModel> myRequestsTypeEnum = [];
|
|
|
|
populateRequestsFilterList() async {
|
|
if (requestsTypeFilterOptions.isNotEmpty) return;
|
|
|
|
if (myRequestsTypeEnum.isEmpty) {
|
|
myRequestsTypeEnum = await commonRepo.getEnumTypeValues(enumTypeID: 16); //TODO: 16 is to get Requests Filter Enums
|
|
}
|
|
for (int i = 0; i < myRequestsTypeEnum.length; i++) {
|
|
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 {
|
|
if (isNeedToRebuild) setState(ViewState.busy);
|
|
|
|
var paramsForGetRequests = <String, dynamic>{};
|
|
|
|
paramsForGetRequests = {
|
|
"pageSize": 100,
|
|
"pageIndex": 0,
|
|
"requestType": 0,
|
|
};
|
|
if (appType == AppType.provider) {
|
|
paramsForGetRequests.addEntries([MapEntry("providerID", AppState().getUser.data!.userInfo!.providerId)]);
|
|
} else {
|
|
paramsForGetRequests.addEntries([MapEntry("customerID", AppState().getUser.data!.userInfo!.customerId)]);
|
|
}
|
|
myRequests = await requestRepo.getRequests(paramsForGetRequests);
|
|
applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest);
|
|
setState(ViewState.idle);
|
|
notifyListeners();
|
|
}
|
|
|
|
addChatMessagesInRequestsModel({required ChatMessageModel msg, required int index}) {
|
|
myFilteredRequests[index].chatMessages.add(msg);
|
|
notifyListeners();
|
|
}
|
|
|
|
overwriteChatMessagesInRequestsModel({required List<ChatMessageModel> messages, required int index}) {
|
|
myFilteredRequests[index].chatMessages.clear();
|
|
myFilteredRequests[index].chatMessages = messages;
|
|
notifyListeners();
|
|
}
|
|
|
|
applyFilterOnRequestsVM({required RequestsTypeEnum requestsTypeEnum}) {
|
|
if (requestsTypeFilterOptions.isEmpty) return;
|
|
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();
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
List<File> pickedVehicleImages = [];
|
|
String vehicleImageError = "";
|
|
|
|
void removeImageFromList(String filePath) {
|
|
int index = pickedVehicleImages.indexWhere((element) => element.path == filePath);
|
|
if (index == -1) {
|
|
return;
|
|
}
|
|
pickedVehicleImages.removeAt(index);
|
|
notifyListeners();
|
|
}
|
|
|
|
void pickMultipleImages() async {
|
|
List<File> images = await commonServices.pickMultipleImages();
|
|
pickedVehicleImages.addAll(images);
|
|
if (pickedVehicleImages.isNotEmpty) vehicleImageError = "";
|
|
notifyListeners();
|
|
}
|
|
|
|
bool isFetchingRequestType = false;
|
|
bool isFetchingVehicleType = true;
|
|
bool isFetchingVehicleDetail = false;
|
|
List<VehicleTypeModel> vehicleTypes = [];
|
|
VehicleDetailsModel? vehicleDetails;
|
|
List<VehicleBrandsModel> vehicleBrands = [];
|
|
List<VehicleModel> vehicleModels = [];
|
|
List<VehicleYearModel> vehicleModelYears = [];
|
|
List<VehicleCountryModel> vehicleCountries = [];
|
|
List<VehicleCityModel> vehicleCities = [];
|
|
|
|
SelectionModel requestTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateSelectionRequestTypeId(SelectionModel id) async {
|
|
requestTypeId = id;
|
|
getVehicleTypes();
|
|
notifyListeners();
|
|
}
|
|
|
|
SelectionModel vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
Future<void> getVehicleTypes() async {
|
|
resetRequestCreationForm();
|
|
isFetchingVehicleType = true;
|
|
vehicleTypes = await commonRepo.getVehicleTypes();
|
|
isFetchingVehicleType = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
resetRequestCreationForm() {
|
|
vehicleTypeId.selectedId = -1;
|
|
vehicleBrandId.selectedId = -1;
|
|
vehicleModelId.selectedId = -1;
|
|
vehicleModelYearId.selectedId = -1;
|
|
vehicleCountryId.selectedId = -1;
|
|
vehicleCityId.selectedId = -1;
|
|
}
|
|
|
|
void updateSelectionVehicleTypeId(SelectionModel id) async {
|
|
vehicleTypeId = id;
|
|
getVehicleBrandsByVehicleTypeId();
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> getVehicleBrandsByVehicleTypeId() async {
|
|
// if (vehicleBrandId.selectedId == -1) {
|
|
// return;
|
|
// }
|
|
isFetchingVehicleDetail = true;
|
|
notifyListeners();
|
|
vehicleDetails = await commonRepo.getVehicleDetails(vehicleTypeId: vehicleTypeId.selectedId);
|
|
|
|
if (vehicleDetails != null) {
|
|
vehicleBrands = vehicleDetails!.vehicleBrands!;
|
|
vehicleModels = vehicleDetails!.vehicleModels!;
|
|
vehicleModelYears = vehicleDetails!.vehicleModelYears!;
|
|
vehicleCountries = vehicleDetails!.vehicleCountries!;
|
|
}
|
|
isFetchingVehicleDetail = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
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: "");
|
|
notifyListeners();
|
|
}
|
|
|
|
SelectionModel vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateSelectionVehicleModelId(SelectionModel id) {
|
|
vehicleModelId = id;
|
|
vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
notifyListeners();
|
|
}
|
|
|
|
SelectionModel vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateSelectionVehicleModelYearId(SelectionModel id) {
|
|
vehicleModelYearId = id;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool isShippingDeliveryEnabled = false;
|
|
|
|
void updateShippingDeliverEnabled(bool v) {
|
|
isShippingDeliveryEnabled = v;
|
|
notifyListeners();
|
|
}
|
|
|
|
bool isCountryFetching = false;
|
|
SelectionModel vehicleCountryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateSelectionVehicleCountryId(SelectionModel id) async {
|
|
vehicleCountryId = id;
|
|
isCountryFetching = true;
|
|
notifyListeners();
|
|
vehicleCities = await commonRepo.getVehicleCities(countryId: vehicleCountryId.selectedId);
|
|
isCountryFetching = false;
|
|
notifyListeners();
|
|
}
|
|
|
|
SelectionModel vehicleCityId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
|
|
|
|
void updateSelectionVehicleCityId(SelectionModel id) {
|
|
vehicleCityId = id;
|
|
notifyListeners();
|
|
}
|
|
|
|
//Request Management
|
|
String price = "", description = "";
|
|
|
|
updatePrice(String v) {
|
|
price = v;
|
|
}
|
|
|
|
updateDescription(String v) {
|
|
description = v;
|
|
}
|
|
|
|
Future<VehiclePostingImages> convertFileToRequestPostingImages({required File file}) async {
|
|
List<int> imageBytes = await file.readAsBytes();
|
|
String image = base64Encode(imageBytes);
|
|
String fileName = file.path.split('/').last;
|
|
VehiclePostingImages vehiclePostingImages = VehiclePostingImages(
|
|
imageName: fileName,
|
|
imageStr: image,
|
|
imageUrl: file.path,
|
|
);
|
|
return vehiclePostingImages;
|
|
}
|
|
|
|
Future<List<VehiclePostingImages>> getVehiclePostingImageList() async {
|
|
List<VehiclePostingImages> vehicleImages = [];
|
|
log("vehicleImages: ${pickedVehicleImages.length}");
|
|
|
|
for (var image in pickedVehicleImages) {
|
|
var value = await convertFileToRequestPostingImages(file: image);
|
|
vehicleImages.add(value);
|
|
}
|
|
|
|
return vehicleImages;
|
|
}
|
|
|
|
Future<void> onCreateRequestTapped(BuildContext context) async {
|
|
if (validateCreateRequestForm()) {
|
|
Utils.showLoading(context);
|
|
|
|
List<VehiclePostingImages> vehicleImages = await getVehiclePostingImageList();
|
|
Map<String, dynamic> body = {
|
|
"customerID": AppState().getUser.data!.userInfo!.customerId ?? 0,
|
|
"requestType": requestTypeId.selectedId,
|
|
"vehicleTypeID": vehicleTypeId.selectedId,
|
|
"brand": vehicleBrandId.selectedOption,
|
|
"model": vehicleModelId.selectedOption,
|
|
"year": vehicleModelYearId.selectedOption,
|
|
"isNew": true,
|
|
"countryID": vehicleCountryId.selectedId,
|
|
"cityID": vehicleCityId.selectedId,
|
|
"price": price,
|
|
"description": description,
|
|
"isSpecialServiceNeeded": false,
|
|
"requestImages": vehicleImages,
|
|
};
|
|
try {
|
|
GenericRespModel respModel = await requestRepo.createRequest(body);
|
|
Utils.hideLoading(context);
|
|
if (respModel.messageStatus == 1) {
|
|
Utils.showToast("Request Successfully Created");
|
|
Navigator.pop(context);
|
|
await getRequests(appType: AppType.customer);
|
|
} else {
|
|
Utils.showToast(respModel.message.toString());
|
|
}
|
|
} catch (e, s) {
|
|
Utils.hideLoading(context);
|
|
log(s.toString());
|
|
}
|
|
}
|
|
}
|
|
|
|
bool validateCreateRequestForm() {
|
|
bool isValid = true;
|
|
if (requestTypeId.selectedId == -1) {
|
|
Utils.showToast("Please select valid Request Type");
|
|
isValid = false;
|
|
} else if (vehicleTypeId.selectedId == -1) {
|
|
Utils.showToast("Please select valid Vehicle Type");
|
|
isValid = false;
|
|
} else if (vehicleBrandId.selectedId == -1) {
|
|
Utils.showToast("Please select valid Brand");
|
|
isValid = false;
|
|
} else if (vehicleModelId.selectedId == -1) {
|
|
Utils.showToast("Please select valid Model");
|
|
isValid = false;
|
|
} else if (vehicleModelYearId.selectedId == -1) {
|
|
Utils.showToast("Please select valid Year");
|
|
isValid = false;
|
|
} else if (vehicleCountryId.selectedId == -1) {
|
|
Utils.showToast("Please select valid Country");
|
|
isValid = false;
|
|
} else if (vehicleCityId.selectedId == -1) {
|
|
Utils.showToast("Please select valid City");
|
|
isValid = false;
|
|
} else if (price.isEmpty) {
|
|
Utils.showToast("Please add valid Price");
|
|
isValid = false;
|
|
} else if (description.isEmpty) {
|
|
Utils.showToast("Please add valid Description");
|
|
isValid = false;
|
|
}
|
|
return isValid;
|
|
}
|
|
|
|
Future<List<OffersModel>> getOffersByRequest({required int requestId, required BuildContext context}) async {
|
|
try {
|
|
Utils.showLoading(context);
|
|
List<OffersModel> respModel = await requestRepo.getOffersByRequest(requestId: requestId);
|
|
Utils.hideLoading(context);
|
|
return respModel;
|
|
} catch (e) {
|
|
Utils.showToast(e.toString());
|
|
Utils.hideLoading(context);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
String offerPriceError = "";
|
|
String offerDescriptionError = "";
|
|
|
|
String offerPrice = "";
|
|
|
|
void updateOfferPrice(String value) {
|
|
offerPrice = value;
|
|
if (value.isNotEmpty) {
|
|
offerPriceError = "";
|
|
}
|
|
}
|
|
|
|
String offerDescription = "";
|
|
|
|
void updateOfferDescription(String value) {
|
|
offerDescription = value;
|
|
if (value.isNotEmpty) {
|
|
offerDescriptionError = "";
|
|
}
|
|
}
|
|
|
|
//SENDING OFFER
|
|
bool isSendOfferValidated() {
|
|
bool isValidated = true;
|
|
if (offerPrice.isEmpty) {
|
|
offerPriceError = GlobalConsts.demandAmountError;
|
|
isValidated = false;
|
|
notifyListeners();
|
|
} else {
|
|
offerPriceError = "";
|
|
}
|
|
|
|
if (offerDescription.isEmpty) {
|
|
offerDescriptionError = GlobalConsts.descriptionError;
|
|
isValidated = false;
|
|
notifyListeners();
|
|
} else {
|
|
offerDescriptionError = "";
|
|
}
|
|
notifyListeners();
|
|
|
|
return isValidated;
|
|
}
|
|
|
|
void resetSendOfferBottomSheet() {
|
|
offerPrice = "";
|
|
offerDescription = "";
|
|
offerDescriptionError = "";
|
|
offerDescription = "";
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> onSendOfferPressed({
|
|
required BuildContext context,
|
|
required String receiverId,
|
|
required String message,
|
|
required int requestId,
|
|
required String offerPrice,
|
|
required RequestModel requestModel,
|
|
required int requestIndex,
|
|
required bool isFromChatScreen,
|
|
}) async {
|
|
if (isSendOfferValidated()) {
|
|
final chatVM = context.read<ChatVM>();
|
|
bool status = await chatVM.onSendMessageForRequestOffer(
|
|
receiverId: receiverId,
|
|
chatMessageType: ChatMessageTypeEnum.offer,
|
|
message: message,
|
|
requestId: requestId,
|
|
offerPrice: offerPrice,
|
|
context: context,
|
|
);
|
|
|
|
if (status) {
|
|
final senderName = AppState().getUser.data!.userInfo!.firstName;
|
|
final senderId = AppState().getUser.data!.userInfo!.userId;
|
|
// resetSendOfferBottomSheet();
|
|
Navigator.pop(context);
|
|
ChatMessageModel chatMessageModel = ChatMessageModel(
|
|
isMyMessage: true,
|
|
chatText: message,
|
|
messageType: ChatMessageTypeEnum.offer.getIdFromChatMessageTypeEnum(),
|
|
senderName: senderName,
|
|
senderUserID: senderId,
|
|
receiverUserID: receiverId,
|
|
chatMessageTypeEnum: ChatMessageTypeEnum.offer,
|
|
requestID: requestModel.id,
|
|
offerStatus: RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
|
|
reqOffer: ReqOffer(
|
|
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);
|
|
if (!isFromChatScreen) {
|
|
ChatViewArguments chatViewArguments = ChatViewArguments(
|
|
chatTypeEnum: ChatTypeEnum.requestOffer,
|
|
requestId: requestModel.id,
|
|
receiverId: requestModel.customerID,
|
|
senderId: senderId ?? "",
|
|
requestIndex: requestIndex,
|
|
providerIndex: -1,
|
|
);
|
|
navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|