Repository navigation
fix(orders): real rejection reasons on the order form; input a11y and layout fixes - #28
Merged
Merged
Conversation
… layout Diagnosed "some error occurred" on order placement: verified live (fresh KYC/account-approved, funded test customer) that the exact wire path -- frontend payload construction, CreateOrderRequest schema, Units/Price decimal-string convention -- works correctly end to end (a direct POST with the exact VTI/Buy/2/$20 payload succeeded, 201). The real bug is that frontend/src/utils/apiErrorMessage.js has zero mappings for any order-specific rejection code, so every real, specific reason the backend returns (insufficient_investable_cash, kyc_verification_pending, kyc_verification_rejected, account_approval_pending, account_approval_rejected, customer_not_eligible) collapsed into the generic "Something went wrong" fallback. Reproduced live against an approved-but-unfunded account: before this fix, "Something went wrong"; after, "You don't have enough investable cash for this order." New ordersErrorMessage.js mirrors funding's existing fundingErrorMessage.js pattern; wired into OrderForm, OrderList, and ApprovalBanner (all three previously called the bare utility). Also, per a careful read of every input field: wired validation/server errors into Input's `error` prop (fixes a real accessibility gap -- aria-invalid/aria-describedby never fired before, message rendered through a disconnected sibling paragraph); trimmed the reference-price value before validating and sending (quantity already did this via parseQuantity, reference price did not); added an explicit empty-state message if the securities list is ever empty instead of letting the selected security silently go undefined; added `required` to both selects for parity with the inputs. Layout: OrderForm.css hard-coded max-width: 360px with no breakpoint, and the form wasn't wrapped in a Card -- confirmed visually (a live 1280px snapshot showed the four fields as a narrow login-form-sized column with the rest of the page empty). Replaced with a responsive 2-column field grid (Security+Side, Quantity+Reference price) at 768px+ matching FeesPage.css/FundingPage.css's established breakpoint convention, collapsing to one column below it; wrapped in a Card at the page's --reading-max-width (640px) -- verified both breakpoints live. No backend changes -- the wire contract was already correct.
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.
Problem
Placing an order (security VTI, side Buy, quantity 2, reference price 20) failed with a generic
"some error occurred," and the order form's four fields were stacked in a narrow column not using
the available page width.
Diagnosis (verified live, not guessed)
The wire path is correct. Registered a fresh customer, approved KYC/account, funded and
confirmed $1,000 cash through the real
DepositService, then posted the exact frontend payload(
security_idUUID,side: "buy",quantity: "2",reference_price: "20") directly toPOST /api/v1/orders— 201, order created. Payload construction,CreateOrderRequest'sschema, and the
Units/Pricedecimal-string convention all match exactly.Root cause: every order-specific rejection reason was thrown away.
frontend/src/utils/apiErrorMessage.js's code map has zero entries for any codeorders.pyactually returns (insufficient_investable_cash,kyc_verification_pending,kyc_verification_rejected,account_approval_pending,account_approval_rejected,customer_not_eligible) — all of them fall through to the generic"Something went wrong. Please try again."I reproduced this live against anapproved-but-unfunded account (a KYC-pending account can't even reach this page —
RequireOnboardedredirects to
/onboardingfirst, confirmed): before the fix, the form showed the generic message;after, it shows "You don't have enough investable cash for this order."
Fix
frontend/src/features/orders/ordersErrorMessage.js, mirroring the existingfundingErrorMessage.jspattern, mapping all six real order-rejection codes to specific,actionable copy. Wired into
OrderForm,OrderList, andApprovalBanner(all three previouslycalled the bare utility).
wired into
Input'serrorprop (fixes a real accessibility gap —aria-invalid/aria-describedbynever fired before); reference price is now trimmed before validating/sending(quantity already was, via
parseQuantity); an explicit empty-state message replaces a silentundefinedselection if the securities list is ever empty;requiredadded to both selects forparity with the inputs.
OrderForm.csshard-codedmax-width: 360pxwith no breakpoint and noCardwrapper —replaced with a responsive 2-column field grid (Security+Side, Quantity+Reference price) at
768px+, matching this codebase's established
FeesPage.css/FundingPage.cssbreakpointconvention, collapsing to one column below it, wrapped in a
Cardat the page's--reading-max-width(640px).No backend changes — the wire contract was already correct.
Validation evidence
npm run lint,npm run build— both clean.against an approved-but-unfunded test account — confirmed the specific message now renders.
no overflow) confirming the layout fix at both breakpoints.
Security / DB / API impact
None. Frontend-only change; no new endpoint, no wire-shape change, no migration.