Skip to content
This repository was archived by the owner on Jul 15, 2025. It is now read-only.

Commit 27310e7

Browse files
Merge pull request #42 from deriv-com/f_ui_fixes
Contract Detail Desktop View and UI Fixes
2 parents 86ce2c6 + 622b9e1 commit 27310e7

File tree

6 files changed

+193
-30
lines changed

6 files changed

+193
-30
lines changed

src/components/MarketInfo/MarketInfo.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ export const MarketInfo: React.FC<MarketInfoProps> = ({
2121
if (isMobile) {
2222
return (
2323
<div
24-
className="w-full cursor-pointer"
24+
className="inline-flex cursor-pointer mx-4 my-2"
2525
data-id="market-info"
2626
onClick={onClick}
2727
>
28-
<div className="flex items-center gap-4 px-4 py-3 bg-black/[0.04]">
28+
<div className="flex items-center gap-4 px-4 py-3 bg-black/[0.04] rounded-lg">
2929
{selectedMarket && (
3030
<div className="w-8 h-8 flex items-center justify-center">
3131
<MarketIcon
@@ -49,7 +49,7 @@ export const MarketInfo: React.FC<MarketInfoProps> = ({
4949

5050
return (
5151
<div
52-
className="inline-flex cursor-pointer bg-white hover:bg-gray-100 active:bg-gray-200 rounded-lg transition-colors"
52+
className="inline-flex cursor-pointer bg-gray-100 hover:bg-gray-100 active:bg-gray-200 rounded-lg transition-colors"
5353
data-id="market-info"
5454
onClick={onClick}
5555
>
@@ -65,12 +65,12 @@ export const MarketInfo: React.FC<MarketInfoProps> = ({
6565
)}
6666
<div className="min-w-0">
6767
<div className="flex items-center gap-2">
68-
<div className="text-base font-bold text-black/[0.72] leading-6 font-ibm-plex-sans truncate">{title}</div>
69-
<ChevronDown className="w-5 text-black/[0.72] flex-shrink-0 stroke-[1.5]" />
68+
<div className="text-base font-bold text-[#4C4C4C] leading-6 font-ibm-plex-sans truncate">{title}</div>
69+
<ChevronDown className="w-5 text-[#4C4C4C] flex-shrink-0 stroke-[1.5]" />
7070
</div>
71-
<div className="text-sm text-black/[0.48] leading-5 font-ibm-plex-sans truncate">{subtitle}</div>
71+
<div className="text-sm text-[#808080] leading-5 font-ibm-plex-sans truncate">{subtitle}</div>
7272
</div>
7373
</div>
7474
</div>
7575
)
76-
}
76+
}

src/components/PositionsSidebar/PositionsSidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,4 @@ export const PositionsSidebar: FC<PositionsSidebarProps> = ({ isOpen, onClose })
146146
);
147147
};
148148

149-
export default PositionsSidebar;
149+
export default PositionsSidebar;

src/layouts/MainLayout/MainLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ export const MainLayout: React.FC<MainLayoutProps> = ({ children }) => {
6565
</div>
6666
</div>
6767
);
68-
};
68+
};
Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
1-
import React, { useEffect } from "react";
2-
import { useNavigate } from "react-router-dom";
3-
import { useHeaderStore } from "@/stores/headerStore";
4-
import { useBottomNavStore } from "@/stores/bottomNavStore";
1+
import React, { useEffect } from "react"
2+
import { useNavigate } from "react-router-dom"
3+
import { useDeviceDetection } from "@/hooks/useDeviceDetection"
4+
import { useHeaderStore } from "@/stores/headerStore"
5+
import { useBottomNavStore } from "@/stores/bottomNavStore"
6+
import DesktopContractDetailsPage from "./DesktopContractDetailsPage"
57
import {
68
Header,
79
ContractSummary,
810
OrderDetails,
911
Chart,
1012
Payout,
1113
EntryExitDetails,
12-
} from "./components";
14+
} from "./components"
1315

14-
const ContractDetailsPage: React.FC = () => {
15-
const navigate = useNavigate();
16-
const setHeaderVisible = useHeaderStore(state => state.setIsVisible);
17-
const setBottomNavVisible = useBottomNavStore(state => state.setIsVisible);
16+
const MobileContractDetailsPage: React.FC = () => {
17+
const navigate = useNavigate()
18+
const setHeaderVisible = useHeaderStore((state) => state.setIsVisible)
19+
const setBottomNavVisible = useBottomNavStore((state) => state.setIsVisible)
1820

1921
useEffect(() => {
20-
setHeaderVisible(false);
21-
setBottomNavVisible(false);
22+
setHeaderVisible(false)
23+
setBottomNavVisible(false)
2224
return () => {
23-
setHeaderVisible(true);
24-
setBottomNavVisible(true);
25-
};
26-
}, [setHeaderVisible, setBottomNavVisible]);
25+
setHeaderVisible(true)
26+
setBottomNavVisible(true)
27+
}
28+
}, [setHeaderVisible, setBottomNavVisible])
29+
2730
return (
2831
<div className="w-full bg-gray-100 h-screen flex flex-col">
2932
<Header />
@@ -35,11 +38,11 @@ const ContractDetailsPage: React.FC = () => {
3538
<Payout />
3639
<EntryExitDetails />
3740
</div>
38-
</div>
41+
</div>
3942

4043
{/* Close Button */}
41-
<div className=" fixed bottom-0 left-0 right-0 z-[60]">
42-
<div className="mx-2 text-center">
44+
<div className="fixed bottom-0 left-0 right-0 z-[60]">
45+
<div className="mx-2 text-center">
4346
<button
4447
onClick={() => navigate(-1)}
4548
className="text-white bg-black max-w-[500px] mx-auto w-full p-3 px-8 text-center rounded-xl shadow-md"
@@ -49,7 +52,16 @@ const ContractDetailsPage: React.FC = () => {
4952
</div>
5053
</div>
5154
</div>
52-
);
53-
};
55+
)
56+
}
57+
58+
const ContractDetailsPage: React.FC = () => {
59+
const { isMobile } = useDeviceDetection()
60+
return isMobile ? (
61+
<MobileContractDetailsPage />
62+
) : (
63+
<DesktopContractDetailsPage />
64+
)
65+
}
5466

55-
export default ContractDetailsPage;
67+
export default ContractDetailsPage
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from "react"
2+
import { useNavigate } from "react-router-dom"
3+
import { X } from "lucide-react"
4+
import {
5+
ContractSummary,
6+
EntryExitDetails,
7+
OrderDetails,
8+
Payout,
9+
} from "./components"
10+
11+
const DesktopContractDetailsPage: React.FC = () => {
12+
const navigate = useNavigate()
13+
14+
return (
15+
<div className="flex flex-col h-screen bg-gray-50 w-full" data-testid="desktop-contract-details">
16+
<div className="flex justify-between items-center p-4 bg-white">
17+
<h1 className="text-xl font-bold mx-auto">Contract details</h1>
18+
<button onClick={() => navigate(-1)} className="text-gray-600">
19+
<X className="w-6 h-6" />
20+
</button>
21+
</div>
22+
23+
<div className="flex flex-1 overflow-hidden relative">
24+
<div className="w-[320px] border-r bg-white flex flex-col" data-testid="left-panel">
25+
<div className="flex-1 overflow-y-auto p-4 pb-40" data-testid="content-area">
26+
<ContractSummary />
27+
<OrderDetails />
28+
<Payout />
29+
<EntryExitDetails />
30+
</div>
31+
<div className="absolute bottom-16 left-0 right-0 m-4 w-[290px] b-[55px]" data-testid="close-button-container">
32+
<div className="max-w-[1200px] mx-auto">
33+
<button
34+
onClick={() => navigate(-1)}
35+
className="w-full bg-black text-white py-3 rounded-lg"
36+
>
37+
Close
38+
</button>
39+
</div>
40+
</div>
41+
</div>
42+
<div className="flex-1 flex flex-col">
43+
<div className="flex-1 m-4 mb-20 bg-white rounded-lg border flex items-center justify-center text-gray-500 ">
44+
Chart placeholder
45+
</div>
46+
</div>
47+
</div>
48+
</div>
49+
)
50+
}
51+
52+
export default DesktopContractDetailsPage
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import React from "react";
2+
import { render, screen, fireEvent } from "@testing-library/react";
3+
import { useNavigate } from "react-router-dom";
4+
import DesktopContractDetailsPage from "../DesktopContractDetailsPage";
5+
6+
// Mock the router hook
7+
jest.mock("react-router-dom", () => ({
8+
useNavigate: jest.fn(),
9+
}));
10+
11+
// Mock the components
12+
jest.mock("../components", () => ({
13+
ContractSummary: function ContractSummary() { return React.createElement('div', { 'data-testid': 'contract-summary' }, 'Contract Summary') },
14+
OrderDetails: function OrderDetails() { return React.createElement('div', { 'data-testid': 'order-details' }, 'Order Details') },
15+
Payout: function Payout() { return React.createElement('div', { 'data-testid': 'payout' }, 'Payout') },
16+
EntryExitDetails: function EntryExitDetails() { return React.createElement('div', { 'data-testid': 'entry-exit-details' }, 'Entry Exit Details') },
17+
}), { virtual: true });
18+
19+
describe("DesktopContractDetailsPage", () => {
20+
const mockNavigate = jest.fn();
21+
22+
beforeEach(() => {
23+
(useNavigate as jest.Mock).mockReturnValue(mockNavigate);
24+
});
25+
26+
afterEach(() => {
27+
jest.clearAllMocks();
28+
});
29+
30+
it("renders all components correctly", () => {
31+
render(<DesktopContractDetailsPage />);
32+
33+
// Check header
34+
expect(screen.getByText("Contract details")).toBeInTheDocument();
35+
36+
// Check all sections are rendered
37+
expect(screen.getByTestId("contract-summary")).toBeInTheDocument();
38+
expect(screen.getByTestId("order-details")).toBeInTheDocument();
39+
expect(screen.getByTestId("payout")).toBeInTheDocument();
40+
expect(screen.getByTestId("entry-exit-details")).toBeInTheDocument();
41+
42+
// Check chart placeholder
43+
expect(screen.getByText("Chart placeholder")).toBeInTheDocument();
44+
45+
// Check close button
46+
expect(screen.getByText("Close")).toBeInTheDocument();
47+
});
48+
49+
it("navigates back when close button is clicked", () => {
50+
render(<DesktopContractDetailsPage />);
51+
52+
const closeButton = screen.getByText("Close");
53+
fireEvent.click(closeButton);
54+
55+
expect(mockNavigate).toHaveBeenCalledWith(-1);
56+
});
57+
58+
it("navigates back when header close button is clicked", () => {
59+
render(<DesktopContractDetailsPage />);
60+
61+
const headerCloseButton = screen.getByRole("button", { name: /close/i });
62+
fireEvent.click(headerCloseButton);
63+
64+
expect(mockNavigate).toHaveBeenCalledWith(-1);
65+
});
66+
67+
it("has correct layout structure", () => {
68+
render(<DesktopContractDetailsPage />);
69+
70+
// Check main container
71+
const mainContainer = screen.getByTestId("desktop-contract-details");
72+
expect(mainContainer).toHaveClass("flex flex-col h-screen bg-gray-50 w-full");
73+
74+
// Check left panel
75+
const leftPanel = screen.getByTestId("left-panel");
76+
expect(leftPanel).toHaveClass("w-[320px] border-r bg-white flex flex-col");
77+
78+
// Check content area
79+
const contentArea = screen.getByTestId("content-area");
80+
expect(contentArea).toHaveClass("flex-1 overflow-y-auto p-4 pb-40");
81+
82+
// Check close button container
83+
const closeButtonContainer = screen.getByTestId("close-button-container");
84+
expect(closeButtonContainer).toHaveClass("absolute bottom-16 left-0 right-0 m-4 w-[290px] b-[55px]");
85+
});
86+
87+
it("renders in correct order", () => {
88+
render(<DesktopContractDetailsPage />);
89+
90+
const content = screen.getByTestId("content-area");
91+
const children = Array.from(content.children);
92+
93+
// Check components are rendered in correct order
94+
expect(children[0]).toHaveAttribute("data-testid", "contract-summary");
95+
expect(children[1]).toHaveAttribute("data-testid", "order-details");
96+
expect(children[2]).toHaveAttribute("data-testid", "payout");
97+
expect(children[3]).toHaveAttribute("data-testid", "entry-exit-details");
98+
});
99+
});

0 commit comments

Comments
 (0)