Skip to content

Commit 91686f7

Browse files
authored
Merge branch 'deriv-com:master' into master
2 parents bb59903 + e2bc794 commit 91686f7

13 files changed

+471
-77
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { Text } from "@deriv-com/quill-ui";
2+
import { observer } from "mobx-react-lite";
3+
import { tradingPanelStore } from "../../../stores/TradingPanelStore";
4+
5+
export const ContractItem = observer(() => {
6+
const { openContracts } = tradingPanelStore;
7+
8+
if (openContracts.length === 0) {
9+
return (
10+
<div className="contract-item">
11+
<Text as="p" size="sm">
12+
No open contracts
13+
</Text>
14+
</div>
15+
);
16+
}
17+
18+
return openContracts.map((contract) => (
19+
<div key={contract.contract_id} className="contract-item">
20+
<Text as="p" size="sm" className="text-bold">
21+
{contract.display_name} - {contract.contract_type}
22+
</Text>
23+
<div className="contract-details">
24+
<div className="detail-row">
25+
<Text as="span" size="sm">
26+
Entry Price:
27+
</Text>
28+
<Text as="span" size="sm">
29+
{contract.entry_spot_display_value}
30+
</Text>
31+
</div>
32+
<div className="detail-row">
33+
<Text as="span" size="sm">
34+
Current Price:
35+
</Text>
36+
<Text as="span" size="sm">
37+
{contract.current_spot_display_value}
38+
</Text>
39+
</div>
40+
<div className="detail-row">
41+
<Text as="span" size="sm">
42+
Buy Price:
43+
</Text>
44+
<Text as="span" size="sm">
45+
{contract.buy_price} {contract.currency}
46+
</Text>
47+
</div>
48+
<div className="detail-row">
49+
<Text as="span" size="sm">
50+
Payout:
51+
</Text>
52+
<Text as="span" size="sm">
53+
{contract.payout} {contract.currency}
54+
</Text>
55+
</div>
56+
<div className="detail-row">
57+
<Text as="span" size="sm">
58+
Profit/Loss:
59+
</Text>
60+
<Text
61+
as="span"
62+
size="sm"
63+
className={contract.profit >= 0 ? "profit" : "loss"}
64+
>
65+
{contract.profit.toFixed(2)} {contract.currency} (
66+
{contract.profit_percentage.toFixed(2)}%)
67+
</Text>
68+
</div>
69+
</div>
70+
</div>
71+
));
72+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
.open-contracts-modal {
2+
.quill-modal__button-wrapper {
3+
display: none;
4+
}
5+
6+
.contracts-container {
7+
padding: 16px;
8+
}
9+
10+
.contracts-list {
11+
max-height: 60vh;
12+
overflow-y: auto;
13+
padding-right: 8px;
14+
15+
&::-webkit-scrollbar {
16+
width: 4px;
17+
}
18+
19+
&::-webkit-scrollbar-track {
20+
background: var(--system-light-2-secondary, #f2f3f4);
21+
border-radius: 2px;
22+
}
23+
24+
&::-webkit-scrollbar-thumb {
25+
background: var(--text-less-prominent, #999999);
26+
border-radius: 2px;
27+
}
28+
}
29+
30+
.contract-item {
31+
background: var(--system-light-2-secondary, #f2f3f4);
32+
border-radius: 8px;
33+
padding: 16px;
34+
margin-bottom: 12px;
35+
36+
&:last-child {
37+
margin-bottom: 0;
38+
}
39+
40+
.contract-details {
41+
margin-top: 12px;
42+
43+
.detail-row {
44+
display: flex;
45+
justify-content: space-between;
46+
align-items: center;
47+
margin-bottom: 8px;
48+
49+
&:last-child {
50+
margin-bottom: 0;
51+
margin-top: 12px;
52+
}
53+
}
54+
}
55+
56+
.profit {
57+
color: var(--text-profit-success, #4bb4b3);
58+
}
59+
60+
.loss {
61+
color: var(--text-profit-danger, #ec3f3f);
62+
}
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Modal } from "@deriv-com/quill-ui";
2+
import { observer } from "mobx-react-lite";
3+
import { tradingPanelStore } from "../../../stores/TradingPanelStore";
4+
import { ContractItem } from "./ContractItem";
5+
import "./OpenContractsModal.scss";
6+
7+
export const OpenContractsModal = observer(() => {
8+
const { isOpenContractsModalVisible, setOpenContractsModalVisible } =
9+
tradingPanelStore;
10+
11+
return (
12+
<Modal
13+
className="open-contracts-modal"
14+
isOpened={isOpenContractsModalVisible}
15+
toggleModal={() => setOpenContractsModalVisible(false)}
16+
title="Open Contracts"
17+
>
18+
<div className="contracts-container">
19+
<div className="contracts-list">
20+
<ContractItem />
21+
</div>
22+
</div>
23+
</Modal>
24+
);
25+
});

src/components/TradingComponents/TradeButton/TradeButton.tsx

+9-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import {
77
interface TradeButtonProps {
88
type: "rise" | "fall";
99
percentage: string;
10+
onBuy: (type: "rise" | "fall") => void;
1011
}
1112

12-
export const TradeButton = ({ type, percentage }: TradeButtonProps) => {
13+
export const TradeButton = ({ type, percentage, onBuy }: TradeButtonProps) => {
1314
const Icon =
1415
type === "rise"
1516
? TradeTypesUpsAndDownsRiseIcon
@@ -18,7 +19,13 @@ export const TradeButton = ({ type, percentage }: TradeButtonProps) => {
1819
const className = `${type}-button`;
1920

2021
return (
21-
<Button variant="primary" size="lg" fullWidth className={className}>
22+
<Button
23+
variant="primary"
24+
size="lg"
25+
fullWidth
26+
className={className}
27+
onClick={() => onBuy(type)}
28+
>
2229
<div className="button-content">
2330
<div className="left">
2431
<Icon />

src/components/TradingComponents/TradingPanel/TradingPanel.scss

+28
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,32 @@
177177
background: linear-gradient(90deg, #ec3f3f 0%, #ff5c5c 100%);
178178
}
179179
}
180+
181+
.open-contracts-button {
182+
display: flex;
183+
justify-content: center;
184+
margin-top: 8px;
185+
186+
button {
187+
display: flex;
188+
align-items: center;
189+
gap: 8px;
190+
padding: 8px 16px;
191+
border-radius: 4px;
192+
background: var(--system-light-2-secondary, #f2f3f4);
193+
transition: background-color 0.3s ease;
194+
195+
&:hover {
196+
background: var(--system-light-3-hover, #e6e9ea);
197+
}
198+
199+
span:last-child {
200+
background: var(--brand-blue, #85acb0);
201+
color: var(--text-colored-background, #ffffff);
202+
padding: 2px 8px;
203+
border-radius: 8px;
204+
font-size: 12px;
205+
}
206+
}
207+
}
180208
}

src/components/TradingComponents/TradingPanel/TradingPanel.tsx

+34-11
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { DurationSection } from "../DurationSection/DurationSection";
1212
import { StakeSection } from "../StakeSection/StakeSection";
1313
import { TradeButton } from "../TradeButton/TradeButton";
1414
import { PayoutInfo } from "../PayoutInfo/PayoutInfo";
15+
import { OpenContractsModal } from "../OpenContractsModal/OpenContractsModal";
1516
import "./TradingPanel.scss";
1617

1718
export const TradingPanel = observer(() => {
@@ -29,17 +30,20 @@ export const TradingPanel = observer(() => {
2930
durationError,
3031
priceError,
3132
is_rise_fall_valid,
33+
openContracts,
34+
setOpenContractsModalVisible,
3235
} = tradingPanelStore;
3336

34-
const { proposal, clearProposal, isLoading } = useRiseFallTrading(
35-
chartStore.symbol,
36-
price,
37-
duration,
38-
selectedStakeTab,
39-
durationError,
40-
priceError,
41-
is_rise_fall_valid
42-
);
37+
const { proposal, clearProposal, isLoading, buyContract } =
38+
useRiseFallTrading(
39+
chartStore.symbol,
40+
price,
41+
duration,
42+
selectedStakeTab,
43+
durationError,
44+
priceError,
45+
is_rise_fall_valid
46+
);
4347

4448
const getAmount = (type: "rise" | "fall"): string => {
4549
const currentProposal = proposal[type];
@@ -131,22 +135,41 @@ export const TradingPanel = observer(() => {
131135
*/}
132136

133137
<div className="payout-section">
134-
<TradeButton type="rise" percentage={getPercentage("rise")} />
138+
<TradeButton
139+
type="rise"
140+
percentage={getPercentage("rise")}
141+
onBuy={buyContract}
142+
/>
135143
<PayoutInfo
136144
type="rise"
137145
label={label}
138146
amount={getAmount("rise")}
139147
isLoading={isLoading.rise}
140148
/>
141149

142-
<TradeButton type="fall" percentage={getPercentage("fall")} />
150+
<TradeButton
151+
type="fall"
152+
percentage={getPercentage("fall")}
153+
onBuy={buyContract}
154+
/>
143155
<PayoutInfo
144156
type="fall"
145157
label={label}
146158
amount={getAmount("fall")}
147159
isLoading={isLoading.fall}
148160
/>
149161
</div>
162+
163+
<div className="open-contracts-button">
164+
<Button
165+
variant="secondary"
166+
onClick={() => setOpenContractsModalVisible(true)}
167+
>
168+
Show Open Contracts {openContracts.length ?? 0}
169+
</Button>
170+
</div>
171+
172+
<OpenContractsModal />
150173
</>
151174
)}
152175
</div>

src/hooks/useBuyContract.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { getDerivAPI } from "../services/deriv-api.instance";
2+
import { tradingPanelStore } from "../stores/TradingPanelStore";
3+
4+
export const useBuyContract = (
5+
price: string,
6+
handleProposal: () => Promise<void>
7+
) => {
8+
const buyContract = async (type: "rise" | "fall") => {
9+
const derivAPI = getDerivAPI();
10+
const contractId =
11+
type === "rise"
12+
? tradingPanelStore.riseContractId
13+
: tradingPanelStore.fallContractId;
14+
15+
if (!contractId) {
16+
console.error("No contract ID available for", type);
17+
return;
18+
}
19+
20+
try {
21+
const response = await derivAPI.sendRequest({
22+
buy: contractId,
23+
price: parseFloat(price),
24+
});
25+
26+
if (response.error) {
27+
console.error("Buy contract error:", response.error);
28+
return;
29+
}
30+
31+
tradingPanelStore.setRiseContractId(null);
32+
tradingPanelStore.setFallContractId(null);
33+
await handleProposal();
34+
return response;
35+
} catch (error) {
36+
console.error("Error buying contract:", error);
37+
}
38+
};
39+
40+
return { buyContract };
41+
};

0 commit comments

Comments
 (0)