Section groups with collapsible headers + Sinking Funds #12

Merged
claude-code merged 4 commits from feat/11-groups-and-sinks into main 2026-04-17 12:46:04 -06:00
Collaborator

Closes #11 (will be manually closed on merge).

Summary

Introduces four collapsible section groups (Income, Committed, Savings, Flexible) on both the budget and month pages, and adds a Sinking Funds section for savings goals.

  • Section enum gains sinking_fund with label "Sinking Funds"
  • src/quartermaster/groups.py defines the Group enum, labels, section-to-group mapping, default open state, and ordering
  • <details> / <summary> provides the expand/collapse with no JavaScript; chevron rotates via CSS on [open]
  • Budget and month pages iterate groups, render a section for each enum member, and inject the Primary Debt Target card inside the Committed group after Debt Minimums
  • Income and Flexible default open, Committed and Savings default closed
  • Every mutation response now carries OOB spans for all four group subtotals so the header stays live regardless of which section changed
  • No schema migration needed: section is a plain VARCHAR(32) without a CHECK, so new enum values do not require DDL

Test plan

  • uv run pytest passes (68/68, +14 new)
  • Live smoke on a throwaway DB:
    • Empty page renders all four group headers; Income and Flexible open, Committed and Savings closed
    • Adding an income entry updates group-total-income via OOB swap
    • Adding a sinking-fund entry lands in the Savings group with the correct subtotal
    • Full page after seeding shows group totals summing to the expected values
    • Month page renders paired (applied / planned) subtotals per group
  • Existing zero-amount widget and debt-target OOB swaps still fire on mutations

Screens you asked for

Collapsed view (all closed):

▶ INCOME       $2500.00
▶ COMMITTED    $1750.00
▶ SAVINGS       $500.00
▶ FLEXIBLE      $450.00

Mixed view (income + flexible open, as default):

▼ INCOME                 $2500.00
  Incomes
    Paycheck    $2500.00  [×]
    [ Add row ]

▶ COMMITTED              $1750.00
▶ SAVINGS                 $500.00

▼ FLEXIBLE                $450.00
  Food and Essentials
    Groceries    $400.00  [×]
  Subscriptions
    Netflix       $15.00  [×]
    Spotify       $10.00  [×]
  Other
    Parking       $25.00  [×]

Out of scope

  • localStorage persistence of open/closed state across reloads
  • Notes field per entry (issue B, next)
  • Reconciliation / close-out flow (issue C, bigger effort)
Closes #11 (will be manually closed on merge). ## Summary Introduces four collapsible section groups (Income, Committed, Savings, Flexible) on both the budget and month pages, and adds a Sinking Funds section for savings goals. * Section enum gains `sinking_fund` with label "Sinking Funds" * `src/quartermaster/groups.py` defines the Group enum, labels, section-to-group mapping, default open state, and ordering * `<details>` / `<summary>` provides the expand/collapse with no JavaScript; chevron rotates via CSS on `[open]` * Budget and month pages iterate groups, render a section for each enum member, and inject the Primary Debt Target card inside the Committed group after Debt Minimums * Income and Flexible default open, Committed and Savings default closed * Every mutation response now carries OOB spans for all four group subtotals so the header stays live regardless of which section changed * No schema migration needed: `section` is a plain VARCHAR(32) without a CHECK, so new enum values do not require DDL ## Test plan * [x] `uv run pytest` passes (68/68, +14 new) * [x] Live smoke on a throwaway DB: * [x] Empty page renders all four group headers; Income and Flexible open, Committed and Savings closed * [x] Adding an income entry updates `group-total-income` via OOB swap * [x] Adding a sinking-fund entry lands in the Savings group with the correct subtotal * [x] Full page after seeding shows group totals summing to the expected values * [x] Month page renders paired (applied / planned) subtotals per group * [x] Existing zero-amount widget and debt-target OOB swaps still fire on mutations ## Screens you asked for Collapsed view (all closed): ``` ▶ INCOME $2500.00 ▶ COMMITTED $1750.00 ▶ SAVINGS $500.00 ▶ FLEXIBLE $450.00 ``` Mixed view (income + flexible open, as default): ``` ▼ INCOME $2500.00 Incomes Paycheck $2500.00 [×] [ Add row ] ▶ COMMITTED $1750.00 ▶ SAVINGS $500.00 ▼ FLEXIBLE $450.00 Food and Essentials Groceries $400.00 [×] Subscriptions Netflix $15.00 [×] Spotify $10.00 [×] Other Parking $25.00 [×] ``` ## Out of scope * localStorage persistence of open/closed state across reloads * Notes field per entry (issue B, next) * Reconciliation / close-out flow (issue C, bigger effort)
claude-code added 4 commits 2026-04-17 12:44:49 -06:00
Section enum gains sinking_fund with label "Sinking Funds". A new
groups module maps each section to one of Income, Committed, Savings,
Flexible and records the default open state per group. The existing
section column is a plain VARCHAR(32) with no CHECK, so no schema
migration is needed to accept the new value.

Refs #11

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
budget_group_views composes SectionViews into grouped dataclasses
with a combined total and the default open flag. month_group_views
does the same with planned and applied totals. Group order, labels,
and section-to-group mapping all come from the groups module.

Refs #11

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Budget and month pages now wrap sections in native <details> blocks
with summary rows showing the group name and subtotal. Income and
Flexible default open, Committed and Savings default closed so the
day-to-day editing targets are visible and the set-and-forget
commitments collapse out of the way. Primary Debt Target renders
inside the Committed group after Debt Minimums.

Every mutation appends a group-totals partial with OOB spans for
all four group subtotals so the header stays in sync without a
reload regardless of which section changed.

Refs #11

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every section maps to a group. Group order and defaults match the
spec. Budget and month subtotal calculations check out across
seeded entries. Pages render the expected details ids, income is
open by default, committed is closed. Mutations return OOB group
total spans. Sinking Funds section is visible on both pages.

Refs #11

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-code merged commit 1eecfc3ae8 into main 2026-04-17 12:46:04 -06:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: archeious/quartermaster#12
No description provided.