feat(predict): add Positions/Outcomes tab bar to game details#28668
feat(predict): add Positions/Outcomes tab bar to game details#28668
Conversation
Extract PredictGameDetailsTabs component to house tab bar logic for game event details, gated behind a placeholder feature flag. Move "Your picks" title from PredictPicks into PredictGameDetailsTabs so PredictPicks renders items only, while the title shows in the flag-off path. When enabled, the component renders PredictMarketDetailsTabBar with Positions/Outcomes tabs and an outcomes placeholder.
…on fetching Lift position fetching to PredictGameDetailsContent as the single source of truth, eliminating duplicate usePredictPositions calls from useGameDetailsTabs and PredictPicks. Replace the placeholder ENABLE_GAME_TABS constant with the real extendedSportsMarketsLeagues feature flag gated per league. PredictPicks now receives positions as required props, and "Your picks" title only renders when positions exist.
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #28668 +/- ##
==========================================
+ Coverage 82.13% 82.15% +0.02%
==========================================
Files 4942 4951 +9
Lines 129947 130101 +154
Branches 28977 29017 +40
==========================================
+ Hits 106732 106887 +155
- Misses 15917 15920 +3
+ Partials 7298 7294 -4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
app/components/UI/Predict/components/PredictGameDetailsContent/PredictGameDetailsContent.tsx
Show resolved
Hide resolved
...omponents/UI/Predict/components/PredictGameDetailsContent/PredictGameDetailsContent.test.tsx
Outdated
Show resolved
Hide resolved
...components/UI/Predict/components/PredictGameDetailsContent/PredictGameDetailsTabsContent.tsx
Show resolved
Hide resolved
...omponents/UI/Predict/components/PredictGameDetailsContent/PredictGameDetailsContent.test.tsx
Show resolved
Hide resolved
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
These changes affect the Predict market details view - specifically how user positions are displayed and navigated. The SmokePredictions tag directly covers position lifecycle (opening positions, cashing out, claiming winnings) which is the core functionality affected by these UI changes. Per SmokePredictions tag description: when selecting SmokePredictions, also select SmokeWalletPlatform (Trending section - Predictions is embedded there) and SmokeConfirmations (opening/closing positions are on-chain transactions). No changes to core infrastructure, navigation, controllers, or shared components that would warrant broader test coverage. Performance Test Selection: |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8bf539c. Configure here.
...omponents/UI/Predict/components/PredictGameDetailsContent/PredictGameDetailsContent.test.tsx
Show resolved
Hide resolved
|
|
✅ E2E Fixture Validation — Schema is up to date |
matallui
left a comment
There was a problem hiding this comment.
A couple of questions, but nothing blocking
| const { data: activePositions = [] } = usePredictPositions({ | ||
| marketId: market.id, | ||
| claimable: false, | ||
| refetchInterval: 10000, | ||
| }); | ||
| const { data: claimablePositions = [] } = usePredictPositions({ | ||
| marketId: market.id, | ||
| claimable: true, | ||
| }); |
There was a problem hiding this comment.
I believe you can fetch both claimable and active if you don't set claimable in this hook. Do we need these 2 separately? I also don't see why we'd need to refetch. We know the user can only get new active positions is they buy/sell, at which point we invalidate the query
There was a problem hiding this comment.
I think we can remove the refetch. PredictPicks already handles live position updates internally, so I don’t think we need it.
We also separate claimable positions for two reasons: we don’t need live positions for claimable ones, and we want to show claimable positions after the active ones.
The first part could be moved into the usePredictLivePositions hook, but if we still want to show claimable positions after the active ones in the list, I’m not sure whether that filter should live inside the live positions logic.
| useEffect(() => { | ||
| if (!enabled) return; | ||
| if (activeTab >= tabs.length) { | ||
| setActiveTab(0); | ||
| } | ||
| }, [tabs, activeTab, enabled]); |
There was a problem hiding this comment.
Not needed after all. Removing on the next task.




Description
Adds a Positions/Outcomes tab bar to the game details screen, gated behind the
extendedSportsMarketsLeaguesfeature flag per league.What changed:
useGameDetailsTabshook — New hook that reads theextendedSportsMarketsLeaguesremote flag, computes tabs (Positions + Outcomes when user has positions, Outcomes-only otherwise), manages active tab state, and determines sticky header indices.PredictGameDetailsContent— Fetches positions as a single source of truth and passes them to both the hook (for tab logic) andPredictGameDetailsTabsContent(for rendering). RendersPredictMarketDetailsTabBaras a directScrollViewchild for sticky behavior.PredictGameDetailsTabsContent— New component with three rendering paths:PredictPicksnullPredictPicks— Refactored to acceptpositionsandclaimablePositionsas required props instead of fetching internally. Removed "Your picks" title (now owned by parent). Removed internal empty-state check (parent controls visibility).PredictMarketDetailsTabBar— Added optionaltabTwStyleprop to allow consumers to override individual tab styling (game details passesflex-1for 2-tab even distribution).Changelog
CHANGELOG entry: Added Positions and Outcomes tab bar to sports game detail screens
Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/PRED-802
Manual testing steps
Screenshots/Recordings
Before
tabsbefore.mp4
After
tabsafter.mp4
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Medium risk: changes game details rendering flow and how positions data is fetched/prop-drilled to drive tabbed UI (including sticky header behavior), gated by a remote feature flag but still impacts a user-facing screen.
Overview
Adds a feature-flagged Positions/Outcomes tab experience to the Predict game details screen, including a sticky
PredictMarketDetailsTabBarwhen the user has positions in an enabled league and an outcomes placeholder when they don’t.Refactors
PredictPicksto be purely presentational by requiringpositions/claimablePositionsprops (no internal fetching or header), and introducesuseGameDetailsTabs+PredictGameDetailsTabsContentto centralize tab state/visibility and conditionally render picks vs outcomes content. Updates/expands tests accordingly and removes the prior snapshot test.Reviewed by Cursor Bugbot for commit 8bf539c. Bugbot is set up for automated code reviews on this repo. Configure here.