Skip to content

Add a required country to every place, a country API filter and a map country filter - #337

Merged
AnayDhawan merged 1 commit into
StudentSuite:mainfrom
propcgamer20-png:feat/country-field
Nov 2, 2026
Merged

AnayDhawan merged 1 commit into
StudentSuite:mainfrom
propcgamer20-png:feat/country-field

Conversation

@propcgamer20-png

Copy link
Copy Markdown
Member

What this changes

Fixes #288, steps 2 to 5 (step 1, the optional field in the schema, type and validator, was already on main).

Step 2, backfill (data/places/*.json). All 2,005 records now carry country. I mapped each lat/lng to a country with a one-off script using the Natural Earth 10m country polygons (point-in-polygon, then nearest border within 0.15 degrees for coastal points); the script is not committed and nothing new is a runtime dependency. 67 distinct codes, the largest being US 538, IN 220, TR 181, AE 122, BR 101, NG 95, CA 94, GB 87. Natural Earth tags Taiwan CN-TW; the field takes TW.

Checks on the mapping:

  • 5 city slugs resolve to more than one country, which the issue asked to list rather than guess: al_ain (AE, plus one SAT centre, Future International School id 52059, whose coordinates are in Oman and which OpenStreetMap also places in Oman), arona (Arona, Italy and Arona, Tenerife, Spain), kingston (Kingston, Ontario and Kingston, Pennsylvania), and the two below. Each record keeps the country of its own coordinates; splitting the slugs is left for a follow-up.
  • 20 records lie within about 4 km of another country's border. Natural Earth's border is coarse at the Detroit River and put Detroit City Hall (detroit-gov_offices-01) in Canada; an OpenStreetMap reverse lookup says US, so that one is set to US by hand. The other 19 agree with their addresses.
  • Two SAT centres filed under tokyo had coordinates in the wrong country, which the backfill exposed. 67350 International School of the Sacred Heart (Hiroo, Shibuya) pointed at Thalassery, Kerala, India; it is now 35.652712, 139.72131 (OpenStreetMap). 67294 Global Indian International School Tokyo, Nishi-Kasai pointed at Kuala Lumpur, Malaysia; it is now 35.65675, 139.85882 (the coordinates on its Wikipedia page, which I could not cross-check against OpenStreetMap, so the pin is the campus neighbourhood). Both gmaps_link values were updated to match.

Step 3, required. country is in required in data/places.schema.json, so npm run validate now fails on a missing country and on "india" (see Proof). It stays optional on the TypeScript Place type because a signed-in visitor's private saved places have none. data/CONTRIBUTING.md and the three docs-page examples show the field.

Step 4, API. GET /api/places?country=in matches case-insensitively (src/lib/places-api.ts, src/app/api/places/route.ts). A value that is not two letters, such as India, is a 400; so is a well-formed code no place uses (ZZ), via a new unknownCountryError. /docs/places-api describes the parameter.

Step 5, map. A "Filter by country" select (country-filter.tsx) in the map panel; picking a country narrows the city filter to its cities and clears a selected city that is not in it. country is a share-link parameter (src/lib/share.ts), so it survives a reload and works for /embed too, and it is part of Reset and of the active-filter summary.

Proof

  • Acceptance criteria, run locally: with "country": "india" on the first record npm run validate:places exits 1 (country must be a two-letter upper-case ISO 3166-1 alpha-2 code); with the field removed it reports missing required field "country"; restored, npm run validate passes. A node one-liner over data/places/*.json reports 2005 records and 0 without country. GET /api/places?country=in&limit=1 returns 200 with country: "IN"; country=ZZ and country=India return 400 (route tests).
  • New tests: 15 across places-api.test.ts, route.test.ts, share.test.ts, places.test.ts and places-map.test.tsx (country filter, URL round trip, shared link, city dropped on country change).
  • npm run typecheck, npm run lint, npm run format:check clean; npm run build succeeds; unit tests all pass.

Not verified

  • I did not open /map in a browser, so the layout of the new select in the sidebar and the mobile sheet is unchecked; behaviour is covered by the component tests.
  • The country of every record is the country of its coordinates. If a coordinate is wrong, the country is wrong with it (that is how the two Tokyo records were found), so there may be more such records that sit inside a plausible country.
  • Intl.DisplayNames names the countries; I did not check how it renders in every browser.

Type of change

  • Code or fix
  • New public place(s)
  • New or updated benefit guide
  • New or updated resource link
  • Docs

@vercel

vercel Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

@propcgamer20-png is attempting to deploy a commit to the studentsuite Team on Vercel.

A member of the Team first needs to authorize it.

@AnayDhawan
AnayDhawan merged commit 9a1fca7 into StudentSuite:main Nov 2, 2026
4 of 5 checks passed
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.

Places have no country field, so no country search, filter or API param

2 participants