Skip to content

feat(ui): visual journey map + pure-state interactivity (trust-safe gamification) - #18

Open
AnikaWilliams wants to merge 2 commits into
feat/calmer-uifrom
feat/interactive-journey
Open

AnikaWilliams wants to merge 2 commits into
feat/calmer-uifrom
feat/interactive-journey

Conversation

@AnikaWilliams

Copy link
Copy Markdown
Owner

What

Make the relocation a visible, interactive journey — every game mechanic a faithful projection of state the app already computes, so it's engaging without trivializing the legal stakes.

  • 🗺️ Flagship Journey Map — the flat "Your journey" list becomes a connected, chapter-grouped visual path (chapters from an authored category→chapter map in src/utils/journeyChapters.ts: Before you go · Your permit · After you arrive · Settling in). Each node shows its real state (done / available / current / locked) from statusFor() and a per-node document meter from docProgress(). Available nodes are clickable; locked nodes stay fully readable (only "Mark done" is gated) and show the specific "Unlocks after: …" prerequisite.
  • 📊 Per-task document meter on the active card (the nearer goal-gradient).
  • ✨ Instant motivation micro-confirmation (derived from the real applicableTasks count).
  • 👋 Non-punitive "Welcome back" continuity (no streaks, countdowns, or shaming).
  • 🎉 Per-chapter milestone notes extending the existing momentum toast.

Trust posture (the important part)

No dark patterns. No streaks/streak-loss, no countdowns/fake urgency, no points/XP/leaderboards, no celebration that reads as legal approval. Every meter reflects only real done/skip state (skipped docs count as resolved). A unit test (tests/journeyChapters.test.ts) bans outcome/approval words ("approved", "all set", "ready to move") in chapter copy — a durable regression guard. The disclaimer modal gate, provenance (source + last-verified on every claim), Impressum, and the required Russia-sanctions + route-not-covered notices are untouched. prefers-reduced-motion respected; journey nodes keyboard-accessible.

Verification

astro check 0 errors · build + provenance gate (15 pages) · 281/281 tests (incl. the route + plan-correctness tripwires, unchanged) · a11y PASS (WCAG 2.2 AA audited — keyboard nodes, accessible names, reduced-motion) · trust/dark-pattern review PASS · full flow confirmed live (a 6-node journey map for the family route with honest "unlocks after" reasons + document meters).

Deferred (flagged in research)

Endowed head-start pre-credit; wizard auto-advance; the interactive Swiss canton map (needs sourced/verified boundary geometry not in the repo).

Merge order (stacked)

Base is feat/calmer-ui (PR #17) so this shows only the journey diff. Sequence: #16 (cantonal notes) → #17 (calmer UI, after lawyer sign-off) → this. As always, develop → main is yours.

🤖 Generated with Claude Code

…, trust-safe)

Design-research-led: make the relocation a VISIBLE journey while keeping every
mechanic a faithful projection of state the app already computes.

- Flagship JOURNEY MAP: the flat 'Your journey' list becomes a connected,
  chapter-grouped visual path (chapters from an authored category->chapter map
  in src/utils/journeyChapters.ts). Each node shows real state
  (done/available/current/locked) from statusFor() + a per-node document meter
  from docProgress(); available nodes clickable; LOCKED nodes stay readable
  (only Mark-done gated) and show the specific 'Unlocks after: <prereq>' reason.
- Per-task document meter on the active card (nearer goal-gradient).
- Instant motivation micro-confirmation (from the real applicableTasks count).
- Non-punitive 'Welcome back' continuity (no streaks/countdowns/shaming).
- Per-chapter milestone notes extending the existing momentum toast.

NO dark patterns: no streaks/countdowns/points/false-approval; rewards reflect
only real done/skip state; a unit test (tests/journeyChapters.test.ts) bans
outcome/approval words in chapter copy. Disclaimer modal gate, provenance,
Impressum, Russia-sanctions + route-not-covered notices untouched;
prefers-reduced-motion respected; keyboard-accessible nodes.

Deferred: endowed head-start pre-credit, wizard auto-advance, interactive
canton map (needs sourced boundary geometry).

Verified: astro check 0 errors; build + provenance gate (15 pages); 281/281
tests; a11y PASS (WCAG 2.2 AA audited); trust/dark-pattern review PASS; full
flow confirmed live (6-node journey map, honest unlocks-after, doc meters).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@AnikaWilliams

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0be009ad4d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/CorridorApp.tsx Outdated
Comment on lines +1246 to +1252
const orderedChapters = [...present.values()].sort(compareChapters);

return orderedChapters.map((chapter) => ({
chapter,
items: orderedTasks
.map((task, i) => ({ task, stepIndex: i + 1 }))
.filter(({ task }) => chapterForCategory(task.category).id === chapter.id),

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 Badge Keep chapter grouping in topological order

Sorting the chapters and then collecting every task in each chapter reorders the dependency-respecting orderedTasks array. For example, on the US→Ireland work route, employment-permit-type is labeled Step 2 and depends on employment-permit (Step 1), but its employment category places it in “Before you go,” so it renders before Step 1 in “Your permit.” This makes the visual path show locked dependents ahead of their prerequisites—and produces sequences such as Step 2 followed by Step 1—across work/study routes. Group contiguous runs instead of sorting tasks by chapter.

Useful? React with 👍 / 👎.

Comment thread src/components/CorridorApp.tsx Outdated
Comment on lines +1281 to +1287
const stateWord = done
? 'done'
: isActive
? 'current step, available'
: available
? 'available'
: 'locked';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Announce selected locked nodes as locked

When a user selects one of the newly clickable locked nodes, both isActive and locked are true, but this ternary prioritizes isActive and announces “current step, available.” Screen-reader users therefore hear that the task is available even though its completion button is disabled and the same accessible name may subsequently say it unlocks after another task. Give the locked state precedence while retaining the current-step indication.

Useful? React with 👍 / 👎.

…nodes as locked

groupTasksByChapter now carves contiguous runs out of the topological order
instead of sorting chapters and collecting tasks per chapter, so a locked
dependent can never render ahead of its prerequisite (e.g. employment-permit-
type before employment-permit on the US->Ireland work route). Run keys are
unique so non-contiguous chapter runs don't collide as React keys. JourneyNode
uses a shared stateWordFor helper that gives locked precedence, so a selected
locked node is announced 'current step, locked' rather than 'available'.

Regression tests cover both behaviours.
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