import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_typography.dart'; import '../../../services/alerts/road_alert_models.dart'; import '../../../services/alerts/road_alert_service.dart'; import '../../../services/map/map_provider_interface.dart'; import '../../../services/map/unified_map_view.dart'; import '../../../services/navigation/navigation_session_service.dart'; import '../../../services/telemetry_service.dart'; /// Embedded tactical map panel for Touring mode and responsive dashboard views. /// /// Subscribes to vehicle coordinates and heading via [telemetryStreamProvider] /// and alert pins via [activeAlertsStreamProvider]. class DashboardMapPanel extends ConsumerWidget { final double zoom; const DashboardMapPanel({ super.key, this.zoom = 16.5, }); @override Widget build(BuildContext context, WidgetRef ref) { final vehicleCoords = ref.watch( telemetryStreamProvider.select( (s) => ( lat: s.value?.latitude, lng: s.value?.longitude, heading: s.value?.heading ?? 0.0, isGpsFresh: s.value?.isGpsFresh ?? false, ), ), ); final centerLat = (vehicleCoords.lat != null && vehicleCoords.lat != 0.0) ? vehicleCoords.lat! : 37.7749; final centerLng = (vehicleCoords.lng != null && vehicleCoords.lng != 0.0) ? vehicleCoords.lng! : -122.4194; final isFresh = vehicleCoords.isGpsFresh; final hasCoordinates = vehicleCoords.lat != null && vehicleCoords.lat != 0.0; final vehicleMarker = AppMapMarker( id: 'dash_vehicle', position: AppLatLng(centerLat, centerLng), heading: vehicleCoords.heading, iconWidget: Icon( Icons.navigation, color: isFresh ? AppColors.cyberCyan : AppColors.cyberCyan.withValues(alpha: 0.38), size: 36, ), ); final activeAlertsAsync = ref.watch(activeAlertsStreamProvider); final activeAlerts = activeAlertsAsync.value ?? []; final mapMarkers = [vehicleMarker]; for (final alert in activeAlerts) { mapMarkers.add( AppMapMarker( id: 'dash_alert__', position: AppLatLng(alert.latitude, alert.longitude), heading: alert.heading ?? 0.0, label: alert.category.displayName, iconWidget: Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: alert.category.color.withValues(alpha: 0.9), shape: BoxShape.circle, boxShadow: const [BoxShadow(color: Colors.black54, blurRadius: 4)], ), child: Icon(alert.category.icon, color: Colors.black, size: 16), ), ), ); } final navSession = ref.watch(navigationSessionProvider); final polylines = []; if (navSession.isNavigating && navSession.calculationResult?.geometry.isNotEmpty == true) { polylines.add( AppPolyline( id: 'dash_active_nav_route', points: navSession.calculationResult!.geometry, color: const Color(0xFF00E5FF), width: 5.0, ), ); } return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(14), border: Border.all( color: Theme.of(context).brightness == Brightness.dark ? AppColors.darkOutline : AppColors.lightOutline, width: 1.2, ), ), clipBehavior: Clip.antiAlias, child: LayoutBuilder( builder: (context, constraints) { return SizedBox( width: constraints.maxWidth, height: constraints.maxHeight, child: Stack( children: [ Positioned.fill( child: UnifiedMapView( key: const ValueKey('dash_map_x'), center: AppLatLng(centerLat, centerLng), zoom: zoom, bearing: 0.0, markers: mapMarkers, polylines: polylines, ), ), if (!isFresh && hasCoordinates) Positioned( top: 10, left: 10, child: Container( key: const ValueKey('stale_gps_pill'), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.75), borderRadius: BorderRadius.circular(6), border: Border.all(color: AppColors.warningAmber, width: 1.0), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.location_off, size: 13, color: AppColors.warningAmber), SizedBox(width: 5), Text( 'LAST KNOWN LOCATION', style: TextStyle( fontFamily: AppTypography.fontTelemetry, fontSize: 10, fontWeight: FontWeight.w700, letterSpacing: 0.5, color: AppColors.warningAmber, ), ), ], ), ), ), ], ), ); }, ), ); } }