ios build, connected data (not finished)
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../utils/breakpoints.dart';
|
||||
|
||||
class MapSidebarLayout extends StatelessWidget {
|
||||
final Widget mapWidget;
|
||||
final Widget sidebarWidget;
|
||||
final double mapRatio;
|
||||
|
||||
const MapSidebarLayout({
|
||||
super.key,
|
||||
required this.mapWidget,
|
||||
required this.sidebarWidget,
|
||||
this.mapRatio = 2 / 3,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobile = MediaQuery.of(context).size.width < Breakpoints.tablet;
|
||||
|
||||
if (isMobile) {
|
||||
return sidebarWidget;
|
||||
}
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: (mapRatio * 100).toInt(),
|
||||
child: mapWidget,
|
||||
),
|
||||
Expanded(
|
||||
flex: ((1 - mapRatio) * 100).toInt(),
|
||||
child: sidebarWidget,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user