Skip to content

Show the booking details behind an imported element - #70

Merged
dfalling merged 1 commit into
mainfrom
support-element-metadata
Aug 10, 2026
Merged

Show the booking details behind an imported element#70
dfalling merged 1 commit into
mainfrom
support-element-metadata

Conversation

@dfalling

Copy link
Copy Markdown
Owner

Summary

The API now parses structured details out of an imported booking — flight numbers, reservation codes, seats, departure/arrival — and exposes them as element_metadata. The app fetched none of it, so a flight imported from a confirmation email looked like any other pin.

  • Fetch metadata wherever a full element is fetched (detail query, plus the import and update mutations so an element lands in the cache with its booking details attached)
  • New src/map/metadataRows.ts turns the metadata into labelled rows, mirroring the web app's presentation so one booking reads the same in both places:
    • row order: number → From → To → Reservation → Seat → Payment → Address
    • type never gets its own row; it titles the number instead (Flight / Train / Bus / Ferry)
    • flight numbers link to a status search — a search, not a tracker URL, because parsed numbers range from IB3216 to American Airlines 291
    • the raw address only shows when geocoding failed, since otherwise it's already the element's location
  • A "Booking" section on the element detail screen, with a fixed label column so codes line up for scanning
  • 11 unit tests covering ordering, titling, the address rule, and value trimming

Metadata is read-only server-side (ElementInput has no metadata field), so the edit screen needed nothing.

Fixing GraphQL codegen

Adding a field meant running codegen, which turned out to be broken two ways — both from @graphql-codegen/typescript-react-apollo:

  • its latest release peers at graphql <=16, so it crashed on the installed 17 (Cannot read properties of undefined (reading 'find') — 17 leaves optional AST list fields undefined where 16 gave [])
  • its hooks are Apollo v3-shaped, so every regen needed ~15 @ts-ignores and import rewrites applied by hand

Dropped it, along with the typescript plugin whose schema types typescript-operations 6.x now emits itself (running both defined every input twice → TS2300). Codegen now emits a TypedDocumentNode per operation, passed to Apollo's own hooks, which infer results and variables from it:

const {data, loading} = useQuery(ElementDetailDocument, {variables: {id}});
const [importShare] = useMutation(ImportShareDocument);

bun run codegen ./schema.graphql now runs on graphql 17 with the repo's declared deps, output is idempotent, and needs no touch-ups. The generated file dropped from ~1400 lines to 450. README stack/example sections updated to match, and __generated__ is excluded from the documents glob — codegen was reading its own output back in as duplicate documents.

Three call-site changes worth a look:

  • enums are string-literal unions now, not TS enums: labelsMatch: 'ALL' instead of LabelMatchMode.All. In MapScreen the literal sat inside a useMemo that widened it to string, so it's annotated with Pick<ElementsQueryVariables, …> to stay checked against the schema
  • photoUpload and authClient lost their explicit generics (mutate<LogoutMutation>), which were looser than inference — they left variables untyped
  • generated types no longer carry __typename (visitor-plugin-common 7.x only emits it when a selection asks). Apollo still adds it on the wire and keys its cache off it, so normalization is unaffected

Testing

bunx tsc --noEmit, bun run lint, and 51 tests all pass; codegen output verified byte-identical across repeated runs.

⚠️ Not run on a device — no emulator was attached, so the Booking section's layout and the migrated hooks are unverified at runtime.

🤖 Generated with Claude Code

The API now parses structured details out of an imported booking — flight
numbers, reservation codes, seats, where transport leaves from and arrives —
and exposes them as element_metadata. The app fetched none of it, so a flight
imported from a confirmation email looked like any other pin.

Renders them as a Booking section on the element detail screen, ordered and
titled the same way the web app does so one booking reads the same in both
places: the kind of transport titles the number rather than taking a row of its
own, a flight number links out to its status, and the raw address only appears
when geocoding failed (otherwise it's already the element's location).

Fetching metadata on the import and update mutations too, so an element lands
in the cache with its booking details already attached.

Fix GraphQL codegen while here, since adding a field required running it.
It couldn't run at all: typescript-react-apollo peers at graphql <=16 and
crashed on the installed 17, and its Apollo v3-shaped hooks needed ~15
@ts-ignores hand-applied after every regen. Dropped it, along with the
typescript plugin whose schema types typescript-operations 6.x now emits
itself (running both defined every input twice). Codegen emits a
TypedDocumentNode per operation instead, passed to Apollo's own hooks, which
infer results and variables from it — so `bun run codegen` is now a clean,
idempotent, no-touch-ups command.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dfalling
dfalling enabled auto-merge (squash) August 10, 2026 11:51
@dfalling
dfalling merged commit bfe5bc7 into main Aug 10, 2026
2 checks passed
@dfalling
dfalling deleted the support-element-metadata branch August 10, 2026 11:58
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