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'; import '../filter/view.dart'; class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin { final BaseLogic baseLogic = Get.find(); final distance = Distance(); Rx currentLocation = LatLng(34.798315281272544, 48.51479142983491).obs; Rx>> allPoultryLocation = Resource>.loading().obs; RxList markers = [].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; late Rx slidController; Rx mapController = MapController().obs; late final AnimatedMapController animatedMapController; late DraggableBottomSheetController filterBottomSheetController; late DraggableBottomSheetController selectedLocationBottomSheetController; late DraggableBottomSheetController detailsLocationBottomSheetController; late final BottomSheetManager bottomSheetManager; InspectionRepositoryImp inspectionRepository = diInspection.get(); @override void onInit() { super.onInit(); animatedMapController = AnimatedMapController( vsync: this, duration: const Duration(milliseconds: 500), curve: Curves.easeInOut, cancelPreviousAnimations: true, ); fetchAllPoultryLocations(); filterBottomSheetController = DraggableBottomSheetController( initialHeight: 350, minHeight: 200, maxHeight: Get.height * 0.5, ); selectedLocationBottomSheetController = DraggableBottomSheetController( initialHeight: 200, minHeight: 100, maxHeight: 200, ); detailsLocationBottomSheetController = DraggableBottomSheetController( initialHeight: Get.height * 0.5, minHeight: Get.height * 0.37, maxHeight: Get.height * 0.5, ); slidController = SlidableController(this).obs; bottomSheetManager = BottomSheetManager({ filterBottomSheetController: () => filterWidget(filterIndex: filterIndex, showIndex: showIndex), selectedLocationBottomSheetController: () => selectedLocationWidget( showHint: selectedLocationBottomSheetController.isVisible.value && showSlideHint, sliderController: slidController.value, trigger: triggerSlidableAnimation, toggle: selectedLocationBottomSheetController.toggle, ), detailsLocationBottomSheetController: () => markerDetailsWidget(), }); } @override void onReady() { super.onReady(); //determineCurrentPosition(); } @override void onClose() { slidController.close(); 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), () { var raduis = getVisibleRadiusKm( zoom: zoom, screenWidthPx: Get.width.toDouble(), latitude: center.latitude, ); final filtered = filterNearbyMarkers( allPoultryLocation.value.data ?? [], center.latitude, center.longitude, raduis * 1000, // Radius in meters ); markers.assignAll( filtered.map( (e) => Marker( point: LatLng(e.lat ?? 0, e.long ?? 0), child: Icon(Icons.location_on, color: Colors.red), ), ), ); }); } 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()); }, ); } 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 } }