import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/general_models/generic_resp_model.dart'; import 'package:mc_common_app/repositories/branch_repo.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/document.dart'; import 'package:mc_common_app/models/provider_branches_models/profile/services.dart'; import 'package:mc_common_app/models/provider_branches_models/provider_model.dart'; import 'package:mc_common_app/models/services_models/item_model.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; import 'package:mc_common_app/models/user_models/branch_user.dart'; import 'package:mc_common_app/models/user_models/cities.dart'; import 'package:mc_common_app/models/user_models/country.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; import 'package:mc_common_app/services/common_services.dart'; import 'package:mc_common_app/utils/app_permission_handler.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/widgets/dropdown/dropdow_field.dart'; import 'package:easy_localization/easy_localization.dart'; class ServiceVM extends BaseVM { final BranchRepo branchRepo; final CommonAppServices commonServices; final CommonRepo commonRepo; ServiceVM({ required this.branchRepo, required this.commonServices, required this.commonRepo, }); // Documents & Branches int selectedBranchStatus = 3; Document? document; ProviderModel? branches; Country? country; Cities? cities; DropValue? countryValue; DropValue? cityValue; List countryDropList = []; List citiesDropList = []; double latitude = 0; double longitude = 0; String openTime = ""; String closedTime = ""; int role = -1; int countryId = -1; int cityId = -1; String countryCode = ""; String address = ""; String branchName = ""; String branchDescription = ""; String branchErrorScreen = ""; void updateSelectionOpenTime(String date) { openTime = date; notifyListeners(); } void updateSelectionCloseTime(String date) { closedTime = date; notifyListeners(); } double getDistanceFromMe({ required String destLatitude, required String destLongitude, }) { double distance = commonServices.getDistanceBetween( curLatitude: AppState().currentLocation.latitude, curLongitude: AppState().currentLocation.longitude, destLatitude: double.parse(destLatitude), destLongitude: double.parse(destLongitude), ); return distance; } Future getServiceProviderDocument(int providerId) async { setState(ViewState.busy); document = await branchRepo.getServiceProviderDocument(providerId); setState(ViewState.idle); } List pickedBranchImages = []; String branchImageError = ""; void removeImageFromList(String filePath) { int index = pickedBranchImages.indexWhere((element) => element.filePath == filePath); if (index == -1) { return; } pickedBranchImages.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)); } pickedBranchImages.addAll(imageModels); if (pickedBranchImages.isNotEmpty) branchImageError = ""; notifyListeners(); } Future selectFile(BuildContext context, int index) async { final status = await AppPermissions.checkStoragePermissions(context); if (status) { final File? file = await commonServices.pickFile( context, fileType: FileType.custom, allowedExtensions: ['png', 'pdf', 'jpeg'], ); if (file != null) { int sizeInBytes = file.lengthSync(); // double sizeInMb = sizeInBytes / (1024 * 1024); if (sizeInBytes > 1000000) { Utils.showToast(LocaleKeys.fileLarger.tr()); } else { document!.data![index].document = Utils.convertFileToBase64(file); document!.data![index].fileExt = Utils.checkFileExt(file.path); document!.data![index].documentUrl = file.path; setState(ViewState.idle); } } else { // User canceled the picker } } } Future updateDocument(List? data) async { return await branchRepo.serviceProviderDocumentsUpdate(data); } // Create new branch Future getBranchAndServices() async { setState(ViewState.busy); branches = await branchRepo.getBranchAndServices(); setState(ViewState.idle); } Future getAllCountriesList(BranchDetailModel? branchData, String countryCode) async { cities = null; country = null; setState(ViewState.busy); resetValues(); country = await commonRepo.getAllCountries(); country!.data?.forEach((element) { if (branchData != null && branchData.id != null) { if (element.id == branchData.countryID) { countryId = element.id ?? -1; countryValue = DropValue( element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? "", ); } } countryDropList.add( DropValue( element.id ?? 0, countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""), element.countryCode ?? "", ), ); }); if (branchData != null && branchData.id != null) { await getAllCities(branchData, countryCode); } setState(ViewState.idle); } Future getAllCities(BranchDetailModel? branchData, String countryCode) async { setState(ViewState.busy); citiesDropList = []; cities = null; cityId = -1; cityValue = null; cities = await commonRepo.getAllCites(countryId.toString()); cities!.data?.forEach((element) { if (branchData != null && branchData.id != null) { if (element.id == branchData.cityId) { address = branchData.address!; branchName = branchData.branchName!; branchDescription = branchData.branchDescription!; latitude = double.parse(branchData.latitude ?? ""); longitude = double.parse(branchData.longitude ?? ""); openTime = branchData.openTime ?? ""; closedTime = branchData.closeTime ?? ""; countryId = branchData.countryID!; cityId = branchData.cityId!; cityValue = DropValue( element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), (element.id ?? "").toString(), ); } } citiesDropList.add( DropValue( element.id ?? 0, countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""), (element.id ?? "").toString(), ), ); }); setState(ViewState.idle); } void resetValues() { countryCode = ""; address = ""; branchName = ""; branchDescription = ""; openTime = ""; closedTime = ""; branchErrorScreen = ""; latitude = 0; longitude = 0; role = -1; countryId = -1; cityId = -1; countryDropList.clear(); countryId = -1; cityId = -1; cities = null; categoryDropList = []; servicesDropList = []; services = null; pickedBranchImages.clear(); } // Create Services Services? services; List categoryDropList = []; List servicesDropList = []; Future fetchBranchCategory(String countryCode) async { categoryDropList.clear(); servicesDropList = []; services = null; setOnlyState(ViewState.busy); Category? category = await branchRepo.fetchBranchCategory(); category.data?.forEach((element) { categoryDropList.add( DropValue( element.id ?? 0, ((element.categoryName!.isEmpty ? "N/A" : countryCode == "SA" ? element.categoryNameN : element.categoryName) ?? "N/A"), "", ), ); }); setState(ViewState.idle); } Future fetchServicesByCategoryId(int categoryId) async { servicesDropList = []; setState(ViewState.busy); services = await branchRepo.fetchServicesByCategoryId(serviceCategoryId: categoryId); // to get all the services for (var element in services!.data!) { servicesDropList.add( DropValue( element.id ?? 0, element.description ?? "N/A", "", ), ); } setState(ViewState.idle); } Future fetchProviderServices(String branchID, String categoryId) async { servicesDropList = []; services = null; setState(ViewState.busy); services = await branchRepo.fetchProviderServices(branchID, categoryId); for (var element in services!.data!) { servicesDropList.add( DropValue( element.id ?? 0, element.description ?? "N/A", "", ), ); } setState(ViewState.idle); } Future createService(List> map) async { return await branchRepo.createService(map); } Future updateServices(List> map) async { return await branchRepo.updateService(map); } void updateSelectedBranchType(int status) { selectedBranchStatus = status; notifyListeners(); } List? matchedServices; bool isAllSelected = false; Future getAllMatchedServices(int oldBranchId, int newBranchId, int categoryId) async { matchedServices = null; final GenericRespModel response = await branchRepo.getMatchedServices(oldBranchId, newBranchId, categoryId); matchedServices = []; if (response.messageStatus == 1) { matchedServices = List.from(response.data.map((x) => ServiceModel.fromJson(x))); } notifyListeners(); } void selectAllServices(bool value) { for (var element in matchedServices!) { element.isExpandedOrSelected = value; for (var item in element.serviceItems!) { item.isUpdateOrSelected = value; } } isAllSelected = value; notifyListeners(); } void updateServiceItem(int serviceIndex, bool value) { for (var element in matchedServices![serviceIndex].serviceItems!) { element.isUpdateOrSelected = value; } notifyListeners(); } void copyItems(int index, List copiedItems) { matchedServices![index].serviceItems = copiedItems; notifyListeners(); } Future duplicateItems(Map map) async { return await branchRepo.duplicateItems(map); } // Branch Users List allProviderDealersList = []; List branchUserList = []; getAllProviderDealers(Map map) async { setState(ViewState.busy); GenericRespModel response = await branchRepo.getAllProviderDealers(map); if (response.messageStatus == 1) { allProviderDealersList = []; allProviderDealersList = List.from(response.data.map((x) => BranchUser.fromJson(x))); } setState(ViewState.idle); } Future getBranchUsers(Map map) async { setState(ViewState.busy); GenericRespModel response = await branchRepo.getBranchUsers(map); if (response.messageStatus == 1) { branchUserList = []; branchUserList = List.from(response.data.map((x) => BranchUser.fromJson(x))); } setState(ViewState.idle); } Future assignDealerToBranch(Map map) async { GenericRespModel response = await branchRepo.assignDealerToBranch(map); return response; } Future removeDealerFromBranch(Map map) async { GenericRespModel response = await branchRepo.removeDealerFromBranch(map); return response; } Future addNewServiceInAppointment(Map map) async { GenericRespModel response = await branchRepo.addNewServicesInAppointment(map); return response; } Future convertFileToBranchPostingImages({required ImageModel imageModel}) async { BranchPostingImages branchPostingImages; if (imageModel.isFromNetwork ?? false) { branchPostingImages = BranchPostingImages(id: imageModel.id, imageUrl: imageModel.filePath); } else { File file = File(imageModel.filePath!); List imageBytes = await file.readAsBytes(); String image = base64Encode(imageBytes); String fileName = file.path.split('/').last; branchPostingImages = BranchPostingImages( imageName: fileName, imageStr: image, imageUrl: file.path, // id: isAdEditEnabled ? previousAdDetails!.vehiclePostingID : null, // TODO NEED TO PASS ID HERE IN CASE OF EDIT BRANCH ); } return branchPostingImages; } Future onCreateBranchPressed({ required BuildContext context, required String branchName, required String branchDesc, required int cityID, required String address, required String openTime, required String closeTime, required double latitude, required double longitude, }) async { if (branchName.isEmpty || branchDesc.isEmpty || address.isEmpty) { branchErrorScreen = GlobalConsts.fillAllFields; notifyListeners(); return; } if (pickedBranchImages.length < 3) { branchErrorScreen = GlobalConsts.attachImageError; notifyListeners(); return; } try { Utils.showLoading(context); List branchImages = []; for (var image in pickedBranchImages) { branchImages.add(await convertFileToBranchPostingImages(imageModel: image)); } GenericRespModel res = await branchRepo.createBranch( branchName: branchName, branchDescription: branchDesc, openTime: branchDesc, closeTime: branchDesc, cityId: cityID, address: address, latitude: latitude, longitude: longitude, imagesList: branchImages, ); Utils.hideLoading(context); if (res.messageStatus == 1) { Utils.showToast(LocaleKeys.branch_created.tr()); updateSelectedBranchType(1); pop(context); getBranchAndServices(); } else { Utils.showToast(res.message ?? ""); } } catch (e) { Utils.hideLoading(context); Utils.showToast(e.toString()); } } Future onUpdateBranchPressed({ required BuildContext context, required int branchID, required String branchName, required String branchDesc, required String openTime, required String closedTime, required int cityID, required String address, required String latitude, required String longitude, }) async { if (branchName.isEmpty || branchDesc.isEmpty || address.isEmpty) { branchErrorScreen = GlobalConsts.fillAllFields; notifyListeners(); return; } if (pickedBranchImages.length < 3) { branchErrorScreen = GlobalConsts.attachImageError; notifyListeners(); return; } try { Utils.showLoading(context); List branchImages = []; for (var image in pickedBranchImages) { branchImages.add(await convertFileToBranchPostingImages(imageModel: image)); } GenericRespModel res = await branchRepo.updateBranch( branchId: branchID, branchName: branchName, branchDescription: branchDesc, openTime: openTime, closeTime: closedTime, cityId: cityID, address: address, latitude: latitude, longitude: longitude, imagesList: branchImages, ); Utils.hideLoading(context); if (res.messageStatus == 1) { Utils.showToast(LocaleKeys.branch_updated.tr()); pop(context); pop(context); getBranchAndServices(); } else { Utils.showToast(res.message ?? ""); } } catch (e) { Utils.hideLoading(context); Utils.showToast(e.toString()); } } Future onDeleteBranchPressed({required BuildContext context, required int branchID}) async { try { Utils.showLoading(context); GenericRespModel res = await branchRepo.deleteBranch(branchId: branchID); Utils.hideLoading(context); if (res.messageStatus == 1) { Utils.showToast(LocaleKeys.branch_deleted.tr()); pop(context); pop(context); getBranchAndServices(); } else { Utils.showToast(res.message ?? ""); } } catch (e) { Utils.hideLoading(context); Utils.showToast(e.toString()); } } }