fix: QA batch - streak strip date math, OTP login race, route blanking, UI polish - #168
Conversation
…g, UI polish - streak: extract buildStreakWeekDays into @orbit/shared (midnight-anchored comparisons so the lastActiveDate day no longer renders as missed) + tests - auth(mobile): persist tokens before clearing the query cache on login; retry 401s with the newest stored token before resetting the session - web: deriveRowState applies bad/overdue dot state to sub-habit rows (mobile parity) - web: route transitions use AnimatePresence popLayout (no blank gap on heavy mounts) and tab routes are prefetched - mobile: calendar selected-day highlight uses an explicit circular radius - mobile: today search restyled to a single field with Cancel outside (web parity) - celebrations: remove Continue button from streak + all-done overlays - achievements: 2-column grid, uniform card height, always-visible descriptions - summary: clamp threshold follows shared AI_SUMMARY_MAX_CHARS (300) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
There was a problem hiding this comment.
Nine QA bugs fixed in a clean, well-structured batch. A few highlights worth calling out:
Streak date math — the buildStreakWeekDays extraction into @orbit/shared is the right move: midnight-anchored via startOfDay instead of raw new Date() comparisons, 7 targeted unit tests covering the tricky boundary (lastActive day was the bug), and both platforms now share identical logic. The future status was also cleanly removed since the 7-day window ends today.
OTP login race — the two-part fix is correct. Persisting tokens before queryClient.clear() eliminates the root cause; the apiClient token-rotation retry (compare tokenUsed to the latest stored token before triggering the refresh flow) covers in-flight requests during the narrow window. The tests nail both ordering invariants.
deriveRowState parity fix — removing the !isChild gate for bad/overdue is the right call; the mobile behavior was already correct, and the web test now locks in the expected state value on child rows via data-state.
footerStyle in useCelebrationEntrance — still consumed by streak-freeze, goal-completed, and level-up overlays, so no dead code issue. The two components that dropped their Continue buttons cleaned up their destructuring correctly.
Overall: solid bug-batch PR with tests for every non-trivial fix, both platforms updated, shared utility well-tested. Good to merge.
…ver 140 chars The display clamp threshold was raised to 300 together with the backend generation cap, which removed the collapse affordance for every summary the backend can now produce. The two limits are independent: generation stays at 300, display clamps at 140 (AI_SUMMARY_CLAMP_CHARS). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Second commit holds up: extracts the magic 140 into AI_SUMMARY_CLAMP_CHARS in packages/shared, both platforms import it, and the JSDoc clearly documents the independence from the API's 300-char generation cap. Full PR is solid — nine targeted bug fixes with tests for every non-trivial path, cross-platform parity throughout, and CI green. Good to merge.
|



What
Nine user-reported issues fixed in one batch. Paired backend PR: thomasluizon/orbit-api#203.
Bugs
subDays(new Date(), n)(carries time-of-day) againstparseISO(lastActiveDate)(midnight), sodate <= lastActiveDateexcluded the last-active day itself. Yesterday looked empty even with 28 logs, then "filled in" after today''s first log. The duplicated derivation now lives in@orbit/sharedasbuildStreakWeekDays(midnight-anchored, 7 unit tests); both apps consume it. Paired with on-read recalc in the API PR.login()ranqueryClient.clear()before writing tokens; clearing refetches root-mounted queries (profile is mounted on the login screen), those fired with the old/empty token, hit the 401 path, andclearSessionAndResetAuth()wiped the brand-new session. Tokens are now persisted first, andapiClientretries a 401 with the newest stored token before resetting the session (covers requests that were in flight across the login).RouteTransitionShellusedAnimatePresence mode="wait"- the heavy Today mount stalled the main thread right after the old page faded to opacity 0, leaving nothing on screen until the mount finished. Switched tomode="popLayout"(new route mounts immediately) and tab routes are now prefetched (WebNavusesrouter.push, which never prefetches - every tab switch paid a full RSC round trip).deriveRowStategatedbad(andoverdue) behind!isChild; mobile applies both to child rows. Gates removed for parity.UX changes
AppTextInput''s built-in field chrome is neutralized inside the search pill) and gains the web-style Cancel button outside the field.AI_SUMMARY_CLAMP_CHARS = 140with the see-more/see-less toggle.Tests
packages/sharedstreak-week suite (7), web habit-list bad-child state, web achievements description visibility, mobile api-client token-rotation retry, mobile auth-store ordering.🤖 Generated with Claude Code