import 'package:equatable/equatable.dart'; import '../data/models/fare_quote.dart'; import '../data/models/geo_point.dart'; import '../data/models/place.dart'; import '../data/models/ride_type.dart'; import '../data/models/route_info.dart'; import '../data/models/trip.dart'; /// مراحل شاشة الراكب. المرحلة تحدّد ما يُعرض على الخريطة وما في الورقة /// السفلية — «الشاشة مهمة واحدة» (docs/26 §8.1). enum RidePhase { /// الخريطة والبطاقة المطوية «إلى أين؟». idle, /// المخطّط الموسّع: المصدر والوجهة والمحطات. planning, /// المستخدم يحرّك الخريطة والدبّوس ثابت في المنتصف. pickingOnMap, /// المسار والتسعيرة معروضان بانتظار التأكيد. confirming, /// البحث عن سائق. searching, /// رحلة جارية. active, } /// أيّ حقلٍ يلتقط اختيار الخريطة. enum PickTarget { origin, destination } enum RideError { none, noDrivers, quoteFailed, routeFailed, requestFailed, /// الموقع مرفوض أو الخدمة مطفأة — بلا موقع لا خريطة مفيدة. noLocation, } class RideState extends Equatable { const RideState({ this.phase = RidePhase.idle, this.origin, this.destination, this.originLabel = '', this.destinationLabel = '', this.stops = const [], this.rideTypes = const [], this.selectedRideType, this.route, this.quote, this.quotes = const {}, this.trip, this.driverLocation, this.pickupRoute, this.searchResults = const [], this.searching = false, this.busy = false, this.error = RideError.none, this.pickTarget = PickTarget.destination, this.cameraTarget, this.couponCode = '', }); final RidePhase phase; final GeoPoint? origin; final GeoPoint? destination; final String originLabel; final String destinationLabel; final List stops; final List rideTypes; final RideType? selectedRideType; final RouteInfo? route; /// تسعيرة النوع المختار — مشتقّة من [quotes] للراحة. final FareQuote? quote; /// **كل الأنواع مسعَّرة دفعةً واحدة** بمفتاح `RideType.code`. /// /// الراكب يرى أسعار الاقتصادي والمريح والعائلي معاً فيقارن ويقرّر — بدل /// نداء شبكة عند كل ضغطة نوع. المسافة والمدة ثابتتان للمسار، فالنداءات /// متوازية ومرة واحدة. final Map quotes; final Trip? trip; /// موقع السائق الحيّ من `driver:location`. final GeoPoint? driverLocation; /// مسار **السائق ← الراكب** أثناء الاقتراب، ومنه الوقت والمسافة المعروضان. /// /// منفصل عن [route] (مسار الرحلة نفسها) لأنهما يُرسمان معاً بلونين /// مختلفين، ولأن هذا يُعاد حسابه مع حركة السائق بينما ذاك ثابت. final RouteInfo? pickupRoute; final List searchResults; /// بحث نصّي جارٍ — منفصل عن [busy] كي لا يقفل مؤشّرُ البحثِ الشاشةَ كلها. final bool searching; final bool busy; final RideError error; final PickTarget pickTarget; /// وجهة الكاميرا حين يقودها المنطق لا المستخدم. final GeoPoint? cameraTarget; /// كود الخصم — يُقيَّم على الخادم عند الطلب لا في التطبيق. final String couponCode; /// تسعيرة نوعٍ بعينه — لعرض السعر تحت كل خيار. FareQuote? quoteFor(String code) => quotes[code]; bool get canConfirm => origin != null && destination != null && selectedRideType != null && quote?.isUsable == true; RideState copyWith({ RidePhase? phase, GeoPoint? origin, GeoPoint? destination, String? originLabel, String? destinationLabel, List? stops, List? rideTypes, RideType? selectedRideType, RouteInfo? route, FareQuote? quote, Map? quotes, Trip? trip, GeoPoint? driverLocation, RouteInfo? pickupRoute, List? searchResults, bool? searching, bool? busy, RideError? error, PickTarget? pickTarget, GeoPoint? cameraTarget, String? couponCode, bool clearDestination = false, bool clearRoute = false, bool clearTrip = false, bool clearCamera = false, bool clearPickupRoute = false, }) { return RideState( phase: phase ?? this.phase, origin: origin ?? this.origin, destination: clearDestination ? null : (destination ?? this.destination), originLabel: originLabel ?? this.originLabel, destinationLabel: clearDestination ? '' : (destinationLabel ?? this.destinationLabel), stops: stops ?? this.stops, rideTypes: rideTypes ?? this.rideTypes, selectedRideType: selectedRideType ?? this.selectedRideType, route: clearRoute ? null : (route ?? this.route), quote: clearRoute ? null : (quote ?? this.quote), quotes: clearRoute ? const {} : (quotes ?? this.quotes), trip: clearTrip ? null : (trip ?? this.trip), driverLocation: driverLocation ?? this.driverLocation, pickupRoute: clearPickupRoute || clearRoute ? null : (pickupRoute ?? this.pickupRoute), searchResults: searchResults ?? this.searchResults, searching: searching ?? this.searching, busy: busy ?? this.busy, error: error ?? this.error, pickTarget: pickTarget ?? this.pickTarget, cameraTarget: clearCamera ? null : (cameraTarget ?? this.cameraTarget), couponCode: couponCode ?? this.couponCode, ); } @override List get props => [ phase, origin, destination, originLabel, destinationLabel, stops, rideTypes, selectedRideType, route, quote, quotes, trip, driverLocation, pickupRoute, searchResults, searching, busy, error, pickTarget, cameraTarget, couponCode, ]; }