Files
EM2_ERP/em2rp/lib/views/widgets/common/route_map_widget.dart
T

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),
],
);
}
}