import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart'; import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository_imp.dart'; import 'package:rasadyar_inspection/injection/inspection_di.dart'; import 'package:rasadyar_inspection/presentation/widget/base_page/logic.dart'; class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin { final BaseLogic baseLogic = Get.find(); InspectionRepositoryImp inspectionRepository = diInspection.get(); final distance = Distance(); Rx currentLocation = LatLng(34.798315281272544, 48.51479142983491).obs; Rx>> allPoultryLocation = Resource>.initial().obs; Rx>> searchedPoultryLocation = Resource>.initial().obs; RxList markers = [].obs; RxList markers2 = [].obs; Timer? _debounceTimer; RxBool isLoading = false.obs; RxBool isSelectedDetailsLocation = false.obs; RxInt filterIndex = 0.obs; RxInt showIndex = 0.obs; bool showSlideHint = true; RxInt currentZoom = 15.obs; Rx mapController = MapController().obs; late final AnimatedMapController animatedMapController; @override void onInit() { super.onInit(); animatedMapController = AnimatedMapController( vsync: this, duration: const Duration(milliseconds: 500), curve: Curves.easeInOut, cancelPreviousAnimations: true, ); fetchAllPoultryLocations(); debounce(baseLogic.searchValue, (callback) { if (callback != null && callback.trim().isNotEmpty && searchedPoultryLocation.value.status != ResourceStatus.loading) { searchPoultryLocations(); } }, time: Duration(seconds: 2)); } @override void onReady() { super.onReady(); //determineCurrentPosition(); } @override void onClose() { super.onClose(); } Future determineCurrentPosition() async { isLoading.value = true; final position = await Geolocator.getCurrentPosition( locationSettings: AndroidSettings(accuracy: LocationAccuracy.best), ); final latLng = LatLng(position.latitude, position.longitude); /*currentLocation.value = latLng; markers.add(PoultryLocationModel( lat: latLng.latitude, long: latLng.longitude ));*/ animatedMapController.animateTo( dest: latLng, zoom: 18, curve: Curves.easeInOut, duration: const Duration(seconds: 1), ); isLoading.value = false; } void debouncedUpdateVisibleMarkers({required LatLng center, required double zoom}) { _debounceTimer?.cancel(); _debounceTimer = Timer(const Duration(milliseconds: 300), () { final radius = getVisibleRadiusKm( zoom: zoom, screenWidthPx: Get.width.toDouble(), latitude: center.latitude, ); final filtered = filterNearbyMarkers( allPoultryLocation.value.data ?? [], center.latitude, center.longitude, radius * 1000, ); final existingIds = markers2.map((e) => e.id).toSet(); final uniqueFiltered = filtered.where((e) => !existingIds.contains(e.id)).toList(); markers2.addAll(uniqueFiltered); }); } List filterNearbyMarkers( List allMarkers, double centerLat, double centerLng, double radiusInMeters, ) { final center = LatLng(centerLat, centerLng); return allMarkers.where((marker) { var tmp = LatLng(marker.lat ?? 0, marker.long ?? 0); return distance(center, tmp) <= radiusInMeters; }).toList(); } Future triggerSlidableAnimation() async { await Future.delayed(Duration(milliseconds: 200)); //await slidController.value.openEndActionPane(); await Future.delayed(Duration(milliseconds: 200)); //await slidController.value.close(); showSlideHint = false; } Future fetchAllPoultryLocations() async { isLoading.value = true; allPoultryLocation.value = Resource>.loading(); await safeCall( call: () => inspectionRepository.getNearbyLocation( centerLat: currentLocation.value.latitude, centerLng: currentLocation.value.longitude, radius: 15, // Radius in K meters ), onSuccess: (result) { if (result != null) { allPoultryLocation.value = Resource>.success(result); } else { allPoultryLocation.value = Resource>.error( 'No locations found', ); } }, onError: (error, stackTrace) { allPoultryLocation.value = Resource>.error(error.toString()); }, ); } Future searchPoultryLocations() async { searchedPoultryLocation.value = Resource>.loading(); await safeCall( call: () => inspectionRepository.getNearbyLocation(value: baseLogic.searchValue.value), onSuccess: (result) { if (result != null || result!.isNotEmpty) { searchedPoultryLocation.value = Resource>.success(result); } else { searchedPoultryLocation.value = Resource>.empty(); } }, onError: (error, stackTrace) { searchedPoultryLocation.value = Resource>.error( error.toString(), ); }, ); } double getVisibleRadiusKm({ required double zoom, required double screenWidthPx, required double latitude, }) { double metersPerPixel = 156543.03392 * cos(latitude * pi / 180) / pow(2, zoom); double visibleWidthInMeters = metersPerPixel * screenWidthPx; return (visibleWidthInMeters / 2) / 1000; // radius in KM } }