// transit_live_map_page.dart — تتبع الباص الحي على الخريطة import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intaleq_maps/intaleq_maps.dart'; import '../../constant/colors.dart'; import '../../constant/style.dart'; import '../../env/env.dart'; import '../../controller/transit/transit_controller.dart'; import '../widgets/my_scafold.dart'; class TransitLiveMapPage extends StatefulWidget { final int routeId; final String routeName; const TransitLiveMapPage({super.key, required this.routeId, required this.routeName}); @override State createState() => _TransitLiveMapPageState(); } class _TransitLiveMapPageState extends State { IntaleqMapController? _mapController; @override void initState() { super.initState(); Get.find().openLiveRoute(widget.routeId); } @override void dispose() { Get.find().closeLiveRoute(); super.dispose(); } @override Widget build(BuildContext context) { return GetBuilder( builder: (c) { final stops = (c.liveTripData?['stops'] is List) ? List.from(c.liveTripData!['stops']) : []; final markers = {}; for (final s in stops) { final lat = double.tryParse(s['latitude']?.toString() ?? '') ?? 0; final lng = double.tryParse(s['longitude']?.toString() ?? '') ?? 0; if (lat == 0 && lng == 0) continue; markers.add(Marker( markerId: MarkerId('stop_${s['id']}'), position: LatLng(lat, lng), infoWindow: InfoWindow(title: s['name_ar']?.toString() ?? ''), icon: InlqBitmap.defaultMarkerWithHue( (s['is_major']?.toString() ?? '0') == '1' ? 30 : 200), )); } LatLng? busLatLng; if (c.liveBusPosition != null) { busLatLng = LatLng(c.liveBusPosition!.lat, c.liveBusPosition!.lng); markers.add(Marker( markerId: const MarkerId('bus'), position: busLatLng, rotation: c.liveBusPosition!.heading, anchor: const Offset(0.5, 0.5), icon: InlqBitmap.defaultMarkerWithHue(120), )); if (_mapController != null) { _mapController!.animateCamera(CameraUpdate.newLatLng(busLatLng)); } } final initialTarget = busLatLng ?? (markers.isNotEmpty ? markers.first.position : const LatLng(31.95, 35.93)); return MyScafolld( title: widget.routeName, isleading: true, body: [ Expanded( child: Stack( children: [ IntaleqMap( apiKey: Env.mapSaasKey, initialCameraPosition: CameraPosition(target: initialTarget, zoom: 14), markers: markers, onMapCreated: (ctrl) => _mapController = ctrl, ), if (c.isLoadingLiveTrip) const Positioned.fill( child: ColoredBox( color: Colors.black12, child: Center(child: CircularProgressIndicator()), ), ), if (!c.isLoadingLiveTrip && c.liveError.isNotEmpty) Positioned( top: 16, left: 16, right: 16, child: _statusBanner(c.liveError, AppColor.redColor), ), if (!c.isLoadingLiveTrip && c.liveError.isEmpty && c.liveBusPosition == null) Positioned( top: 16, left: 16, right: 16, child: _statusBanner( 'No bus running on this route right now'.tr, AppColor.yellowColor), ), if (c.liveTripData?['trip']?['delay_minutes'] != null && (int.tryParse(c.liveTripData!['trip']['delay_minutes'].toString()) ?? 0) > 0) Positioned( bottom: 24, left: 16, right: 16, child: _statusBanner( '${'Bus is delayed'.tr} ${c.liveTripData!['trip']['delay_minutes']} ${'min'.tr}', AppColor.yellowColor, ), ), ], ), ), ], ); }, ); } Widget _statusBanner(String text, Color color) { return Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), decoration: BoxDecoration( color: AppColor.cardColor, borderRadius: BorderRadius.circular(12), border: Border(right: BorderSide(color: color, width: 4)), boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 6)], ), child: Text(text, style: AppStyle.title.copyWith(color: color, fontWeight: FontWeight.bold)), ); } }