From 831c2784aa5b8fd03b23fb19ccd55c0c3458d92c Mon Sep 17 00:00:00 2001 From: David <60177543+davd-gzl@users.noreply.github.com> Date: Mon, 5 Oct 2026 05:14:35 +0000 Subject: [PATCH 1/7] Add Interrail as a pass choice Interrail holders can now pick their pass in the header. Every train in the SNCF feed counts for them, since each takes a pass-holder reservation, and every result says that no open data tells whether a pass-holder seat is left. The data-refresh script now also writes public/data/interrail.json: the whole feed in a compact format that stores each service once with a bitmask of the dates it runs, so the full feed stays a small static file. Switching between a MAX pass and Interrail opens the page again on the other snapshot; the worker, the boot preload and the copy (11 locales) follow the pass. Refs #81 --- .github/workflows/update-data.yml | 2 +- docs/user-flows.md | 11 +++ index.html | 1 - public/api.json | 2 +- public/llms.txt | 2 +- public/theme.js | 20 +++++ scripts/fetch-data.ts | 29 ++++++- scripts/prerender.mjs | 4 + src/app.ts | 31 ++++++- src/config.ts | 6 ++ src/data/compact.ts | 129 ++++++++++++++++++++++++++++++ src/data/dataset.ts | 22 +++-- src/data/profile.ts | 56 ++++++++++++- src/i18n/ar.ts | 16 ++++ src/i18n/de.ts | 16 ++++ src/i18n/en.ts | 16 ++++ src/i18n/es.ts | 16 ++++ src/i18n/fr.ts | 16 ++++ src/i18n/index.ts | 12 +++ src/i18n/it.ts | 16 ++++ src/i18n/ja.ts | 16 ++++ src/i18n/ko.ts | 16 ++++ src/i18n/nl.ts | 16 ++++ src/i18n/pt.ts | 16 ++++ src/i18n/zh.ts | 16 ++++ src/main.ts | 7 +- src/search/search.worker.ts | 23 +++--- src/state/store.ts | 5 +- src/types.ts | 6 +- src/ui/form.ts | 4 + src/ui/shell.ts | 7 +- tests/core.test.ts | 1 + tests/interrail-app.test.ts | 71 ++++++++++++++++ tests/interrail.test.ts | 88 ++++++++++++++++++++ 34 files changed, 675 insertions(+), 40 deletions(-) create mode 100644 src/data/compact.ts create mode 100644 tests/interrail-app.test.ts create mode 100644 tests/interrail.test.ts diff --git a/.github/workflows/update-data.yml b/.github/workflows/update-data.yml index 555b045..071215f 100644 --- a/.github/workflows/update-data.yml +++ b/.github/workflows/update-data.yml @@ -37,7 +37,7 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add public/data/tgvmax.json public/data/meta.json + git add public/data/tgvmax.json public/data/meta.json public/data/interrail.json public/data/interrail-meta.json if git diff --cached --quiet; then echo "No changes to commit." else diff --git a/docs/user-flows.md b/docs/user-flows.md index 73fe039..c359e5a 100644 --- a/docs/user-flows.md +++ b/docs/user-flows.md @@ -214,6 +214,17 @@ the destination is reachable, with its calendar open. from any screen. (The two overlap — a known cleanup item.) A saved trip opens its ticket modal, whose "See all dates" opens the route page; a favorite prefills the Trip tab with that route alone. +- **Pass** — the header's pass picker: **MAX JEUNE** (default), **MAX SENIOR**, or + **Interrail**. Both MAX passes search the MAX snapshot (trains with a free MAX seat). + Interrail searches every train in the SNCF feed (`interrail.json`, see + `src/data/compact.ts`): each one takes a pass-holder reservation, international stops + included. No open data says whether an Interrail seat is left, so every Interrail result + page opens with a notice saying so, and copy that would claim a free MAX seat reads its + `_ir` variant instead ("green = at least one train"). Switching between a MAX pass + and Interrail opens the page again on the other snapshot, results shown straight away; + switching between the two MAX passes re-runs in place. Booking still opens SNCF Connect, + where pass-holder reservations are sold; "How does it work?" links Interrail's page on + French reservations. A `card=interrail` link loads the Interrail snapshot at boot. - **Settings** — theme, MAX Jeune/Senior, comfortable/compact, and Low-end mode (map off + reduced motion + compact) with a one-time nudge on weak devices; language. - **Mobile** — the form is a sheet that collapses to a search bar (a long route wraps it to diff --git a/index.html b/index.html index 716acb8..04846ff 100644 --- a/index.html +++ b/index.html @@ -38,7 +38,6 @@ -