import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:get/get.dart'; import 'package:latlong2/latlong.dart'; import 'package:terepi_seged/services/gnss/gnss_service.dart'; import 'package:terepi_seged/services/stakeout_service.dart'; import '../../../../models/stakeout_point.dart'; /// Kitűzési térképréteg — a SharedMapWidget children listájába illesztendő. /// /// Csak akkor rajzol, ha a StakeoutService aktív (mode == stakeout), így /// feltétel nélkül bent maradhat a rétegek között. Tartalma: vonalanként /// polyline (station-sorrendben), státusz-színezett markerek (koppintás = /// célváltás), vezetővonal a pozíciótól a célig. class StakeoutMapLayers extends StatelessWidget { const StakeoutMapLayers({super.key}); @override Widget build(BuildContext context) { if (!Get.isRegistered()) return const SizedBox.shrink(); return Obx(() { final svc = StakeoutService.to; if (!svc.active.value || svc.points.isEmpty) { return const SizedBox.shrink(); } final points = svc.points; final target = svc.target.value; final g = GnssService.to; final hasPos = svc.hasPosition.value && g.latitude.value != 0; // Vonalanként polyline (station-sorrendben, eltolt pontok nélkül). final linePolys = []; for (final line in svc.lines) { final lp = points.where((p) => p.lineId == line && !p.isOffset).toList() ..sort((a, b) => a.station.compareTo(b.station)); if (lp.length < 2) continue; linePolys.add(Polyline( points: [for (final p in lp) LatLng(p.planLat, p.planLon)], color: Colors.blueGrey.withOpacity(0.5), strokeWidth: 2, )); } // 300 pont fölött a címkék csak a célon (teljesítmény). final showLabels = points.length <= 300; return Stack(children: [ PolylineLayer(polylines: [ ...linePolys, if (hasPos && target != null) Polyline( points: [ LatLng(g.latitude.value, g.longitude.value), LatLng(target.planLat, target.planLon), ], color: Colors.blue, strokeWidth: 3, ), ]), MarkerLayer(markers: [ for (final p in points) Marker( point: LatLng(p.planLat, p.planLon), width: 56, height: 40, child: GestureDetector( onTap: () => svc.setTarget(p), child: _StakeoutMarker( point: p, isTarget: p.uuid == target?.uuid, showLabel: showLabels || p.uuid == target?.uuid, ), ), ), ]), ]); }); } } class _StakeoutMarker extends StatelessWidget { final StakeoutPoint point; final bool isTarget; final bool showLabel; const _StakeoutMarker( {required this.point, required this.isTarget, required this.showLabel}); @override Widget build(BuildContext context) { final (color, icon) = switch (point.status) { StakeoutStatus.staked => (Colors.green, Icons.check_circle), StakeoutStatus.skipped => (Colors.grey, Icons.block), StakeoutStatus.pending => point.isOffset ? (Colors.purple, Icons.change_history) : (Colors.deepOrange, Icons.change_history), }; return Column( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: isTarget ? 26 : 16, color: isTarget ? Colors.red : color), if (showLabel) Container( padding: const EdgeInsets.symmetric(horizontal: 3), decoration: BoxDecoration( color: Colors.white.withOpacity(0.85), borderRadius: BorderRadius.circular(4), ), child: Text( point.name, style: TextStyle( fontSize: 9, fontWeight: isTarget ? FontWeight.w700 : FontWeight.w400, color: isTarget ? Colors.red : Colors.black87, ), ), ), ], ); } }