import 'package:flutter/material.dart'; import 'package:google_navigation_flutter/google_navigation_flutter.dart'; import '../models/delivery.dart'; class DeliveryMap extends StatefulWidget { final List deliveries; final Delivery? selectedDelivery; final ValueChanged? onDeliverySelected; const DeliveryMap({ super.key, required this.deliveries, this.selectedDelivery, this.onDeliverySelected, }); @override State createState() => _DeliveryMapState(); } class _DeliveryMapState extends State { GoogleNavigationViewController? _navigationController; bool _isNavigating = false; LatLng? _destinationLocation; @override void initState() { super.initState(); _initializeNavigation(); } Future _initializeNavigation() async { try { debugPrint('🗺️ Starting navigation initialization'); // Check if terms and conditions need to be shown final termsAccepted = await GoogleMapsNavigator.areTermsAccepted(); debugPrint('🗺️ Terms accepted: $termsAccepted'); if (!termsAccepted) { debugPrint('🗺️ Showing terms and conditions dialog'); // Show terms and conditions await GoogleMapsNavigator.showTermsAndConditionsDialog( 'Plan B Logistics', 'com.goutezplanb.planbLogistic', ); } // Initialize navigation session debugPrint('🗺️ Initializing navigation session'); await GoogleMapsNavigator.initializeNavigationSession(); debugPrint('🗺️ Navigation session initialized successfully'); } catch (e) { debugPrint('❌ Error initializing navigation: $e'); } } @override void didUpdateWidget(DeliveryMap oldWidget) { super.didUpdateWidget(oldWidget); if (oldWidget.selectedDelivery != widget.selectedDelivery) { _updateDestination(); } } void _updateDestination() { if (widget.selectedDelivery != null) { final address = widget.selectedDelivery!.deliveryAddress; if (address?.latitude != null && address?.longitude != null) { setState(() { _destinationLocation = LatLng( latitude: address!.latitude!, longitude: address.longitude!, ); }); _navigateToLocation(_destinationLocation!); } } } Future _navigateToLocation(LatLng location) async { if (_navigationController == null) return; try { await _navigationController!.animateCamera( CameraUpdate.newLatLngZoom(location, 15), ); } catch (e) { debugPrint('Error moving camera: $e'); } } Future _startNavigation() async { if (_destinationLocation == null) return; try { final waypoint = NavigationWaypoint.withLatLngTarget( title: widget.selectedDelivery?.name ?? 'Destination', target: _destinationLocation!, ); final destinations = Destinations( waypoints: [waypoint], displayOptions: NavigationDisplayOptions(showDestinationMarkers: true), ); await GoogleMapsNavigator.setDestinations(destinations); await GoogleMapsNavigator.startGuidance(); setState(() { _isNavigating = true; }); } catch (e) { debugPrint('Error starting navigation: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error starting navigation: $e')), ); } } } Future _stopNavigation() async { try { await GoogleMapsNavigator.stopGuidance(); await GoogleMapsNavigator.clearDestinations(); setState(() { _isNavigating = false; }); } catch (e) { debugPrint('Error stopping navigation: $e'); } } @override Widget build(BuildContext context) { final initialPosition = widget.selectedDelivery?.deliveryAddress != null && widget.selectedDelivery!.deliveryAddress!.latitude != null && widget.selectedDelivery!.deliveryAddress!.longitude != null ? LatLng( latitude: widget.selectedDelivery!.deliveryAddress!.latitude!, longitude: widget.selectedDelivery!.deliveryAddress!.longitude!, ) : const LatLng(latitude: 45.5017, longitude: -73.5673); // Default to Montreal return Stack( children: [ GoogleMapsNavigationView( onViewCreated: (controller) { debugPrint('🗺️ Map view created successfully'); _navigationController = controller; controller.setMyLocationEnabled(true); // Set initial camera position controller.animateCamera( CameraUpdate.newLatLngZoom(initialPosition, 12), ); debugPrint('🗺️ Initial camera position set to: $initialPosition'); }, initialNavigationUIEnabledPreference: NavigationUIEnabledPreference.disabled, initialCameraPosition: CameraPosition( target: initialPosition, zoom: 12, ), ), if (_destinationLocation != null && !_isNavigating) Positioned( bottom: 24, left: 24, right: 24, child: ElevatedButton.icon( onPressed: _startNavigation, icon: const Icon(Icons.navigation), label: const Text('Start Navigation'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.all(16), backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Theme.of(context).colorScheme.onPrimary, ), ), ), if (_isNavigating) Positioned( bottom: 24, left: 24, right: 24, child: ElevatedButton.icon( onPressed: _stopNavigation, icon: const Icon(Icons.stop), label: const Text('Stop Navigation'), style: ElevatedButton.styleFrom( padding: const EdgeInsets.all(16), backgroundColor: Theme.of(context).colorScheme.error, foregroundColor: Theme.of(context).colorScheme.onError, ), ), ), Positioned( top: 16, right: 16, child: Column( children: [ FloatingActionButton.small( heroTag: 'zoom_in', onPressed: () { _navigationController?.animateCamera(CameraUpdate.zoomIn()); }, child: const Icon(Icons.add), ), const SizedBox(height: 8), FloatingActionButton.small( heroTag: 'zoom_out', onPressed: () { _navigationController?.animateCamera(CameraUpdate.zoomOut()); }, child: const Icon(Icons.remove), ), ], ), ), ], ); } @override void dispose() { GoogleMapsNavigator.cleanup(); super.dispose(); } }