Files
SimpleFinanceDash/.planning/phases/06-template-frontend-and-workflow-replacement/06-02-PLAN.md

257 lines
13 KiB
Markdown

---
phase: 06-template-frontend-and-workflow-replacement
plan: 02
type: execute
wave: 2
depends_on: ["06-01"]
files_modified:
- frontend/src/components/BudgetSetup.tsx
- frontend/src/components/BudgetSetup.test.tsx
- frontend/src/pages/DashboardPage.tsx
- frontend/src/pages/DashboardPage.test.tsx
- frontend/src/lib/api.ts
- frontend/src/i18n/en.json
- frontend/src/i18n/de.json
- frontend/src/components/BillsTracker.tsx
- frontend/src/components/VariableExpenses.tsx
- frontend/src/components/DebtTracker.tsx
autonomous: false
requirements: [TMPL-03, TMPL-06]
must_haves:
truths:
- "Clicking 'Create Budget' opens a month picker instead of the old manual setup form"
- "Selecting a month auto-generates a budget from the user's template via POST /api/budgets/generate"
- "Fixed template items appear in the generated budget with their template amounts"
- "Variable template items appear in the generated budget with zero/blank amounts"
- "If a budget already exists for the selected month (409), the app navigates to that existing budget"
- "The 'Copy from previous' select dropdown is no longer visible anywhere in the app"
- "Budget item rows in tracker tables show an item_tier badge (Fixed/Variable/One-off)"
artifacts:
- path: "frontend/src/components/BudgetSetup.tsx"
provides: "Month-based budget creation via template generation"
contains: "generate"
- path: "frontend/src/pages/DashboardPage.tsx"
provides: "Dashboard wired to template-based budget creation"
contains: "generate"
- path: "frontend/src/components/BillsTracker.tsx"
provides: "Bills tracker table with item_tier badge rendering"
contains: "item_tier"
- path: "frontend/src/components/VariableExpenses.tsx"
provides: "Variable expenses tracker table with item_tier badge rendering"
contains: "item_tier"
- path: "frontend/src/components/DebtTracker.tsx"
provides: "Debt tracker table with item_tier badge rendering"
contains: "item_tier"
key_links:
- from: "frontend/src/components/BudgetSetup.tsx"
to: "/api/budgets/generate"
via: "budgets.generate API call"
pattern: "budgets\\.generate"
- from: "frontend/src/pages/DashboardPage.tsx"
to: "BudgetSetup"
via: "component import"
pattern: "BudgetSetup"
- from: "frontend/src/components/BillsTracker.tsx"
to: "Badge"
via: "Badge component rendering item_tier"
pattern: "item_tier.*Badge|Badge.*item_tier"
- from: "frontend/src/components/VariableExpenses.tsx"
to: "Badge"
via: "Badge component rendering item_tier"
pattern: "item_tier.*Badge|Badge.*item_tier"
- from: "frontend/src/components/DebtTracker.tsx"
to: "Badge"
via: "Badge component rendering item_tier"
pattern: "item_tier.*Badge|Badge.*item_tier"
---
<objective>
Replace the manual budget creation and copy-from-previous workflow with template-based auto-generation, and display item tier badges in tracker tables.
Purpose: TMPL-03 requires auto-generating budgets from templates when navigating to a new month. TMPL-06 requires removing the old copy-from-previous flow entirely. Together these replace the legacy workflow with the new template system.
Output: Simplified budget creation flow using month picker + template generation, item tier visibility in trackers.
</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/STATE.md
@.planning/phases/05-template-data-model-and-api/05-02-SUMMARY.md
@.planning/phases/06-template-frontend-and-workflow-replacement/06-01-PLAN.md
<interfaces>
<!-- From Plan 06-01 (will exist when this plan runs) -->
From frontend/src/lib/api.ts (after Plan 01):
```typescript
export type ItemTier = 'fixed' | 'variable' | 'one_off'
export interface BudgetItem {
// ... existing fields ...
item_tier: ItemTier
}
export const budgets = {
// ... existing methods ...
generate: (data: { month: string, currency: string }) =>
request<BudgetDetail>('/budgets/generate', { method: 'POST', body: JSON.stringify(data) }),
copyFrom: (id: string, srcId: string) => // TO BE REMOVED
request<BudgetDetail>(`/budgets/${id}/copy-from/${srcId}`, { method: 'POST' }),
}
```
From frontend/src/components/BudgetSetup.tsx (current):
```typescript
interface Props {
existingBudgets: Budget[]
onCreated: () => void
onCancel: () => void
}
// Currently: manual form with name, dates, currency, carryover, copy-from-previous select
```
From backend API (Phase 5):
- POST /api/budgets/generate with { month: "2026-04", currency: "EUR" }
- Returns 201 with BudgetDetail (budget auto-named from locale month)
- Returns 409 with { error: "...", budget_id: "..." } if budget exists for that month
- If user has no template: creates empty budget with zero items
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Replace BudgetSetup with template-based month picker and remove copy-from-previous</name>
<files>frontend/src/components/BudgetSetup.tsx, frontend/src/components/BudgetSetup.test.tsx, frontend/src/pages/DashboardPage.tsx, frontend/src/pages/DashboardPage.test.tsx, frontend/src/lib/api.ts, frontend/src/i18n/en.json, frontend/src/i18n/de.json</files>
<action>
1. **Rewrite `frontend/src/components/BudgetSetup.tsx`** to a simplified month-based creation flow:
- Keep the same Props interface: `{ existingBudgets: Budget[], onCreated: () => void, onCancel: () => void }`
- Replace the full form with a compact Card containing:
- A month input (`<Input type="month" />`) for selecting the target month (e.g. "2026-04")
- A currency input (keep the existing currency Input, default "EUR")
- A "Generate" button (not "Create") with Spinner on loading
- On submit:
- Call `budgets.generate({ month: selectedMonth, currency })` (the month format from `<input type="month">` is "YYYY-MM" which matches the API)
- On success (201): call `onCreated()` to refresh the budget list
- On error with status 409: parse the response body to get `budget_id`, then call `onCreated()` (the dashboard will refresh and show the existing budget). Optionally show a toast or just silently navigate.
- The `ApiError` class in api.ts only captures the error message. For 409 handling, update the generate function to handle this specially: catch the ApiError, check if status === 409, and in the BudgetSetup component handle that case by calling `onCreated()` (the existing budget will appear in the list).
- Remove ALL references to `copyFromId`, `copyFrom`, `budgetsApi.copyFrom`
- Remove name, startDate, endDate, carryover fields (the generate endpoint auto-computes these from the month parameter and user locale)
- Update the Card header text to use `t('budget.generate')` instead of `t('budget.setup')`
- Disable Generate button when month is empty or saving is true
2. **Update `frontend/src/lib/api.ts`**:
- Remove the `copyFrom` method from the `budgets` object (TMPL-06: no more copy-from-previous)
3. **Update `frontend/src/pages/DashboardPage.tsx`**:
- No structural changes needed. The BudgetSetup component is already rendered when `showCreate` is true.
- The `handleBudgetCreated` callback already calls `fetchList()` which will pick up the newly generated budget.
4. **Update `frontend/src/components/BudgetSetup.test.tsx`**:
- Update test to reflect new month-picker UI instead of old manual form
- Remove any references to copyFrom mock
- Test that month input and currency input render
- Test that Generate button is present (not "Create")
5. **Update `frontend/src/pages/DashboardPage.test.tsx`**:
- Remove `copyFrom` from any budgets API mock objects
6. **Update i18n files** -- add to both en.json and de.json:
- EN: `"budget.generate": "Generate from Template"`, `"budget.month": "Month"`, `"budget.generating": "Generating..."`
- DE: `"budget.generate": "Aus Vorlage erstellen"`, `"budget.month": "Monat"`, `"budget.generating": "Wird erstellt..."`
- Remove `"budget.copyFrom"` key from both files (TMPL-06)
- Remove `"budget.setup"` key from both files (replaced by generate)
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && npx tsc --noEmit 2>&1 | head -30 && bun run build 2>&1 | tail -5</automated>
</verify>
<done>BudgetSetup shows month picker + currency + Generate button. No copy-from-previous UI anywhere. copyFrom removed from api.ts. Tests updated. Budget generation calls POST /api/budgets/generate.</done>
</task>
<task type="auto">
<name>Task 2: Display item_tier badge in tracker table rows</name>
<files>frontend/src/components/BillsTracker.tsx, frontend/src/components/VariableExpenses.tsx, frontend/src/components/DebtTracker.tsx</files>
<action>
1. In each tracker component (`BillsTracker.tsx`, `VariableExpenses.tsx`, `DebtTracker.tsx`):
- Import `Badge` from `@/components/ui/badge`
- Import `useTranslation` (already imported in BillsTracker, verify for others)
- In each item table row, add a Badge after the category name cell showing the item tier:
- In the TableCell that shows `item.category_name`, append a Badge component:
```tsx
<TableCell>
{item.category_name}
<Badge variant="outline" className="ml-2 text-xs font-normal">
{t(`template.${item.item_tier === 'one_off' ? 'oneOff' : item.item_tier}`)}
</Badge>
</TableCell>
```
- Badge shows translated tier name: "Fixed", "Variable", or "One-off" (using i18n keys added in Plan 01: `template.fixed`, `template.variable`, `template.oneOff`)
- The badge is purely informational -- no click behavior
- Use `variant="outline"` for a subtle, non-distracting appearance that works with the pastel theme
Note: The `item_tier` field is already on the `BudgetItem` interface (added in Plan 01). The backend already returns it. This task just makes it visible.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && npx tsc --noEmit 2>&1 | head -30 && bun run build 2>&1 | tail -5</automated>
</verify>
<done>Each budget item row in BillsTracker, VariableExpenses, and DebtTracker displays a small outline badge showing its tier (Fixed/Variable/One-off), translated via i18n</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<name>Task 3: Verify template-based workflow replacement</name>
<files>none</files>
<action>
Human verifies the complete template-based budget generation workflow end-to-end, including template page from Plan 01 and workflow replacement from this plan.
</action>
<verify>Human visual and functional verification</verify>
<done>User confirms: month picker generates budgets from template, copy-from-previous is gone, item tier badges display correctly</done>
<what-built>
Template-based budget generation workflow replacing manual creation and copy-from-previous. Item tier badges visible in all tracker tables.
</what-built>
<how-to-verify>
1. Start the app: `cd frontend && bun run dev` (and ensure backend is running with `cd backend && go run ./cmd/server`)
2. Navigate to the Template page via sidebar -- verify it loads (from Plan 01)
3. Add a few template items (fixed with amounts, variable without)
4. Go to Dashboard, click "Create Budget"
5. Verify: month picker + currency input shown (NOT the old form with name/dates/carryover/copy-from)
6. Select a future month, click "Generate from Template"
7. Verify: budget is created and selected, items from template appear with correct amounts
8. Verify: each item row shows a small tier badge (Fixed/Variable/One-off)
9. Try generating the same month again -- should handle gracefully (409 case)
10. Confirm: "Copy from previous" dropdown is nowhere to be seen
</how-to-verify>
<resume-signal>Type "approved" or describe issues</resume-signal>
</task>
</tasks>
<verification>
- TypeScript compiles: `cd frontend && npx tsc --noEmit`
- Build succeeds: `cd frontend && bun run build`
- Tests pass: `cd frontend && bun vitest --run`
- No references to `copyFrom` remain in component code (only test mocks removed)
- `budgets.generate` function exists in api.ts
- BudgetSetup renders month input, not date range / name / carryover fields
</verification>
<success_criteria>
- Creating a budget uses month picker + template generation (not manual form)
- Copy-from-previous UI and API function are completely removed
- 409 conflict (budget already exists) is handled gracefully
- Item tier badges display on all tracker table rows
- All text is i18n-translated
- Existing tests updated to reflect new UI
</success_criteria>
<output>
After completion, create `.planning/phases/06-template-frontend-and-workflow-replacement/06-02-SUMMARY.md`
</output>