// transit_controller.dart — تحكم شاشات مواصلاتي (جهة الراكب) import 'package:get/get.dart'; import '../home/map/map_socket_controller.dart'; import '../../print.dart'; import 'transit_models.dart'; import 'transit_service.dart'; class TransitController extends GetxController { bool isLoadingEnrollments = false; List myEnrollments = []; bool isLoadingOrgs = false; List browsableOrgs = []; bool isLoadingRoutes = false; List currentOrgRoutes = []; int? currentOrgId; // ── تتبع الباص الحي ────────────────────────────────────────── int? liveRouteId; int? liveTripId; Map? liveTripData; BusPosition? liveBusPosition; String liveError = ''; bool isLoadingLiveTrip = false; @override void onInit() { super.onInit(); fetchMyEnrollments(); } Future fetchMyEnrollments() async { isLoadingEnrollments = true; update(); final res = await TransitService.getMyEnrollments(); if (res.success) myEnrollments = res.data ?? []; isLoadingEnrollments = false; update(); } Future browseOrgs({String? search}) async { isLoadingOrgs = true; update(); final res = await TransitService.browseOrgs(search: search); if (res.success) browsableOrgs = res.data ?? []; isLoadingOrgs = false; update(); } Future activateEnrollment(int orgId, String studentId) async { final res = await TransitService.activateEnrollment( orgId: orgId, studentId: studentId, ); if (res.success) { await fetchMyEnrollments(); return true; } Get.snackbar('مواصلاتي', res.message); return false; } Future openOrgRoutes(int orgId) async { currentOrgId = orgId; isLoadingRoutes = true; currentOrgRoutes = []; update(); final res = await TransitService.getRoutesForOrg(orgId); if (res.success) { currentOrgRoutes = res.data ?? []; } else { Get.snackbar('مواصلاتي', res.message); } isLoadingRoutes = false; update(); } // ── الخط الحي: تحميل أولي + اشتراك سوكيت ──────────────────── Future openLiveRoute(int routeId) async { liveRouteId = routeId; liveTripData = null; liveBusPosition = null; liveError = ''; isLoadingLiveTrip = true; update(); final res = await TransitService.getLiveTrip(routeId: routeId); if (res.success && res.data != null) { liveTripData = res.data; liveTripId = int.tryParse(liveTripData?['trip']?['id']?.toString() ?? ''); final pos = liveTripData?['bus_position']; if (pos is Map) liveBusPosition = BusPosition.fromJson(pos); } else { liveError = res.message; } isLoadingLiveTrip = false; update(); if (Get.isRegistered()) { final ms = Get.find(); ms.onBusLocationUpdate = _handleLiveBusUpdate; ms.subscribeToTransitRoute(routeId); } } void _handleLiveBusUpdate(Map data) { final incomingRouteId = int.tryParse(data['route_id']?.toString() ?? ''); if (incomingRouteId == null || incomingRouteId != liveRouteId) return; liveBusPosition = BusPosition( lat: double.tryParse(data['latitude']?.toString() ?? '0') ?? 0, lng: double.tryParse(data['longitude']?.toString() ?? '0') ?? 0, heading: double.tryParse(data['heading']?.toString() ?? '0') ?? 0, speed: double.tryParse(data['speed']?.toString() ?? '0') ?? 0, currentStopSeq: data['current_stop_seq'] == null ? null : int.tryParse(data['current_stop_seq'].toString()), ); Log.print('🚌 Live bus update: ${liveBusPosition?.lat}, ${liveBusPosition?.lng}'); update(); } void closeLiveRoute() { if (liveRouteId != null && Get.isRegistered()) { final ms = Get.find(); ms.unsubscribeFromTransitRoute(liveRouteId!); ms.onBusLocationUpdate = null; } liveRouteId = null; liveTripId = null; liveTripData = null; liveBusPosition = null; } @override void onClose() { closeLiveRoute(); super.onClose(); } }