Files
Flights/api_docs/route_explorer_captures/schedule_AA2178.json
T
Trey T b403bfd970 Add route-explorer.com integration: connection finder + departures board
- RouteExplorerClient: anonymous HMAC token (route-explorer.com/api/token,
  IP rate-limited 10/min), POST /api/flight-search with X-API-Token; auto
  retry on 401/403 token rotation. Wraps the SuperJSON {json:{...}} envelope
  for the upstream tRPC endpoints.
- RouteExplorerModels: Codable types for /route, /departures responses
  (RouteConnection, RouteFlight, cabins, appendix). Custom ISO-8601
  decoder for the dateTime-with-offset timestamps. Bridge helper
  RouteFlight.toFlightSchedule(...) so route-explorer legs reuse the
  existing FlightLoadDetailView and AirlineLoadService flow for
  supported carriers (UA/AA/NK/KE/B6/AS/EK/XE).
- RoutePlannerView: feature (a) — direct + multi-stop A→B routing via
  /route with maxStops 0/1/2, sortBy departure_time/duration, optional
  interline-only filter. Renders one ConnectionRow per itinerary with
  chained legs and layover indicators.
- WhereToGoView: feature (b) — "where can I go" departures board for an
  airport over a 2/4/6/12/24h window. Capacity pills (F/J/W/Y), color-
  coded countdown, cross-midnight rollover. Tap any leg → load detail.
- IATAAirportPicker: lightweight local-only picker against
  AirportDatabase (no flightconnections roundtrip needed since
  route-explorer keys on IATA, not FC IDs).
- ContentView: two new entry-point cards (Find Connections, Where can I
  go?) above the favorites list.
- api_docs/route_explorer_api.md + captures: full endpoint reference and
  representative response samples (DFW→LAS direct, DFW→KOA 1-stop,
  LBB→KOA 2-stop, AA2178 schedule, DFW departures).

No tests yet — project has no test target and adding TDD would require
scaffolding XCTest first. Worth backfilling tests for the date decoder,
layover math, and toFlightSchedule bridge using the saved fixtures.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 10:23:17 -05:00

556 lines
13 KiB
JSON

{
"json": {
"flights": [
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-04-24T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-04-24T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_04_24",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
},
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-04-25T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-04-25T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_04_25",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
},
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-04-26T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-04-26T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_04_26",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
},
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-04-27T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-04-27T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_04_27",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
},
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-04-28T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-04-28T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_04_28",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
},
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-04-29T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-04-29T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_04_29",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
},
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-04-30T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-04-30T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_04_30",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
},
{
"flightNumber": 2178,
"flightSuffix": null,
"departure": {
"airportIata": "DFW",
"dateTime": "2026-05-01T16:45:00-05:00",
"terminal": "0"
},
"arrival": {
"airportIata": "LAS",
"dateTime": "2026-05-01T17:46:00-07:00",
"terminal": "1"
},
"durationMinutes": 181,
"equipmentIata": "32Q",
"serviceType": "J",
"isCodeshare": false,
"stops": 0,
"stopCodes": null,
"totalSeats": 196,
"classes": {
"first": {
"seats": 0,
"mealCodes": []
},
"business": {
"seats": 20,
"mealCodes": [
"D"
]
},
"premiumEconomy": {
"seats": 0,
"mealCodes": []
},
"economy": {
"seats": 176,
"mealCodes": [
"R",
"D"
]
}
},
"inFlightService": [
12,
18,
22,
23,
24,
26,
27,
28,
29,
31
],
"id": "AA_2178_DFW_2026_05_01",
"carrierIata": "AA",
"carrierIcao": "AAL",
"isWetlease": false,
"codeshares": []
}
],
"appendix": {
"airports": [
{
"iataCode": "DFW",
"name": "Dallas Dallas/Fort Worth Intl Apt",
"cityCode": "DFW",
"countryCode": "US",
"stateCode": "TX",
"latitude": 32.896944,
"longitude": -97.038056,
"timezone": "America/Chicago",
"locationType": "A",
"locationCategory": "A",
"icaoCode": "KDFW",
"cityName": "Dallas",
"countryName": "United States"
},
{
"iataCode": "LAS",
"name": "Las Vegas Harry Reid Intl",
"cityCode": "LAS",
"countryCode": "US",
"stateCode": "NV",
"latitude": 36.08,
"longitude": -115.152222,
"timezone": "America/Los_Angeles",
"locationType": "A",
"locationCategory": "A",
"icaoCode": "KLAS",
"cityName": "Las Vegas",
"countryName": "United States"
}
],
"airlines": [
{
"iataCode": "AA",
"icaoCode": "AAL",
"name": "American Airlines",
"countryCode": "US",
"alliance": "oneworld",
"isLowCost": false,
"isControlledDuplicate": false,
"websiteUrl": "https://www.aa.com",
"webCheckinUrl": "https://www.aa.com/reservation/flightCheckInViewReservationsAccess.do",
"mobileCheckinUrl": null,
"baggageUrl": "https://www.aa.com/i18n/travel-info/baggage/baggage.jsp?anchorEvent=false&ampfrom=Nav",
"foundedYear": 1926,
"callsign": "AMERICAN"
}
],
"equipment": [
{
"iataCode": "32Q",
"icaoCode": null,
"generalCode": "32S",
"name": "Airbus A321neo/LR/XLR Passenger",
"equipmentType": "J",
"bodyType": "N",
"isSurfaceTransport": false
}
]
}
}
}