Two visit steps join the getting-started path: "Browse categories and
keywords" (5th) and "Browse the reports" (8th). Nothing in the database
counts them: they are done by "Got it" on their card, stored as
onboarding_acknowledged_<key> in user_preferences (no migration).
- computeChecklist: eight rows; the visit rows are locked until the
profile's visit steps are initialized, so a finished path does not
flash a "Next step" before they are marked done.
- initializeVisitSteps: once per profile, after the first successful
load with the Budget entitlement known; acknowledges both steps when
every other step is done or skipped, then sets the flag. No
transaction (D16): idempotent writes, the flag last.
- Reducer: ACKNOWLEDGE wins over an older snapshot like SKIP but keeps
the card latch, so the card says "Done." and offers the next step.
- StepCard: "Got it" before "Skip this step" when onAcknowledge is
given; OnboardingStepCard passes it for a visit step.
- Banner counter, card rank and end of path wait for
budgetReady && visitStepsInitialized; the list shows the visit rows
"pending" until then.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 15 test files whose fake t returned the bare key (the 12 of the
issue, plus the three category render tests added by #423) now mock
react-i18next with i18nMock. Assertions naming a displayed text are
rewritten in the marked form, t(key[options]), so a text that skipped
t fails them. Components without such an assertion get one:
PriceFetchControl, PriceFetchConsentToggle (rendered through the hook
harness, its loading slot preset), CategoryDetailPanel, SourceList and
SourceCard, and the region label of OnboardingChecklist.
Each component was proved by a mutation removing one t call: every one
turns at least one test red (exit 1).
Refs #389
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The getting-started path now follows the user: AppShell mounts
OnboardingBanner at the top of <main>, in the page flow, and the
provider's mode keeps it off a hidden path, the dashboard of a profile
without transactions, a page that carries a step card and the first
load. The banner shows "Getting started n/N" once the Budget
entitlement is known, the next step linked with its navigation state,
"Show the list", which unfolds the detailed list in place, and "Hide";
at the end, the closing message, "Open the guide" and "Close". Each
route mounts its own banner slot, so a page always starts folded.
The dashboard's compact bar and the compact mode of
OnboardingChecklist are gone (D7). The detailed list reads each state
out to screen readers, shows a skipped step with its badge and
"Resume", and gives every link to a step the same navigation state
(stepNavState), with the guided entry for the manual category.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A profile without any transaction now opens a dashboard that says what to
do: a welcome card with the expanded getting-started checklist and one
primary action towards the import page, instead of widgets showing 0 $.
With transactions, the compact checklist sits between the title and the
filter panel until it is complete or dismissed.
- `EmptyState` (pure, dashed card from the import source list; a `to`
action renders a react-router `<Link>`, an `onClick` action a button)
- `OnboardingChecklist` (pure, expanded and compact modes; undone rows
link to their route, the locked Budget row shows a lock, the "Base and
up" label and links to the license card; neutral budget row and hidden
counter until the entitlement is known)
- `DashboardEmptyState` composes both
- `DashboardPage` branches on the hook `status`: loading renders the title,
help and banner only; error falls back to the v0.15.0 page without the
list and logs a warning; ready with zero transactions renders the empty
state outside the `isLoading` veil
- `useOnboardingChecklist` exposes `counters` and `error` for the page
- Users settings: "Show the getting-started checklist" button in the Guide
section, visible only when the preference is set, with an inline
confirmation after the click
- FR + EN keys `dashboard.empty.*`, `onboarding.checklist.*`,
`settings.users.onboarding.*`
Tests: `EmptyState.test.tsx` and `OnboardingChecklist.test.tsx` by direct
call (FilterPanel pattern). No DB migration. CHANGELOG left to #357.
Resolves#352
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>