import { TextInputProps, TouchableOpacityProps } from "react-native"; declare interface Driver { id: number; first_name: string; last_name: string; profile_image_url: string; car_image_url: string; car_seats: number; rating: number; service: string; online?: boolean; latitude?: number | null; longitude?: number | null; /** Degrees clockwise from north; null when the device couldn't determine it. */ heading?: number | null; /** km/h at the last fix; null when unknown, 0 when stationary. */ speed_kph?: number | null; user_id?: string | null; car_model?: string | null; last_seen?: string | null; } declare interface MarkerData { latitude: number; longitude: number; id: number; title?: string; profile_image_url: string; car_image_url: string; car_seats: number; rating: number; first_name: string; last_name: string; service?: string; online?: boolean; car_model?: string | null; heading?: number | null; speed_kph?: number | null; time?: number; price?: string; } declare interface MapProps { destinationLatitude?: number; destinationLongitude?: number; onDriverTimesCalculated?: (driversWithTimes: MarkerData[]) => void; selectedDriver?: number | null; onMapReady?: () => void; } /** * Ride lifecycle (see lib/ride-lifecycle.ts, which owns the server-side sets): * requested → accepted → arrived → en_route → completed, with cancelled from * any pre-trip state and expired when nobody offered in time. A request is * broadcast to every driver nearby and gets its driver at one moment only: * when the rider picks one of the offers that came back. */ declare type RideStatus = | "requested" | "accepted" | "arrived" | "en_route" | "completed" | "cancelled" | "expired"; /** * `cash` is a fare still owed to the driver; `cash_collected` is one they've * confirmed taking at drop-off. Both are "settled" only in the second case — * the distinction is what makes the cash ledger reconcilable. */ declare type PaymentStatus = /** Requested but not yet assigned — the rider pays when they pick a driver. */ | "pending" | "paid" | "cash" | "cash_collected"; declare interface Ride { ride_id?: number; origin_address: string; destination_address: string; origin_latitude: number; origin_longitude: number; destination_latitude: number; destination_longitude: number; ride_time: number; fare_price: number; payment_status: PaymentStatus | string; status: RideStatus | string; service: string; driver_id: number | null; user_id?: string; payment_order_id?: string | null; created_at: string; accepted_at?: string | null; arrived_at?: string | null; started_at?: string | null; completed_at?: string | null; cancelled_at?: string | null; cancelled_by?: "rider" | "driver" | "system" | null; cancellation_reason?: string | null; cash_collected_at?: string | null; /** Shown to the rider only while the code is still live (pre-trip). */ pickup_code?: string | null; /** The rating this rider left, or null if they haven't rated yet. */ my_rating?: number | null; /** Drivers who have volunteered, while the request is still open. */ offers?: RideOffer[]; /** Server clock at read time — elapsed time is measured against this, not * the phone's own clock, which can be seconds out either way. */ now?: string; /** How long a request stays open for offers, in seconds. */ request_ttl_seconds?: number; driver: { id: number | null; first_name: string | null; last_name: string | null; car_seats: number | null; profile_image_url: string | null; car_image_url: string | null; rating: number | null; rating_count?: number | null; service: string | null; car_model: string | null; latitude: number | null; longitude: number | null; }; } /** * A driver volunteering for an open request, as the rider's screen sees it. * * Deliberately carries no coordinates: choosing between drivers needs how far * away each one is, not where they are, and only the driver who is actually * picked has a position the rider is entitled to watch. */ declare interface RideOffer { offer_id: number; driver_id: number; offered_at: string; /** Metres from the driver to the pickup, as of when they offered. */ pickup_distance_m: number | null; first_name: string | null; last_name: string | null; profile_image_url: string | null; car_image_url: string | null; car_model: string | null; car_seats: number | null; rating: number | null; rating_count: number | null; service: string | null; } // In-app chat message between a rider and their assigned driver, scoped to a // ride. `sender_id` is the users.id (UUID) or drivers.id (INT) depending on // `sender_type`; the API stringifies it so the client treats both uniformly. declare interface Message { id: number; ride_id: number; sender_type: "rider" | "driver"; sender_id: string; body: string; created_at: string; sender_name?: string; sender_avatar?: string | null; } // The active ride that has an open chat conversation (the other party is // assigned), returned by GET /(api)/chat/active. `peer` is the other party. declare interface ChatActiveRide { ride_id: number; status: string; role: "rider" | "driver"; peer: { name: string; avatar: string | null; service?: string | null; car_model?: string | null; } | null; } // A WebRTC audio call's signaling + lifecycle row, returned by the call // endpoints. SDP offer/answer are JSON-stringified RTCSessionDescriptions with // gathered ICE candidates embedded (non-trickle). declare interface CallRecord { id: number; ride_id: number; caller_type: "rider" | "driver"; status: "ringing" | "answered" | "ended" | "declined" | "missed"; is_caller: boolean; sdp_offer?: string | null; sdp_answer?: string | null; started_at?: string | null; ended_at?: string | null; created_at: string; } // The client-side call state machine driven by useCall. declare type CallStatus = | "idle" | "outgoing" | "incoming" | "connecting" | "in-call" | "ended"; declare interface NearbyPlace { name: string; address: string; latitude: number; longitude: number; /** Straight-line distance from the rider. */ distanceMeters?: number; /** Distance and time along the actual driving route, when one was found. */ routeDistanceMeters?: number; routeDurationSeconds?: number; category?: string; } declare interface ButtonProps extends TouchableOpacityProps { title: string; bgVariant?: "primary" | "secondary" | "danger" | "outline" | "success"; textVariant?: "primary" | "default" | "secondary" | "danger" | "success"; iconLeft?: React.ComponentType; iconRight?: React.ComponentType; className?: string; /** * Touchable to build the button on. Defaults to react-native's, which is * wrong in exactly one place: inside a @gorhom/bottom-sheet on Android it * swallows the first press. Screens living in a sheet pass the touchable * the sheet exports instead. */ Touchable?: React.ComponentType; } declare interface GoogleInputProps { icon?: string; initialLocation?: string; containerStyles?: string; textInputBackgroundColor?: string; handlePress: ({ latitude, longitude, address, }: { latitude: number; longitude: number; address: string; }) => void; } declare interface InputFieldProps extends TextInputProps { label: string; icon?: any; secureTextEntry?: boolean; labelStyles?: string; containerStyles?: string; inputStyles?: string; iconStyles?: string; className?: string; } declare interface PaymentProps { fullName: string; email: string; amount: string; driverId: number; rideTime: number; } declare interface LocationStore { userLatitude: number | null; userLongitude: number | null; userAddress: string | null; destinationLatitude: number | null; destinationLongitude: number | null; destinationAddress: string | null; setUserLocation: ({ latitude, longitude, address, }: { latitude: number; longitude: number; address: string; }) => void; setDestinationLocation: ({ latitude, longitude, address, }: { latitude: number; longitude: number; address: string; }) => void; /** Forget the destination — a finished trip must not keep drawing a route. */ clearDestination: () => void; } declare interface DriverStore { drivers: MarkerData[]; selectedDriver: number | null; setSelectedDriver: (driverId: number) => void; setDrivers: (drivers: MarkerData[]) => void; clearSelectedDriver: () => void; } declare interface DriverCardProps { item: MarkerData; selected: number; setSelected: () => void; }