Skip to content

Search for a place instead of only nearby ones - #18

Merged
frewsxcv merged 1 commit into
mainfrom
claude/bump-dependencies-omi2m9
Sep 2, 2026
Merged

frewsxcv merged 1 commit into
mainfrom
claude/bump-dependencies-omi2m9

Conversation

@frewsxcv

@frewsxcv frewsxcv commented Sep 2, 2026

Copy link
Copy Markdown
Owner

The place step only ever offered the places iNaturalist returns for the browser's geolocation, so there was no way to study somewhere you aren't. This adds a search box on that step, backed by iNaturalist's place autocomplete endpoint.

Behaviour

An empty box keeps showing the nearby places, so search is an alternative to the location-based suggestions rather than a step in front of them:

Box Shows
empty the nearby places, exactly as before
fake matching places from autocomplete
no matches No places found matching “…”.
request failed Could not search for places. Check your connection and try again.

Clearing the box brings the nearby places back. Selecting a searched place dispatches the same PLACE_SELECTED action, so nothing downstream changes.

Queries are debounced (300ms), and a query that changes while a request is in flight aborts it — otherwise a slow response for an earlier prefix could land after a newer one and overwrite it.

Supporting changes

  • geometry_geojson on Place is now optional. The autocomplete endpoint isn't documented to return geometry for every hit, and the map preview is the only thing that needs it. A place without geometry now renders as a card with no map, rather than an empty map of the Atlantic. The nearby path is unaffected.
  • apiV1Fetch rejects on a non-2xx response and accepts an AbortSignal. It previously read results off an error body and handed back undefined, which gave the new error state nothing to trigger on.
  • Place cards are keyed by place id rather than list index. Leaflet only initializes a map on mount, so with index keys a searched place would have reused the previous place's map instance.

Verification

npm run lint, npx jest --config=configs/jest.json and npm run build all pass.

Driven in a real browser (Playwright, against the offline fixture since this sandbox can't reach api.inaturalist.org):

  1. Nearby places show with an empty box ✅
  2. A matching query swaps the list ✅
  3. A non-matching query shows the empty state and no cards ✅
  4. Clearing the box restores the nearby list ✅
  5. Selecting a searched place advances to the taxa step with the place in the navbar ✅

No page errors or React exceptions in any step.

Two things worth flagging

  • I could not exercise the real endpoint. This environment's egress proxy blocks api.inaturalist.org, so the live request path is unverified against the actual API. The one assumption it rests on is that autocomplete results carry id and display_name — id is all the rest of the flow needs. I made geometry optional rather than assume it's present.
  • The search box still sits behind the geolocation prompt. Reaching this step requires LocationStep to succeed, so someone who denies location can't get to the search at all — and that error path is currently a no-op expression that renders nothing. Letting the user skip straight to search is the natural follow-up, but it changes the app's step machine, so I left it out. Happy to do it if you want.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J7nU5T9UJU7ydrRdENiKuQ


Generated by Claude Code

The place step only ever offered the places iNaturalist returns for the
browser's geolocation, so there was no way to study somewhere you aren't.
This adds a search box backed by iNaturalist's place autocomplete endpoint.

An empty box keeps showing the nearby places, so search is an alternative to
the location-based suggestions rather than a step in front of them. Typing
replaces the list with matches, and clearing it brings the nearby places
back. Selecting a searched place feeds the same PLACE_SELECTED action, so
the rest of the flow is unchanged.

Queries are debounced, and a query that changes while a request is still in
flight aborts it — otherwise a slow response for an earlier prefix could
land after a newer one and overwrite it.

Two supporting changes:

- `geometry_geojson` on `Place` is now optional. The autocomplete endpoint
  is not documented to return geometry for every hit, and the map preview
  is the only thing that needs it, so a place without geometry renders as a
  card with no map rather than an empty map of the Atlantic.
- `apiV1Fetch` now rejects on a non-2xx response and accepts an
  `AbortSignal`. It previously read `results` off an error body and handed
  back `undefined`, which gave the new error state nothing to trigger on.

Place cards are now keyed by place id rather than list index. Leaflet only
initializes a map on mount, so with index keys a searched place would have
reused the previous place's map.

Verified in a browser against the offline fixture: nearby places show with
an empty box, a matching query swaps the list, a non-matching one shows the
empty state, clearing restores the nearby list, and selecting a searched
place advances to the taxa step with the place in the navbar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J7nU5T9UJU7ydrRdENiKuQ
@frewsxcv
frewsxcv merged commit 0b39b17 into main Sep 2, 2026
1 check passed
@frewsxcv
frewsxcv deleted the claude/bump-dependencies-omi2m9 branch September 2, 2026 22:42
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.

2 participants