// 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 String serviceItemName, required int manufacturedById, required String manufacturedOn, 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, manufacturedById: manufacturedById, manufacturedOn: manufacturedOn, serviceItemName: serviceItemName, 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), manufacturedById: manufacturedById, manufacturedOn: manufacturedOn, serviceItemName: serviceItemName, 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); } } } } }