Skip to content

fix(ux): P0 — dashboard dataset widgets, detail field leak, startup race - #103

Merged
os-zhuang merged 1 commit into
mainfrom
fix/ux-p0-dashboard-detail-startup
Jun 10, 2026
Merged

fix(ux): P0 — dashboard dataset widgets, detail field leak, startup race#103
os-zhuang merged 1 commit into
mainfrom
fix/ux-p0-dashboard-detail-startup

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes the three P0 issues from the mobile UX walkthrough. Verified in-browser against a live app-todo server (8.0 dataset dashboard).

1. Dashboard widgets span forever → real data + terminal states

8.0-spec widgets declare an analytics dataset (+ values/dimensions/layout/options) instead of a raw object. The data hook ran useQuery disabled, and useQuery leaves isLoading: true forever when disabled — hence the perpetual spinners.

  • resolveDatasetWidget() resolves a dataset → its base object + the measure's aggregate/valueField + the dimension's categoryField, then reuses the existing client-side aggregation. No dependency on a server analytics endpoint (the dev/published runtime's /analytics/query is unreliable / may be unmounted).
  • useWidgetQuery short-circuits any still-unqueryable widget to a terminal empty state — never a stuck spinner.
  • Fixed buildChartData returning all-zero buckets for a count chart with no value field (the common dataset case).
  • Added {current_week_start} / {N_weeks_ago} filter macros the widgets use.

Result: Total Tasks 8, Tasks by Status/Category charts render real grouped data, Overdue/Due Today/Weekly show proper No datazero infinite spinners.

2. Detail screen leaked Organization Id

The no-form-view fallback laid out raw Object.keys(record), leaking injected tenancy keys (organization_id) and metadata-hidden fields at the top. It now mirrors the form's isEntryField filtering (drops internal/tenancy + hidden/system fields). Detail now leads with Subject.

3. Cold-start request storm against the default host

Before hydrate() re-targeted the clients, the whole nav tree mounted and fired session/notifications/meta/dashboard requests at the default API host — a storm of ERR_CONNECTION_REFUSED (and the dev-overlay error). The app shell (auth session + providers + navigation) is now gated on hydration, so the first request — including better-auth's get-session — hits the configured server. Verified zero stale-host requests on reload.

Tests

+9 tests (dataset resolution, count-chart fix, spinner guard, week macros, detail field filtering). 1275 pass, typecheck + lint clean.

🤖 Generated with Claude Code

Three P0 issues surfaced by the mobile UX walkthrough:

1. Dashboard widgets spun forever. 8.0-spec widgets reference an analytics
   `dataset` (+ `values`/`dimensions`) instead of a raw `object`, so the data
   hook ran `useQuery` disabled — and `useQuery` leaves `isLoading: true`
   forever when disabled. Resolve each dataset to its base object + measure
   aggregate + dimension field (client-side aggregation, no dependency on a
   server analytics endpoint the published runtime may not mount), and
   short-circuit any still-unqueryable widget to a terminal empty state. Also
   fix count-aggregate charts returning all-zero buckets when the count
   measure has no value field, and add `{current_week_start}` / `{N_weeks_ago}`
   filter macros the widgets use.

2. Detail screen leaked `Organization Id` (and other injected tenancy /
   metadata-hidden fields) at the top of the auto-layout. The fallback now
   mirrors the form's `isEntryField` filtering.

3. Cold start fired a storm of connection-refused requests against the default
   API host before `hydrate()` re-targeted the clients. Gate the whole app
   shell (auth session + data providers + navigation) on hydration so the
   first request — including better-auth's get-session — hits the configured
   server. Verified zero stale-host requests on reload.

All three verified in the browser against a live app-todo server (widgets show
real data + proper empty states, detail leads with Subject, no :3100 storm).
+9 tests; 1275 pass, typecheck + lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@os-zhuang
os-zhuang merged commit 905bc5d into main Jun 10, 2026
1 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant