114 lines
3.5 KiB
Dart
114 lines
3.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_map/flutter_map.dart';
|
|
import 'package:latlong2/latlong.dart';
|
|
import 'package:em2rp/models/route_result_model.dart';
|
|
import '../../../utils/polyline_utils.dart';
|
|
|
|
/// Affiche 1 ou 2 itinéraires sur une carte OpenStreetMap.
|
|
/// Route TOLL = bleu, Route TOLL_FREE = vert.
|
|
class RouteMapWidget extends StatelessWidget {
|
|
final List<RouteResult> routes;
|
|
final RouteResult? selectedRoute;
|
|
|
|
const RouteMapWidget({
|
|
super.key,
|
|
required this.routes,
|
|
this.selectedRoute,
|
|
});
|
|
|
|
List<LatLng> _decode(String encoded) {
|
|
final pts = safeDecodePolyline(encoded);
|
|
// DEBUG: afficher dans la console du navigateur
|
|
// ignore: avoid_print
|
|
print('[MAP DEBUG] encoded length=${encoded.length}, decoded ${pts.length} points');
|
|
if (pts.isNotEmpty) {
|
|
// ignore: avoid_print
|
|
print('[MAP DEBUG] first=${pts.first.latitude},${pts.first.longitude} last=${pts.last.latitude},${pts.last.longitude}');
|
|
}
|
|
return pts;
|
|
}
|
|
|
|
LatLngBounds? _computeBounds(List<List<LatLng>> allPoints) {
|
|
final flat = allPoints.expand((e) => e).cast<LatLng>().toList();
|
|
if (flat.isEmpty) return null;
|
|
return LatLngBounds.fromPoints(flat);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final allPolylines = <Polyline>[];
|
|
final allPointGroups = <List<LatLng>>[];
|
|
|
|
for (final route in routes) {
|
|
final pts = _decode(route.encodedPolyline);
|
|
if (pts.isEmpty) continue;
|
|
allPointGroups.add(pts);
|
|
|
|
final isSelected =
|
|
selectedRoute == null || selectedRoute!.routeType == route.routeType;
|
|
final isToll = route.routeType == 'TOLL';
|
|
|
|
allPolylines.add(Polyline(
|
|
points: pts,
|
|
strokeWidth: isSelected ? 5.0 : 3.0,
|
|
color: isToll
|
|
? (isSelected
|
|
? const Color(0xFF1565C0)
|
|
: const Color(0xFF1565C0).withValues(alpha: 0.4))
|
|
: (isSelected
|
|
? const Color(0xFF2E7D32)
|
|
: const Color(0xFF2E7D32).withValues(alpha: 0.4)),
|
|
));
|
|
}
|
|
|
|
final bounds = _computeBounds(allPointGroups);
|
|
final mapController = MapController();
|
|
|
|
// Marqueurs de départ / arrivée
|
|
final markers = <Marker>[];
|
|
for (final group in allPointGroups) {
|
|
if (group.isEmpty) continue;
|
|
// Départ
|
|
markers.add(Marker(
|
|
point: group.first,
|
|
width: 32,
|
|
height: 32,
|
|
child: const Icon(Icons.circle, color: Colors.green, size: 20),
|
|
));
|
|
// Arrivée
|
|
markers.add(Marker(
|
|
point: group.last,
|
|
width: 32,
|
|
height: 32,
|
|
child: const Icon(Icons.location_pin, color: Colors.red, size: 32),
|
|
));
|
|
}
|
|
|
|
return FlutterMap(
|
|
mapController: mapController,
|
|
options: MapOptions(
|
|
initialCameraFit: bounds != null
|
|
? CameraFit.bounds(
|
|
bounds: bounds,
|
|
padding: const EdgeInsets.all(32),
|
|
)
|
|
: CameraFit.bounds(
|
|
bounds: LatLngBounds.fromPoints([LatLng(46.2276, 2.2137)]),
|
|
padding: const EdgeInsets.all(32),
|
|
),
|
|
interactionOptions: const InteractionOptions(
|
|
flags: InteractiveFlag.all,
|
|
),
|
|
),
|
|
children: [
|
|
TileLayer(
|
|
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
|
userAgentPackageName: 'com.em2events.em2rp',
|
|
),
|
|
PolylineLayer(polylines: allPolylines),
|
|
MarkerLayer(markers: markers),
|
|
],
|
|
);
|
|
}
|
|
}
|