diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 84f8dc4..cf1c649 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -94,8 +94,8 @@ Plans:
**Plans:** 2/2 plans complete
Plans:
-- [ ] 05-01-PLAN.md — DB migration (item_tier enum, templates/template_items tables) + Go models + query functions
-- [ ] 05-02-PLAN.md — HTTP handlers for template CRUD, budget generation endpoint, route wiring
+- [x] 05-01-PLAN.md — DB migration (item_tier enum, templates/template_items tables) + Go models + query functions
+- [x] 05-02-PLAN.md — HTTP handlers for template CRUD, budget generation endpoint, route wiring
#### Phase 6: Template Frontend and Workflow Replacement
**Goal**: Users can manage their template on a dedicated page, navigate to any month and get a budget auto-generated from their template, and the old "copy from previous month" flow is gone
@@ -106,12 +106,11 @@ Plans:
2. The template management page lets the user add, remove, and reorder fixed and variable items without leaving the page
3. When adding a budget item (fixed or variable), the user can tag it inline as fixed, variable, or one-off
4. The "copy from previous month" button is no longer visible anywhere in the app
-**Plans**: TBD
+**Plans:** 2 plans
Plans:
-- [ ] 06-01: Item type tagging UI — inline fixed/variable/one-off selector on add/edit forms
-- [ ] 06-02: Template management page — add, remove, reorder items with live preview
-- [ ] 06-03: Auto-generate budget on navigate — wire frontend to generation endpoint, remove copy-from-previous
+- [ ] 06-01-PLAN.md — Template API client, useTemplate hook, TemplatePage with add/remove/reorder, routing and i18n
+- [ ] 06-02-PLAN.md — Replace BudgetSetup with template-based month picker, remove copy-from-previous, item tier badges in trackers
#### Phase 7: Quick-Add Library
**Goal**: Users can save frequently-used one-off expense categories to a personal library and insert them into any month's budget in one click, eliminating re-entry friction for recurring one-offs like pharmacy visits
@@ -153,7 +152,7 @@ Phases execute in numeric order: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8
| 2. Layout and Brand Identity | v1.0 | 2/2 | Complete | 2026-03-12 |
| 3. Interaction Quality and Completeness | v1.0 | 4/4 | Complete | 2026-03-12 |
| 4. Chart Polish and Bug Fixes | v1.0 | 2/2 | Complete | 2026-03-12 |
-| 5. Template Data Model and API | 2/2 | Complete | 2026-03-12 | - |
-| 6. Template Frontend and Workflow Replacement | v1.1 | 0/3 | Not started | - |
+| 5. Template Data Model and API | v1.1 | 2/2 | Complete | 2026-03-12 |
+| 6. Template Frontend and Workflow Replacement | v1.1 | 0/2 | Not started | - |
| 7. Quick-Add Library | v1.1 | 0/2 | Not started | - |
| 8. Layout and Density Rethink | v1.1 | 0/2 | Not started | - |
diff --git a/.planning/phases/06-template-frontend-and-workflow-replacement/06-01-PLAN.md b/.planning/phases/06-template-frontend-and-workflow-replacement/06-01-PLAN.md
new file mode 100644
index 0000000..80b5402
--- /dev/null
+++ b/.planning/phases/06-template-frontend-and-workflow-replacement/06-01-PLAN.md
@@ -0,0 +1,275 @@
+---
+phase: 06-template-frontend-and-workflow-replacement
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - frontend/src/lib/api.ts
+ - frontend/src/hooks/useTemplate.ts
+ - frontend/src/pages/TemplatePage.tsx
+ - frontend/src/components/AppLayout.tsx
+ - frontend/src/App.tsx
+ - frontend/src/i18n/en.json
+ - frontend/src/i18n/de.json
+autonomous: true
+requirements: [TMPL-05]
+
+must_haves:
+ truths:
+ - "User can navigate to a Template page from the sidebar"
+ - "Template page shows current template items grouped by tier (fixed items with amounts, variable items without)"
+ - "User can add a new item to the template by selecting a category and tier"
+ - "User can remove an item from the template"
+ - "User can reorder template items via move-up/move-down buttons"
+ - "One-off tier is not available when adding template items"
+ artifacts:
+ - path: "frontend/src/lib/api.ts"
+ provides: "Template API functions (get, create item, update item, delete item, reorder, generate)"
+ contains: "template"
+ - path: "frontend/src/hooks/useTemplate.ts"
+ provides: "useTemplate hook with CRUD operations"
+ exports: ["useTemplate"]
+ - path: "frontend/src/pages/TemplatePage.tsx"
+ provides: "Template management page component"
+ exports: ["TemplatePage"]
+ - path: "frontend/src/components/AppLayout.tsx"
+ provides: "Sidebar nav item for Template"
+ contains: "template"
+ - path: "frontend/src/App.tsx"
+ provides: "Route for /template"
+ contains: "/template"
+ key_links:
+ - from: "frontend/src/pages/TemplatePage.tsx"
+ to: "/api/template"
+ via: "useTemplate hook"
+ pattern: "useTemplate"
+ - from: "frontend/src/components/AppLayout.tsx"
+ to: "/template"
+ via: "Link component in nav"
+ pattern: "to.*template"
+ - from: "frontend/src/App.tsx"
+ to: "TemplatePage"
+ via: "Route element"
+ pattern: "Route.*template"
+---
+
+
+Create the template management page where users can add, remove, and reorder fixed and variable budget items in their monthly template.
+
+Purpose: TMPL-05 requires a dedicated template page for managing the items that auto-populate new monthly budgets. This plan builds the full frontend: API client functions, data hook, page component, routing, and navigation.
+
+Output: Working template management page accessible from sidebar, with full CRUD for template items.
+
+
+
+@/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md
+@/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/05-template-data-model-and-api/05-01-SUMMARY.md
+@.planning/phases/05-template-data-model-and-api/05-02-SUMMARY.md
+
+
+
+
+From backend/internal/models/models.go:
+```go
+type ItemTier string
+const (
+ ItemTierFixed ItemTier = "fixed"
+ ItemTierVariable ItemTier = "variable"
+ ItemTierOneOff ItemTier = "one_off"
+)
+
+type TemplateItem struct {
+ ID uuid.UUID `json:"id"`
+ TemplateID uuid.UUID `json:"template_id"`
+ CategoryID uuid.UUID `json:"category_id"`
+ CategoryName string `json:"category_name,omitempty"`
+ CategoryType CategoryType `json:"category_type,omitempty"`
+ CategoryIcon string `json:"category_icon,omitempty"`
+ ItemTier ItemTier `json:"item_tier"`
+ BudgetedAmount *decimal.Decimal `json:"budgeted_amount"`
+ SortOrder int `json:"sort_order"`
+}
+
+type TemplateDetail struct {
+ Template // id, user_id, name, created_at, updated_at
+ Items []TemplateItem `json:"items"`
+}
+```
+
+API endpoints (from Phase 5 Plan 02):
+- GET /api/template -> TemplateDetail (empty items array when no template)
+- PUT /api/template -> update name
+- POST /api/template/items -> add item (auto-creates template if needed)
+- PUT /api/template/items/{itemId} -> update item
+- DELETE /api/template/items/{itemId} -> remove item (204)
+- PUT /api/template/items/reorder -> batch update sort_order (204)
+- POST /api/budgets/generate -> { month: "2026-04", currency: "EUR" } -> BudgetDetail or 409
+
+From frontend/src/lib/api.ts:
+```typescript
+export type CategoryType = 'bill' | 'variable_expense' | 'debt' | 'saving' | 'investment' | 'income'
+export interface Category {
+ id: string; name: string; type: CategoryType; icon: string; sort_order: number
+}
+export interface BudgetItem {
+ id: string; budget_id: string; category_id: string; category_name: string;
+ category_type: CategoryType; budgeted_amount: number; actual_amount: number; notes: string
+}
+export const categories = { list: () => request('/categories') }
+```
+
+From frontend/src/components/AppLayout.tsx:
+```typescript
+const navItems = [
+ { path: '/', label: t('nav.dashboard'), icon: LayoutDashboard },
+ { path: '/categories', label: t('nav.categories'), icon: Tags },
+ { path: '/settings', label: t('nav.settings'), icon: Settings },
+]
+```
+
+
+
+
+
+
+ Task 1: API client extensions and useTemplate hook
+ frontend/src/lib/api.ts, frontend/src/hooks/useTemplate.ts
+
+ 1. In `frontend/src/lib/api.ts`:
+ - Add `item_tier` field to existing `BudgetItem` interface: `item_tier: 'fixed' | 'variable' | 'one_off'`
+ - Add `ItemTier` type alias: `export type ItemTier = 'fixed' | 'variable' | 'one_off'`
+ - Add `TemplateItem` interface: `{ id: string, template_id: string, category_id: string, category_name: string, category_type: CategoryType, category_icon: string, item_tier: ItemTier, budgeted_amount: number | null, sort_order: number }`
+ - Add `TemplateDetail` interface: `{ id: string | null, name: string, items: TemplateItem[] }`
+ - Add `template` API object:
+ ```
+ get: () => request('/template')
+ updateName: (name: string) => request('/template', { method: 'PUT', body: JSON.stringify({ name }) })
+ addItem: (data: { category_id: string, item_tier: ItemTier, budgeted_amount?: number }) => request('/template/items', { method: 'POST', body: JSON.stringify(data) })
+ updateItem: (itemId: string, data: { item_tier?: ItemTier, budgeted_amount?: number }) => request(`/template/items/${itemId}`, { method: 'PUT', body: JSON.stringify(data) })
+ deleteItem: (itemId: string) => request(`/template/items/${itemId}`, { method: 'DELETE' })
+ reorder: (items: { id: string, sort_order: number }[]) => request('/template/items/reorder', { method: 'PUT', body: JSON.stringify({ items }) })
+ ```
+ - Add `generate` function to `budgets` object:
+ `generate: (data: { month: string, currency: string }) => request('/budgets/generate', { method: 'POST', body: JSON.stringify(data) })`
+
+ 2. Create `frontend/src/hooks/useTemplate.ts`:
+ - Import `template as templateApi, categories as categoriesApi` from api.ts
+ - State: `templateDetail` (TemplateDetail | null), `categories` (Category[]), `loading` (boolean)
+ - `fetchTemplate`: calls templateApi.get(), sets state
+ - `fetchCategories`: calls categoriesApi.list(), sets state
+ - `addItem(data)`: calls templateApi.addItem(data), then refetches template
+ - `removeItem(itemId)`: calls templateApi.deleteItem(itemId), then refetches template
+ - `moveItem(itemId, direction: 'up' | 'down')`: compute new sort_order values for the swapped pair, call templateApi.reorder with full item list's updated sort_orders, then refetch
+ - `updateItem(itemId, data)`: calls templateApi.updateItem(itemId, data), then refetches
+ - useEffect on mount: fetch both template and categories
+ - Return: `{ template: templateDetail, categories, loading, addItem, removeItem, moveItem, updateItem, refetch: fetchTemplate }`
+
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && npx tsc --noEmit 2>&1 | head -30
+
+ api.ts has template and generate API functions, BudgetItem includes item_tier, useTemplate hook compiles without errors
+
+
+
+ Task 2: TemplatePage component, routing, navigation, and i18n
+ frontend/src/pages/TemplatePage.tsx, frontend/src/components/AppLayout.tsx, frontend/src/App.tsx, frontend/src/i18n/en.json, frontend/src/i18n/de.json
+
+ 1. Create `frontend/src/pages/TemplatePage.tsx`:
+ - Import useTemplate hook, useTranslation, shadcn components (Card, CardHeader, CardTitle, CardContent, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Input, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Badge), EmptyState, lucide icons (FileText, Plus, Trash2, ArrowUp, ArrowDown, GripVertical)
+ - Use `useTemplate()` to get template, categories, and CRUD functions
+ - Layout: Card with pastel gradient header (use `headerGradient` pattern from palette.ts -- pick a suitable palette key or use inline violet/indigo gradient similar to BudgetSetup)
+ - **Add item form** at top of card content:
+ - Row with: Category select (filtered to exclude categories already in template), Item tier select (only "fixed" and "variable" -- NOT "one_off"), budgeted_amount Input (only shown when tier is "fixed"), Add button (Plus icon)
+ - On add: call `addItem({ category_id, item_tier, budgeted_amount })`, clear form
+ - Disable Add button when category not selected or (tier is fixed and amount is empty)
+ - **Template items table** below the add form:
+ - Columns: Reorder (up/down arrow buttons), Category (name + icon), Tier (Badge showing "Fixed" or "Variable"), Amount (show formatted amount for fixed, dash for variable), Actions (Trash2 delete button)
+ - Items displayed in sort_order
+ - Move up disabled on first item, move down disabled on last item
+ - Delete button calls `removeItem(itemId)`
+ - **Empty state** when template has no items: use EmptyState component with FileText icon, heading like "No template items", subtext explaining to add fixed and variable items
+ - Show loading skeleton while data loads (use Skeleton component with pastel tint)
+ - Use `useTranslation()` for all visible text via `t('template.*')` keys
+
+ 2. Update `frontend/src/components/AppLayout.tsx`:
+ - Import `FileText` icon from lucide-react
+ - Add template nav item to `navItems` array after categories: `{ path: '/template', label: t('nav.template'), icon: FileText }`
+
+ 3. Update `frontend/src/App.tsx`:
+ - Import `TemplatePage` from pages
+ - Add route: `} />`
+
+ 4. Update `frontend/src/i18n/en.json`:
+ - Add `"nav.template": "Template"` (inside nav object)
+ - Add `"template"` object with keys:
+ ```
+ "title": "Monthly Template",
+ "addItem": "Add Item",
+ "category": "Category",
+ "tier": "Tier",
+ "fixed": "Fixed",
+ "variable": "Variable",
+ "oneOff": "One-off",
+ "amount": "Amount",
+ "actions": "Actions",
+ "noItems": "No template items yet",
+ "noItemsHint": "Add fixed and variable items to define your monthly budget template.",
+ "selectCategory": "Select category",
+ "selectTier": "Select tier"
+ ```
+
+ 5. Update `frontend/src/i18n/de.json`:
+ - Add `"nav.template": "Vorlage"` (inside nav object)
+ - Add `"template"` object with German translations:
+ ```
+ "title": "Monatliche Vorlage",
+ "addItem": "Eintrag hinzufuegen",
+ "category": "Kategorie",
+ "tier": "Typ",
+ "fixed": "Fest",
+ "variable": "Variabel",
+ "oneOff": "Einmalig",
+ "amount": "Betrag",
+ "actions": "Aktionen",
+ "noItems": "Noch keine Vorlageneintraege",
+ "noItemsHint": "Fuegen Sie feste und variable Eintraege hinzu, um Ihre monatliche Budgetvorlage zu definieren.",
+ "selectCategory": "Kategorie auswaehlen",
+ "selectTier": "Typ auswaehlen"
+ ```
+
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && npx tsc --noEmit 2>&1 | head -30 && bun run build 2>&1 | tail -5
+
+ Template page renders with add/remove/reorder functionality, accessible via sidebar nav item at /template, all text uses i18n keys in both EN and DE
+
+
+
+
+
+- TypeScript compiles without errors: `cd frontend && npx tsc --noEmit`
+- Production build succeeds: `cd frontend && bun run build`
+- Template page is reachable at /template route
+- Sidebar shows Template nav item between Categories and Settings
+- Template API functions exist in api.ts and have correct method/path
+
+
+
+- TemplatePage shows add form with category select, tier select (fixed/variable only), and conditional amount input
+- Existing template items display in a table with tier badges and delete buttons
+- Reorder arrows move items up/down and persist via API
+- Empty state shown when no template items exist
+- Sidebar navigation includes Template link
+- All UI text is i18n-translated (EN + DE)
+
+
+
diff --git a/.planning/phases/06-template-frontend-and-workflow-replacement/06-02-PLAN.md b/.planning/phases/06-template-frontend-and-workflow-replacement/06-02-PLAN.md
new file mode 100644
index 0000000..fb6c821
--- /dev/null
+++ b/.planning/phases/06-template-frontend-and-workflow-replacement/06-02-PLAN.md
@@ -0,0 +1,232 @@
+---
+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
+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"
+ 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"
+---
+
+
+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.
+
+
+
+@/home/jean-luc-makiola/.claude/get-shit-done/workflows/execute-plan.md
+@/home/jean-luc-makiola/.claude/get-shit-done/templates/summary.md
+
+
+
+@.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
+
+
+
+
+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('/budgets/generate', { method: 'POST', body: JSON.stringify(data) }),
+ copyFrom: (id: string, srcId: string) => // TO BE REMOVED
+ request(`/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
+
+
+
+
+
+
+ Task 1: Replace BudgetSetup with template-based month picker and remove copy-from-previous
+ 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
+
+ 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 (``) 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 `` 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)
+
+
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && npx tsc --noEmit 2>&1 | head -30 && bun run build 2>&1 | tail -5
+
+ 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.
+
+
+
+ Task 2: Display item_tier badge in tracker table rows
+ frontend/src/components/BillsTracker.tsx, frontend/src/components/VariableExpenses.tsx, frontend/src/components/DebtTracker.tsx
+
+ 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
+
+ {item.category_name}
+
+ {t(`template.${item.item_tier === 'one_off' ? 'oneOff' : item.item_tier}`)}
+
+
+ ```
+ - 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.
+
+
+ cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && npx tsc --noEmit 2>&1 | head -30 && bun run build 2>&1 | tail -5
+
+ Each budget item row in BillsTracker, VariableExpenses, and DebtTracker displays a small outline badge showing its tier (Fixed/Variable/One-off), translated via i18n
+
+
+
+ Task 3: Verify template-based workflow replacement
+ none
+
+ Human verifies the complete template-based budget generation workflow end-to-end, including template page from Plan 01 and workflow replacement from this plan.
+
+ Human visual and functional verification
+ User confirms: month picker generates budgets from template, copy-from-previous is gone, item tier badges display correctly
+
+ Template-based budget generation workflow replacing manual creation and copy-from-previous. Item tier badges visible in all tracker tables.
+
+
+ 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
+
+ Type "approved" or describe issues
+
+
+
+
+
+- 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
+
+
+
+- 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
+
+
+