Merge branch 'feature/travel-cost-calculator' into main
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
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).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),
|
||||
)
|
||||
: const CameraFit.coordinates(
|
||||
coordinates: [LatLng(46.2276, 2.2137)], padding: 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),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user