ionic-planb-logistic-app-fl.../lib/components/delivery_map.dart

231 lines
7.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:google_navigation_flutter/google_navigation_flutter.dart';
import '../models/delivery.dart';
class DeliveryMap extends StatefulWidget {
final List<Delivery> deliveries;
final Delivery? selectedDelivery;
final ValueChanged<Delivery?>? onDeliverySelected;
const DeliveryMap({
super.key,
required this.deliveries,
this.selectedDelivery,
this.onDeliverySelected,
});
@override
State<DeliveryMap> createState() => _DeliveryMapState();
}
class _DeliveryMapState extends State<DeliveryMap> {
GoogleNavigationViewController? _navigationController;
bool _isNavigating = false;
LatLng? _destinationLocation;
@override
void initState() {
super.initState();
_initializeNavigation();
}
Future<void> _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<void> _navigateToLocation(LatLng location) async {
if (_navigationController == null) return;
try {
await _navigationController!.animateCamera(
CameraUpdate.newLatLngZoom(location, 15),
);
} catch (e) {
debugPrint('Error moving camera: $e');
}
}
Future<void> _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<void> _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();
}
}