import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:generp/Notifiers/HomeScreenNotifier.dart'; import 'package:generp/screens/crm/LeadDetailsByMode.dart'; import 'package:generp/screens/genTracker/GeneratorDetails.dart'; import 'package:generp/services/api_calling.dart'; import 'package:geolocator/geolocator.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:image_picker/image_picker.dart'; import 'package:geocoding/geocoding.dart' as geocoding; import 'package:location/location.dart' as Location; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import '../../Models/crmModels/NearbyOpenLeadsResponse.dart'; import '../../Utils/commonServices.dart'; class crmNearbyOpenLeadsProvider extends ChangeNotifier { List _leadslist = []; TextEditingController _locationController = TextEditingController(); String _googleApikey = "AIzaSyBGzvgMMKwPBAANTwaoRsAnrCpiWCj8wVs"; GoogleMapController? _mapController; CameraPosition? _cameraPosition; LatLng _startLocation = const LatLng(17.439112226708446, 78.43292499146135); String _latlongs = ""; List _markers = []; List _addresses = []; Location.LocationData? _currentLocation; bool _isLocationEnabled = false; bool _hasLocationPermission = false; Timer? _timer; File? _image; bool _isLoading = true; double _currentValue = 1.0; Timer? _debounceTimer; List get leadsList => _leadslist; TextEditingController get LocationController => _locationController; String get googleAPIKey => _googleApikey; GoogleMapController? get mapController => _mapController; CameraPosition? get cameraPosition => _cameraPosition; LatLng get startLocation => _startLocation; String get latlongs => _latlongs; List get markers => _markers; List get addresses => _addresses; Location.LocationData? get currentLocation => _currentLocation; bool get isLocationEnabled => _isLocationEnabled; bool get hasLocationPermission => _hasLocationPermission; bool get isLoading => _isLoading; Timer? get timer => _timer; File? get image => _image; double get currentValue => _currentValue; set currentValue(value){ _currentValue = value; notifyListeners(); } set markers(List value){ _markers = value; notifyListeners(); } set mapController(value){ _mapController = value; notifyListeners(); } void resetAll(){ _currentValue = 1.0; _markers= []; _addresses = []; } Future getLocationPermission(context) async { // Check if location services are enabled _isLocationEnabled = await Geolocator.isLocationServiceEnabled(); // Check if the app has been granted location permission LocationPermission permission = await Geolocator.checkPermission(); _hasLocationPermission = permission == LocationPermission.always || permission == LocationPermission.whileInUse; final Location.Location location = Location.Location(); bool serviceEnabled; Location.PermissionStatus permissionGranted; serviceEnabled = await location.serviceEnabled(); if (!serviceEnabled) { serviceEnabled = await location.requestService(); if (!serviceEnabled) { return; } } _isLoading = false; permissionGranted = (await location.hasPermission()); if (permissionGranted == PermissionStatus) { permissionGranted = (await location.requestPermission()); if (permissionGranted != PermissionStatus) { return; } } final Location.LocationData locData = await location.getLocation(); _currentLocation = locData; if (_currentLocation != null) { _mapController?.animateCamera( CameraUpdate.newLatLng( LatLng(_currentLocation!.latitude!, _currentLocation!.longitude!), ), ); final lat = _currentLocation!.latitude; final lang = _currentLocation!.longitude!; _latlongs = '$lat,$lang'; LoadNearbyOpenLeadsAPI(context,_currentValue); } } void onCameraMove(context, CameraPosition position) { _timer?.cancel(); // Cancel any previous timer _timer = Timer(Duration(seconds: 1), () { getLocationPermission(context); }); } void debounce(VoidCallback callback, Duration duration) { _debounceTimer?.cancel(); _debounceTimer = Timer(duration, callback); } Future LoadNearbyOpenLeadsAPI(BuildContext context,radius) async { if (_latlongs.isEmpty || _currentValue <= 0) { print("Invalid parameters: latlongs=$_latlongs, currentValue=$_currentValue"); return; } try { var provider = Provider.of(context, listen: false); final data = await ApiCalling.loadNearbyOpenLeadsAPI( provider.empId, provider.session, _latlongs, radius ); if (data != null) { if (data.error == 0) { _leadslist = data.leadList!; await updateMarkersFromApiResponse(context, data.leadList!); _isLoading = false; notifyListeners(); } else if(data.error==1){ toast(context, data.message); } } else { toast(context, "Something went wrong, Please try again."); } } on Exception catch (e) { print("$e"); } } Future updateMarkersFromApiResponse( BuildContext context, List leadsList, ) async { _markers = await createMarkersFromApiResponse(context, leadsList); _addresses.clear(); await Future.forEach(leadsList, (store) async { String address = await _getAddressFromLatLng(store.loc); _addresses.add(address); }); notifyListeners(); // for (int i = 0; i < _addresses.length; i++) { // //print('List of Addresses:' "${addresses[i]}"); // // print('List of Addresses:' "${addresses[1]}" ); // } } Future> createMarkersFromApiResponse( BuildContext context, List leadsList, ) async { List markers = []; // print("Hello Nutsby!"); ByteData data = await rootBundle.load("assets/images/leads_ic.png"); Uint8List bytes = data.buffer.asUint8List(); await Future.forEach(leadsList, (leads) async { ui.Codec codec = await ui.instantiateImageCodec( bytes, ); ui.FrameInfo fi = await codec.getNextFrame(); Uint8List resizedBytes = (await fi.image.toByteData( format: ui.ImageByteFormat.png, ))!.buffer.asUint8List(); markers.add( Marker( markerId: MarkerId(leads.id.toString()), position: _parseLatLng(leads.loc), icon: BitmapDescriptor.fromBytes(resizedBytes), infoWindow: InfoWindow( onTap:() { // onMarkerTap(context, leads.id); Navigator.push( context, // Use the widget's BuildContext, which is valid here MaterialPageRoute( builder: (context) => LeadDetailsByMode( mode: "", pageTitleName: "Lead Details", leadId:leads.id , ), ), ); }, anchor: Offset(0, 0), title: "Name: ${leads.name}", snippet: "Address: ${leads.address}", ), zIndex: 100, onTap: () { int index = leadsList.indexWhere( (techResponse) => techResponse.id == leads.id, ); // onMarkerTap( // context, // leads.id, // ); // print("index:${index}"); // Navigator.push( // context, // MaterialPageRoute( // builder: // (context) => Generatordetails( // activityName: "NearByGenerators", // genLocation: generator.loc, // generatorId: generator.generatorId, // ), // ), // ); }, ), ); }); return markers; } Future onMarkerTap(context, leadID) async { ///uncomment with screen navigation Navigator.push( context, // Use the widget's BuildContext, which is valid here MaterialPageRoute( builder: (context) => LeadDetailsByMode( mode: "", pageTitleName: "Lead Details", leadId:leadID , ), ), ); _markers = markers; notifyListeners(); } LatLng _parseLatLng(String? location) { if (location != null) { List parts = location.split(','); if (parts.length == 2) { double lat = double.tryParse(parts[0]) ?? 0.0; double lng = double.tryParse(parts[1]) ?? 0.0; return LatLng(lat, lng); } } return const LatLng(0.0, 0.0); } Future _getAddressFromLatLng(String? location) async { if (location != null) { List parts = location.split(','); if (parts.length == 2) { double lat = double.tryParse(parts[0]) ?? 0.0; double lng = double.tryParse(parts[1]) ?? 0.0; List placemarks = await geocoding .placemarkFromCoordinates(lat, lng); if (placemarks.isNotEmpty) { final placemark = placemarks.first; String address = '${placemark.street ?? ''}, ' '${placemark.thoroughfare ?? ''} ' // '${placemark.subThoroughfare ?? ''}, ' // '${placemark.name ?? ''}, ' '${placemark.subLocality ?? ''}, ' '${placemark.locality ?? ''}, ' '${placemark.administrativeArea ?? ''}, ' '${placemark.subAdministrativeArea ?? ''} ' '${placemark.postalCode ?? ''}, ' '${placemark.country ?? ''}'; return address.trim(); } } } return "Address not found"; } }