fix(03): revise plans based on checker feedback

This commit is contained in:
2026-03-11 22:27:07 +01:00
parent 0d40043615
commit 72fb62635d
6 changed files with 202 additions and 34 deletions

View File

@@ -0,0 +1,161 @@
---
phase: 03-interaction-quality-and-completeness
plan: 00
type: execute
wave: 0
depends_on: []
files_modified:
- frontend/src/components/BudgetSetup.test.tsx
- frontend/src/pages/CategoriesPage.test.tsx
- frontend/src/pages/DashboardPage.test.tsx
- frontend/src/components/BillsTracker.test.tsx
autonomous: true
requirements: [IXTN-01, IXTN-05, STATE-01, STATE-02, STATE-03]
must_haves:
truths:
- "All 4 test stub files exist and can be loaded by vitest"
- "Each stub contains at least one pending/skipped test describing the target behavior"
artifacts:
- path: "frontend/src/components/BudgetSetup.test.tsx"
provides: "Test stub for budget form spinner (IXTN-01)"
contains: "BudgetSetup"
- path: "frontend/src/pages/CategoriesPage.test.tsx"
provides: "Test stubs for delete confirmation (IXTN-05) and empty state (STATE-02)"
contains: "CategoriesPage"
- path: "frontend/src/pages/DashboardPage.test.tsx"
provides: "Test stub for dashboard empty state (STATE-01)"
contains: "DashboardPage"
- path: "frontend/src/components/BillsTracker.test.tsx"
provides: "Test stub for tinted skeleton (STATE-03)"
contains: "BillsTracker"
key_links: []
---
<objective>
Create Wave 0 test stub files for the 4 components that lack test coverage. Each stub imports the component, renders it with minimal props, and contains skipped (it.skip) test cases describing the behaviors that Plans 01-03 will implement.
Purpose: Satisfy Nyquist compliance — every task in Plans 01-03 must have a runnable test file in its verify command. Wave 0 ensures those files exist before execution begins.
Output: 4 new test files with pending test stubs.
</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/03-interaction-quality-and-completeness/03-CONTEXT.md
@.planning/phases/03-interaction-quality-and-completeness/03-VALIDATION.md
<interfaces>
From frontend/src/components/BudgetSetup.tsx:
```typescript
interface Props {
existingBudgets: Budget[]
onCreated: () => void
onCancel: () => void
}
export function BudgetSetup({ existingBudgets, onCreated, onCancel }: Props)
```
From frontend/src/pages/CategoriesPage.tsx:
```typescript
// Default export, no props — uses hooks internally (useTranslation, etc.)
export default function CategoriesPage()
```
From frontend/src/pages/DashboardPage.tsx:
```typescript
// Default export, no props — uses hooks internally
export default function DashboardPage()
```
From frontend/src/components/BillsTracker.tsx:
```typescript
interface Props {
budget: BudgetDetail
onUpdate: (itemId: string, data: { actual_amount?: number; budgeted_amount?: number }) => Promise<void>
}
export function BillsTracker({ budget, onUpdate }: Props)
```
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Create 4 test stub files with pending test cases</name>
<files>frontend/src/components/BudgetSetup.test.tsx, frontend/src/pages/CategoriesPage.test.tsx, frontend/src/pages/DashboardPage.test.tsx, frontend/src/components/BillsTracker.test.tsx</files>
<action>
Create each test file with the following structure: import vitest globals (describe, it, expect), import @testing-library/react (render, screen), import the component, wrap tests in a describe block, and add `it.skip` stubs for the behaviors that will be implemented in Plans 01-03.
**BudgetSetup.test.tsx:**
- Import `BudgetSetup` from `@/components/BudgetSetup`
- Mock `@/lib/api` (budgets.create) and `react-i18next` (useTranslation returns t = key passthrough)
- `it.skip('shows spinner in create button when saving')` — IXTN-01
- `it.skip('disables create button when saving')` — IXTN-01
- Add one basic `it('renders without crashing')` test that renders BudgetSetup with minimal props: `existingBudgets: [], onCreated: vi.fn(), onCancel: vi.fn()` — this validates the stub file works.
**CategoriesPage.test.tsx:**
- Import `CategoriesPage` from `@/pages/CategoriesPage`
- Mock `@/lib/api` (categories.list returns [], categories.delete) and `react-i18next`
- `it.skip('opens confirmation dialog when delete button clicked')` — IXTN-05
- `it.skip('executes delete on confirm and shows spinner')` — IXTN-05
- `it.skip('shows error inline when delete fails')` — IXTN-05
- `it.skip('shows empty state when no categories exist')` — STATE-02
- Add one basic `it('renders without crashing')` that renders CategoriesPage inside a MemoryRouter (it uses routing).
**DashboardPage.test.tsx:**
- Import `DashboardPage` from `@/pages/DashboardPage`
- Mock `@/lib/api` (budgets.list returns []) and `react-i18next`
- `it.skip('shows empty state with CTA when no budgets')` — STATE-01
- `it.skip('shows loading skeleton while fetching')` — STATE-03
- Add one basic `it('renders without crashing')` that renders DashboardPage inside a MemoryRouter.
**BillsTracker.test.tsx:**
- Import `BillsTracker` from `@/components/BillsTracker`
- Mock `react-i18next`
- `it.skip('shows tinted skeleton when no bill items')` — STATE-03
- `it.skip('flashes row green on successful inline save')` — IXTN-03
- `it.skip('flashes row red on failed inline save')` — IXTN-03
- Add one basic `it('renders without crashing')` that renders BillsTracker with a minimal budget fixture (empty items array) and `onUpdate: vi.fn()`.
For components needing MemoryRouter (page-level components with routing), wrap in `<MemoryRouter>` from `react-router-dom`.
Pattern for all mocks:
```typescript
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key: string) => key, i18n: { language: 'en' } }),
}))
```
Each file MUST have at least one non-skipped test that passes to confirm the stub is valid.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/components/BudgetSetup.test.tsx src/pages/CategoriesPage.test.tsx src/pages/DashboardPage.test.tsx src/components/BillsTracker.test.tsx</automated>
</verify>
<done>All 4 test stub files exist, each has at least one passing basic test and multiple it.skip stubs describing target behaviors. Vitest runs all 4 files without errors.</done>
</task>
</tasks>
<verification>
- `cd frontend && bun vitest run` — full test suite passes (new stubs + existing tests)
- All 4 files importable by vitest
- Each file has at least one non-skipped passing test
</verification>
<success_criteria>
- BudgetSetup.test.tsx, CategoriesPage.test.tsx, DashboardPage.test.tsx, BillsTracker.test.tsx all exist
- Each file has skip-marked stubs for the behaviors Plans 01-03 will implement
- Each file has at least one passing smoke test
- Full test suite remains green
</success_criteria>
<output>
After completion, create `.planning/phases/03-interaction-quality-and-completeness/03-00-SUMMARY.md`
</output>

View File

@@ -3,7 +3,7 @@ phase: 03-interaction-quality-and-completeness
plan: 01
type: execute
wave: 1
depends_on: []
depends_on: ["03-00"]
files_modified:
- frontend/src/components/InlineEditCell.tsx
- frontend/src/components/InlineEditCell.test.tsx
@@ -49,10 +49,12 @@ must_haves:
---
<objective>
Add pencil icon hover affordance and save/error callbacks to InlineEditCell, plus loading spinners to all four form submit buttons.
Add pencil icon hover affordance and save/error callbacks to InlineEditCell, plus loading spinners to three form submit buttons (Login, Register, Budget Create).
Purpose: Make inline editing discoverable (pencil icon on hover) and prepare the callback interface for row-level flash feedback in downstream plans. Make form submissions feel responsive with spinner indicators.
Output: Enhanced InlineEditCell with pencil + callbacks, spinner-enabled Login/Register/BudgetSetup forms.
Note: CONTEXT.md specifies spinners on "all four forms: Login, Register, Budget Create, Budget Edit." No Budget Edit form component exists in the codebase — only BudgetSetup (create-only). Budget Edit spinner is deferred until that form is built. This plan covers the 3 existing forms.
</objective>
<execution_context>
@@ -151,10 +153,12 @@ export function formatCurrency(value: number, currency: string): string
- Add `className="min-w-[120px]"` to Button.
- Replace button text with: `{saving ? <Spinner /> : t('budget.create')}`
Note: CONTEXT.md mentions "Budget Edit" as a fourth form, but no Budget Edit component exists in the codebase (BudgetSetup is create-only). Spinner for Budget Edit is deferred until that form is created.
Do NOT modify any other logic in these files — only the Button content and className.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/pages/LoginPage.test.tsx src/pages/RegisterPage.test.tsx && bun run build</automated>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/pages/LoginPage.test.tsx src/pages/RegisterPage.test.tsx src/components/BudgetSetup.test.tsx && bun run build</automated>
</verify>
<done>All three form submit buttons show Spinner component when loading/saving state is true, buttons are disabled during loading, min-width prevents layout shift. Build passes with zero errors.</done>
</task>
@@ -171,6 +175,7 @@ export function formatCurrency(value: number, currency: string): string
- Pencil icon renders in InlineEditCell display mode (opacity-0, visible on hover via CSS)
- onSaveSuccess fires after successful save; onSaveError fires and reverts value on failure
- Login, Register, BudgetSetup buttons show Spinner when loading, disabled to prevent double-submit
- Budget Edit spinner is explicitly deferred (no form component exists yet)
- All existing tests continue to pass; new tests cover the added behaviors
</success_criteria>

View File

@@ -3,7 +3,7 @@ phase: 03-interaction-quality-and-completeness
plan: 02
type: execute
wave: 1
depends_on: []
depends_on: ["03-00"]
files_modified:
- frontend/src/pages/CategoriesPage.tsx
- frontend/src/pages/DashboardPage.tsx
@@ -105,6 +105,9 @@ export { Spinner }
<name>Task 1: Create shared EmptyState component and wire into Dashboard and Categories pages</name>
<files>frontend/src/components/EmptyState.tsx, frontend/src/pages/DashboardPage.tsx, frontend/src/pages/CategoriesPage.tsx</files>
<action>
**Step 0 — Check shadcn registry first (per project skill rules):**
Run `bunx --bun shadcn@latest search -q empty` in the frontend directory. If shadcn provides an EmptyState or similar component, use it instead of creating a custom one. If nothing relevant is found (expected), proceed with custom component below.
**Create `frontend/src/components/EmptyState.tsx`:**
```typescript
interface EmptyStateProps {
@@ -128,7 +131,7 @@ export { Spinner }
- Guard the grouped cards render with `{grouped.length > 0 && grouped.map(...)}` so both empty state and cards don't show simultaneously.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun run build</automated>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/pages/DashboardPage.test.tsx src/pages/CategoriesPage.test.tsx && bun run build</automated>
</verify>
<done>EmptyState component exists and is used in DashboardPage (no-budgets case) and CategoriesPage (no-categories case). CategoriesPage has loading state to prevent empty-state flash. Build passes.</done>
</task>
@@ -190,7 +193,7 @@ export { Spinner }
**CRITICAL:** The ON DELETE RESTRICT constraint means deleting a category with budget items returns 500. The catch block handles this — the error message displays inline in the dialog. The dialog does NOT auto-close on error, letting the user read the message and dismiss manually.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun run build</automated>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/pages/CategoriesPage.test.tsx && bun run build</automated>
</verify>
<done>Delete button opens confirmation dialog. Confirm executes delete with spinner. Error from ON DELETE RESTRICT shows inline. Cancel closes dialog. Build passes with zero errors.</done>
</task>

View File

@@ -3,7 +3,7 @@ phase: 03-interaction-quality-and-completeness
plan: 03
type: execute
wave: 2
depends_on: ["03-01"]
depends_on: ["03-01", "03-00"]
files_modified:
- frontend/src/components/BillsTracker.tsx
- frontend/src/components/VariableExpenses.tsx
@@ -171,7 +171,7 @@ From frontend/src/components/ui/skeleton.tsx:
**Do NOT modify** the totals row or the CardHeader — only add flash state and wire callbacks.
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun run build</automated>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/components/BillsTracker.test.tsx && bun run build</automated>
</verify>
<done>All three tracker components have flash state, triggerFlash helper, inline style on data rows, and onSaveSuccess/onSaveError wired to InlineEditCell. Build passes.</done>
</task>
@@ -234,7 +234,7 @@ From frontend/src/components/ui/skeleton.tsx:
**Note:** These skeletons show when a budget exists but has no items of that type — they serve as visual placeholders indicating the section exists. This is distinct from the DashboardPage loading skeleton (which shows before any data loads).
</action>
<verify>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run && bun run build</automated>
<automated>cd /home/jean-luc-makiola/Development/projects/SimpleFinanceDash/frontend && bun vitest run src/components/BillsTracker.test.tsx src/pages/DashboardPage.test.tsx && bun run build</automated>
</verify>
<done>Dashboard loading skeleton uses palette-tinted backgrounds per section. Each tracker shows tinted skeletons when no items of its type exist. All tests pass, build succeeds.</done>
</task>

View File

@@ -2,7 +2,7 @@
phase: 3
slug: interaction-quality-and-completeness
status: draft
nyquist_compliant: false
nyquist_compliant: true
wave_0_complete: false
created: 2026-03-11
---
@@ -38,24 +38,22 @@ created: 2026-03-11
| Task ID | Plan | Wave | Requirement | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|-----------|-------------------|-------------|--------|
| 03-00-01 | 00 | 0 | IXTN-01 | unit stub | `bun vitest run src/components/BudgetSetup.test.tsx` | ❌ W0 | pending |
| 03-00-02 | 00 | 0 | IXTN-05, STATE-02 | unit stub | `bun vitest run src/pages/CategoriesPage.test.tsx` | ❌ W0 | ⬜ pending |
| 03-00-03 | 00 | 0 | STATE-01 | unit stub | `bun vitest run src/pages/DashboardPage.test.tsx` | ❌ W0 | pending |
| 03-00-04 | 00 | 0 | STATE-03 | unit stub | `bun vitest run src/components/BillsTracker.test.tsx` | W0 | pending |
| 03-01-01 | 01 | 1 | IXTN-02, IXTN-03 | unit | `bun vitest run src/components/InlineEditCell.test.tsx` | ✅ extend | ⬜ pending |
| 03-01-02 | 01 | 1 | IXTN-01 | unit | `bun vitest run src/pages/LoginPage.test.tsx src/pages/RegisterPage.test.tsx` | ✅ extend | ⬜ pending |
| 03-01-03 | 01 | 1 | IXTN-01 | unit | `bun vitest run src/components/BudgetSetup.test.tsx` | W0 | pending |
| 03-02-01 | 02 | 1 | IXTN-05 | unit | `bun vitest run src/pages/CategoriesPage.test.tsx` | ❌ W0 | ⬜ pending |
| 03-02-02 | 02 | 1 | STATE-01 | unit | `bun vitest run src/pages/DashboardPage.test.tsx` | ❌ W0 | ⬜ pending |
| 03-02-03 | 02 | 1 | STATE-02 | unit | `bun vitest run src/pages/CategoriesPage.test.tsx` | ❌ W0 | ⬜ pending |
| 03-02-04 | 02 | 1 | STATE-03 | unit | `bun vitest run src/components/BillsTracker.test.tsx` | ❌ W0 | ⬜ pending |
| 03-00-01 | 00 | 0 | IXTN-01, IXTN-05, STATE-01, STATE-02, STATE-03 | unit stub | `bun vitest run src/components/BudgetSetup.test.tsx src/pages/CategoriesPage.test.tsx src/pages/DashboardPage.test.tsx src/components/BillsTracker.test.tsx` | Created by 03-00 | pending |
| 03-01-01 | 01 | 1 | IXTN-02, IXTN-03 | unit | `bun vitest run src/components/InlineEditCell.test.tsx` | extend | pending |
| 03-01-02 | 01 | 1 | IXTN-01 | unit | `bun vitest run src/pages/LoginPage.test.tsx src/pages/RegisterPage.test.tsx src/components/BudgetSetup.test.tsx` | extend + W0 | pending |
| 03-02-01 | 02 | 1 | STATE-01, STATE-02 | unit | `bun vitest run src/pages/DashboardPage.test.tsx src/pages/CategoriesPage.test.tsx` | W0 | pending |
| 03-02-02 | 02 | 1 | IXTN-05 | unit | `bun vitest run src/pages/CategoriesPage.test.tsx` | W0 | pending |
| 03-03-01 | 03 | 2 | IXTN-03 | unit | `bun vitest run src/components/BillsTracker.test.tsx` | W0 | pending |
| 03-03-02 | 03 | 2 | STATE-03 | unit | `bun vitest run src/components/BillsTracker.test.tsx src/pages/DashboardPage.test.tsx` | W0 | pending |
*Status: pending · ✅ green · ❌ red · ⚠️ flaky*
*Status: pending / green / red / flaky*
---
## Wave 0 Requirements
Plan 03-00-PLAN.md creates all 4 stub files:
- [ ] `frontend/src/components/BudgetSetup.test.tsx` — stubs for IXTN-01 (budget form spinner)
- [ ] `frontend/src/pages/CategoriesPage.test.tsx` — stubs for IXTN-05 (delete confirmation), STATE-02 (empty state)
- [ ] `frontend/src/pages/DashboardPage.test.tsx` — stubs for STATE-01 (dashboard empty state)
@@ -82,11 +80,11 @@ created: 2026-03-11
## Validation Sign-Off
- [ ] All tasks have `<automated>` verify or Wave 0 dependencies
- [ ] Sampling continuity: no 3 consecutive tasks without automated verify
- [ ] Wave 0 covers all MISSING references
- [ ] No watch-mode flags
- [ ] Feedback latency < 20s
- [ ] `nyquist_compliant: true` set in frontmatter
- [x] All tasks have `<automated>` verify or Wave 0 dependencies
- [x] Sampling continuity: no 3 consecutive tasks without automated verify
- [x] Wave 0 covers all MISSING references (03-00-PLAN.md)
- [x] No watch-mode flags
- [x] Feedback latency < 20s
- [ ] `wave_0_complete: true` set after 03-00 executes
**Approval:** pending
**Approval:** pending execution