Files
SimpleFinanceDash/.planning/phases/02-dashboard-charts-and-layout/02-01-PLAN.md

9.3 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
02-dashboard-charts-and-layout 01 execute 1
src/hooks/useMonthParam.ts
src/components/dashboard/MonthNavigator.tsx
src/components/dashboard/charts/ChartEmptyState.tsx
src/i18n/en.json
src/i18n/de.json
true
UI-DASH-01
truths artifacts key_links
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
path provides exports
src/hooks/useMonthParam.ts Month URL state hook
useMonthParam
path provides exports
src/components/dashboard/MonthNavigator.tsx Month navigation UI with arrows and dropdown
MonthNavigator
path provides exports
src/components/dashboard/charts/ChartEmptyState.tsx Shared empty state placeholder for chart cards
ChartEmptyState
from to via pattern
src/hooks/useMonthParam.ts react-router-dom useSearchParams useSearchParams.*month
from to via pattern
src/components/dashboard/MonthNavigator.tsx src/hooks/useMonthParam.ts import 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.

<execution_context> @/home/jlmak/.claude/get-shit-done/workflows/execute-plan.md @/home/jlmak/.claude/get-shit-done/templates/summary.md </execution_context>

@.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:

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:

export function useBudgets(): {
  budgets: Budget[]; loading: boolean;
  getBudget: (id: string) => ReturnType<typeof useBudgetDetail>;
  createBudget: UseMutationResult; generateFromTemplate: UseMutationResult;
  updateItem: UseMutationResult; createItem: UseMutationResult;
  deleteItem: UseMutationResult; deleteBudget: UseMutationResult;
}

From src/components/shared/PageShell.tsx:

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:

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.*`

<success_criteria>

  • 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 </success_criteria>
After completion, create `.planning/phases/02-dashboard-charts-and-layout/02-01-SUMMARY.md`