--- phase: 02-dashboard-charts-and-layout plan: 01 type: execute wave: 1 depends_on: [] files_modified: - src/hooks/useMonthParam.ts - src/components/dashboard/MonthNavigator.tsx - src/components/dashboard/charts/ChartEmptyState.tsx - src/i18n/en.json - src/i18n/de.json autonomous: true requirements: [UI-DASH-01] must_haves: truths: - "useMonthParam hook reads month from URL search params and falls back to current month" - "MonthNavigator renders prev/next arrows and a dropdown listing all budget months" - "Navigating months updates URL without page reload" - "ChartEmptyState renders a muted placeholder with message text inside a chart card" - "i18n keys exist for month navigation and chart labels in both EN and DE" artifacts: - path: "src/hooks/useMonthParam.ts" provides: "Month URL state hook" exports: ["useMonthParam"] - path: "src/components/dashboard/MonthNavigator.tsx" provides: "Month navigation UI with arrows and dropdown" exports: ["MonthNavigator"] - path: "src/components/dashboard/charts/ChartEmptyState.tsx" provides: "Shared empty state placeholder for chart cards" exports: ["ChartEmptyState"] key_links: - from: "src/hooks/useMonthParam.ts" to: "react-router-dom" via: "useSearchParams" pattern: "useSearchParams.*month" - from: "src/components/dashboard/MonthNavigator.tsx" to: "src/hooks/useMonthParam.ts" via: "import" pattern: "useMonthParam" --- Create the month navigation infrastructure and chart empty state component for the dashboard. Purpose: Provides the URL-based month selection hook, the MonthNavigator UI (prev/next arrows + month dropdown), and a shared ChartEmptyState placeholder. These are foundational pieces consumed by all chart components and the dashboard layout in Plan 03. Output: Three new files (useMonthParam hook, MonthNavigator component, ChartEmptyState component) plus updated i18n files with new translation keys. @/home/jlmak/.claude/get-shit-done/workflows/execute-plan.md @/home/jlmak/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/02-dashboard-charts-and-layout/02-CONTEXT.md @.planning/phases/02-dashboard-charts-and-layout/02-RESEARCH.md From src/lib/types.ts: ```typescript export type CategoryType = "income" | "bill" | "variable_expense" | "debt" | "saving" | "investment" export interface Budget { id: string; user_id: string; start_date: string; end_date: string; currency: string; carryover_amount: number; created_at: string; updated_at: string; } ``` From src/hooks/useBudgets.ts: ```typescript export function useBudgets(): { budgets: Budget[]; loading: boolean; getBudget: (id: string) => ReturnType; createBudget: UseMutationResult; generateFromTemplate: UseMutationResult; updateItem: UseMutationResult; createItem: UseMutationResult; deleteItem: UseMutationResult; deleteBudget: UseMutationResult; } ``` From src/components/shared/PageShell.tsx: ```typescript interface PageShellProps { title: string; description?: string; action?: React.ReactNode; children: React.ReactNode; } export function PageShell({ title, description, action, children }: PageShellProps): JSX.Element ``` From src/components/ui/chart.tsx: ```typescript export type ChartConfig = { [k in string]: { label?: React.ReactNode; icon?: React.ComponentType } & ({ color?: string; theme?: never } | { color?: never; theme: Record<"light" | "dark", string> }) } ``` Task 1: Create useMonthParam hook and MonthNavigator component src/hooks/useMonthParam.ts, src/components/dashboard/MonthNavigator.tsx **useMonthParam hook** (`src/hooks/useMonthParam.ts`): - Import `useSearchParams` from `react-router-dom` - Read `month` param from URL search params - Fall back to current month as `YYYY-MM` format if param is missing - Provide `setMonth(newMonth: string)` that updates the param using callback form: `setSearchParams(prev => { prev.set("month", value); return prev })` (preserves other params per Pitfall 5 from research) - Provide `navigateMonth(delta: number)` that computes next/prev month using `new Date(year, mo - 1 + delta, 1)` for automatic year rollover - Return `{ month, setMonth, navigateMonth }` where month is `YYYY-MM` string - Export as named export `useMonthParam` **MonthNavigator component** (`src/components/dashboard/MonthNavigator.tsx`): - Accept props: `availableMonths: string[]` (array of `YYYY-MM` strings that have budgets), `t: (key: string) => string` - Import `useMonthParam` from hooks - Import `ChevronLeft`, `ChevronRight` from `lucide-react` - Import `Button` from `@/components/ui/button` - Import `Select`, `SelectContent`, `SelectItem`, `SelectTrigger`, `SelectValue` from `@/components/ui/select` - Layout: horizontal flex row with left arrow button, month selector (Select dropdown), right arrow button - Left arrow: `Button` variant="ghost" size="icon" with `ChevronLeft`, onClick calls `navigateMonth(-1)` - Right arrow: `Button` variant="ghost" size="icon" with `ChevronRight`, onClick calls `navigateMonth(1)` - Center: `Select` component whose value is the current `month` from hook. `onValueChange` calls `setMonth`. SelectTrigger shows formatted month name (use `Date` to format `YYYY-MM` into locale-aware month+year display, e.g., "March 2026") - SelectItems: map over `availableMonths` prop, displaying each as formatted month+year - Arrow buttons allow navigating beyond existing budgets (per user decision) -- they just call navigateMonth regardless - Dropdown only lists months that have budgets (per user decision) - Keep presentational -- accept `t()` as prop (follows Phase 1 pattern) - Export as named export `MonthNavigator` cd /home/jlmak/Projects/jlmak/SimpleFinanceDash && bun run build useMonthParam hook reads/writes month URL param with fallback to current month. MonthNavigator renders prev/next arrows and a dropdown of available months. Build passes with no type errors. Task 2: Create ChartEmptyState component and add i18n keys src/components/dashboard/charts/ChartEmptyState.tsx, src/i18n/en.json, src/i18n/de.json **ChartEmptyState component** (`src/components/dashboard/charts/ChartEmptyState.tsx`): - Create the `src/components/dashboard/charts/` directory - Accept props: `message: string`, `className?: string` - Render a muted placeholder inside a div matching chart area dimensions: `min-h-[250px] w-full` (matches ChartContainer sizing) - Center content vertically and horizontally: `flex items-center justify-center` - Background: `bg-muted/30 rounded-lg border border-dashed border-muted-foreground/20` - Message text: `text-sm text-muted-foreground` - This is a simple presentational component -- no chart logic, just the visual placeholder per user decision ("greyed-out chart outline with text overlay") - Export as named export `ChartEmptyState` **i18n keys** (add to both `en.json` and `de.json`): Add new keys under the existing `"dashboard"` object. Do NOT remove any existing keys. Add: ``` "monthNav": "Month", "noData": "No data to display", "expenseDonut": "Expense Breakdown", "incomeChart": "Income: Budget vs Actual", "spendChart": "Spending by Category", "budgeted": "Budgeted", "actual": "Actual", "noBudgetForMonth": "No budget for this month", "createBudget": "Create Budget", "generateFromTemplate": "Generate from Template" ``` German translations: ``` "monthNav": "Monat", "noData": "Keine Daten vorhanden", "expenseDonut": "Ausgabenverteilung", "incomeChart": "Einkommen: Budget vs. Ist", "spendChart": "Ausgaben nach Kategorie", "budgeted": "Budgetiert", "actual": "Tatsaechlich", "noBudgetForMonth": "Kein Budget fuer diesen Monat", "createBudget": "Budget erstellen", "generateFromTemplate": "Aus Vorlage generieren" ``` cd /home/jlmak/Projects/jlmak/SimpleFinanceDash && bun run build ChartEmptyState renders a muted placeholder with centered message text. i18n files contain all new chart and month navigation keys in both English and German. Build passes. - `bun run build` passes with no type errors - `src/hooks/useMonthParam.ts` exports `useMonthParam` with `{ month, setMonth, navigateMonth }` return type - `src/components/dashboard/MonthNavigator.tsx` exports `MonthNavigator` component - `src/components/dashboard/charts/ChartEmptyState.tsx` exports `ChartEmptyState` component - Both i18n files contain all new keys under `dashboard.*` - useMonthParam reads `?month=YYYY-MM` from URL, falls back to current month, provides setMonth and navigateMonth - MonthNavigator shows prev/next arrows and a month dropdown - ChartEmptyState renders a visually muted placeholder for empty charts - All new i18n keys present in en.json and de.json - `bun run build` passes After completion, create `.planning/phases/02-dashboard-charts-and-layout/02-01-SUMMARY.md`