feat(my-predictions): status and title filters with a filtered summary - #1795
Open
bilhokista wants to merge 3 commits into
Open
feat(my-predictions): status and title filters with a filtered summary#1795bilhokista wants to merge 3 commits into
bilhokista wants to merge 3 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Closes #1556.
Starting point
A status filter already existed (All / Active / Won / Lost / Pending) with counts on each tab. Missing were the Refunded status, the text search, the summary chips, and URL persistence — and the existing summary had a subtler problem, below.
The change
Filtering and summarising move into a new pure module,
frontend/src/lib/predictions.ts, so the rules can be tested without rendering the page. The page keeps rendering and URL state.Text search matches the market title, case-insensitively, trimmed. Status and search compose.
Refunded. Cancelling a prediction used to delete the row:
A refund is part of the history the user opened this page to review, so it is now marked
Refundedinstead of vanishing, and has its own tab and badge.URL persistence via
?status=&q=, written withrouter.replacerather thanpushso typing in the search box does not bury the previous page under a stack of history entries. Values at their default are omitted, keeping a pristine URL clean. An unrecognised status in a hand-edited or stale link falls back to defaults rather than failing.Because
useSearchParamsopts the subtree into client rendering and Next refuses to build a page that calls it outside a Suspense boundary, the screen moved intoMyPredictionsContentand the default export now supplies that boundary.Two judgement calls worth review
The summary now describes the filtered set, not lifetime totals. The issue asks for exactly this ("summary reflects the filtered set"), and it is what makes the chips useful while filtering — but it does change what the four cards at the top of the page mean. The first card relabels itself from "Total Predictions" to "Predictions Shown" when a filter is active, so the number is not mistaken for a lifetime count.
Win rate is won ÷ settled, not won ÷ total. On the sample data that is 1 of 2 settled = 50%; over all six it would read 17% and would keep falling every time the user places a new prediction, which reads as though they are getting worse at this.
winRateisnullwhen nothing has settled, so the card shows "—" rather than a misleading 0%.Also: net P/L counts a win as payout minus stake, not the gross payout, and treats open stakes as 0 rather than as losses — otherwise an untouched account with open bets looks under water.
Scope note
The page still renders
MOCK_PREDICTIONS. The issue listsfrontend/src/lib/api.tsin its file list, but wiring a real endpoint is a separate piece of work with its own contract to agree, so I left the fixture in place and kept this change to filtering and presentation.filterPredictionsandsummarisePredictionsare generic over the prediction shape, so swapping in real data later does not touch them.ActivePrediction.tsxturned out not to be involved in this page and is untouched.Tests
New
predictions.test.ts, 30 cases acrossparseAmount,computePnl,filterPredictions,summarisePredictions,formatSignedAmount, and the URL round-trip — including the empty set (no division by zero), a search of pure whitespace, an unparseable amount, "-0.00" never being rendered as a loss, and an explicit case asserting the summary follows the filtered set.Honest note on verification: I could not run the frontend Vitest suite locally (no full workspace install). Both changed files and the new module were parsed with the TypeScript compiler API, and
predictions.tswas transpiled and executed standalone against 32 assertions — all passed. The page component itself needs CI; it has no test of its own here, since the logic worth asserting is in the module and testing the page would mostly re-test React.🤖 Generated with Claude Code
https://claude.ai/code/session_01CrfEY1tvXrbeMDAUzxfuk7