Skip to content

feat(aviation): date chips, Google Flights link, city name aliases#2530

Open
koala73 wants to merge 1 commit intomainfrom
feat/aviation-cmd-date-chips-gf-link
Open

feat(aviation): date chips, Google Flights link, city name aliases#2530
koala73 wants to merge 1 commit intomainfrom
feat/aviation-cmd-date-chips-gf-link

Conversation

@koala73
Copy link
Copy Markdown
Owner

@koala73 koala73 commented Mar 29, 2026

Summary

  • Default date is now tomorrow (not +7 days). +7 was arbitrary and confusing.
  • Clickable date chips: Tomorrow · +3d · +7d · +14d · +30d appear below the result header. Clicking any chip reruns the price query with that date and updates the input field. The active date is highlighted.
  • Google Flights link: result header now has a "Google Flights →" link that opens the exact route+date in a new tab.
  • City name aliases: added EXTRA_CITY_IATA table for airports not in MONITORED_AIRPORTSnewcastle → NCL, manchester → MAN, birmingham → BHX, edinburgh → EDI, glasgow → GLA, brussels → BRU, milan → MXP, oslo → OSL, stockholm → ARN, copenhagen → CPH, and more. price newcastle dubai now resolves correctly.

Test plan

  • price newcastle dubai resolves and returns results
  • price manchester DXB resolves MAN correctly
  • Default date in results is tomorrow (not 7 days out)
  • Date chips render below the route header
  • Clicking +7d chip reruns with correct date, input updates, active chip highlights
  • "Google Flights →" link opens correct Google Flights search in new tab
  • Existing price LHR DXB and price London Dubai still work

…-monitored airports

- Default date: tomorrow instead of +7 days (less arbitrary)
- Date chips: clickable Tomorrow/+3d/+7d/+14d/+30d buttons in price results; clicking reruns with that date injected into the input
- Google Flights link: header now links to google.com/travel/flights search for the route+date
- EXTRA_CITY_IATA: aliases for airports not in MONITORED_AIRPORTS (newcastle→NCL, manchester→MAN, birmingham→BHX, etc.) so city names resolve correctly
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
worldmonitor Ignored Ignored Mar 29, 2026 7:39pm

Request Review

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 29, 2026

Greptile Summary

This PR adds four improvements to the AviationCommandBar: a city-name alias table (EXTRA_CITY_IATA) for airports not in MONITORED_AIRPORTS, clickable date chips that re-run the price query with a new date, a Google Flights deep-link in the results header, and a shift of the default search date from +7 days to tomorrow. The overlay click handler is extended cleanly via event delegation (closest('[data-rerun]')).

Key findings:

  • Bug (P1): The default date uses Date.now() + 86400000 (UTC), while the date chips compute dates relative to setHours(12, 0, 0, 0) (local noon). For users with large negative UTC offsets (e.g. UTC-5) in the evening, these two calculations yield different calendar dates. The "Tomorrow" chip will not be highlighted as active on the initial results load, and the price query actually fetches prices for a day further out than the user expects.
  • The EXTRA_CITY_IATA lookup, resolveIata fallback order, and the parseIntent uppercase/lowercase round-trip all look correct.
  • escapeHtml and sanitizeUrl are applied appropriately on all injected values; the data-rerun attribute value is always an IATA-code+date string with no special characters, so the HTML-entity roundtrip through dataset is safe.
  • Chip click history behaviour (addToHistory before run) is consistent with the existing Enter-key path.

Confidence Score: 4/5

Safe to merge after fixing the UTC vs. local-time mismatch in the default date calculation.

One P1 issue: in UTC-5 (and similar) timezones in the evening the default price query date is 'day after tomorrow' local while the 'Tomorrow' chip shows 'tomorrow' local — the chip never highlights and the wrong date is queried by default. All other changes (alias table, event delegation, Google Flights link) look correct and well-guarded.

src/components/AviationCommandBar.ts — lines 160-165, the default date derivation

Important Files Changed

Filename Overview
src/components/AviationCommandBar.ts Adds city-name aliases, date chips, Google Flights link, and chip-click re-run handler; one timezone bug causes the "Tomorrow" chip to not highlight correctly when the default date is derived from UTC while chips use local noon.

Sequence Diagram

sequenceDiagram
    participant U as User
    participant Input as Command Input
    participant Parser as parseIntent()
    participant Resolver as resolveIata()
    participant Execute as executeIntent()
    participant GF as Google Flights API
    participant DOM as Result DOM

    U->>Input: "price newcastle dubai"
    Input->>Parser: parseIntent("price newcastle dubai")
    Parser->>Resolver: resolveIata("NEWCASTLE")
    Note over Resolver: MONITORED_AIRPORTS miss →<br/>EXTRA_CITY_IATA["newcastle"] = "NCL"
    Resolver-->>Parser: "NCL"
    Parser->>Resolver: resolveIata("DUBAI")
    Resolver-->>Parser: "DXB" (from MONITORED_AIRPORTS)
    Parser-->>Execute: { type: PRICE_WATCH, origin: NCL, dest: DXB, date: undefined }
    Execute->>Execute: date = Date.now()+86400000 (UTC tomorrow)
    Execute->>Execute: build date chips (local noon + N days)
    Execute->>GF: fetchGoogleFlights(NCL, DXB, date)
    GF-->>Execute: flights[]
    Execute->>DOM: render header + date chips + rows
    DOM-->>U: Results shown

    U->>DOM: Click "+7d" chip
    DOM->>Input: inp.value = "price NCL DXB 2025-05-06"
    DOM->>Execute: run("price NCL DXB 2025-05-06")
    Execute->>GF: fetchGoogleFlights(NCL, DXB, 2025-05-06)
    GF-->>Execute: flights[]
    Execute->>DOM: re-render with +7d chip highlighted
Loading

Reviews (1): Last reviewed commit: "feat(aviation): date chips, Google Fligh..." | Re-trigger Greptile

Comment on lines +160 to +165
const date = intent.date ?? new Date(Date.now() + 86400000).toISOString().slice(0, 10); // default: tomorrow
const dateLabel = new Date(date + 'T12:00:00').toLocaleDateString([], { month: 'short', day: 'numeric' });
const header = `<div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px">
const gfUrl = `https://www.google.com/travel/flights/search?q=Flights+from+${encodeURIComponent(intent.origin)}+to+${encodeURIComponent(intent.destination)}+on+${encodeURIComponent(date)}`;
const todayBase = new Date(); todayBase.setHours(12, 0, 0, 0);
const dateChips = ([1, 3, 7, 14, 30] as const).map(days => {
const d = new Date(todayBase.getTime() + days * 86400000).toISOString().slice(0, 10);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Default date and Tomorrow chip can disagree across timezones

The default date is computed in pure UTC (Date.now() + 86400000), but the date chips anchor to local noon (todayBase.setHours(12, 0, 0, 0)). These two methods can yield different calendar dates, causing the "Tomorrow" chip to never be highlighted as active on first load.

Concrete failure case — user in UTC-5 at 9 PM local (= 2 AM UTC Tuesday):

  • date (default) = Date.now() + 86400000 = 2 AM UTC Wednesday → "Wednesday" date string
  • "Tomorrow" chip = noon local Monday → 5 PM UTC Monday → + 86400000 = 5 PM UTC Tuesday → "Tuesday" date string
  • "Tuesday" !== "Wednesday" → chip is not highlighted, and the query actually fetches prices two days out from the user's perspective

Fix: derive the default date with the same local-noon anchor used by the chips:

Suggested change
const date = intent.date ?? new Date(Date.now() + 86400000).toISOString().slice(0, 10); // default: tomorrow
const dateLabel = new Date(date + 'T12:00:00').toLocaleDateString([], { month: 'short', day: 'numeric' });
const header = `<div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px">
const gfUrl = `https://www.google.com/travel/flights/search?q=Flights+from+${encodeURIComponent(intent.origin)}+to+${encodeURIComponent(intent.destination)}+on+${encodeURIComponent(date)}`;
const todayBase = new Date(); todayBase.setHours(12, 0, 0, 0);
const dateChips = ([1, 3, 7, 14, 30] as const).map(days => {
const d = new Date(todayBase.getTime() + days * 86400000).toISOString().slice(0, 10);
const todayBase = new Date(); todayBase.setHours(12, 0, 0, 0);
const date = intent.date ?? new Date(todayBase.getTime() + 86400000).toISOString().slice(0, 10); // default: tomorrow (local)
const dateLabel = new Date(date + 'T12:00:00').toLocaleDateString([], { month: 'short', day: 'numeric' });
const gfUrl = `https://www.google.com/travel/flights/search?q=Flights+from+${encodeURIComponent(intent.origin)}+to+${encodeURIComponent(intent.destination)}+on+${encodeURIComponent(date)}`;
const dateChips = ([1, 3, 7, 14, 30] as const).map(days => {

This also allows the separate todayBase declaration on line 163 to be removed (it becomes redundant).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant