Skip to content

Commit 3d1cea8

Browse files
caieumatallui
andauthored
chore(predict): cash out screen changes (MetaMask#22272)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** - cash out changes <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Updates the Predict cash out preview to show per‑share price with fallback, localizes copy, refactors layout/styles, adds locale strings, and adjusts tests accordingly. > > - **Predict Sell Preview (UI/Logic)**: > - Localizes header/button text and replaces hardcoded labels with `strings('predict.cash_out')`. > - Displays per‑share price using `preview.sharePrice ?? position.price` and adds line under current value via `predict.at_price_per_share`. > - Shows initial position info (amount, outcome, avg entry price) via `predict.cashout_info`. > - Refactors layout to `Box` components, tweaks icon container, and simplifies details rendering. > - **State/Computation**: > - Adds `currentPrice` derived from `preview?.sharePrice ?? position?.price`; leverages `position.avgPrice` for display. > - **Styles**: > - `app/components/UI/Predict/components/PredictPosition/PredictPosition.styles.ts`: make `positionDetails` `flex: 1`; remove extra width/flex on `positionPnl`. > - `app/components/UI/Predict/views/PredictSellPreview/PredictSellPreview.styles.ts`: remove unused containers/fields; keep core layout and button styles. > - **Tests** (`PredictSellPreview.test.tsx`): > - Update assertions to new copy (“Cash out”, `$50.00 on Yes at 50¢`), and add test for undefined `preview.sharePrice` using fallback. > - **Locales** (`locales/languages/en.json`): > - Add `predict.at_price_per_share` and `predict.cashout_info`; ensure “Cash out” casing alignment. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fae7da8. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Luis Taniça <matallui@gmail.com>
1 parent 721177c commit 3d1cea8

5 files changed

Lines changed: 55 additions & 43 deletions

File tree

app/components/UI/Predict/components/PredictPosition/PredictPosition.styles.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ const styleSheet = () =>
2020
flexDirection: 'column',
2121
justifyContent: 'flex-start',
2222
alignItems: 'flex-start',
23-
width: '100%',
24-
flex: 5,
23+
flex: 1,
2524
},
2625
positionImageContainer: {
2726
paddingTop: 4,
@@ -36,8 +35,6 @@ const styleSheet = () =>
3635
flexDirection: 'column',
3736
justifyContent: 'flex-end',
3837
alignItems: 'flex-end',
39-
width: '100%',
40-
flex: 2,
4138
},
4239
marketEntry: {
4340
flexDirection: 'column',

app/components/UI/Predict/views/PredictSellPreview/PredictSellPreview.styles.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,6 @@ const styleSheet = (params: { theme: Theme }) => {
4141
paddingBottom: 0,
4242
gap: 16,
4343
},
44-
positionContainer: {
45-
flexDirection: 'row',
46-
alignItems: 'center',
47-
gap: 16,
48-
width: '100%',
49-
},
50-
positionDetails: {
51-
flexDirection: 'column',
52-
gap: 4,
53-
flex: 1,
54-
minWidth: 0,
55-
},
5644
detailsLine: {
5745
flexDirection: 'row',
5846
gap: 16,
@@ -62,11 +50,6 @@ const styleSheet = (params: { theme: Theme }) => {
6250
flex: 1,
6351
minWidth: 0,
6452
},
65-
detailsResolves: {
66-
flex: 1,
67-
minWidth: 0,
68-
color: theme.colors.text.alternative,
69-
},
7053
detailsRight: {
7154
flexShrink: 0,
7255
color: theme.colors.text.alternative,

app/components/UI/Predict/views/PredictSellPreview/PredictSellPreview.test.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,16 +440,16 @@ describe('PredictSellPreview', () => {
440440

441441
describe('rendering', () => {
442442
it('renders cash out screen with position details', () => {
443-
const { getByText, queryByText } = renderWithProvider(
443+
const { getAllByText, getByText, queryByText } = renderWithProvider(
444444
<PredictSellPreview />,
445445
{
446446
state: initialState,
447447
},
448448
);
449449

450-
expect(getByText('Cash Out')).toBeOnTheScreen();
450+
expect(getAllByText('Cash out').length).toBeGreaterThan(0);
451451
expect(getByText('Will Bitcoin reach $150,000?')).toBeOnTheScreen();
452-
expect(getByText('$50.00 on Yes')).toBeOnTheScreen();
452+
expect(getByText('$50.00 on Yes at 50¢')).toBeOnTheScreen();
453453

454454
expect(
455455
queryByText('Funds will be added to your available balance'),
@@ -512,6 +512,29 @@ describe('PredictSellPreview', () => {
512512
expect(mockFormatPercentage).toHaveBeenCalledWith(-20);
513513
});
514514

515+
it('uses position price when preview sharePrice is undefined', () => {
516+
mockPreview = {
517+
marketId: 'market-1',
518+
outcomeId: 'outcome-456',
519+
outcomeTokenId: 'outcome-token-789',
520+
timestamp: Date.now(),
521+
side: 'SELL',
522+
sharePrice: undefined as unknown as number,
523+
maxAmountSpent: 100,
524+
minAmountReceived: 60,
525+
slippage: 0.005,
526+
tickSize: 0.01,
527+
minOrderSize: 1,
528+
negRisk: false,
529+
};
530+
531+
const { getByText } = renderWithProvider(<PredictSellPreview />, {
532+
state: initialState,
533+
});
534+
535+
expect(getByText('At price: 50¢ per share')).toBeOnTheScreen();
536+
});
537+
515538
it('renders position icon with correct source', () => {
516539
renderWithProvider(<PredictSellPreview />, {
517540
state: initialState,

app/components/UI/Predict/views/PredictSellPreview/PredictSellPreview.tsx

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ const PredictSellPreview = () => {
126126
}, [dispatch, result]);
127127

128128
const currentValue = preview?.minAmountReceived ?? 0;
129-
const { cashPnl, percentPnl } = position;
129+
const currentPrice = preview?.sharePrice ?? position?.price;
130+
const { cashPnl, percentPnl, avgPrice } = position;
130131

131132
const signal = useMemo(() => (cashPnl >= 0 ? '+' : '-'), [cashPnl]);
132133

@@ -198,7 +199,9 @@ const PredictSellPreview = () => {
198199
return (
199200
<SafeAreaView style={tw.style('flex-1 bg-background-default')}>
200201
<BottomSheetHeader onClose={() => goBack()}>
201-
<Text variant={TextVariant.HeadingMD}>Cash Out</Text>
202+
<Text variant={TextVariant.HeadingMD}>
203+
{strings('predict.cash_out')}
204+
</Text>
202205
</BottomSheetHeader>
203206
<View
204207
testID={PredictCashOutSelectorsIDs.CONTAINER}
@@ -208,6 +211,14 @@ const PredictSellPreview = () => {
208211
<Text style={styles.currentValue} variant={TextVariant.BodyMDMedium}>
209212
{formatPrice(currentValue, { maximumDecimals: 2 })}
210213
</Text>
214+
<Text
215+
variant={TextVariant.BodyMDMedium}
216+
color={TextColor.Alternative}
217+
>
218+
{strings('predict.at_price_per_share', {
219+
price: (currentPrice * 100).toFixed(0),
220+
})}
221+
</Text>
211222
<Text
212223
style={styles.percentPnl}
213224
color={percentPnl > 0 ? TextColor.Success : TextColor.Error}
@@ -228,30 +239,26 @@ const PredictSellPreview = () => {
228239
{strings('predict.order.order_failed_generic')}
229240
</Text>
230241
)}
231-
<View style={styles.positionContainer}>
232-
<View>
242+
<Box twClassName="flex-row items-center gap-4">
243+
<Box twClassName="w-10 h-10 self-start mt-1">
233244
<Image source={{ uri: icon }} style={styles.positionIcon} />
234-
</View>
235-
<View style={styles.positionDetails}>
236-
<Text
237-
numberOfLines={1}
238-
ellipsizeMode="tail"
239-
style={styles.detailsLeft}
240-
variant={TextVariant.HeadingSM}
241-
>
242-
{outcomeTitle}
243-
</Text>
245+
</Box>
246+
<Box twClassName="flex-col gap-1 flex-1">
247+
<Text variant={TextVariant.HeadingSM}>{outcomeTitle}</Text>
244248
<Text
245249
numberOfLines={1}
246250
ellipsizeMode="tail"
247-
style={styles.detailsResolves}
248251
variant={TextVariant.BodySMMedium}
252+
color={TextColor.Alternative}
249253
>
250-
{formatPrice(initialValue, { maximumDecimals: 2 })} on{' '}
251-
{outcomeSideText}
254+
{strings('predict.cashout_info', {
255+
amount: formatPrice(initialValue, { maximumDecimals: 2 }),
256+
outcome: outcomeSideText,
257+
initialPrice: (avgPrice * 100).toFixed(0),
258+
})}
252259
</Text>
253-
</View>
254-
</View>
260+
</Box>
261+
</Box>
255262
<View style={styles.cashOutButtonContainer}>
256263
{renderCashOutButton()}
257264
<Text variant={TextVariant.BodyXS} style={styles.cashOutButtonText}>

locales/languages/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,6 +1771,8 @@
17711771
"sell_position": "Sell Position",
17721772
"cash_out": "Cash out",
17731773
"cash_out_info": "Funds will be added to your available balance",
1774+
"at_price_per_share": "At price: {{price}}¢ per share",
1775+
"cashout_info": "{{amount}} on {{outcome}} at {{initialPrice}}¢",
17741776
"buy_yes": "Yes",
17751777
"buy_no": "No",
17761778
"outcomes": "outcomes",

0 commit comments

Comments
 (0)