From e09025430b884ad94572f0f168b667c6bac570ca Mon Sep 17 00:00:00 2001 From: null Date: Fri, 3 Jul 2026 12:50:43 -0500 Subject: [PATCH] docs(qa): archive IMP-IA-01 (Data in primary nav) Co-Authored-By: Claude Opus 4.8 --- HISTORY.md | 4 ++++ docs/QA_PLAN.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index a35f9d6..e39a5d2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -16,6 +16,10 @@ - **[Money] `toCents` lost a cent on 3-decimal half values** — `toCents(1.005)` returned `100` ($1.00) instead of `101`, because `Math.round(n * 100)` inherits binary-float error (`1.005 * 100 === 100.4999…`). Now rounds off the shortest decimal string that round-trips the value (half away from zero); output is **identical** for every integer / ≤2-decimal / `"$1,234.56"` input, so no downstream behavior changes. Added `tests/money.test.js` (9 tests). (was QA-B7-01) - **[a11y] Nested interactive controls in Categories & Snowball rows** — Categories rows were `role="button"` (and draggable) yet wrapped their own move/edit/delete buttons, and the Snowball plan-status header wrapped its action buttons *inside* the collapsible trigger button (axe **serious `nested-interactive`**). Restructured both: Categories now use a plain container with a dedicated chevron toggle button (click-anywhere still expands via mouse; keyboard/SR use the chevron); the Snowball header splits into a name/progress toggle, sibling action buttons, and a chevron toggle. Expand/collapse verified by `e2e/categories.spec.js`; all 8 authenticated pages now pass axe. (completes QA-B14-02) +### ✨ QA Improvements + +- **[Nav] Data is now a first-class menu item** — import/export/backups (`/data`) was only reachable from the account overflow dropdown and the command palette, easy to miss for how central it is. It now lives in the main app nav (desktop dropdown + mobile) alongside Bills/Categories/Spending. Same visibility gate as before (hidden for the default-admin account). (was IMP-IA-01) + ### 🧹 QA Cleanup - **[Client] One source of truth for money formatting** — the client had ~15 hand-rolled currency formatters (local `fmt`/`money`/`fmtFull`/`fmtDollars`/… across pages and components) alongside a canonical `fmt` in `lib/utils` used at ~190 sites — the same rules copy-pasted with inconsistent handling of negatives, whole-dollar, cents-vs-dollars, and blank input. Added `client/lib/money.js` (`formatUSD` / `formatUSDWhole` / `formatCentsUSD`, with `signed`/`dash`/`whole` options) as the single implementation; inputs are coerced so `null`/`''`/`NaN` never render as `$NaN` and `-0` never shows as `-$0.00`. `lib/utils.fmt` now delegates to it (byte-identical — guarded by the existing `utils.test.js` suite) and the 15 local formatters were removed in favor of it. Tests: `client/lib/money.test.js`. (was IMP-CODE-01) diff --git a/docs/QA_PLAN.md b/docs/QA_PLAN.md index 55fc951..0838a72 100644 --- a/docs/QA_PLAN.md +++ b/docs/QA_PLAN.md @@ -217,7 +217,7 @@ graduate to `roadmap.md`/`FUTURE.md`. | IMP-CODE-01 | Code | `client/lib/money.js` (+16 files) | ~~No shared client money formatter.~~ **Shipped `a15f00c`:** added `client/lib/money.js` (`formatUSD`/`formatUSDWhole`/`formatCentsUSD`); `lib/utils.fmt` delegates to it and 15 local formatters were removed. `null`/`NaN`/`-0` all handled. Test `client/lib/money.test.js`; full client suite + build green. | M | ✅ Shipped | | IMP-CODE-02 | Code | `db/database.js` (4,174 ln) | **Oversized module.** One file mixes the migration engine, query helpers, settings, and connection lifecycle. Split into cohesive modules (behavior-preserving, test-guarded) for navigability and lower merge-conflict risk. | L | 🔵 Noted | | IMP-CODE-03 | Code | `services/*match*`, `bankSync*` | **Overlapping match logic.** `transactionMatchService` / `matchSuggestionService` / `merchantStoreMatchService` each write `match_status` + bill/payment links; QA-B5-04 showed how easily these drift out of sync. Extract one canonical "set/clear match" helper so state transitions live in one place. | M | 🔵 Noted | -| IMP-IA-01 | IA | Sidebar · `/data` | **Central features under an overflow menu.** Data (import/export/backups) and account pages are reachable only via the account overflow dropdown + `Ctrl+K`, not the primary nav. For how central import/export/backup is, consider a primary-nav or labeled "Manage" entry so it's easier to find. | S | 🔵 Noted | +| IMP-IA-01 | IA | Sidebar · `/data` | ~~Central features under an overflow menu.~~ **Shipped `0b1c6a8`:** Data moved into the main app nav (desktop dropdown + mobile) alongside Bills/Categories/Spending; same default-admin gate preserved; removed the redundant account-dropdown entry. | S | ✅ Shipped | | IMP-UX-01 | UX | Bills / Categories delete | **Retention isn't surfaced.** Soft-delete keeps records 30 days, but the only restore affordance is a transient "Undo" toast — dismiss it and a bill deleted an hour ago is unrecoverable via UI. Add a lightweight "Recently deleted / restore" view to actually leverage the retention window. | M | 🔵 Noted | | IMP-UX-02 | UX | all list pages | **State audit.** Systematically verify every list/page has an empty-state with a CTA, a skeleton/loading state, and a recoverable error state (pair with B14 fault-injection) — no dead ends, no silent failures. | M | 🔵 Noted |