docs(04-01): complete locale-aware formatCurrency plan

This commit is contained in:
2026-03-12 09:24:54 +01:00
parent eb1bb8aeec
commit 1412aacf92
4 changed files with 122 additions and 10 deletions

View File

@@ -45,7 +45,7 @@ Requirements for this milestone. Each maps to roadmap phases.
### Bug Fixes
- [ ] **FIX-01**: `formatCurrency` uses the user's locale preference instead of hardcoded `de-DE`
- [x] **FIX-01**: `formatCurrency` uses the user's locale preference instead of hardcoded `de-DE`
- [x] **FIX-02**: `InlineEditRow` extracted into a shared component (currently duplicated in BillsTracker, VariableExpenses, DebtTracker)
## v2 Requirements
@@ -111,7 +111,7 @@ Which phases cover which requirements. Updated during roadmap creation.
| STATE-02 | Phase 3 | Complete |
| STATE-03 | Phase 3 | Complete |
| IXTN-04 | Phase 4 | Pending |
| FIX-01 | Phase 4 | Pending |
| FIX-01 | Phase 4 | Complete |
**Coverage:**
- v1 requirements: 23 total

View File

@@ -74,7 +74,7 @@ Plans:
1. All chart fills (donut slices, bar segments) use the semantic category colors from `lib/palette.ts` — "Bills" is the same color in the donut chart as it is in the FinancialOverview table
2. Chart tooltips display values formatted with the budget's currency (e.g., "1,234.56" not "1234.56")
3. The `formatCurrency` function uses the user's locale preference from their settings instead of the hardcoded `de-DE` — an English-locale user sees their numbers formatted correctly
**Plans:** 2 plans
**Plans:** 1/2 plans executed
Plans:
- [ ] 04-01-PLAN.md — TDD: formatCurrency locale parameter fix (FIX-01)
- [ ] 04-02-PLAN.md — Chart tooltip wiring and locale threading (IXTN-04)
@@ -89,4 +89,4 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4
| 1. Design Token Foundation | 2/2 | Complete | 2026-03-11 |
| 2. Layout and Brand Identity | 0/2 | In progress | - |
| 3. Interaction Quality and Completeness | 0/4 | Not started | - |
| 4. Chart Polish and Bug Fixes | 0/2 | Not started | - |
| 4. Chart Polish and Bug Fixes | 1/2 | In Progress| |

View File

@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.0
milestone_name: milestone
status: planning
stopped_at: Completed 03-03-PLAN.md
last_updated: "2026-03-11T21:41:42.367Z"
stopped_at: Completed 04-01-PLAN.md
last_updated: "2026-03-12T08:24:41.212Z"
last_activity: 2026-03-11 — Roadmap created from requirements and research
progress:
total_phases: 4
completed_phases: 3
total_plans: 8
completed_plans: 8
total_plans: 10
completed_plans: 9
percent: 0
---
@@ -58,6 +58,7 @@ Progress: [░░░░░░░░░░] 0%
| Phase 03-interaction-quality-and-completeness P01 | 2m | 2 tasks | 5 files |
| Phase 03-interaction-quality-and-completeness P02 | 5 | 2 tasks | 3 files |
| Phase 03-interaction-quality-and-completeness P03 | 5 | 2 tasks | 4 files |
| Phase 04-chart-polish-and-bug-fixes P01 | 1 | 2 tasks | 2 files |
## Accumulated Context
@@ -87,6 +88,8 @@ Recent decisions affecting current work:
- [Phase 03-interaction-quality-and-completeness]: CategoriesPage loading state initialized true, set false in finally block to prevent empty-state flash
- [Phase 03-interaction-quality-and-completeness]: triggerFlash uses two separate state vars (flashRowId/errorRowId) for flash feedback — no race conditions between success and error states
- [Phase 03-interaction-quality-and-completeness]: Empty tracker sections show tinted skeleton card (not null) — section always visible with palette-tinted placeholders when no items exist
- [Phase 04-chart-polish-and-bug-fixes]: formatCurrency third parameter defaults to 'en', replacing hardcoded 'de-DE' — all existing 2-arg call sites now produce English formatting (FIX-01)
- [Phase 04-chart-polish-and-bug-fixes]: Defensive locale || 'en' guard in formatCurrency prevents RangeError when empty string is passed
### Pending Todos
@@ -99,6 +102,6 @@ None yet.
## Session Continuity
Last session: 2026-03-11T21:37:48.889Z
Stopped at: Completed 03-03-PLAN.md
Last session: 2026-03-12T08:24:41.210Z
Stopped at: Completed 04-01-PLAN.md
Resume file: None

View File

@@ -0,0 +1,109 @@
---
phase: 04-chart-polish-and-bug-fixes
plan: 01
subsystem: ui
tags: [intl, locale, currency, formatting, typescript, vitest]
# Dependency graph
requires: []
provides:
- "Locale-aware formatCurrency(amount, currency, locale='en') with 'en' default"
- "Unit tests covering English, German, USD, zero, negative, and empty-string edge cases"
affects:
- 04-02-chart-tooltips
- any component calling formatCurrency
# Tech tracking
tech-stack:
added: []
patterns:
- "Intl.NumberFormat locale parameter passed from call site — no hardcoded locale in utility functions"
key-files:
created:
- frontend/src/lib/format.test.ts
modified:
- frontend/src/lib/format.ts
key-decisions:
- "formatCurrency third parameter defaults to 'en', replacing hardcoded 'de-DE' — all existing 2-arg call sites now produce English formatting (FIX-01)"
- "Defensive locale || 'en' guard prevents RangeError when empty string is passed"
patterns-established:
- "TDD pattern: write failing test first (RED commit), then implement (GREEN commit) — verified by vitest run between steps"
requirements-completed: [FIX-01]
# Metrics
duration: 5min
completed: 2026-03-12
---
# Phase 4 Plan 01: Locale-Aware formatCurrency Summary
**`Intl.NumberFormat` locale parameter added to `formatCurrency` with `'en'` default, replacing hardcoded `'de-DE'` — English users now see `1,234.56` instead of `1.234,56`**
## Performance
- **Duration:** 5 min
- **Started:** 2026-03-12T08:23:13Z
- **Completed:** 2026-03-12T08:28:00Z
- **Tasks:** 2 (TDD RED + TDD GREEN)
- **Files modified:** 2
## Accomplishments
- Added optional `locale` parameter to `formatCurrency` with `'en'` as the default
- Removed the hardcoded `'de-DE'` locale that was forcing German number formatting for all users
- Defensive `locale || 'en'` guard prevents `RangeError` on empty string input
- 8 unit tests cover English formatting, German formatting, USD, zero, negative amounts, and edge cases
- All 51 frontend tests pass with no regressions
## Task Commits
Each task was committed atomically:
1. **TDD RED: Failing tests for locale-aware formatCurrency** - `6ffce76` (test)
2. **TDD GREEN: Implement locale parameter** - `eb1bb8a` (feat)
_Note: TDD tasks have two commits (test → feat). No refactor needed._
## Files Created/Modified
- `frontend/src/lib/format.test.ts` - 8 unit tests for locale behavior, defaults, and edge cases
- `frontend/src/lib/format.ts` - Updated function signature with `locale: string = 'en'` parameter
## Decisions Made
- Third parameter defaults to `'en'` (not `'en-US'` or `'de-DE'`) — bare `'en'` is a valid BCP 47 tag and produces comma-grouped, period-decimal output consistent with user expectations for English locale
- `locale || 'en'` fallback is intentional — empty string is not a valid BCP 47 locale and `Intl.NumberFormat('')` throws `RangeError` in some environments
## Deviations from Plan
None - plan executed exactly as written.
## Issues Encountered
None. Pre-existing `act(...)` warnings in unrelated test files (`InlineEditCell.test.tsx`, `CategoriesPage.test.tsx`) were observed but are out of scope per deviation rules — logged to deferred items.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- `formatCurrency(amount, currency, locale)` is ready for use in chart tooltips (04-02)
- All call sites currently pass 2 args and will automatically receive English formatting
- Callers can pass user's `preferred_locale` from API response as the third arg
## Self-Check: PASSED
- `frontend/src/lib/format.ts` — FOUND
- `frontend/src/lib/format.test.ts` — FOUND
- `04-01-SUMMARY.md` — FOUND
- Commit `6ffce76` (test RED) — FOUND
- Commit `eb1bb8a` (feat GREEN) — FOUND
---
*Phase: 04-chart-polish-and-bug-fixes*
*Completed: 2026-03-12*