// 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/generated/locale_keys.g.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/ad_view_model.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'; import 'package:easy_localization/easy_localization.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 myRequests = []; List myFilteredRequests = []; List requestsTypeFilterOptions = []; List myRequestsTypeEnum = []; RequestModel? currentSelectedRequest; void updateCurrentSelectedRequest(RequestModel value) { currentSelectedRequest = value; } populateRequestsFilterList() async { if (requestsTypeFilterOptions.isNotEmpty) return; if (myRequestsTypeEnum.isEmpty) { 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)); } notifyListeners(); } Future getRequests({bool isNeedToRebuild = false, required AppType appType}) async { if (isNeedToRebuild) setState(ViewState.busy); int providerOrCustomerID = 0; if (appType == AppType.provider) { providerOrCustomerID = AppState().getUser.data!.userInfo!.providerId ?? 0; } else { providerOrCustomerID = AppState().getUser.data!.userInfo!.customerId ?? 0; } myRequests = await requestRepo.getRequests(providerOrCustomerID: providerOrCustomerID); applyFilterOnRequestsVM(requestsTypeEnum: RequestsTypeEnum.specialCarRequest); setState(ViewState.idle); notifyListeners(); } Future> getServiceRequestsForProviders() async { setState(ViewState.busy); List serviceRequestsForProviders = await requestRepo.getServiceRequestsForProviders(serviceProviderID: AppState().getUser.data!.userInfo!.providerId); setState(ViewState.idle); return serviceRequestsForProviders; } addChatMessagesInRequestsModel({required ChatMessageModel msg, required int index}) { myFilteredRequests[index].chatMessages.add(msg); notifyListeners(); } overwriteChatMessagesInRequestsModel({required List messages, required int index, required BuildContext context}) { myFilteredRequests[index].chatMessages.clear(); myFilteredRequests[index].chatMessages = messages; if (myFilteredRequests[index].chatMessages.isNotEmpty) { for (var message in myFilteredRequests[index].chatMessages) { if (message.chatMessageTypeEnum == ChatMessageTypeEnum.offer) { context.read().updateLatestOfferId(message.reqOfferID ?? 0); } } } notifyListeners(); } applyFilterOnRequestsVM({required RequestsTypeEnum requestsTypeEnum}) async { if (requestsTypeFilterOptions.isEmpty) return; for (var value in requestsTypeFilterOptions) { value.isSelected = false; } requestsTypeFilterOptions[requestsTypeEnum.getIdFromRequestTypeStatusEnum() - 1].isSelected = true; // -1 to match with the index if (AppState().currentAppType == AppType.provider && requestsTypeEnum == RequestsTypeEnum.serviceRequest) { myFilteredRequests = await getServiceRequestsForProviders(); return; } myFilteredRequests = myRequests.where((element) => element.requestType == requestsTypeEnum.getIdFromRequestTypeStatusEnum()).toList(); notifyListeners(); } List pickedVehicleImages = []; String vehicleImageError = ""; void removeImageFromList(String filePath) { int index = pickedVehicleImages.indexWhere((element) => element.filePath == filePath); if (index == -1) { return; } pickedVehicleImages.removeAt(index); notifyListeners(); } void pickMultipleImages() async { List imageModels = []; List images = await commonServices.pickMultipleImages(); for (var element in images) { imageModels.add(ImageModel(filePath: element.path, isFromNetwork: false)); } pickedVehicleImages.addAll(imageModels); if (pickedVehicleImages.isNotEmpty) vehicleImageError = ""; notifyListeners(); } bool isFetchingRequestType = false; bool isFetchingVehicleType = true; bool isFetchingVehicleDetail = false; List vehicleTypes = []; VehicleDetailsModel? vehicleDetails; List vehicleBrands = []; List vehicleModels = []; List vehicleModelYears = []; List vehicleCountries = []; List 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 getVehicleTypes() async { isFetchingVehicleType = true; vehicleTypes = await commonRepo.getVehicleTypes(); isFetchingVehicleType = false; notifyListeners(); } resetRequestCreationForm() { requestTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleCountryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); vehicleCityId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: ""); pickedVehicleImages.clear(); price = ''; description = ''; } void updateSelectionVehicleTypeId(SelectionModel id) async { vehicleTypeId = id; getVehicleBrandsByVehicleTypeId(); notifyListeners(); } Future 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 = ""; String description = ""; updatePrice(String v) { price = v; } updateDescription(String v) { description = v; } Future convertFileToRequestPostingImages({required File file}) async { List imageBytes = await file.readAsBytes(); String image = base64Encode(imageBytes); RequestPostingImages vehiclePostingImages = RequestPostingImages(requestImage: image); return vehiclePostingImages; } Future> getVehiclePostingImageList() async { List requestImages = []; log("requestImages: ${pickedVehicleImages.length}"); for (var image in pickedVehicleImages) { var value = await convertFileToRequestPostingImages(file: File(image.filePath!)); requestImages.add(value); } return requestImages; } Future onCreateRequestTapped(BuildContext context) async { if (validateCreateRequestForm()) { Utils.showLoading(context); List vehicleImages = await getVehiclePostingImageList(); List requestImages = []; vehicleImages.forEach((element) { requestImages.add(element.toJson()); }); try { GenericRespModel respModel = await requestRepo.createRequest( requestTypeId: requestTypeId.selectedId, vehicleTypeId: vehicleTypeId.selectedId, brand: vehicleBrandId.selectedOption, model: vehicleModelId.selectedOption, year: vehicleModelYearId.selectedOption, countryID: vehicleCountryId.selectedId, cityID: vehicleCityId.selectedId, price: price, description: description, isSpecialServiceNeeded: false, requestImages: requestImages, ); Utils.hideLoading(context); if (respModel.messageStatus == 1) { Utils.showToast(LocaleKeys.requestSuccessfullyCreated.tr()); Navigator.pop(context); resetRequestCreationForm(); 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(LocaleKeys.selectValidRequestType.tr()); isValid = false; } else if (vehicleTypeId.selectedId == -1) { Utils.showToast(LocaleKeys.vehicle_selectValidVehicleType.tr()); isValid = false; } else if (vehicleBrandId.selectedId == -1) { Utils.showToast(LocaleKeys.selectValidBrand.tr()); isValid = false; } else if (vehicleModelId.selectedId == -1) { Utils.showToast(LocaleKeys.selectValidModel.tr()); isValid = false; } else if (vehicleModelYearId.selectedId == -1) { Utils.showToast(LocaleKeys.selectValidYear.tr()); isValid = false; } else if (vehicleCountryId.selectedId == -1) { Utils.showToast(LocaleKeys.selectValidCountry.tr()); isValid = false; } else if (vehicleCityId.selectedId == -1) { Utils.showToast(LocaleKeys.selectValidCity.tr()); isValid = false; } else if (price.isEmpty) { Utils.showToast(LocaleKeys.addValidPrice.tr()); isValid = false; } else if (description.isEmpty) { Utils.showToast(LocaleKeys.addValidDescription.tr()); isValid = false; } return isValid; } Future> getOffersByRequest({required int requestId, required BuildContext context}) async { try { Utils.showLoading(context); List 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 itemManufacturer = ""; void updateItemManufacturer(String value) { itemManufacturer = value; } String serviceItem = ""; void updateServiceItem(String value) { serviceItem = value; } String serviceItemCreatedOn = ""; void updateServiceItemCreatedOn(String value) { serviceItemCreatedOn = value; notifyListeners(); } 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 = ""; serviceItem = ""; serviceItemCreatedOn = ""; itemManufacturer = ""; notifyListeners(); } Future 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(); bool status = await chatVM.onOfferSendForRequest( 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().onNewMessageReceivedForRequestOffer(messages: [chatMessageModel], requestsVM: this, isMyOwnOffer: true); if (!isFromChatScreen) { ChatViewArgumentsForRequest chatViewArgumentsForRequest = ChatViewArgumentsForRequest( chatTypeEnum: ChatTypeEnum.requestOffer, requestId: requestModel.id, receiverId: requestModel.customerID, senderId: senderId ?? "", requestIndex: requestIndex, providerIndex: -1, requestModel: requestModel, ); ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.requestOffer, chatViewArgumentsForRequest: chatViewArgumentsForRequest); navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments); } } } } }