The v4 upgrade codemod rewrote arbitrary-value opacity modifiers like
bg-emerald-500/[0.025] to bare fractional form (/2.5), but v4 emits NO
rule for fractional bare opacity — the tracker/calendar row tints and
two banner backgrounds silently disappeared (6 classes, 4 files). Found
by the code-review line-scan; invisible to the screenshot baseline
(login page only) and the text-based census. Restored the /[0.025]
arbitrary form; compiled CSS verified to emit all six selectors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Official codemod (run in a clean worktree; docker-owned data/ blocks it
in-tree): tailwind.config.js inlined into client/index.css as CSS-first
@theme/@utility (config file deleted — v4 auto-detects content, which
also retires the .tsx-content-glob failure class from the TS migration),
33 template files' class renames applied, tailwindcss-animate loads via
the v4 @plugin bridge. Build runs through @tailwindcss/vite; postcss
config is now plugin-free. tailwind-merge -> 3 (v4 class model).
Visual-regression gate: only diffs were a ~2px global preflight shift +
the version string (baseline predated 0.41.1); re-baselined both login
screenshots in this commit after review. webauthn.probe confined to the
probe project (it enables WebAuthn for the seeded user, racing the
parallel UI projects' password logins).
e2e 27 passed, probe 18/18, PROD SMOKE PASS, typecheck/lint/tests green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Small follow-ups the rest of the refresh depends on:
- client/lib/trackerUtils.ts: status-tone helper now returns the
'good' / 'warn' / 'danger' tokens the new TonedCard / ToneDot
consume, so the per-row badges stay in sync with the new design
tokens.
- client/lib/version.ts: release-notes shape accepts the optional
brand_image field that HISTORY.md now uses for the 'Doing my
part' release image.
This is commit 8 of 9 in the v0.42.0 brand refresh. Depends on
1807456 (admin + data + dialogs).
The mobile tracker row (consumes branded TrackerRow + shared payment hooks).
Supporting: TrackerRow.sparkline typed number[]|null; ROW_STATUS_CLS typed
Record<string,string> (it has no `skipped` key, so indexing by TrackerStatus
needed a string index). DragProps/MoveControls interfaces exported. Notable: the
HTML5 drag handlers conflict with framer-motion's own onDrag* gesture types on
motion.div — cast via ComponentProps<typeof motion.div>; quick-pay/remaining
amounts need asDollars at the boundary. typecheck 0, build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New client/types.ts domain-types module. Types the full /tracker response —
TrackerResponse { summary, bank_tracking, cashflow, rows } — with every money
field branded `Dollars` (the server serializes cents→dollars, verified against
statusService.buildTrackerRow + trackerService.getTracker + buildBankTracking +
buildSafeToSpend). api.tracker() now returns Promise<TrackerResponse>.
TrackerRow + TrackerStatus move to @/types (canonical) and are re-exported from
@/lib/trackerUtils for compat; trackerUtils' row money fields upgrade from plain
`number` to branded `Dollars` (rowThreshold -> Dollars, paymentSummary re-brands
its computed amounts via asDollars so callers can fmt() them directly). This is
the first endpoint where the money brand flows end-to-end: fetch layer -> row
helpers, and (in phase B) into the components that format them.
Nested payloads no typed consumer reads yet (summary.trend, autopay_suggestion/
_stats, sparkline) are left `unknown`, to refine when consumed. asDollars is an
identity at runtime, so behavior is unchanged: typecheck 0, lint 0 errors, build
green, 48 client tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The tracker row/status/sort helpers are now typed. Introduces a TrackerRow
domain interface (the fields these helpers read) and a TrackerStatus union
(paid|autodraft|upcoming|due_soon|late|missed|skipped). Row money fields stay
plain `number` for now — branding them Dollars is a later increment, done when
the tracker API response itself is typed so the brand flows in from the source.
Strict-mode handling: STATUS_SORT_ORDER is Record<TrackerStatus,number> (no
undefined on lookup); moveInArray guards the noUncheckedIndexedAccess `T |
undefined` from splice; the sort comparator relies on aliased-condition
narrowing to reach string|number in each branch. typecheck 0 errors, lint 0
errors (47 warnings unchanged), build green, 48 client tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 21:53:45 -05:00
Renamed from client/lib/trackerUtils.js (Browse further)