Skip to content

Commit f0fa145

Browse files
mohandast52Copilot
andauthored
feat(PREDICT-652): Show invalid trades in the AgentUI both Omenstrat and Polystrat (#70)
* feat: Add support for 'invalid' trade status in TradeStatus component and mock data * feat: Implement 'invalid' trade status alert and update styles in TradeStatus component * Update apps/predict-ui/src/components/ui/Alert.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update apps/predict-ui/src/constants/theme.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update apps/predict-ui/src/components/ui/Alert.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * refactor: clarify comments in TradeStatus and update mockTradeHistory total --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent a6906a3 commit f0fa145

6 files changed

Lines changed: 99 additions & 9 deletions

File tree

apps/predict-ui/src/components/TradeHistory/PositionDetailsModal/PositionDetailsModal.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { UNICODE_SYMBOLS } from '@agent-ui-monorepo/util-constants-and-types';
22
import { ClockCircleOutlined } from '@ant-design/icons';
33
import {
4-
Alert,
54
Card as AntdCard,
65
Col,
76
Collapse,
@@ -17,6 +16,7 @@ import styled from 'styled-components';
1716
import { CURRENCY, CurrencyCode } from '../../../constants/currency';
1817
import { COLOR } from '../../../constants/theme';
1918
import { usePositionDetails } from '../../../hooks/useTradeHistory';
19+
import { Alert } from '../../ui/Alert';
2020
import { TradeStatus } from '../TradeStatus';
2121
import { Trade } from './Trade';
2222

@@ -42,6 +42,15 @@ const Card = styled(AntdCard)`
4242
border-color: ${COLOR.WHITE_TRANSPARENT_10};
4343
`;
4444

45+
const InvalidMarketAlert = () => (
46+
<Alert
47+
type="warning"
48+
message="Invalid market"
49+
description="This market was marked invalid. The payout for an invalid market can be full, partial, or $0 depending on how it was settled."
50+
style={{ marginBottom: 16 }}
51+
/>
52+
);
53+
4554
const formatCurrency = (n: number, currency: CurrencyCode) => {
4655
const currencySymbol = CURRENCY[currency]?.symbol || '$';
4756
return `${currencySymbol}${n.toFixed(3)}`;
@@ -87,9 +96,10 @@ export const PositionDetailsModal = ({ id, onClose }: PositionDetailsModalProps)
8796
<Skeleton active title={false} paragraph={{ rows: 3 }} />
8897
</Card>
8998
) : error ? (
90-
<Alert type="error" description={error.message} showIcon />
99+
<Alert type="error" message={error.message} />
91100
) : data ? (
92101
<>
102+
{data.status === 'invalid' && <InvalidMarketAlert />}
93103
<Card variant="outlined" className="mb-8" styles={{ body: { padding: 16 } }}>
94104
<Text>
95105
<a
@@ -112,7 +122,11 @@ export const PositionDetailsModal = ({ id, onClose }: PositionDetailsModalProps)
112122
</Col>
113123
<Col xs={24} sm={8} md={8}>
114124
<Metric
115-
label={data.status === 'won' ? 'Won' : 'To win'}
125+
label={(() => {
126+
if (data.status === 'invalid') return 'Payout';
127+
if (data.status === 'won') return 'Won';
128+
return 'To win';
129+
})()}
116130
value={formatCurrency(data.to_win, data.currency)}
117131
/>
118132
</Col>
@@ -129,7 +143,9 @@ export const PositionDetailsModal = ({ id, onClose }: PositionDetailsModalProps)
129143
net_profit={data.net_profit}
130144
styles={{ fontSize: '105%' }}
131145
extra={
132-
<ClockCircleOutlined style={{ color: COLOR.WHITE_TRANSPARENT_75 }} />
146+
data.status === 'pending' ? (
147+
<ClockCircleOutlined style={{ color: COLOR.WHITE_TRANSPARENT_75 }} />
148+
) : null
133149
}
134150
/>
135151
</Flex>

apps/predict-ui/src/components/TradeHistory/TradeStatus.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,16 @@ export const TradeStatus = ({
4242
};
4343
}
4444

45-
// If status is pending and remaining_seconds is provided
46-
// show countdown
45+
if (status === 'invalid') {
46+
return {
47+
color: COLOR.YELLOW,
48+
background: COLOR.YELLOW_BACKGROUND,
49+
text: `Invalid`,
50+
};
51+
}
52+
53+
// If status is pending and remaining_seconds is provided, show countdown
54+
// Otherwise show the traded amount
4755
if (remaining_seconds !== undefined) {
4856
return {
4957
color: COLOR.WHITE_TRANSPARENT_75,
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { WarningOutlined } from '@ant-design/icons';
2+
import { Alert as AntdAlert, Flex } from 'antd';
3+
import { CSSProperties, ReactNode } from 'react';
4+
import styled from 'styled-components';
5+
6+
import { COLOR } from '../../constants/theme';
7+
8+
type AlertType = 'warning' | 'error';
9+
10+
type AlertProps = {
11+
type: AlertType;
12+
message: ReactNode;
13+
description?: ReactNode;
14+
style?: CSSProperties;
15+
};
16+
17+
const StyledAlert = styled(AntdAlert)<{ $alertType: AlertType }>`
18+
padding: 12px;
19+
align-items: flex-start;
20+
background: ${(props) =>
21+
props.$alertType === 'warning' ? COLOR.YELLOW_BACKGROUND : COLOR.RED_BACKGROUND};
22+
border-color: ${(props) =>
23+
props.$alertType === 'warning' ? COLOR.YELLOW_BACKGROUND : COLOR.RED_BACKGROUND};
24+
color: ${(props) => (props.$alertType === 'warning' ? COLOR.YELLOW : COLOR.RED)};
25+
`;
26+
27+
export const Alert = ({ type, message, description, style }: AlertProps) => {
28+
return (
29+
<StyledAlert
30+
$alertType={type}
31+
message={
32+
<Flex gap={8} vertical>
33+
<span style={{ fontWeight: 500 }}>{message}</span>
34+
{description && <span>{description}</span>}
35+
</Flex>
36+
}
37+
type={type}
38+
showIcon
39+
icon={
40+
type === 'warning' ? (
41+
<WarningOutlined style={{ fontSize: 18, marginTop: '2px', color: COLOR.YELLOW }} />
42+
) : undefined
43+
}
44+
style={{ ...style }}
45+
/>
46+
);
47+
};

apps/predict-ui/src/constants/theme.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ export const COLOR = {
5151
GREEN: '#1AFF7B',
5252

5353
RED: '#F5222D',
54+
RED_BACKGROUND: 'rgba(245, 34, 45, 0.1)',
55+
56+
YELLOW: '#FFFF00',
57+
YELLOW_BACKGROUND: 'rgba(255, 255, 0, 0.1)',
58+
5459
BLUE: '#1677FF',
5560
LIGHT_GRAY: '#F8F9FA',
5661
};

apps/predict-ui/src/mocks/mockTradeHistory.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const mockTradeHistory: AgentPredictionHistoryResponse = {
55
currency: 'USD',
66
page: 1,
77
page_size: 10,
8-
total: 5,
8+
total: 6,
99
items: [
1010
{
1111
id: 'pred_001',
@@ -81,6 +81,20 @@ export const mockTradeHistory: AgentPredictionHistoryResponse = {
8181
created_at: '2025-11-16T13:45:00Z',
8282
settled_at: '2025-12-01T16:10:00Z',
8383
},
84+
{
85+
id: 'pred_006',
86+
market: {
87+
id: 'market_4',
88+
title: 'Will Bitcoin close above $50,000 on December 31, 2025?',
89+
external_url: 'https://example.com/market/market_4',
90+
},
91+
prediction_side: 'yes',
92+
bet_amount: 0.05,
93+
status: 'invalid',
94+
net_profit: 0.12,
95+
created_at: '2025-11-16T13:45:00Z',
96+
settled_at: '2025-12-01T16:10:00Z',
97+
},
8498
],
8599
} as const;
86100

apps/predict-ui/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export type AgentMetricsResponse = {
5050
};
5151
};
5252

53-
export type PredictionStatus = 'pending' | 'won' | 'lost';
53+
export type PredictionStatus = 'pending' | 'won' | 'lost' | 'invalid';
5454

5555
export type PredictionSide = 'yes' | 'no';
5656

@@ -107,7 +107,7 @@ export type PositionDetails = {
107107
currency: CurrencyCode;
108108
total_bet: number;
109109
to_win: number;
110-
/** If status is pending, show remaining_seconds else net profit */
110+
/** For pending status, display remaining_seconds; for won/lost/invalid, display net_profit */
111111
status: PredictionStatus;
112112
/** time left in seconds */
113113
remaining_seconds?: number;

0 commit comments

Comments
 (0)