Files
SimpleFinanceDash/.planning/phases/04-chart-polish-and-bug-fixes/04-02-PLAN.md

220 lines
9.0 KiB
Markdown

---
phase: 04-chart-polish-and-bug-fixes
plan: 02
type: execute
wave: 2
depends_on:
- "04-01"
files_modified:
- frontend/src/pages/DashboardPage.tsx
- frontend/src/components/ExpenseBreakdown.tsx
- frontend/src/components/AvailableBalance.tsx
autonomous: true
requirements:
- IXTN-04
must_haves:
truths:
- "Hovering over an ExpenseBreakdown pie slice shows a tooltip with the category name and currency-formatted value"
- "Hovering over an AvailableBalance donut slice shows a tooltip with the segment name and currency-formatted value"
- "Chart tooltip values use the budget's currency code (not hardcoded EUR)"
- "Chart tooltip values use the user's preferred_locale for number formatting"
- "AvailableBalance center text also receives the user's locale for formatting"
artifacts:
- path: "frontend/src/components/ExpenseBreakdown.tsx"
provides: "Custom Recharts Tooltip with formatted currency"
contains: "formatCurrency"
- path: "frontend/src/components/AvailableBalance.tsx"
provides: "Custom Recharts Tooltip on donut chart + locale-aware center text"
contains: "Tooltip"
- path: "frontend/src/pages/DashboardPage.tsx"
provides: "Locale threading from useAuth to chart components"
contains: "useAuth"
key_links:
- from: "frontend/src/pages/DashboardPage.tsx"
to: "frontend/src/hooks/useAuth.ts"
via: "useAuth() hook call to get user.preferred_locale"
pattern: "useAuth\\(\\)"
- from: "frontend/src/pages/DashboardPage.tsx"
to: "frontend/src/components/ExpenseBreakdown.tsx"
via: "locale prop passed to ExpenseBreakdown"
pattern: "locale=.*userLocale"
- from: "frontend/src/pages/DashboardPage.tsx"
to: "frontend/src/components/AvailableBalance.tsx"
via: "locale prop passed to AvailableBalance"
pattern: "locale=.*userLocale"
- from: "frontend/src/components/ExpenseBreakdown.tsx"
to: "frontend/src/lib/format.ts"
via: "formatCurrency called inside Tooltip content renderer"
pattern: "formatCurrency.*budget\\.currency.*locale"
- from: "frontend/src/components/AvailableBalance.tsx"
to: "frontend/src/lib/format.ts"
via: "formatCurrency called inside Tooltip content renderer and center text"
pattern: "formatCurrency.*budget\\.currency.*locale"
---
<objective>
Wire custom currency-formatted tooltips into both chart components and thread the user's locale preference from `useAuth` through `DashboardPage` to the charts. After this plan, hovering over any chart segment shows a properly formatted currency value.
Purpose: IXTN-04 — chart tooltips currently show raw numbers without currency formatting
Output: Both charts have styled tooltips, locale flows from user settings to chart display
</objective>
<execution_context>
@/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md
@/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/04-chart-polish-and-bug-fixes/04-RESEARCH.md
@.planning/phases/04-chart-polish-and-bug-fixes/04-01-SUMMARY.md
<interfaces>
<!-- Key types and contracts the executor needs -->
From frontend/src/lib/format.ts (after Plan 01):
```typescript
export function formatCurrency(amount: number, currency?: string, locale?: string): string
```
From frontend/src/lib/api.ts:
```typescript
export interface User {
// ...
preferred_locale: string
// ...
}
export interface BudgetDetail {
id: string
name: string
currency: string
// ...
totals: BudgetTotals
items: BudgetItem[]
}
```
From frontend/src/hooks/useAuth.ts:
```typescript
export function useAuth(): {
user: User | null
loading: boolean
login: (email: string, password: string) => Promise<void>
// ...
}
```
From frontend/src/components/ExpenseBreakdown.tsx (current):
```typescript
interface Props {
budget: BudgetDetail
}
// Needs locale prop added
```
From frontend/src/components/AvailableBalance.tsx (current):
```typescript
interface Props {
budget: BudgetDetail
}
// Needs locale prop added, also needs Tooltip import added
```
From frontend/src/lib/palette.ts:
```typescript
export type CategoryType = 'income' | 'bill' | 'variable_expense' | 'debt' | 'saving' | 'investment' | 'carryover'
export const palette: Record<CategoryType, { light: string; medium: string; base: string }>
```
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Add locale prop and custom Tooltip to both chart components</name>
<files>frontend/src/components/ExpenseBreakdown.tsx, frontend/src/components/AvailableBalance.tsx</files>
<action>
**ExpenseBreakdown.tsx:**
1. Add `locale?: string` to the `Props` interface
2. Import `formatCurrency` from `@/lib/format`
3. Replace bare `<Tooltip />` with a custom `content` renderer:
```tsx
<Tooltip
content={({ active, payload }) => {
if (!active || !payload?.length) return null
const item = payload[0]
return (
<div className="rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl">
<p className="font-medium text-foreground">{item.name}</p>
<p className="font-mono tabular-nums text-muted-foreground">
{formatCurrency(Number(item.value), budget.currency, locale)}
</p>
</div>
)
}}
/>
```
4. Destructure `locale = 'en'` from props with default
**AvailableBalance.tsx:**
1. Add `locale?: string` to the `Props` interface
2. Import `Tooltip` from `recharts` (add to existing import)
3. Add `<Tooltip>` with identical custom `content` renderer pattern inside the `<PieChart>` after the `<Pie>` element
4. Update the center text `formatCurrency(available, budget.currency)` call to include locale: `formatCurrency(available, budget.currency, locale)`
5. Destructure `locale = 'en'` from props with default
**Do NOT** use `ChartContainer` or `ChartTooltipContent` from shadcn — these charts use raw Recharts primitives and the project rule forbids editing shadcn ui source files.
**Tooltip styling** must match shadcn design system: `rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl` — this replicates the ChartTooltipContent styling without importing it.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run</automated>
</verify>
<done>Both chart components accept an optional locale prop, render custom tooltips with formatCurrency, and AvailableBalance center text passes locale to formatCurrency</done>
</task>
<task type="auto">
<name>Task 2: Thread user locale from useAuth through DashboardPage to chart components</name>
<files>frontend/src/pages/DashboardPage.tsx</files>
<action>
1. Add `useAuth` import: `import { useAuth } from '@/hooks/useAuth'`
2. Inside `DashboardPage` function body, call: `const { user } = useAuth()`
3. Derive locale with defensive fallback: `const userLocale = user?.preferred_locale || 'en'`
4. Pass `locale={userLocale}` prop to both chart component instances:
- `<AvailableBalance budget={current} locale={userLocale} />`
- `<ExpenseBreakdown budget={current} locale={userLocale} />`
5. Do NOT pass locale to other components (BillsTracker, VariableExpenses, DebtTracker, FinancialOverview) — those components use formatCurrency with the new 'en' default which is correct. A full locale-threading pass across all table components is out of scope for this phase.
The `useAuth()` hook is idempotent — it reads from the same React state already initialized by `App.tsx`, so there is no double-fetch concern.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run</automated>
</verify>
<done>DashboardPage calls useAuth(), derives userLocale, and passes it to both ExpenseBreakdown and AvailableBalance as a locale prop</done>
</task>
</tasks>
<verification>
1. `cd frontend && bun vitest run` — full test suite passes
2. `cd frontend && bun run build` — production build succeeds with no TypeScript errors
3. Manual: hover over ExpenseBreakdown pie slices — tooltip shows category name + formatted currency
4. Manual: hover over AvailableBalance donut slices — tooltip shows segment name + formatted currency
5. Manual: AvailableBalance center text formats using user's locale preference
</verification>
<success_criteria>
- ExpenseBreakdown shows formatted currency tooltip on hover (not raw numbers)
- AvailableBalance shows formatted currency tooltip on hover (previously had no tooltip)
- AvailableBalance center text uses the user's locale for formatting
- DashboardPage reads user.preferred_locale via useAuth and threads it to both chart components
- Full test suite and build pass with no errors
</success_criteria>
<output>
After completion, create `.planning/phases/04-chart-polish-and-bug-fixes/04-02-SUMMARY.md`
</output>