Repository navigation
fix(frontend): global page-width bug, Refresh status throttle, remove Transactions - #30
Merged
Badri-Rajendran merged 3 commits intoSep 7, 2026
Conversation
…ots/Funding
Investigating "Orders/Portfolio/Dashboard don't use the available
horizontal space" found the actual root cause, not a per-page styling
gap: .tu-page (used by every page) sits in .tu-app-layout__main, a
column flex container. Its own margin: 0 auto centering is a cross-axis
auto margin on a flex item -- per the flexbox spec that opts the item out
of stretch sizing entirely, so it shrinks to its own content's width
instead of the container's, unless that content happens to be wide
enough on its own to force it back open. That's exactly why Fees/Lots/
Funding/the new Orders form never showed it (wide table or filled
multi-column form) while Orders' list, Portfolio, and Dashboard did.
Confirmed live at 1280px, all previously unpatched: Orders list rendered
at 293px, Portfolio at 307px, Dashboard at 510px.
This is the identical bug already found and patched twice this session,
once per page, as each was redesigned and happened to hit it:
LotsPage.css's .tu-page.tu-lots-page and FundingPage.css's
.tu-page.tu-funding-page, both `{ width: 100%; min-width: 0; }`.
Fixed once at the source instead: moved width: 100%; min-width: 0 onto
the base .tu-page rule in PageLayout.css, and deleted both now-redundant
per-page overrides. Fixes Orders, Portfolio, and Dashboard's wasted-space
complaint at the root, plus any future page that hits the same trap --
verified live, Portfolio's existing repeat(auto-fill, minmax(260px,1fr))
grid now correctly spreads its 4 model cards across the full width with
no page-specific change needed there.
Also fixed DashboardPage.css: with .tu-page now actually full width, its
flex-wrap stats row would have just left BalanceCard/ReturnCard small and
left-aligned with the rest of the row empty. Changed to
repeat(auto-fit, minmax(280px, 1fr)), matching the same grid idiom
already used in ModelDetail.css/AssignmentPrompt.css -- verified live,
both cards now stretch to fill the row.
…t all useIdentityStatus.js had zero client-side rate limiting, debounce, or cooldown on refetch(). Each call hits GET /identity/status/<id>, which for a still-pending customer triggers a live outbound Stripe Identity poll, not a cheap read -- and shares a single 30/min-per-IP, in-memory bucket (identity.py, key_func=get_remote_address) with RequireOnboarded's own background calls on every protected-route navigation. A customer clicking "Refresh status" repeatedly could burn through that shared budget for the whole app. The only reason a double-click didn't already double-fire was incidental: flipping status away from 'loaded' unmounts the button along with the entire status card, replaced by a skeleton -- not a real cooldown, and it means every refresh flashes the whole card away rather than updating in place. Added an explicit 10s cooldown tracked by a ref (no extra renders for the tracking itself) plus a ticking cooldownRemainingSeconds state so the button can show "Try again in Ns" and disable itself, verified live: a click immediately shows "Try again in 10s" (disabled), correctly counts down 10s -> 9s -> 8s, and re-enables once it reaches zero. Applies to every caller of refetch() uniformly (the button, KycStep's onCompleted, ErrorState's onRetry) -- a spammed retry deserves the same protection as a spammed manual refresh, and centralizing it in the hook is simpler and more robust than duplicating a cooldown at each call site. The initial mount fetch is never throttled -- there's nothing to cool down from yet.
Deleted TransactionsPage.jsx and everything that existed only to serve it: TransactionTable.jsx, useTransactionHistory.js, entryTypeLabels.js (each confirmed to have exactly one importer chain rooted at the page). Removed the /transactions route + import from App.jsx and the nav link from AppLayout.jsx's money group; removed valuationApi.js's now-unused getHistory (getBalance/getReturns stay -- Dashboard's). GET /valuation/history becomes unused by the frontend as a result (confirmed no other feature calls it) -- left the backend endpoint, service, and tests alone; removing working, tested backend surface is a separate decision this change doesn't make.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three unrelated frontend fixes bundled together (three separate commits, easy to review
independently):
a real bug in the shared
.tu-pagerule (used by every page), not a per-page styling gap —already patched twice this session as one-off overrides on Lots and Funding. Fixed once at the
source; deleted both now-redundant patches.
nothing else depending on it.
1. Global page-width bug
.tu-pagesits in a column flex container; its ownmargin: 0 autocentering is a cross-axisauto margin, which per the flexbox spec opts it out of stretch sizing — it shrinks to its content's
width unless that content happens to be wide enough to force it back open. Confirmed live at
1280px, all previously unpatched: Orders list rendered at 293px, Portfolio at 307px,
Dashboard at 510px. Fixed at the source in
PageLayout.css; deleted the redundant.tu-page.tu-lots-page/.tu-page.tu-funding-pageoverrides. Also fixedDashboardPage.css'sstats row (
flex-wrap→repeat(auto-fit, minmax(280px, 1fr))) so the two stat cards actuallyfill the now-full-width row, matching the grid idiom already used in Portfolio's components.
Live-verified: Dashboard's stat cards now span the row; Portfolio's existing
repeat(auto-fill, minmax(260px,1fr))grid now correctly spreads all 4 model cards (noPortfolio-specific change needed); Orders list header now uses the full row; confirmed no
horizontal overflow at 375px.
2. Onboarding refresh throttle
useIdentityStatus.jshad no debounce/cooldown at all — each click can trigger a live outboundStripe Identity poll and shares a 30/min-per-IP bucket with
RequireOnboarded's own backgroundcalls. Added a 10s cooldown (tracked via a ref, no extra renders) with a ticking
cooldownRemainingSecondsso the button shows "Try again in Ns" and disables itself. Appliesuniformly to every
refetch()caller (button,KycStep.onCompleted,ErrorState.onRetry); theinitial mount fetch is never throttled.
Live-verified with a polling test: click → immediately "Try again in 10s" (disabled) → counts down
10s→9s→8s → re-enables at 0.
3. Remove Transactions page
Deleted
TransactionsPage.jsxand everything that existed only to serve it(
TransactionTable.jsx,useTransactionHistory.js,entryTypeLabels.js— each confirmedsingle-importer). Removed the route, import, and nav link.
valuationApi.js's unusedgetHistoryremoved (
getBalance/getReturnsstay).GET /valuation/historybecomes unused by the frontendas a result — backend left alone, that's a separate decision.
Validation evidence
npm run lint,npm run build— clean on every commit.throttle), described above.
grep -rn "TransactionsPage\|TransactionTable\|useTransactionHistory\|/transactions"acrossfrontend/src— zero remaining references.Security / DB / API impact
None. Frontend-only. No new endpoint, no wire-shape change.
GET /valuation/historyis unchangedserver-side, just no longer called by the frontend.